Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/veb_fullstack/product_entities.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ struct Product {
id int @[primary; sql: serial]
user_id int
name string @[sql_type: 'TEXT']
created_at string @[default: 'CURRENT_TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP]
}
6 changes: 3 additions & 3 deletions examples/veb_orm_jwt/user_entities.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ mut:
id int @[primary; sql: serial]
username string @[required; sql_type: 'TEXT']
password string @[required; sql_type: 'TEXT']
created_at string @[default: 'CURRENT_TIMESTAMP']
updated_at string @[default: 'CURRENT_TIMESTAMP']
deleted_at string @[default: 'CURRENT_TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP]
updated_at string @[default: CURRENT_TIMESTAMP]
deleted_at string @[default: CURRENT_TIMESTAMP]
active bool
}
4 changes: 2 additions & 2 deletions vlib/db/mysql/mysql_orm_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ mut:
struct TestDefaultAttribute {
id string @[primary; sql: serial]
name string
created_at string @[default: 'CURRENT_TIMESTAMP'; sql_type: 'TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP; sql_type: 'TIMESTAMP']
}

@[comment: 'This is a table comment']
struct TestCommentAttribute {
id string @[primary; sql: serial]
name string @[comment: 'real user name']
created_at string @[default: 'CURRENT_TIMESTAMP'; sql_type: 'TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP; sql_type: 'TIMESTAMP']
}

fn test_mysql_orm() {
Expand Down
14 changes: 8 additions & 6 deletions vlib/db/pg/orm.v
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,10 @@ fn pg_stmt_match(mut types []u32, mut vals []&char, mut lens []int, mut formats
formats << 1
}
u8 {
types << u32(Oid.t_char)
vals << &char(&data)
lens << int(sizeof(u8))
types << u32(Oid.t_int2)
Comment thread
Jengro777 marked this conversation as resolved.
num := conv.hton16(u16(data))
vals << &char(&num)
lens << int(sizeof(u16))
formats << 1
}
u16 {
Expand All @@ -338,9 +339,10 @@ fn pg_stmt_match(mut types []u32, mut vals []&char, mut lens []int, mut formats
formats << 1
}
i8 {
types << u32(Oid.t_char)
vals << &char(&data)
lens << int(sizeof(i8))
types << u32(Oid.t_int2)
num := conv.hton16(u16(data))
vals << &char(&num)
lens << int(sizeof(i16))
formats << 1
}
i16 {
Expand Down
4 changes: 2 additions & 2 deletions vlib/db/pg/pg_orm_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mut:
struct TestDefaultAttribute {
id string @[default: 'gen_random_uuid()'; primary; sql_type: 'uuid']
name string
created_at string @[default: 'CURRENT_TIMESTAMP'; sql_type: 'TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP; sql_type: 'TIMESTAMP']
}

struct TestInsertDefaultValues {
Expand All @@ -45,7 +45,7 @@ struct TestInsertDefaultValues {
struct TestCommentAttribute {
id string @[primary; sql: serial]
name string @[comment: 'real user name']
created_at string @[default: 'CURRENT_TIMESTAMP'; sql_type: 'TIMESTAMP']
created_at string @[default: CURRENT_TIMESTAMP; sql_type: 'TIMESTAMP']
}

fn test_pg_orm() {
Expand Down
6 changes: 3 additions & 3 deletions vlib/db/sqlite/sqlite_orm_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ struct TestCustomSqlType {
struct TestDefaultAttribute {
id string @[primary; sql: serial]
name string
created_at ?string @[default: 'CURRENT_TIME']
created_at1 ?string @[default: 'CURRENT_DATE']
created_at2 ?string @[default: 'CURRENT_TIMESTAMP']
created_at ?string @[default: CURRENT_TIME]
created_at1 ?string @[default: CURRENT_DATE]
created_at2 ?string @[default: CURRENT_TIMESTAMP]
}

struct TestDurationAlias {
Expand Down
18 changes: 17 additions & 1 deletion vlib/orm/orm.v
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,16 @@ fn trim_attr_arg(arg string) string {
return out
}

fn is_sql_expr(val string) bool {
// Function calls like gen_random_uuid(), NOW(), etc.
// Written as @[default: 'gen_random_uuid()'] — we detect the parens
// and treat it as a raw SQL expression rather than a string literal.
if val.contains('(') && val.ends_with(')') {
return true
Comment thread
Jengro777 marked this conversation as resolved.
Outdated
}
return false
}

fn tenant_filter_array_primitive_type[T](value []T) int {
if value.len > 0 {
first := value[0]
Expand Down Expand Up @@ -1417,6 +1427,7 @@ pub fn orm_table_gen(sql_dialect SQLDialect, table Table, q string, defaults boo
}
mut default_val := field.default_val
mut has_default := default_val != ''
mut is_str_default := false
mut nullable := field.nullable
mut is_unique := false
mut is_skip := false
Expand Down Expand Up @@ -1469,6 +1480,7 @@ pub fn orm_table_gen(sql_dialect SQLDialect, table Table, q string, defaults boo
}
'default' {
has_default = true
is_str_default = attr.kind == .string
if default_val == '' {
default_val = attr.arg.trim_space()
}
Expand Down Expand Up @@ -1525,7 +1537,11 @@ pub fn orm_table_gen(sql_dialect SQLDialect, table Table, q string, defaults boo
stmt = '${q}${field_name}${q} ${col_typ}'
if defaults && has_default {
if default_val != '' {
stmt += ' DEFAULT ${default_val}'
if is_str_default && !is_sql_expr(default_val) {
stmt += " DEFAULT '${default_val}'"
Comment thread
Jengro777 marked this conversation as resolved.
Outdated
} else {
stmt += ' DEFAULT ${default_val}'
Comment thread
Jengro777 marked this conversation as resolved.
}
} else {
// Handle @[default: ''] - explicitly set DEFAULT '' for the column
stmt += " DEFAULT ''"
Expand Down
2 changes: 1 addition & 1 deletion vlib/orm/orm_func_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct UserPart {

struct UrlDefaultAttr {
id int @[primary; sql: serial]
url string @[default: '"https://example.test"']
url string @[default: 'https://example.test']
}

fn test_orm_func_field_attribute_argument_with_colon() {
Expand Down
4 changes: 2 additions & 2 deletions vlib/orm/orm_null_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ struct Foo {
mut:
id u64 @[primary; sql: serial]
a string
b string @[default: '"yes"']
b string @[default: 'yes']
c ?string
d ?string = 'hi'
e int
Expand Down Expand Up @@ -139,7 +139,7 @@ fn test_option_struct_fields_and_none() {
sql db {
create table Foo
}!
assert db.st.last == 'CREATE TABLE IF NOT EXISTS `foo` (`id` serial-type NOT NULL, `a` string-type NOT NULL, `b` string-type DEFAULT "yes" NOT NULL, `c` string-type, `d` string-type, `e` int-type NOT NULL, `f` int-type DEFAULT 33 NOT NULL, `g` int-type, `h` int-type, PRIMARY KEY(`id`));'
assert db.st.last == "CREATE TABLE IF NOT EXISTS `foo` (`id` serial-type NOT NULL, `a` string-type NOT NULL, `b` string-type DEFAULT 'yes' NOT NULL, `c` string-type, `d` string-type, `e` int-type NOT NULL, `f` int-type DEFAULT 33 NOT NULL, `g` int-type, `h` int-type, PRIMARY KEY(`id`));"

_ := sql db {
select from Foo where e > 5 && c is none && c !is none && h == 2
Expand Down
2 changes: 1 addition & 1 deletion vlib/orm/orm_option_time_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import time
struct Foo {
id int @[primary; sql: serial]
name string
created_at time.Time @[default: 'CURRENT_TIME']
created_at time.Time @[default: CURRENT_TIME]
updated_at ?string @[sql_type: 'TIMESTAMP']
deleted_at ?time.Time
children []Child @[fkey: 'parent_id']
Expand Down
2 changes: 1 addition & 1 deletion vlib/orm/orm_upsert_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mut:
struct DefaultUpsertUser {
mut:
id int @[primary]
status string @[default: '"active"']
status string @[default: 'active']
}

fn test_upsert_updates_existing_row_using_unique_field() {
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/tests/orm_array_field_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ struct TaskMetadata {
task_id string
key string
value string
created_at time.Time @[default: 'CURRENT_TIME']
updated_at time.Time @[default: 'CURRENT_TIME']
created_at time.Time @[default: CURRENT_TIME]
updated_at time.Time @[default: CURRENT_TIME]
}

@[table: 'tasks']
Expand Down
28 changes: 14 additions & 14 deletions vlib/v3/tests/orm_join_sql_attr_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ fn main() {
")
assert selector_db_out == ''

mutated_insert_out := orm_join_sql_attr_run(v3_bin, 'orm_mutated_insert_fields', 'import db.sqlite
mutated_insert_out := orm_join_sql_attr_run(v3_bin, 'orm_mutated_insert_fields', "import db.sqlite

struct MutatedInsertUser {
id int @[primary; sql: serial]
name string @[default: \'"db_default"\']
name string @[default: 'db_default']
}

fn main() {
mut db := sqlite.connect(\':memory:\') or { panic(err) }
mut db := sqlite.connect(':memory:') or { panic(err) }
defer {
db.close() or {}
}
Expand All @@ -167,7 +167,7 @@ fn main() {
}!

mut user := MutatedInsertUser{}
user.name = \'Ada\'
user.name = 'Ada'
sql db {
insert user into MutatedInsertUser
}!
Expand All @@ -176,24 +176,24 @@ fn main() {
select from MutatedInsertUser
}!
assert rows.len == 1
assert rows[0].name == \'Ada\'
assert rows[0].name == 'Ada'
}
')
")
assert mutated_insert_out == ''

selector_insert_out := orm_join_sql_attr_run(v3_bin, 'orm_selector_insert_value', 'import db.sqlite
selector_insert_out := orm_join_sql_attr_run(v3_bin, 'orm_selector_insert_value', "import db.sqlite

struct SelectorInsertUser {
id int @[primary]
name string @[default: \'"db_default"\']
name string @[default: 'db_default']
}

struct SelectorInsertRequest {
user SelectorInsertUser
}

fn main() {
mut db := sqlite.connect(\':memory:\') or { panic(err) }
mut db := sqlite.connect(':memory:') or { panic(err) }
defer {
db.close() or {}
}
Expand All @@ -205,7 +205,7 @@ fn main() {
request := SelectorInsertRequest{
user: SelectorInsertUser{
id: 1
name: \'Ada\'
name: 'Ada'
}
}
sql db {
Expand All @@ -216,12 +216,12 @@ fn main() {
select from SelectorInsertUser where id == 1
}!
assert first.len == 1
assert first[0].name == \'Ada\'
assert first[0].name == 'Ada'

update_request := SelectorInsertRequest{
user: SelectorInsertUser{
id: 1
name: \'Grace\'
name: 'Grace'
}
}
sql db {
Expand All @@ -232,9 +232,9 @@ fn main() {
select from SelectorInsertUser where id == 1
}!
assert updated.len == 1
assert updated[0].name == \'Grace\'
assert updated[0].name == 'Grace'
}
')
")
assert selector_insert_out == ''

invalid_out := orm_join_sql_attr_run(v3_bin, 'orm_invalid_static_where', "import db.sqlite
Expand Down
Loading