orm: fix select .. limit 1 . This case now returns an ?Row.
parent
151686501d
commit
49899c649c
|
@ -8,6 +8,12 @@ import strings
|
||||||
|
|
||||||
// `db.select from User where id == 1 && nr_bookings > 0`
|
// `db.select from User where id == 1 && nr_bookings > 0`
|
||||||
fn (p mut Parser) select_query(fn_ph int) string {
|
fn (p mut Parser) select_query(fn_ph int) string {
|
||||||
|
// NB: qprefix, p.sql_i, p.sql_params SHOULD be reset for each query,
|
||||||
|
// because we can have many queries in the _same_ scope.
|
||||||
|
qprefix := p.get_tmp().replace('tmp','sql') + '_'
|
||||||
|
p.sql_i = 0
|
||||||
|
p.sql_params = ''
|
||||||
|
|
||||||
mut q := 'select '
|
mut q := 'select '
|
||||||
p.check(.key_select)
|
p.check(.key_select)
|
||||||
n := p.check_name()
|
n := p.check_name()
|
||||||
|
@ -73,36 +79,55 @@ fn (p mut Parser) select_query(fn_ph int) string {
|
||||||
p.is_sql = false
|
p.is_sql = false
|
||||||
limit := p.cgen.end_tmp()
|
limit := p.cgen.end_tmp()
|
||||||
q += ' limit ' + limit
|
q += ' limit ' + limit
|
||||||
// `limit 1` means we are getting `User`, not `[]User`
|
// `limit 1` means we are getting `?User`, not `[]User`
|
||||||
if limit.trim_space() == '1' {
|
if limit.trim_space() == '1' {
|
||||||
query_one = true
|
query_one = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println('sql query="$q"')
|
println('sql query="$q"')
|
||||||
|
p.cgen.insert_before('// DEBUG_SQL prefix: $qprefix | fn_ph: $fn_ph | query: "$q" ')
|
||||||
|
|
||||||
if n == 'count' {
|
if n == 'count' {
|
||||||
p.cgen.set_placeholder(fn_ph, 'pg__DB_q_int(')
|
p.cgen.set_placeholder(fn_ph, 'pg__DB_q_int(')
|
||||||
p.gen(', tos2("$q"))')
|
p.gen(', tos2("$q"))')
|
||||||
} else {
|
} else {
|
||||||
// Build an object, assign each field.
|
// Build an object, assign each field.
|
||||||
tmp := p.get_tmp()
|
tmp := p.get_tmp()
|
||||||
mut obj_gen := strings.new_builder(100)
|
mut obj_gen := strings.new_builder(300)
|
||||||
for i, field in fields {
|
for i, field in fields {
|
||||||
mut cast := ''
|
mut cast := ''
|
||||||
if field.typ == 'int' {
|
if field.typ == 'int' {
|
||||||
cast = 'string_int'
|
cast = 'string_int'
|
||||||
}
|
}
|
||||||
obj_gen.writeln('$tmp . $field.name = $cast( *(string*)array__get(row.vals, $i) );')
|
obj_gen.writeln('${qprefix}$tmp . $field.name = $cast( *(string*)array__get(${qprefix}row.vals, $i) );')
|
||||||
}
|
}
|
||||||
// One object
|
// One object
|
||||||
if query_one {
|
if query_one {
|
||||||
|
mut params_gen := ''
|
||||||
|
params := p.sql_params.split(',')
|
||||||
|
for i, param in params {
|
||||||
|
params_gen += '${qprefix}params[$i] = int_str($param).str;'
|
||||||
|
}
|
||||||
p.cgen.insert_before('
|
p.cgen.insert_before('
|
||||||
|
|
||||||
pg__Row row = pg__DB_exec_one(db, tos2("$q"));
|
char* ${qprefix}params[$p.sql_i];
|
||||||
$table_name $tmp;
|
$params_gen
|
||||||
|
|
||||||
|
Option_${table_name} opt_${qprefix}$tmp;
|
||||||
|
void* ${qprefix}res = PQexecParams(db.conn, "$q", $p.sql_i, 0, ${qprefix}params, 0, 0, 0) ;
|
||||||
|
array_pg__Row ${qprefix}rows = pg__res_to_rows ( ${qprefix}res ) ;
|
||||||
|
Option_pg__Row opt_${qprefix}row = pg__rows_first_or_empty( ${qprefix}rows );
|
||||||
|
if (! opt_${qprefix}row . ok ) {
|
||||||
|
opt_${qprefix}$tmp = v_error( opt_${qprefix}row . error );
|
||||||
|
}else{
|
||||||
|
$table_name ${qprefix}$tmp;
|
||||||
|
pg__Row ${qprefix}row = *(pg__Row*) opt_${qprefix}row . data;
|
||||||
${obj_gen.str()}
|
${obj_gen.str()}
|
||||||
|
opt_${qprefix}$tmp = opt_ok( & ${qprefix}$tmp, sizeof($table_name) );
|
||||||
|
}
|
||||||
|
|
||||||
')
|
')
|
||||||
p.cgen.resetln(tmp)
|
p.cgen.resetln('opt_${qprefix}$tmp')
|
||||||
}
|
}
|
||||||
// Array
|
// Array
|
||||||
else {
|
else {
|
||||||
|
@ -110,32 +135,31 @@ ${obj_gen.str()}
|
||||||
mut params_gen := ''
|
mut params_gen := ''
|
||||||
params := p.sql_params.split(',')
|
params := p.sql_params.split(',')
|
||||||
for i, param in params {
|
for i, param in params {
|
||||||
params_gen += 'params[$i] = int_str($param).str;'
|
params_gen += '${qprefix}params[$i] = int_str($param).str;'
|
||||||
}
|
}
|
||||||
|
p.cgen.insert_before('char* ${qprefix}params[$p.sql_i];
|
||||||
p.cgen.insert_before('char* params[$p.sql_i];
|
|
||||||
$params_gen
|
$params_gen
|
||||||
|
|
||||||
void* res = PQexecParams(db.conn, "$q", $p.sql_i, 0, params, 0, 0, 0) ;
|
void* ${qprefix}res = PQexecParams(db.conn, "$q", $p.sql_i, 0, ${qprefix}params, 0, 0, 0) ;
|
||||||
array_pg__Row rows = pg__res_to_rows(res);
|
array_pg__Row ${qprefix}rows = pg__res_to_rows(${qprefix}res);
|
||||||
|
|
||||||
// TODO preallocate
|
// TODO preallocate
|
||||||
array arr_$tmp = new_array(0, 0, sizeof($table_name));
|
array ${qprefix}arr_$tmp = new_array(0, 0, sizeof($table_name));
|
||||||
for (int i = 0; i < rows.len; i++) {
|
for (int i = 0; i < ${qprefix}rows.len; i++) {
|
||||||
pg__Row row = *(pg__Row*)array__get(rows, i);
|
pg__Row ${qprefix}row = *(pg__Row*)array__get(${qprefix}rows, i);
|
||||||
$table_name $tmp;
|
$table_name ${qprefix}$tmp;
|
||||||
${obj_gen.str()}
|
${obj_gen.str()}
|
||||||
_PUSH(&arr_$tmp, $tmp, ${tmp}2, $table_name);
|
_PUSH(&${qprefix}arr_$tmp, ${qprefix}$tmp, ${tmp}2, $table_name);
|
||||||
}
|
}
|
||||||
')
|
')
|
||||||
p.cgen.resetln('arr_$tmp')
|
p.cgen.resetln('${qprefix}arr_$tmp')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if n == 'count' {
|
if n == 'count' {
|
||||||
return 'int'
|
return 'int'
|
||||||
} else if query_one {
|
} else if query_one {
|
||||||
return table_name
|
return 'Option_$table_name'
|
||||||
} else {
|
} else {
|
||||||
p.register_array('array_$table_name')
|
p.register_array('array_$table_name')
|
||||||
return 'array_$table_name'
|
return 'array_$table_name'
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub fn (nn int) str() string {
|
||||||
return '0'
|
return '0'
|
||||||
}
|
}
|
||||||
max := 16
|
max := 16
|
||||||
mut buf := malloc(max)
|
mut buf := calloc(max)
|
||||||
mut len := 0
|
mut len := 0
|
||||||
mut is_neg := false
|
mut is_neg := false
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
|
|
22
vlib/pg/pg.v
22
vlib/pg/pg.v
|
@ -29,6 +29,7 @@ pub:
|
||||||
host string
|
host string
|
||||||
user string
|
user string
|
||||||
password string
|
password string
|
||||||
|
dbname string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn C.PQconnectdb(a byteptr) *C.PGconn
|
fn C.PQconnectdb(a byteptr) *C.PGconn
|
||||||
|
@ -106,21 +107,22 @@ pub fn (db DB) exec(query string) []pg.Row {
|
||||||
return res_to_rows(res)
|
return res_to_rows(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (db DB) exec_one(query string) pg.Row {
|
fn rows_first_or_empty(rows []pg.Row) pg.Row? {
|
||||||
res := C.PQexec(db.conn, query.str)
|
|
||||||
e := string(C.PQerrorMessage(db.conn))
|
|
||||||
if e != '' {
|
|
||||||
println('pg exec error:')
|
|
||||||
println(e)
|
|
||||||
return Row{}
|
|
||||||
}
|
|
||||||
rows := res_to_rows(res)
|
|
||||||
if rows.len == 0 {
|
if rows.len == 0 {
|
||||||
return Row{}
|
return error('no row')
|
||||||
}
|
}
|
||||||
return rows[0]
|
return rows[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (db DB) exec_one(query string) pg.Row? {
|
||||||
|
res := C.PQexec(db.conn, query.str)
|
||||||
|
e := string(C.PQerrorMessage(db.conn))
|
||||||
|
if e != '' {
|
||||||
|
return error('pg exec error: "$e"')
|
||||||
|
}
|
||||||
|
row := rows_first_or_empty( res_to_rows(res) )
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
pub fn (db DB) exec_param2(query string, param, param2 string) []pg.Row {
|
pub fn (db DB) exec_param2(query string, param, param2 string) []pg.Row {
|
||||||
|
|
Loading…
Reference in New Issue