orm: fix option type, convert from int to i8, add examples, etc (fix #24211) (#24213)

This commit is contained in:
kbkpbot 2025-04-15 01:19:31 +08:00 committed by GitHub
parent 277c9c5f05
commit b180a03253
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 674 additions and 139 deletions

View file

@ -43,22 +43,6 @@ pub fn (qb_ &QueryBuilder[T]) reset() &QueryBuilder[T] {
return qb
}
// from vlib/v/gen/c/orm.v write_orm_select()
fn type_from(value string) int {
if ret_type := type_idx[value] {
return ret_type
} else {
if value.contains('time.Time') {
return time_
} else if value.contains('struct') {
return type_idx['int']
} else if value.contains('enum') {
return enum_
}
}
return 0
}
// where create a `where` clause
// valid token in the `condition` include: `field's names`, `operator`, `(`, `)`, `?`, `AND`, `OR`, `||`, `&&`,
// valid `operator` incldue: `=`, `!=`, `<>`, `>=`, `<=`, `>`, `<`, `LIKE`, `ILIKE`, `IS NULL`, `IS NOT NULL`
@ -414,10 +398,19 @@ fn struct_meta[T]() []TableField {
}
}
mut field_type := field.typ
if typeof(field).name.contains('time.Time') {
field_type = time_
} else if field.is_struct {
field_type = type_idx['int']
} else if field.is_enum {
field_type = enum_
}
if !is_skip {
meta << TableField{
name: field.name
typ: type_from(typeof(field).name)
typ: field_type
nullable: field.is_option
attrs: attrs
}
@ -435,43 +428,164 @@ fn (qb &QueryBuilder[T]) map_row(row []Primitive) !T {
mm := qb.meta.filter(it.name == field.name)
if mm.len != 0 {
m = mm[0]
}
index := qb.config.fields.index(field.name)
if index >= 0 {
value := row[index]
index := qb.config.fields.index(sql_field_name(m))
if index >= 0 {
value := row[index]
if value == Primitive(Null{}) && m.nullable {
// set to none by default
} else {
$if field.typ is i8 || field.typ is ?i8 {
instance.$(field.name) = value as i8
} $else $if field.typ is i16 || field.typ is ?i16 {
instance.$(field.name) = value as i16
} $else $if field.typ is int || field.typ is ?int {
instance.$(field.name) = value as int
} $else $if field.typ is i64 || field.typ is ?i64 {
instance.$(field.name) = value as i64
} $else $if field.typ is u8 || field.typ is ?u8 {
instance.$(field.name) = value as u8
} $else $if field.typ is u16 || field.typ is ?u16 {
instance.$(field.name) = value as u16
} $else $if field.typ is u32 || field.typ is ?u32 {
instance.$(field.name) = value as u32
} $else $if field.typ is u64 || field.typ is ?u64 {
instance.$(field.name) = value as u64
} $else $if field.typ is f32 || field.typ is ?f32 {
instance.$(field.name) = value as f32
} $else $if field.typ is f64 || field.typ is ?f64 {
instance.$(field.name) = value as f64
} $else $if field.typ is bool || field.typ is ?bool {
instance.$(field.name) = value as bool
} $else $if field.typ is string || field.typ is ?string {
instance.$(field.name) = value as string
} $else $if field.typ is time.Time || field.typ is ?time.Time {
if m.typ == time_ {
instance.$(field.name) = value as time.Time
} else if m.typ == type_string {
instance.$(field.name) = time.parse(value as string)!
if value == Primitive(Null{}) && m.nullable {
// set to none by default
} else {
$if field.typ is i8 || field.typ is ?i8 {
instance.$(field.name) = match value {
i8 { i8(value) }
i16 { i8(value) }
int { i8(value) }
i64 { i8(value) }
u8 { i8(value) }
u16 { i8(value) }
u32 { i8(value) }
u64 { i8(value) }
bool { i8(value) }
else { 0 }
}
} $else $if field.typ is i16 || field.typ is ?i16 {
instance.$(field.name) = match value {
i8 { i16(value) }
i16 { i16(value) }
int { i16(value) }
i64 { i16(value) }
u8 { i16(value) }
u16 { i16(value) }
u32 { i16(value) }
u64 { i16(value) }
bool { i16(value) }
else { 0 }
}
} $else $if field.typ is int || field.typ is ?int {
instance.$(field.name) = match value {
i8 { int(value) }
i16 { int(value) }
int { int(value) }
i64 { int(value) }
u8 { int(value) }
u16 { int(value) }
u32 { int(value) }
u64 { int(value) }
bool { int(value) }
else { 0 }
}
} $else $if field.typ is i64 || field.typ is ?i64 {
instance.$(field.name) = match value {
i8 { i64(value) }
i16 { i64(value) }
int { i64(value) }
i64 { i64(value) }
u8 { i64(value) }
u16 { i64(value) }
u32 { i64(value) }
u64 { i64(value) }
bool { i64(value) }
else { 0 }
}
} $else $if field.typ is u8 || field.typ is ?u8 {
instance.$(field.name) = match value {
i8 { u8(value) }
i16 { u8(value) }
int { u8(value) }
i64 { u8(value) }
u8 { u8(value) }
u16 { u8(value) }
u32 { u8(value) }
u64 { u8(value) }
bool { u8(value) }
else { 0 }
}
} $else $if field.typ is u16 || field.typ is ?u16 {
instance.$(field.name) = match value {
i8 { u16(value) }
i16 { u16(value) }
int { u16(value) }
i64 { u16(value) }
u8 { u16(value) }
u16 { u16(value) }
u32 { u16(value) }
u64 { u16(value) }
bool { u16(value) }
else { 0 }
}
} $else $if field.typ is u32 || field.typ is ?u32 {
instance.$(field.name) = match value {
i8 { u32(value) }
i16 { u32(value) }
int { u32(value) }
i64 { u32(value) }
u8 { u32(value) }
u16 { u32(value) }
u32 { u32(value) }
u64 { u32(value) }
bool { u32(value) }
else { 0 }
}
} $else $if field.typ is u64 || field.typ is ?u64 {
instance.$(field.name) = match value {
i8 { u64(value) }
i16 { u64(value) }
int { u64(value) }
i64 { u64(value) }
u8 { u64(value) }
u16 { u64(value) }
u32 { u64(value) }
u64 { u64(value) }
bool { u64(value) }
else { 0 }
}
} $else $if field.typ is f32 || field.typ is ?f32 {
instance.$(field.name) = match value {
i8 { f32(value) }
i16 { f32(value) }
int { f32(value) }
i64 { f32(value) }
u8 { f32(value) }
u16 { f32(value) }
u32 { f32(value) }
u64 { f32(value) }
bool { f32(value) }
else { 0 }
}
} $else $if field.typ is f64 || field.typ is ?f64 {
instance.$(field.name) = match value {
i8 { f64(value) }
i16 { f64(value) }
int { f64(value) }
i64 { f64(value) }
u8 { f64(value) }
u16 { f64(value) }
u32 { f64(value) }
u64 { f64(value) }
bool { f64(value) }
else { 0 }
}
} $else $if field.typ is bool || field.typ is ?bool {
instance.$(field.name) = match value {
i8 { value != 0 }
i16 { value != 0 }
int { value != 0 }
i64 { value != 0 }
u8 { value != 0 }
u16 { value != 0 }
u32 { value != 0 }
u64 { value != 0 }
bool { value }
else { false }
}
} $else $if field.typ is string || field.typ is ?string {
instance.$(field.name) = value as string
} $else $if field.typ is time.Time || field.typ is ?time.Time {
if m.typ == time_ {
instance.$(field.name) = value as time.Time
} else if m.typ == type_string {
instance.$(field.name) = time.parse(value as string)!
}
}
}
}

View file

@ -4,15 +4,40 @@ import time
@[table: 'sys_users']
struct User {
id int @[primary; serial]
name string
age int
role string
status int
salary int
title string
score int
created_at ?time.Time @[sql_type: 'TIMESTAMP']
id int @[primary; serial]
name string
age int
role string
status int
salary int
title string
score int
created_at ?time.Time @[sql_type: 'TIMESTAMP']
updated_at time.Time @[sql_type: 'TIMESTAMP']
type_i8 i8
type_i16 i16
type_int int
type_i64 i64
type_u8 u8
type_u16 u16
type_u32 u32
type_u64 u64
type_f32 f32
type_f64 f64
type_bool bool
type_string string
option_i8 ?i8
option_i16 ?i16
option_int ?int
option_i64 ?i64
option_u8 ?u8
option_u16 ?u16
option_u32 ?u32
option_u64 ?u64
option_f32 ?f32
option_f64 ?f64
option_bool ?bool
option_string ?string
}
fn test_orm_func_where() {
@ -56,101 +81,351 @@ fn test_orm_func_where() {
fn test_orm_func_stmts() {
users := [
User{
name: 'Tom'
age: 30
role: 'admin'
status: 1
salary: 5000
title: 'manager'
score: 90
created_at: time.now()
name: 'Tom'
age: 30
role: 'admin'
status: 1
salary: 5000
title: 'manager'
score: 90
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Alice'
age: 20
role: 'employee'
status: 2
salary: 2000
title: 'doctor'
score: 95
created_at: time.now()
name: 'Alice'
age: 20
role: 'employee'
status: 2
salary: 2000
title: 'doctor'
score: 95
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Mars'
age: 40
role: 'employer'
status: 3
salary: 1000
title: 'doctor'
score: 85
created_at: time.now()
name: 'Mars'
age: 40
role: 'employer'
status: 3
salary: 1000
title: 'doctor'
score: 85
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Kitty'
age: 18
role: 'employer'
status: 1
salary: 1500
title: 'doctor'
score: 87
created_at: time.now()
name: 'Kitty'
age: 18
role: 'employer'
status: 1
salary: 1500
title: 'doctor'
score: 87
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Silly'
age: 27
role: 'employer'
status: 5
salary: 2500
title: 'doctor'
score: 81
name: 'Silly'
age: 27
role: 'employer'
status: 5
salary: 2500
title: 'doctor'
score: 81
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Smith'
age: 37
role: 'employer'
status: 1
salary: 4500
title: 'doctor'
score: 89
created_at: time.now()
name: 'Smith'
age: 37
role: 'employer'
status: 1
salary: 4500
title: 'doctor'
score: 89
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Bob'
age: 26
role: 'employer'
status: 2
salary: 6500
title: 'doctor'
score: 81
created_at: time.now()
name: 'Bob'
age: 26
role: 'employer'
status: 2
salary: 6500
title: 'doctor'
score: 81
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'Peter'
age: 29
role: 'employer'
status: 1
salary: 3500
title: 'doctor'
score: 80
created_at: time.now()
name: 'Peter'
age: 29
role: 'employer'
status: 1
salary: 3500
title: 'doctor'
score: 80
created_at: time.now()
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'See'
age: 45
role: 'employer'
status: 2
salary: 8500
title: 'doctor'
score: 82
name: 'See'
age: 45
role: 'employer'
status: 2
salary: 8500
title: 'doctor'
score: 82
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
User{
name: 'John'
age: 42
role: 'employer'
status: 1
salary: 10000
title: 'doctor'
score: 88
name: 'John'
age: 42
role: 'employer'
status: 1
salary: 10000
title: 'doctor'
score: 88
updated_at: time.now()
type_i8: 1
type_i16: 2
type_int: 3
type_i64: 4
type_u8: 5
type_u16: 6
type_u32: 7
type_u64: 8
type_f32: 1.1
type_f64: 2.2
type_bool: true
type_string: 'hello'
option_i8: 1
option_i16: 2
option_int: 3
option_i64: 4
option_u8: 5
option_u16: 6
option_u32: 7
option_u64: 8
option_f32: 1.1
option_f64: 2.2
option_bool: true
option_string: 'hello'
},
]
mut db := sqlite.connect(':memory:')!