Skip to content

Commit 4f6ebfb

Browse files
committed
pg: exec_no_null(); gx: remove deprecated test; parser/tmpl: %raw translations; veb: time_to_render()
1 parent b718c42 commit 4f6ebfb

9 files changed

Lines changed: 114 additions & 141 deletions

File tree

‎cmd/tools/vwatch.v‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const scan_period_ms = 1000 / scan_frequency_hz
1515

1616
const max_scan_cycles = scan_timeout_s * scan_frequency_hz
1717

18-
const default_vweb_suffixes = '*.v,*.html,*.css,*.js,*.md'
18+
const default_veb_suffixes = '*.v,*.html,*.css,*.js,*.md,*.tr'
1919

2020
fn get_scan_timeout_seconds() int {
2121
env_vw_timeout := os.getenv('VWATCH_TIMEOUT').int()
@@ -171,14 +171,14 @@ fn (mut context Context) get_stats_for_affected_vfiles() []VFileStat {
171171

172172
if is_vweb_found {
173173
if !os.args.any(it.starts_with('--only-watch')) {
174-
context.only_watch = default_vweb_suffixes.split_any(',')
174+
context.only_watch = default_veb_suffixes.split_any(',')
175175
// vweb is often used with SQLite .db or .sqlite3 files right next to the executable/source,
176176
// that are updated by the vweb app, causing a restart of the app, which in turn causes the
177177
// browser to reload the current page, that probably triggered the update in the first place.
178178
// Note that the problem is not specific to SQLite, any database that stores its files in the
179179
// current (project) folder, will also cause this.
180180
println('`v watch` detected that you are compiling a vweb project.')
181-
println(' Because of that, the `--only-watch=${default_vweb_suffixes}` flag was also implied.')
181+
println(' Because of that, the `--only-watch=${default_veb_suffixes}` flag was also implied.')
182182
println(' In result, `v watch` will ignore changes to other files.')
183183
println(' Add your own --only-watch filter, if you wish to override that choice.')
184184
println('')

‎vlib/db/pg/pg.c.v‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ pub mut:
6969
vals []?string
7070
}
7171

72+
pub struct RowNoNull {
73+
pub mut:
74+
vals []string
75+
}
76+
7277
pub struct Result {
7378
pub:
7479
cols map[string]int
@@ -259,6 +264,22 @@ fn res_to_rows(res voidptr) []Row {
259264
return rows
260265
}
261266

267+
fn res_to_rows_no_null(res voidptr) []RowNoNull {
268+
nr_rows := C.PQntuples(res)
269+
nr_cols := C.PQnfields(res)
270+
mut rows := []RowNoNull{}
271+
for i in 0 .. nr_rows {
272+
mut row := RowNoNull{}
273+
for j in 0 .. nr_cols {
274+
val := C.PQgetvalue(res, i, j)
275+
row.vals << unsafe { cstring_to_vstring(val) }
276+
}
277+
rows << row
278+
}
279+
C.PQclear(res)
280+
return rows
281+
}
282+
262283
// res_to_result creates a `Result` struct out of a `C.PGresult` pointer
263284
fn res_to_result(res voidptr) Result {
264285
nr_rows := C.PQntuples(res)
@@ -338,6 +359,12 @@ pub fn (db &DB) exec(query string) ![]Row {
338359
return db.handle_error_or_rows(res, 'exec')
339360
}
340361

362+
// exec_no_null works like exec, but the fields can't be NULL, no optionals
363+
pub fn (db &DB) exec_no_null(query string) ![]RowNoNull {
364+
res := C.PQexec(db.conn, &char(query.str))
365+
return db.handle_error_or_rows_no_null(res, 'exec')
366+
}
367+
341368
// exec_result submits a command to the database server and wait for the result, returning an error on failure and a `Result` set on success
342369
pub fn (db &DB) exec_result(query string) !Result {
343370
res := C.PQexec(db.conn, &char(query.str))
@@ -440,6 +467,7 @@ fn (db &DB) handle_error_or_rows(res voidptr, elabel string) ![]Row {
440467
e := unsafe { C.PQerrorMessage(db.conn).vstring() }
441468
if e != '' {
442469
C.PQclear(res)
470+
// TODO make it default
443471
$if trace_pg_error ? {
444472
eprintln('pg error: ${e}')
445473
}
@@ -448,6 +476,19 @@ fn (db &DB) handle_error_or_rows(res voidptr, elabel string) ![]Row {
448476
return res_to_rows(res)
449477
}
450478

479+
fn (db &DB) handle_error_or_rows_no_null(res voidptr, elabel string) ![]RowNoNull {
480+
// TODO copypasta
481+
e := unsafe { C.PQerrorMessage(db.conn).vstring() }
482+
if e != '' {
483+
C.PQclear(res)
484+
$if trace_pg_error ? {
485+
eprintln('pg error: ${e}')
486+
}
487+
return error('pg ${elabel} error:\n${e}')
488+
}
489+
return res_to_rows_no_null(res)
490+
}
491+
451492
// hande_error_or_result is an internal function similar to handle_error_or_rows that returns `Result` instead of `[]Row`
452493
fn (db &DB) handle_error_or_result(res voidptr, elabel string) !Result {
453494
e := unsafe { C.PQerrorMessage(db.conn).vstring() }

‎vlib/gx/color_test.v‎

Lines changed: 0 additions & 102 deletions
This file was deleted.

‎vlib/v/checker/fn.v‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
21762176

21772177
method_name := node.name
21782178
if left_type.has_flag(.option) {
2179-
c.error('Option type cannot be called directly, you should unwrap it first', node.left.pos())
2179+
c.error('Option type `${left_sym.name}` cannot be called directly, you should unwrap it first',
2180+
node.left.pos())
21802181
return ast.void_type
21812182
} else if left_type.has_flag(.result) {
21822183
c.error('Result type cannot be called directly', node.left.pos())

‎vlib/v/checker/tests/option_str_call.out‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
vlib/v/checker/tests/option_str_call.vv:7:10: error: Option type cannot be called directly, you should unwrap it first
1+
vlib/v/checker/tests/option_str_call.vv:7:10: error: Option type `net.html.Tag` cannot be called directly, you should unwrap it first
22
5 | footer := doc.get_tags_by_class_name('Box-footer')[0]
33
6 | invalid := footer.get_tag_by_class_name('invalid')
44
7 | println(invalid.str())

‎vlib/v/parser/tmpl.v‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -429,17 +429,33 @@ fn veb_tmpl_${fn_name}() string {
429429

430430
if pos := line.index('%') {
431431
// %translation_key => ${tr('translation_key')}
432+
is_raw := line.contains('%raw ')
432433
mut line_ := line
433-
if pos + 1 < line.len && line[pos + 1].is_letter() { //|| line[pos + 1] == '_' {
434-
mut end := pos + 1
434+
if is_raw {
435+
// Start reading the key after "raw " (pos + 1 + 4)
436+
mut end := pos + 5
437+
// valid variable characters
435438
for end < line.len && (line[end].is_letter() || line[end] == `_`) {
436439
end++
437440
}
438-
key := line[pos + 1..end]
439-
// println('GOT tr key line="${line}" key="${key}"')
440-
// source.writeln('\${tr("${key}")}')
441-
line_ = line.replace('%${key}', '\${veb.tr(ctx.lang.str(), "${key}")}')
442-
// i += key.len
441+
// Extract the key
442+
key := line[pos + 5..end]
443+
// Replace '%raw key' with just '${key}'
444+
// We escape it as \${key} so the generated V code performs the interpolation
445+
// line_ = line.replace('%raw ${key}', '\${${key}}')
446+
line_ = line.replace('%raw ${key}', '\${veb.raw(veb.tr(ctx.lang.str(), "${key}"))}')
447+
} else {
448+
if pos + 1 < line.len && line[pos + 1].is_letter() { //|| line[pos + 1] == '_' {
449+
mut end := pos + 1
450+
for end < line.len && (line[end].is_letter() || line[end] == `_`) {
451+
end++
452+
}
453+
key := line[pos + 1..end]
454+
// println('GOT tr key line="${line}" key="${key}"')
455+
// source.writeln('\${tr("${key}")}')
456+
line_ = line.replace('%${key}', '\${veb.tr(ctx.lang.str(), "${key}")}')
457+
// i += key.len
458+
}
443459
}
444460
// println(source.str())
445461
source.writeln(insert_template_code(fn_name, tmpl_str_start, line_))

‎vlib/veb/context.v‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import json
66
import net
77
import net.http
88
import os
9+
import time
910

1011
enum ContextReturnType {
1112
normal
@@ -443,3 +444,11 @@ pub fn (ctx &Context) ip() string {
443444
}
444445
return ip
445446
}
447+
448+
// time_to_render returns the time in milliseconds that it took to render the page
449+
pub fn (ctx &Context) time_to_render() i64 {
450+
if ctx.page_gen_start == 0 {
451+
return 0
452+
}
453+
return time.ticks() - ctx.page_gen_start
454+
}

‎vlib/veb/veb.v‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ pub fn run[A, X](mut global_app A, port int) {
7272
pub struct RunParams {
7373
pub:
7474
// use `family: .ip, host: 'localhost'` when you want it to bind only to 127.0.0.1
75-
family net.AddrFamily = .ip6
76-
host string
77-
port int = default_port
78-
show_startup_message bool = true
79-
timeout_in_seconds int = 30
75+
family net.AddrFamily = .ip6
76+
host string
77+
port int = default_port
78+
show_startup_message bool = true
79+
timeout_in_seconds int = 30
80+
benchmark_page_generation bool // for the "page rendered in X ms"
8081
}
8182

8283
struct FileResponse {

0 commit comments

Comments
 (0)