mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
V ORM
This commit is contained in:
parent
c67783bcd1
commit
8f8e0dfad7
@ -143,26 +143,6 @@ fn (g mut CGen) set_placeholder(pos int, val string) {
|
|||||||
// g.genln('')
|
// g.genln('')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) add_placeholder2() int {
|
|
||||||
if g.is_tmp {
|
|
||||||
println('tmp in addp2')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
g.lines << ''
|
|
||||||
return g.lines.len - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (g mut CGen) set_placeholder2(pos int, val string) {
|
|
||||||
if g.nogen || g.pass != .main {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if g.is_tmp {
|
|
||||||
println('tmp in setp2')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
g.lines[pos] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (g mut CGen) insert_before(val string) {
|
fn (g mut CGen) insert_before(val string) {
|
||||||
prev := g.lines[g.lines.len - 1]
|
prev := g.lines[g.lines.len - 1]
|
||||||
g.lines[g.lines.len - 1] = '$prev \n $val \n'
|
g.lines[g.lines.len - 1] = '$prev \n $val \n'
|
||||||
@ -240,7 +220,6 @@ fn (p mut Parser) gen_type_alias(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut CGen) add_to_main(s string) {
|
fn (g mut CGen) add_to_main(s string) {
|
||||||
println('add to main')
|
|
||||||
g.fn_main = g.fn_main + s
|
g.fn_main = g.fn_main + s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ mut:
|
|||||||
is_alloc bool // Whether current expression resulted in an allocation
|
is_alloc bool // Whether current expression resulted in an allocation
|
||||||
cur_gen_type string // "App" to replace "T" in current generic function
|
cur_gen_type string // "App" to replace "T" in current generic function
|
||||||
is_vweb bool
|
is_vweb bool
|
||||||
|
is_sql bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -1360,7 +1361,16 @@ fn (p mut Parser) bool_expression() string {
|
|||||||
got_or = true
|
got_or = true
|
||||||
if got_and { p.error(and_or_error) }
|
if got_and { p.error(and_or_error) }
|
||||||
}
|
}
|
||||||
p.gen(' ${p.tok.str()} ')
|
if p.is_sql {
|
||||||
|
if p.tok == .and {
|
||||||
|
p.gen(' and ')
|
||||||
|
}
|
||||||
|
else if p.tok == .logical_or {
|
||||||
|
p.gen(' or ')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.gen(' ${p.tok.str()} ')
|
||||||
|
}
|
||||||
p.check_space(p.tok)
|
p.check_space(p.tok)
|
||||||
p.check_types(p.bterm(), typ)
|
p.check_types(p.bterm(), typ)
|
||||||
}
|
}
|
||||||
@ -1377,21 +1387,24 @@ fn (p mut Parser) bterm() string {
|
|||||||
ph := p.cgen.add_placeholder()
|
ph := p.cgen.add_placeholder()
|
||||||
mut typ := p.expression()
|
mut typ := p.expression()
|
||||||
p.expected_type = typ
|
p.expected_type = typ
|
||||||
is_str := typ=='string'
|
is_str := typ=='string' && !p.is_sql
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
// if tok in [ .eq, .gt, .lt, .le, .ge, .ne] {
|
// if tok in [ .eq, .gt, .lt, .le, .ge, .ne] {
|
||||||
if tok == .eq || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne {
|
if tok == .eq || (tok == .assign && p.is_sql) || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne {
|
||||||
p.fgen(' ${p.tok.str()} ')
|
p.fgen(' ${p.tok.str()} ')
|
||||||
if is_str {
|
if is_str {
|
||||||
p.gen(',')
|
p.gen(',')
|
||||||
}
|
}
|
||||||
|
else if p.is_sql && tok == .eq {
|
||||||
|
p.gen('=')
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
p.gen(tok.str())
|
p.gen(tok.str())
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
p.check_types(p.expression(), typ)
|
p.check_types(p.expression(), typ)
|
||||||
typ = 'bool'
|
typ = 'bool'
|
||||||
if is_str {
|
if is_str { //&& !p.is_sql {
|
||||||
p.gen(')')
|
p.gen(')')
|
||||||
switch tok {
|
switch tok {
|
||||||
case Token.eq: p.cgen.set_placeholder(ph, 'string_eq(')
|
case Token.eq: p.cgen.set_placeholder(ph, 'string_eq(')
|
||||||
@ -1679,7 +1692,6 @@ fn (p mut Parser) var_expr(v Var) string {
|
|||||||
p.gen(')')
|
p.gen(')')
|
||||||
typ = T.func.typ
|
typ = T.func.typ
|
||||||
}
|
}
|
||||||
// users[0] before dot so that we can have
|
|
||||||
// users[0].name
|
// users[0].name
|
||||||
if p.tok == .lsbr {
|
if p.tok == .lsbr {
|
||||||
typ = p.index_expr(typ, fn_ph)
|
typ = p.index_expr(typ, fn_ph)
|
||||||
@ -1687,6 +1699,15 @@ fn (p mut Parser) var_expr(v Var) string {
|
|||||||
// a.b.c().d chain
|
// a.b.c().d chain
|
||||||
// mut dc := 0
|
// mut dc := 0
|
||||||
for p.tok ==.dot {
|
for p.tok ==.dot {
|
||||||
|
if p.peek() == .key_select {
|
||||||
|
p.next()
|
||||||
|
return p.select_query(fn_ph)
|
||||||
|
}
|
||||||
|
if typ == 'pg__DB' && !p.fileis('pg.v') {
|
||||||
|
p.next()
|
||||||
|
p.insert_query(fn_ph)
|
||||||
|
return 'void'
|
||||||
|
}
|
||||||
// println('dot #$dc')
|
// println('dot #$dc')
|
||||||
typ = p.dot(typ, fn_ph)
|
typ = p.dot(typ, fn_ph)
|
||||||
p.log('typ after dot=$typ')
|
p.log('typ after dot=$typ')
|
||||||
@ -1740,6 +1761,9 @@ fn (p &Parser) fileis(s string) bool {
|
|||||||
// user.name => `str_typ` is `User`
|
// user.name => `str_typ` is `User`
|
||||||
// user.company.name => `str_typ` is `Company`
|
// user.company.name => `str_typ` is `Company`
|
||||||
fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
||||||
|
//if p.fileis('orm_test') {
|
||||||
|
//println('ORM dot $str_typ')
|
||||||
|
//}
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
typ := p.find_type(str_typ)
|
typ := p.find_type(str_typ)
|
||||||
if typ.name.len == 0 {
|
if typ.name.len == 0 {
|
||||||
@ -1949,7 +1973,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
|
|||||||
// TODO move this from index_expr()
|
// TODO move this from index_expr()
|
||||||
// TODO if p.tok in ...
|
// TODO if p.tok in ...
|
||||||
// if p.tok in [.assign, .plus_assign, .minus_assign]
|
// if p.tok in [.assign, .plus_assign, .minus_assign]
|
||||||
if p.tok == .assign || p.tok == .plus_assign || p.tok == .minus_assign ||
|
if (p.tok == .assign && !p.is_sql) || p.tok == .plus_assign || p.tok == .minus_assign ||
|
||||||
p.tok == .mult_assign || p.tok == .div_assign || p.tok == .xor_assign || p.tok == .mod_assign ||
|
p.tok == .mult_assign || p.tok == .div_assign || p.tok == .xor_assign || p.tok == .mod_assign ||
|
||||||
p.tok == .or_assign || p.tok == .and_assign || p.tok == .righ_shift_assign ||
|
p.tok == .or_assign || p.tok == .and_assign || p.tok == .righ_shift_assign ||
|
||||||
p.tok == .left_shift_assign {
|
p.tok == .left_shift_assign {
|
||||||
@ -2285,6 +2309,9 @@ fn (p mut Parser) factor() string {
|
|||||||
if p.lit == 'json' && p.peek() == .dot {
|
if p.lit == 'json' && p.peek() == .dot {
|
||||||
return p.js_decode()
|
return p.js_decode()
|
||||||
}
|
}
|
||||||
|
//if p.fileis('orm_test') {
|
||||||
|
//println('ORM name: $p.lit')
|
||||||
|
//}
|
||||||
typ = p.name_expr()
|
typ = p.name_expr()
|
||||||
return typ
|
return typ
|
||||||
case Token.key_default:
|
case Token.key_default:
|
||||||
@ -2414,6 +2441,9 @@ fn (p mut Parser) string_expr() {
|
|||||||
if p.calling_c || (p.pref.translated && p.mod == 'main') {
|
if p.calling_c || (p.pref.translated && p.mod == 'main') {
|
||||||
p.gen('"$f"')
|
p.gen('"$f"')
|
||||||
}
|
}
|
||||||
|
else if p.is_sql {
|
||||||
|
p.gen('\'$str\'')
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
p.gen('tos2((byte*)"$f")')
|
p.gen('tos2((byte*)"$f")')
|
||||||
}
|
}
|
||||||
@ -2457,6 +2487,9 @@ fn (p mut Parser) string_expr() {
|
|||||||
if typ == 'ustring' {
|
if typ == 'ustring' {
|
||||||
args += '.len, ${val}.s.str'
|
args += '.len, ${val}.s.str'
|
||||||
}
|
}
|
||||||
|
if typ == 'bool' {
|
||||||
|
//args += '.len, ${val}.str'
|
||||||
|
}
|
||||||
// Custom format? ${t.hour:02d}
|
// Custom format? ${t.hour:02d}
|
||||||
custom := p.tok == .colon
|
custom := p.tok == .colon
|
||||||
if custom {
|
if custom {
|
||||||
@ -2910,9 +2943,9 @@ fn os_name_to_ifdef(name string) string {
|
|||||||
|
|
||||||
fn (p mut Parser) if_st(is_expr bool, elif_depth int) string {
|
fn (p mut Parser) if_st(is_expr bool, elif_depth int) string {
|
||||||
if is_expr {
|
if is_expr {
|
||||||
if p.fileis('if_expr') {
|
//if p.fileis('if_expr') {
|
||||||
println('IF EXPR')
|
//println('IF EXPR')
|
||||||
}
|
//}
|
||||||
p.inside_if_expr = true
|
p.inside_if_expr = true
|
||||||
p.gen('(')
|
p.gen('(')
|
||||||
}
|
}
|
||||||
@ -3207,7 +3240,7 @@ fn (p mut Parser) switch_statement() {
|
|||||||
if got_comma {
|
if got_comma {
|
||||||
p.gen(') || ')
|
p.gen(') || ')
|
||||||
}
|
}
|
||||||
if typ == 'string' {
|
if typ == 'string' {
|
||||||
p.gen('string_eq($expr, ')
|
p.gen('string_eq($expr, ')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
152
compiler/query.v
Normal file
152
compiler/query.v
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import strings
|
||||||
|
|
||||||
|
// `db.select from User where id == 1 && nr_bookings > 0`
|
||||||
|
fn (p mut Parser) select_query(fn_ph int) string {
|
||||||
|
mut q := 'select '
|
||||||
|
p.check(.key_select)
|
||||||
|
n := p.check_name()
|
||||||
|
if n == 'count' {
|
||||||
|
q += 'count(*) from '
|
||||||
|
p.check_name()
|
||||||
|
}
|
||||||
|
table_name := p.check_name()
|
||||||
|
// Register this type's fields as variables so they can be used in where expressions
|
||||||
|
typ := p.table.find_type(table_name)
|
||||||
|
if typ.name == '' {
|
||||||
|
p.error('unknown type `$table_name`')
|
||||||
|
}
|
||||||
|
// 'select id, name, age from...'
|
||||||
|
if n == 'from' {
|
||||||
|
for i, field in typ.fields {
|
||||||
|
q += field.name
|
||||||
|
if i < typ.fields.len - 1 {
|
||||||
|
q += ', '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q += ' from '
|
||||||
|
}
|
||||||
|
for field in typ.fields {
|
||||||
|
//println('registering sql field var $field.name')
|
||||||
|
p.cur_fn.register_var({ field | is_used:true})
|
||||||
|
}
|
||||||
|
q += table_name
|
||||||
|
// `where` statement
|
||||||
|
if p.tok == .name && p.lit == 'where' {
|
||||||
|
p.next()
|
||||||
|
p.cgen.start_tmp()
|
||||||
|
p.is_sql = true
|
||||||
|
p.bool_expression()
|
||||||
|
p.is_sql = false
|
||||||
|
q += ' where ' + p.cgen.end_tmp()
|
||||||
|
}
|
||||||
|
// limit?
|
||||||
|
mut query_one := false
|
||||||
|
if p.tok == .name && p.lit == 'limit' {
|
||||||
|
p.next()
|
||||||
|
p.cgen.start_tmp()
|
||||||
|
p.is_sql = true
|
||||||
|
p.bool_expression()
|
||||||
|
p.is_sql = false
|
||||||
|
limit := p.cgen.end_tmp()
|
||||||
|
q += ' limit ' + limit
|
||||||
|
// `limit 1` means we are getting `User`, not `[]User`
|
||||||
|
if limit.trim_space() == '1' {
|
||||||
|
query_one = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//println('sql query="$q"')
|
||||||
|
if n == 'count' {
|
||||||
|
p.cgen.set_placeholder(fn_ph, 'pg__DB_q_int(')
|
||||||
|
p.gen(', tos2("$q"))')
|
||||||
|
} else {
|
||||||
|
// Build an object, assign each field.
|
||||||
|
tmp := p.get_tmp()
|
||||||
|
mut obj_gen := strings.new_builder(100)
|
||||||
|
for i, field in typ.fields {
|
||||||
|
mut cast := ''
|
||||||
|
if field.typ == 'int' {
|
||||||
|
cast = 'string_int'
|
||||||
|
}
|
||||||
|
obj_gen.writeln('$tmp . $field.name = $cast( *(string*)array__get(row.vals, $i) );')
|
||||||
|
}
|
||||||
|
// One object
|
||||||
|
if query_one {
|
||||||
|
p.cgen.insert_before('
|
||||||
|
|
||||||
|
pg__Row row = pg__DB_exec_one(db, tos2("$q"));
|
||||||
|
$table_name $tmp;
|
||||||
|
${obj_gen.str()}
|
||||||
|
|
||||||
|
')
|
||||||
|
p.cgen.resetln(tmp)
|
||||||
|
}
|
||||||
|
// Array
|
||||||
|
else {
|
||||||
|
p.cgen.insert_before('
|
||||||
|
|
||||||
|
array_pg__Row rows = pg__DB_exec(db, tos2("$q"));
|
||||||
|
printf("ROWS LEN=%d\\n", rows.len);
|
||||||
|
// TODO preallocate
|
||||||
|
array arr_$tmp = new_array(0, 0, sizeof($table_name));
|
||||||
|
for (int i = 0; i < rows.len; i++) {
|
||||||
|
pg__Row row = *(pg__Row*)array__get(rows, i);
|
||||||
|
$table_name $tmp;
|
||||||
|
${obj_gen.str()}
|
||||||
|
_PUSH(&arr_$tmp, $tmp, ${tmp}2, $table_name);
|
||||||
|
}
|
||||||
|
')
|
||||||
|
p.cgen.resetln('arr_$tmp')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if n == 'count' {
|
||||||
|
return 'int'
|
||||||
|
} else if query_one {
|
||||||
|
return table_name
|
||||||
|
} else {
|
||||||
|
p.register_array('array_$table_name')
|
||||||
|
return 'array_$table_name'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `db.insert(user)`
|
||||||
|
fn (p mut Parser) insert_query(fn_ph int) {
|
||||||
|
p.check_name()
|
||||||
|
p.check(.lpar)
|
||||||
|
var_name := p.check_name()
|
||||||
|
p.check(.rpar)
|
||||||
|
var := p.cur_fn.find_var(var_name)
|
||||||
|
typ := p.table.find_type(var.typ)
|
||||||
|
table_name := var.typ
|
||||||
|
mut fields := '' // 'name, city, country'
|
||||||
|
mut params := '' // params[0] = 'bob'; params[1] = 'Vienna';
|
||||||
|
mut vals := '' // $1, $2, $3...
|
||||||
|
mut nr_vals := 0
|
||||||
|
for i, field in typ.fields {
|
||||||
|
if field.name == 'id' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields += field.name
|
||||||
|
vals += '$' + i.str()
|
||||||
|
nr_vals++
|
||||||
|
params += 'params[${i-1}] = '
|
||||||
|
if field.typ == 'string' {
|
||||||
|
params += '$var_name . $field.name .str;\n'
|
||||||
|
} else if field.typ == 'int' {
|
||||||
|
params += 'int_str($var_name . $field.name).str;\n'
|
||||||
|
} else {
|
||||||
|
p.error('V ORM: unsupported type `$field.typ`')
|
||||||
|
}
|
||||||
|
if i < typ.fields.len - 1 {
|
||||||
|
fields += ', '
|
||||||
|
vals += ', '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.cgen.insert_before('char* params[$nr_vals];' + params)
|
||||||
|
p.cgen.set_placeholder(fn_ph, 'PQexecParams( ')
|
||||||
|
p.genln('.conn, "insert into $table_name ($fields) values ($vals)", $nr_vals,
|
||||||
|
0, params, 0, 0, 0)')
|
||||||
|
}
|
||||||
|
|
@ -761,8 +761,9 @@ fn (p mut Parser) typ_to_fmt(typ string, level int) string {
|
|||||||
}
|
}
|
||||||
switch typ {
|
switch typ {
|
||||||
case 'string': return '%.*s'
|
case 'string': return '%.*s'
|
||||||
|
//case 'bool': return '%.*s'
|
||||||
case 'ustring': return '%.*s'
|
case 'ustring': return '%.*s'
|
||||||
case 'byte', 'int', 'char', 'byte', 'bool', 'u32', 'i32', 'i16', 'u16', 'i8', 'u8': return '%d'
|
case 'byte', 'bool', 'int', 'char', 'byte', 'u32', 'i32', 'i16', 'u16', 'i8', 'u8': return '%d'
|
||||||
case 'f64', 'f32': return '%f'
|
case 'f64', 'f32': return '%f'
|
||||||
case 'i64', 'u64': return '%lld'
|
case 'i64', 'u64': return '%lld'
|
||||||
case 'byte*', 'byteptr': return '%s'
|
case 'byte*', 'byteptr': return '%s'
|
||||||
|
@ -97,6 +97,7 @@ enum Token {
|
|||||||
key_module
|
key_module
|
||||||
key_mut
|
key_mut
|
||||||
key_return
|
key_return
|
||||||
|
key_select
|
||||||
key_sizeof
|
key_sizeof
|
||||||
key_struct
|
key_struct
|
||||||
key_switch
|
key_switch
|
||||||
@ -221,6 +222,7 @@ fn build_token_str() []string {
|
|||||||
s[Token.key_as] = 'as'
|
s[Token.key_as] = 'as'
|
||||||
s[Token.key_defer] = 'defer'
|
s[Token.key_defer] = 'defer'
|
||||||
s[Token.key_match] = 'match'
|
s[Token.key_match] = 'match'
|
||||||
|
s[Token.key_select] = 'select'
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,17 +533,16 @@ pub fn (ar []int) contains(val int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (a []string) to_c() voidptr {
|
pub fn (a []string) to_c() voidptr {
|
||||||
char ** res = malloc(sizeof(char*) * a.len);
|
mut res := malloc(sizeof(byteptr) * a.len)
|
||||||
for i := 0; i < a.len; i++ {
|
for i := 0; i < a.len; i++ {
|
||||||
val := a[i]
|
val := a[i]
|
||||||
# res[i] = val.str;
|
res[i] = val.str
|
||||||
}
|
}
|
||||||
return res;
|
return res
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn is_space(c byte) bool {
|
fn is_space(c byte) bool {
|
||||||
return C.isspace(c)
|
return C.isspace(c)
|
||||||
@ -557,7 +556,6 @@ pub fn (s string) trim_space() string {
|
|||||||
if s == '' {
|
if s == '' {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
// println('TRIM SPACE "$s"')
|
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < s.len && is_space(s[i]) {
|
for i < s.len && is_space(s[i]) {
|
||||||
i++
|
i++
|
||||||
|
@ -1,16 +1,46 @@
|
|||||||
//import pg
|
import pg
|
||||||
|
|
||||||
struct Mod {
|
struct Modules {
|
||||||
id int
|
id int
|
||||||
|
user_id int
|
||||||
name string
|
name string
|
||||||
url string
|
url string
|
||||||
nr_downloads int
|
//nr_downloads int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_orm() {
|
fn test_orm() {
|
||||||
/*
|
/*
|
||||||
db := pg.connect('vpm', 'alex')
|
db := pg.connect('vpm', 'alex')
|
||||||
nr_modules := select count from db.modules
|
//nr_modules := db.select count from modules
|
||||||
|
//nr_modules := db.select count from Modules where id == 1
|
||||||
|
nr_modules := db.select count from Modules where
|
||||||
|
name == 'Bob' && id == 1
|
||||||
|
println(nr_modules)
|
||||||
|
|
||||||
|
mod := db.select from Modules where id = 1 limit 1
|
||||||
|
println(mod)
|
||||||
|
|
||||||
|
mods := db.select from Modules limit 10
|
||||||
|
for mod in mods {
|
||||||
|
println(mod)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
mod := db.retrieve<Module>(1)
|
||||||
|
|
||||||
|
mod := db.update Module set name = name + '!' where id > 10
|
||||||
|
|
||||||
|
|
||||||
|
nr_modules := db.select count from Modules
|
||||||
|
where id > 1 && name == ''
|
||||||
|
println(nr_modules)
|
||||||
|
|
||||||
|
nr_modules := db.select count from modules
|
||||||
|
nr_modules := db.select from modules
|
||||||
|
nr_modules := db[:modules].select
|
||||||
|
*/
|
||||||
|
/*
|
||||||
mod := select from db.modules where id = 1 limit 1
|
mod := select from db.modules where id = 1 limit 1
|
||||||
println(mod.name)
|
println(mod.name)
|
||||||
top_mods := select from db.modules where nr_downloads > 1000 order by nr_downloads desc limit 10
|
top_mods := select from db.modules where nr_downloads > 1000 order by nr_downloads desc limit 10
|
||||||
|
19
vlib/pg/pg.v
19
vlib/pg/pg.v
@ -30,7 +30,8 @@ fn C.PQgetvalue(voidptr, int, int) byteptr
|
|||||||
fn C.PQstatus(voidptr) int
|
fn C.PQstatus(voidptr) int
|
||||||
|
|
||||||
pub fn connect(dbname, user string) DB {
|
pub fn connect(dbname, user string) DB {
|
||||||
conninfo := 'host=localhost user=$user dbname=$dbname'
|
//conninfo := 'host=localhost user=$user dbname=$dbname'
|
||||||
|
conninfo := 'host=127.0.0.1 user=$user dbname=$dbname'
|
||||||
conn:=C.PQconnectdb(conninfo.str)
|
conn:=C.PQconnectdb(conninfo.str)
|
||||||
status := C.PQstatus(conn)
|
status := C.PQstatus(conn)
|
||||||
if status != CONNECTION_OK {
|
if status != CONNECTION_OK {
|
||||||
@ -99,6 +100,21 @@ 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 {
|
||||||
|
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 {
|
||||||
|
return Row{}
|
||||||
|
}
|
||||||
|
return rows[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
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 {
|
||||||
@ -122,3 +138,4 @@ pub fn (db DB) exec_param(query string, param string) []pg.Row {
|
|||||||
return res_to_rows(res)
|
return res_to_rows(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user