orm: mysql fixes (#14772)

master
Louis Schmieder 2022-06-16 19:19:49 +02:00 committed by GitHub
parent fb5a40d1c8
commit 5df3d8ac75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 70 deletions

View File

@ -15,6 +15,7 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
mysql_stmt_binder(mut stmt, where)? mysql_stmt_binder(mut stmt, where)?
mysql_stmt_binder(mut stmt, data)? mysql_stmt_binder(mut stmt, data)?
if data.data.len > 0 || where.data.len > 0 { if data.data.len > 0 || where.data.len > 0 {
stmt.bind_params()? stmt.bind_params()?
} }
@ -24,52 +25,48 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
metadata := stmt.gen_metadata() metadata := stmt.gen_metadata()
fields := stmt.fetch_fields(metadata) fields := stmt.fetch_fields(metadata)
mut dataptr := []Prims{} mut dataptr := []&u8{}
for i in 0 .. num_fields { for i in 0 .. num_fields {
f := unsafe { fields[i] } f := unsafe { fields[i] }
match FieldType(f.@type) { match FieldType(f.@type) {
.type_tiny { .type_tiny {
dataptr << u8(0) dataptr << unsafe { malloc(1) }
} }
.type_short { .type_short {
dataptr << u16(0) dataptr << unsafe { malloc(2) }
} }
.type_long { .type_long {
dataptr << u32(0) dataptr << unsafe { malloc(4) }
} }
.type_longlong { .type_longlong {
dataptr << u64(0) dataptr << unsafe { malloc(8) }
} }
.type_float { .type_float {
dataptr << f32(0) dataptr << unsafe { malloc(4) }
} }
.type_double { .type_double {
dataptr << f64(0) dataptr << unsafe { malloc(8) }
} }
.type_string { .type_string, .type_blob {
dataptr << '' dataptr << unsafe { malloc(512) }
} }
else { else {
dataptr << u8(0) dataptr << &u8(0)
} }
} }
} }
mut vptr := []&char{}
for d in dataptr {
vptr << d.get_data_ptr()
}
unsafe { dataptr.free() }
lens := []u32{len: int(num_fields), init: 0} lens := []u32{len: int(num_fields), init: 0}
stmt.bind_res(fields, vptr, lens, num_fields) stmt.bind_res(fields, dataptr, lens, num_fields)
stmt.bind_result_buffer()? stmt.bind_result_buffer()?
stmt.store_result()? stmt.store_result()?
mut row := 0 mut row := 0
mut types := config.types
if config.is_count {
types = [orm.type_idx['u64']]
}
for { for {
status = stmt.fetch_stmt()? status = stmt.fetch_stmt()?
@ -78,7 +75,8 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
break break
} }
row++ row++
data_list := buffer_to_primitive(vptr, config.types)?
data_list := buffer_to_primitive(dataptr, types)?
ret << data_list ret << data_list
} }
@ -184,7 +182,8 @@ fn stmt_binder_match(mut stmt Stmt, data orm.Primitive) {
stmt.bind_text(data) stmt.bind_text(data)
} }
time.Time { time.Time {
stmt.bind_int(&int(data.unix)) unix := int(data.unix)
stmt_binder_match(mut stmt, unix)
} }
orm.InfixType { orm.InfixType {
stmt_binder_match(mut stmt, data.right) stmt_binder_match(mut stmt, data.right)
@ -192,50 +191,50 @@ fn stmt_binder_match(mut stmt Stmt, data orm.Primitive) {
} }
} }
fn buffer_to_primitive(data_list []&char, types []int) ?[]orm.Primitive { fn buffer_to_primitive(data_list []&u8, types []int) ?[]orm.Primitive {
mut res := []orm.Primitive{} mut res := []orm.Primitive{}
for i, data in data_list { for i, data in data_list {
mut primitive := orm.Primitive(0) mut primitive := orm.Primitive(0)
match types[i] { match types[i] {
5 { orm.type_idx['i8'] {
primitive = *(&i8(data)) primitive = *(unsafe { &i8(data) })
} }
6 { orm.type_idx['i16'] {
primitive = *(&i16(data)) primitive = *(unsafe { &i16(data) })
} }
7, -1 { orm.type_idx['int'], orm.serial {
primitive = *(&int(data)) primitive = *(unsafe { &int(data) })
} }
8 { orm.type_idx['i64'] {
primitive = *(&i64(data)) primitive = *(unsafe { &i64(data) })
} }
9 { orm.type_idx['byte'] {
primitive = *(&u8(data)) primitive = *(unsafe { &u8(data) })
} }
10 { orm.type_idx['u16'] {
primitive = *(&u16(data)) primitive = *(unsafe { &u16(data) })
} }
11 { orm.type_idx['u32'] {
primitive = *(&u32(data)) primitive = *(unsafe { &u32(data) })
} }
12 { orm.type_idx['u64'] {
primitive = *(&u64(data)) primitive = *(unsafe { &u64(data) })
} }
13 { orm.type_idx['f32'] {
primitive = *(&f32(data)) primitive = *(unsafe { &f32(data) })
} }
14 { orm.type_idx['f64'] {
primitive = *(&f64(data)) primitive = *(unsafe { &f64(data) })
} }
15 { orm.type_idx['bool'] {
primitive = *(&bool(data)) primitive = *(unsafe { &bool(data) })
} }
orm.string { orm.string {
primitive = unsafe { cstring_to_vstring(&char(data)) } primitive = unsafe { cstring_to_vstring(&char(data)) }
} }
orm.time { orm.time {
timestamp := *(&int(data)) timestamp := *(unsafe { &int(data) })
primitive = time.unix(timestamp) primitive = time.unix(timestamp)
} }
else { else {
@ -250,30 +249,33 @@ fn buffer_to_primitive(data_list []&char, types []int) ?[]orm.Primitive {
fn mysql_type_from_v(typ int) ?string { fn mysql_type_from_v(typ int) ?string {
str := match typ { str := match typ {
5, 9, 16 { orm.type_idx['i8'], orm.type_idx['byte'] {
'TINYINT' 'TINYINT'
} }
6, 10 { orm.type_idx['i16'], orm.type_idx['u16'] {
'SMALLINT' 'SMALLINT'
} }
7, 11, orm.time { orm.type_idx['int'], orm.type_idx['u32'], orm.time {
'INT' 'INT'
} }
8, 12 { orm.type_idx['i64'], orm.type_idx['u64'] {
'BIGINT' 'BIGINT'
} }
13 { orm.type_idx['f32'] {
'FLOAT' 'FLOAT'
} }
14 { orm.type_idx['f64'] {
'DOUBLE' 'DOUBLE'
} }
orm.string { orm.string {
'TEXT' 'TEXT'
} }
-1 { orm.serial {
'SERIAL' 'SERIAL'
} }
orm.type_idx['bool'] {
'BOOLEAN'
}
else { else {
'' ''
} }
@ -283,14 +285,3 @@ fn mysql_type_from_v(typ int) ?string {
} }
return str return str
} }
fn (p Prims) get_data_ptr() &char {
return match p {
string {
p.str
}
else {
&char(&p)
}
}
}

View File

@ -210,14 +210,14 @@ pub fn (mut stmt Stmt) bind(typ int, buffer voidptr, buf_len u32) {
} }
} }
pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&char, lens []u32, num_fields int) { pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&u8, lens []u32, num_fields int) {
for i in 0 .. num_fields { for i in 0 .. num_fields {
len := FieldType(unsafe { fields[i].@type }).get_len() len := FieldType(unsafe { fields[i].@type }).get_len()
stmt.res << C.MYSQL_BIND{ stmt.res << C.MYSQL_BIND{
buffer_type: unsafe { fields[i].@type } buffer_type: unsafe { fields[i].@type }
buffer: dataptr[i] buffer: dataptr[i]
length: &lens[i] length: &lens[i]
buffer_length: &len buffer_length: len
} }
} }
} }

View File

@ -20,6 +20,7 @@ pub const (
] ]
string = ast.string_type_idx string = ast.string_type_idx
time = -2 time = -2
serial = -1
type_idx = { type_idx = {
'i8': ast.i8_type_idx 'i8': ast.i8_type_idx
'i16': ast.i16_type_idx 'i16': ast.i16_type_idx

View File

@ -1,7 +1,8 @@
// import os // import os
// import term // import term
import time // import mysql
// import pg // import pg
import time
import sqlite import sqlite
struct Module { struct Module {
@ -33,9 +34,17 @@ struct TestTime {
fn test_orm() { fn test_orm() {
db := sqlite.connect(':memory:') or { panic(err) } db := sqlite.connect(':memory:') or { panic(err) }
// db.exec('drop table if exists User') db.exec('drop table if exists User')
// db := pg.connect(host: 'localhost', port: 5432, user: 'louis', password: 'abc', dbname: 'orm') or { panic(err) } // db := pg.connect(host: 'localhost', port: 5432, user: 'louis', password: 'abc', dbname: 'orm') or { panic(err) }
/*
mut db := mysql.Connection{
host: '127.0.0.1'
username: 'root'
password: 'pw'
dbname: 'v'
}
db.connect() or { panic(err) }*/
sql db { sql db {
create table Module create table Module
@ -268,7 +277,7 @@ fn test_orm() {
assert updated_oldest.age == 31 assert updated_oldest.age == 31
// Remove this when pg is used // Remove this when pg is used
db.exec('insert into User (name, age) values (NULL, 31)') // db.exec('insert into User (name, age) values (NULL, 31)')
null_user := sql db { null_user := sql db {
select from User where id == 5 select from User where id == 5
} }
@ -319,6 +328,7 @@ fn test_orm() {
} }
assert data.len == 1 assert data.len == 1
assert tnow.unix == data[0].create.unix
mod := Module{} mod := Module{}

View File

@ -205,7 +205,7 @@ fn pg_type_from_v(typ int) ?string {
orm.string { orm.string {
'TEXT' 'TEXT'
} }
-1 { orm.serial {
'SERIAL' 'SERIAL'
} }
else { else {

View File

@ -20,6 +20,7 @@ pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.Qu
mut ret := [][]orm.Primitive{} mut ret := [][]orm.Primitive{}
if config.is_count { if config.is_count {
eprintln(config)
// 2. Get count of returned values & add it to ret array // 2. Get count of returned values & add it to ret array
step := stmt.step() step := stmt.step()
if step !in [sqlite_row, sqlite_ok, sqlite_done] { if step !in [sqlite_row, sqlite_ok, sqlite_done] {

View File

@ -22,7 +22,7 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
return ast.void_type return ast.void_type
} }
info := sym.info as ast.Struct info := sym.info as ast.Struct
fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name) mut fields := c.fetch_and_verify_orm_fields(info, node.table_expr.pos, sym.name)
mut sub_structs := map[int]ast.SqlExpr{} mut sub_structs := map[int]ast.SqlExpr{}
for f in fields.filter((c.table.type_symbols[int(it.typ)].kind == .struct_ for f in fields.filter((c.table.type_symbols[int(it.typ)].kind == .struct_
|| (c.table.sym(it.typ).kind == .array || (c.table.sym(it.typ).kind == .array
@ -81,6 +81,13 @@ fn (mut c Checker) sql_expr(mut node ast.SqlExpr) ast.Type {
sub_structs[int(typ)] = n sub_structs[int(typ)] = n
} }
if node.is_count {
fields = [
ast.StructField{
typ: ast.int_type
},
]
}
node.fields = fields node.fields = fields
node.sub_structs = sub_structs.move() node.sub_structs = sub_structs.move()
if node.has_where { if node.has_where {