mirror of
https://github.com/vlang/v.git
synced 2025-08-03 17:57:59 -04:00
breaking,orm: add table attrs; add table/field comment support for mysql and pg (#24744)
This commit is contained in:
parent
d52bac1301
commit
d4097212b3
@ -37,6 +37,13 @@ struct TestDefaultAttribute {
|
||||
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']
|
||||
}
|
||||
|
||||
fn test_mysql_orm() {
|
||||
$if !network ? {
|
||||
eprintln('> Skipping test ${@FN}, since `-d network` is not passed.')
|
||||
@ -47,13 +54,17 @@ fn test_mysql_orm() {
|
||||
host: '127.0.0.1'
|
||||
port: 3306
|
||||
username: 'root'
|
||||
password: ''
|
||||
password: '12345678'
|
||||
dbname: 'mysql'
|
||||
)!
|
||||
defer {
|
||||
db.close()
|
||||
}
|
||||
db.create('Test', [
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
db.drop(table) or {}
|
||||
db.create(table, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
@ -80,13 +91,13 @@ fn test_mysql_orm() {
|
||||
},
|
||||
]) or { panic(err) }
|
||||
|
||||
db.insert('Test', orm.QueryData{
|
||||
db.insert(table, orm.QueryData{
|
||||
fields: ['name', 'age']
|
||||
data: [orm.string_to_primitive('Louis'), orm.int_to_primitive(101)]
|
||||
}) or { panic(err) }
|
||||
|
||||
res := db.select(orm.SelectConfig{
|
||||
table: 'Test'
|
||||
table: table
|
||||
has_where: true
|
||||
fields: ['id', 'name', 'age']
|
||||
types: [typeof[int]().idx, typeof[string]().idx, typeof[i64]().idx]
|
||||
@ -272,4 +283,49 @@ fn test_mysql_orm() {
|
||||
'COLUMN_DEFAULT': 'CURRENT_TIMESTAMP'
|
||||
}]
|
||||
assert information_schema_column_default_sql == result_defaults.maps()
|
||||
|
||||
/** test comment attribute
|
||||
*/
|
||||
sql db {
|
||||
create table TestCommentAttribute
|
||||
}!
|
||||
|
||||
mut column_comments := db.query("
|
||||
SELECT COLUMN_COMMENT
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_NAME = 'TestCommentAttribute'
|
||||
ORDER BY ORDINAL_POSITION
|
||||
") or {
|
||||
println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mut table_comment := db.query("
|
||||
SELECT TABLE_COMMENT
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_NAME = 'TestCommentAttribute'
|
||||
") or {
|
||||
println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table TestCommentAttribute
|
||||
}!
|
||||
|
||||
information_schema_column_comment_sql := [{
|
||||
'COLUMN_COMMENT': ''
|
||||
}, {
|
||||
'COLUMN_COMMENT': 'real user name'
|
||||
}, {
|
||||
'COLUMN_COMMENT': ''
|
||||
}]
|
||||
assert information_schema_column_comment_sql == column_comments.maps()
|
||||
|
||||
information_schema_table_comment_sql := [
|
||||
{
|
||||
'TABLE_COMMENT': 'This is a table comment'
|
||||
},
|
||||
]
|
||||
assert information_schema_table_comment_sql == table_comment.maps()
|
||||
}
|
||||
|
@ -122,8 +122,8 @@ pub fn (db DB) select(config orm.SelectConfig, data orm.QueryData, where orm.Que
|
||||
}
|
||||
|
||||
// insert is used internally by V's ORM for processing `INSERT ` queries
|
||||
pub fn (db DB) insert(table string, data orm.QueryData) ! {
|
||||
mut converted_primitive_array := db.convert_query_data_to_primitives(table, data)!
|
||||
pub fn (db DB) insert(table orm.Table, data orm.QueryData) ! {
|
||||
mut converted_primitive_array := db.convert_query_data_to_primitives(table.name, data)!
|
||||
|
||||
converted_primitive_data := orm.QueryData{
|
||||
fields: data.fields
|
||||
@ -139,13 +139,13 @@ pub fn (db DB) insert(table string, data orm.QueryData) ! {
|
||||
}
|
||||
|
||||
// update is used internally by V's ORM for processing `UPDATE ` queries
|
||||
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
pub fn (db DB) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.default, table, '`', .update, false, '?', 1, data, where)
|
||||
mysql_stmt_worker(db, query, data, where)!
|
||||
}
|
||||
|
||||
// delete is used internally by V's ORM for processing `DELETE ` queries
|
||||
pub fn (db DB) delete(table string, where orm.QueryData) ! {
|
||||
pub fn (db DB) delete(table orm.Table, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.default, table, '`', .delete, false, '?', 1, orm.QueryData{},
|
||||
where)
|
||||
mysql_stmt_worker(db, query, orm.QueryData{}, where)!
|
||||
@ -160,16 +160,15 @@ pub fn (db DB) last_id() int {
|
||||
}
|
||||
|
||||
// create is used internally by V's ORM for processing table creation queries (DDL)
|
||||
pub fn (db DB) create(table string, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(table, '`', true, 0, fields, mysql_type_from_v, false) or {
|
||||
return err
|
||||
}
|
||||
pub fn (db DB) create(table orm.Table, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(.mysql, table, '`', true, 0, fields, mysql_type_from_v,
|
||||
false) or { return err }
|
||||
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
|
||||
// drop is used internally by V's ORM for processing table destroying queries (DDL)
|
||||
pub fn (db DB) drop(table string) ! {
|
||||
query := 'DROP TABLE `${table}`;'
|
||||
pub fn (db DB) drop(table orm.Table) ! {
|
||||
query := 'DROP TABLE `${table.name}`;'
|
||||
mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
|
||||
|
@ -31,20 +31,20 @@ pub fn (db DB) select(config orm.SelectConfig, data orm.QueryData, where orm.Que
|
||||
// sql stmt
|
||||
|
||||
// insert is used internally by V's ORM for processing `INSERT ` queries
|
||||
pub fn (db DB) insert(table string, data orm.QueryData) ! {
|
||||
pub fn (db DB) insert(table orm.Table, data orm.QueryData) ! {
|
||||
query, converted_data := orm.orm_stmt_gen(.default, table, '"', .insert, true, '$',
|
||||
1, data, orm.QueryData{})
|
||||
pg_stmt_worker(db, query, converted_data, orm.QueryData{})!
|
||||
}
|
||||
|
||||
// update is used internally by V's ORM for processing `UPDATE ` queries
|
||||
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
pub fn (db DB) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.default, table, '"', .update, true, '$', 1, data, where)
|
||||
pg_stmt_worker(db, query, data, where)!
|
||||
}
|
||||
|
||||
// delete is used internally by V's ORM for processing `DELETE ` queries
|
||||
pub fn (db DB) delete(table string, where orm.QueryData) ! {
|
||||
pub fn (db DB) delete(table orm.Table, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.default, table, '"', .delete, true, '$', 1, orm.QueryData{},
|
||||
where)
|
||||
pg_stmt_worker(db, query, orm.QueryData{}, where)!
|
||||
@ -60,14 +60,21 @@ pub fn (db DB) last_id() int {
|
||||
// DDL (table creation/destroying etc)
|
||||
|
||||
// create is used internally by V's ORM for processing table creation queries (DDL)
|
||||
pub fn (db DB) create(table string, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(table, '"', true, 0, fields, pg_type_from_v, false) or { return err }
|
||||
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
pub fn (db DB) create(table orm.Table, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(.pg, table, '"', true, 0, fields, pg_type_from_v, false) or {
|
||||
return err
|
||||
}
|
||||
stmts := query.split(';')
|
||||
for stmt in stmts {
|
||||
if stmt != '' {
|
||||
pg_stmt_worker(db, stmt + ';', orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop is used internally by V's ORM for processing table destroying queries (DDL)
|
||||
pub fn (db DB) drop(table string) ! {
|
||||
query := 'DROP TABLE "${table}";'
|
||||
pub fn (db DB) drop(table orm.Table) ! {
|
||||
query := 'DROP TABLE "${table.name}";'
|
||||
pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,13 @@ struct TestDefaultAttribute {
|
||||
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']
|
||||
}
|
||||
|
||||
fn test_pg_orm() {
|
||||
$if !network ? {
|
||||
eprintln('> Skipping test ${@FN}, since `-d network` is not passed.')
|
||||
@ -46,15 +53,18 @@ fn test_pg_orm() {
|
||||
host: 'localhost'
|
||||
user: 'postgres'
|
||||
password: '12345678'
|
||||
dbname: 'test'
|
||||
dbname: 'postgres'
|
||||
) or { panic(err) }
|
||||
|
||||
defer {
|
||||
db.close()
|
||||
}
|
||||
db.drop('Test')!
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
db.drop(table) or {}
|
||||
|
||||
db.create('Test', [
|
||||
db.create(table, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[string]().idx
|
||||
@ -94,13 +104,13 @@ fn test_pg_orm() {
|
||||
},
|
||||
]) or { panic(err) }
|
||||
|
||||
db.insert('Test', orm.QueryData{
|
||||
db.insert(table, orm.QueryData{
|
||||
fields: ['name', 'age']
|
||||
data: [orm.string_to_primitive('Louis'), orm.int_to_primitive(101)]
|
||||
}) or { panic(err) }
|
||||
|
||||
res := db.select(orm.SelectConfig{
|
||||
table: 'Test'
|
||||
table: table
|
||||
is_count: false
|
||||
has_where: true
|
||||
has_order: false
|
||||
@ -143,7 +153,7 @@ fn test_pg_orm() {
|
||||
*/
|
||||
sql db {
|
||||
drop table TestCustomSqlType
|
||||
}!
|
||||
} or {}
|
||||
|
||||
sql db {
|
||||
create table TestCustomSqlType
|
||||
@ -232,4 +242,60 @@ fn test_pg_orm() {
|
||||
drop table TestDefaultAttribute
|
||||
}!
|
||||
assert ['gen_random_uuid()', '', 'CURRENT_TIMESTAMP'] == information_schema_defaults_results
|
||||
|
||||
/** test comment attribute
|
||||
*/
|
||||
sql db {
|
||||
create table TestCommentAttribute
|
||||
}!
|
||||
|
||||
mut column_comments := db.exec("
|
||||
SELECT
|
||||
a.attname AS column_name,
|
||||
col_description(a.attrelid, a.attnum) AS column_comment
|
||||
FROM pg_attribute a
|
||||
JOIN pg_class c ON c.oid = a.attrelid
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relname = 'TestCommentAttribute'
|
||||
AND n.nspname = 'public'
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped
|
||||
ORDER BY a.attnum
|
||||
") or {
|
||||
println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mut table_comment := db.exec("
|
||||
SELECT
|
||||
nspname AS schema_name,
|
||||
relname AS table_name,
|
||||
obj_description(pc.oid) AS table_comment
|
||||
FROM pg_class pc
|
||||
JOIN pg_namespace pn ON pn.oid = pc.relnamespace
|
||||
WHERE pc.relkind = 'r' AND pc.relname = 'TestCommentAttribute'
|
||||
ORDER BY schema_name, table_name
|
||||
") or {
|
||||
println(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sql db {
|
||||
drop table TestCommentAttribute
|
||||
}!
|
||||
|
||||
mut information_schema_column_comment_results := []string{}
|
||||
|
||||
for comment in column_comments {
|
||||
x := comment.vals[1]
|
||||
information_schema_column_comment_results << x or { '' }
|
||||
}
|
||||
assert information_schema_column_comment_results == ['', 'real user name', '']
|
||||
|
||||
mut information_schema_table_comment_result := []string{}
|
||||
for comment in table_comment {
|
||||
x := comment.vals[2]
|
||||
information_schema_table_comment_result << x or { '' }
|
||||
}
|
||||
assert information_schema_table_comment_result == ['This is a table comment']
|
||||
}
|
||||
|
@ -52,20 +52,20 @@ pub fn (db DB) select(config orm.SelectConfig, data orm.QueryData, where orm.Que
|
||||
// sql stmt
|
||||
|
||||
// insert is used internally by V's ORM for processing `INSERT ` queries
|
||||
pub fn (db DB) insert(table string, data orm.QueryData) ! {
|
||||
pub fn (db DB) insert(table orm.Table, data orm.QueryData) ! {
|
||||
query, converted_data := orm.orm_stmt_gen(.sqlite, table, '`', .insert, true, '?',
|
||||
1, data, orm.QueryData{})
|
||||
sqlite_stmt_worker(db, query, converted_data, orm.QueryData{})!
|
||||
}
|
||||
|
||||
// update is used internally by V's ORM for processing `UPDATE ` queries
|
||||
pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
pub fn (db DB) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.sqlite, table, '`', .update, true, '?', 1, data, where)
|
||||
sqlite_stmt_worker(db, query, data, where)!
|
||||
}
|
||||
|
||||
// delete is used internally by V's ORM for processing `DELETE ` queries
|
||||
pub fn (db DB) delete(table string, where orm.QueryData) ! {
|
||||
pub fn (db DB) delete(table orm.Table, where orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.sqlite, table, '`', .delete, true, '?', 1, orm.QueryData{},
|
||||
where)
|
||||
sqlite_stmt_worker(db, query, orm.QueryData{}, where)!
|
||||
@ -81,16 +81,15 @@ pub fn (db DB) last_id() int {
|
||||
// DDL (table creation/destroying etc)
|
||||
|
||||
// create is used internally by V's ORM for processing table creation queries (DDL)
|
||||
pub fn (db DB) create(table string, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(table, '`', true, 0, fields, sqlite_type_from_v, false) or {
|
||||
return err
|
||||
}
|
||||
pub fn (db DB) create(table orm.Table, fields []orm.TableField) ! {
|
||||
query := orm.orm_table_gen(.sqlite, table, '`', true, 0, fields, sqlite_type_from_v,
|
||||
false) or { return err }
|
||||
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
|
||||
// drop is used internally by V's ORM for processing table destroying queries (DDL)
|
||||
pub fn (db DB) drop(table string) ! {
|
||||
query := 'DROP TABLE `${table}`;'
|
||||
pub fn (db DB) drop(table orm.Table) ! {
|
||||
query := 'DROP TABLE `${table.name}`;'
|
||||
sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})!
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,10 @@ fn test_sqlite_orm() {
|
||||
defer {
|
||||
db.close() or { panic(err) }
|
||||
}
|
||||
db.create('Test', [
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
db.create(table, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
@ -59,13 +62,13 @@ fn test_sqlite_orm() {
|
||||
},
|
||||
]) or { panic(err) }
|
||||
|
||||
db.insert('Test', orm.QueryData{
|
||||
db.insert(table, orm.QueryData{
|
||||
fields: ['name', 'age']
|
||||
data: [orm.string_to_primitive('Louis'), orm.i64_to_primitive(100)]
|
||||
}) or { panic(err) }
|
||||
|
||||
res := db.select(orm.SelectConfig{
|
||||
table: 'Test'
|
||||
table: table
|
||||
has_where: true
|
||||
fields: ['id', 'name', 'age']
|
||||
types: [typeof[int]().idx, typeof[string]().idx, typeof[i64]().idx]
|
||||
|
@ -91,6 +91,8 @@ pub enum OrderType {
|
||||
|
||||
pub enum SQLDialect {
|
||||
default
|
||||
mysql
|
||||
pg
|
||||
sqlite
|
||||
}
|
||||
|
||||
@ -153,6 +155,12 @@ pub:
|
||||
right Primitive
|
||||
}
|
||||
|
||||
pub struct Table {
|
||||
pub mut:
|
||||
name string
|
||||
attrs []VAttribute
|
||||
}
|
||||
|
||||
pub struct TableField {
|
||||
pub mut:
|
||||
name string
|
||||
@ -163,7 +171,7 @@ pub mut:
|
||||
is_arr bool
|
||||
}
|
||||
|
||||
// table - Table name
|
||||
// table - Table struct
|
||||
// is_count - Either the data will be returned or an integer with the count
|
||||
// has_where - Select all or use a where expr
|
||||
// has_order - Order the results
|
||||
@ -176,7 +184,7 @@ pub mut:
|
||||
// types - Types to select
|
||||
pub struct SelectConfig {
|
||||
pub mut:
|
||||
table string
|
||||
table Table
|
||||
is_count bool
|
||||
has_where bool
|
||||
has_order bool
|
||||
@ -200,11 +208,11 @@ pub mut:
|
||||
pub interface Connection {
|
||||
mut:
|
||||
select(config SelectConfig, data QueryData, where QueryData) ![][]Primitive
|
||||
insert(table string, data QueryData) !
|
||||
update(table string, data QueryData, where QueryData) !
|
||||
delete(table string, where QueryData) !
|
||||
create(table string, fields []TableField) !
|
||||
drop(table string) !
|
||||
insert(table Table, data QueryData) !
|
||||
update(table Table, data QueryData, where QueryData) !
|
||||
delete(table Table, where QueryData) !
|
||||
create(table Table, fields []TableField) !
|
||||
drop(table Table) !
|
||||
last_id() int
|
||||
}
|
||||
|
||||
@ -213,7 +221,7 @@ mut:
|
||||
// num - Stmt uses nums at prepared statements (? or ?1)
|
||||
// qm - Character for prepared statement (qm for question mark, as in sqlite)
|
||||
// start_pos - When num is true, it's the start position of the counter
|
||||
pub fn orm_stmt_gen(sql_dialect SQLDialect, table string, q string, kind StmtKind, num bool, qm string,
|
||||
pub fn orm_stmt_gen(sql_dialect SQLDialect, table Table, q string, kind StmtKind, num bool, qm string,
|
||||
start_pos int, data QueryData, where QueryData) (string, QueryData) {
|
||||
mut str := ''
|
||||
mut c := start_pos
|
||||
@ -257,7 +265,7 @@ pub fn orm_stmt_gen(sql_dialect SQLDialect, table string, q string, kind StmtKin
|
||||
c++
|
||||
}
|
||||
|
||||
str += 'INSERT INTO ${q}${table}${q} '
|
||||
str += 'INSERT INTO ${q}${table.name}${q} '
|
||||
|
||||
are_values_empty := values.len == 0
|
||||
|
||||
@ -272,7 +280,7 @@ pub fn orm_stmt_gen(sql_dialect SQLDialect, table string, q string, kind StmtKin
|
||||
}
|
||||
}
|
||||
.update {
|
||||
str += 'UPDATE ${q}${table}${q} SET '
|
||||
str += 'UPDATE ${q}${table.name}${q} SET '
|
||||
for i, field in data.fields {
|
||||
str += '${q}${field}${q} = '
|
||||
if data.data.len > i {
|
||||
@ -310,7 +318,7 @@ pub fn orm_stmt_gen(sql_dialect SQLDialect, table string, q string, kind StmtKin
|
||||
str += ' WHERE '
|
||||
}
|
||||
.delete {
|
||||
str += 'DELETE FROM ${q}${table}${q} WHERE '
|
||||
str += 'DELETE FROM ${q}${table.name}${q} WHERE '
|
||||
}
|
||||
}
|
||||
// where
|
||||
@ -319,7 +327,7 @@ pub fn orm_stmt_gen(sql_dialect SQLDialect, table string, q string, kind StmtKin
|
||||
}
|
||||
str += ';'
|
||||
$if trace_orm_stmt ? {
|
||||
eprintln('> orm_stmt sql_dialect: ${sql_dialect} | table: ${table} | kind: ${kind} | query: ${str}')
|
||||
eprintln('> orm_stmt sql_dialect: ${sql_dialect} | table: ${table.name} | kind: ${kind} | query: ${str}')
|
||||
}
|
||||
$if trace_orm ? {
|
||||
eprintln('> orm: ${str}')
|
||||
@ -352,7 +360,7 @@ pub fn orm_select_gen(cfg SelectConfig, q string, num bool, qm string, start_pos
|
||||
}
|
||||
}
|
||||
|
||||
str += ' FROM ${q}${cfg.table}${q}'
|
||||
str += ' FROM ${q}${cfg.table.name}${q}'
|
||||
|
||||
mut c := start_pos
|
||||
|
||||
@ -441,19 +449,19 @@ fn gen_where_clause(where QueryData, q string, qm string, num bool, mut c &int)
|
||||
}
|
||||
|
||||
// Generates an sql table stmt, from universal parameter
|
||||
// table - Table name
|
||||
// table - Table struct
|
||||
// q - see orm_stmt_gen
|
||||
// defaults - enables default values in stmt
|
||||
// def_unique_len - sets default unique length for texts
|
||||
// fields - See TableField
|
||||
// sql_from_v - Function which maps type indices to sql type names
|
||||
// alternative - Needed for msdb
|
||||
pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int, fields []TableField, sql_from_v fn (int) !string,
|
||||
pub fn orm_table_gen(sql_dialect SQLDialect, table Table, q string, defaults bool, def_unique_len int, fields []TableField, sql_from_v fn (int) !string,
|
||||
alternative bool) !string {
|
||||
mut str := 'CREATE TABLE IF NOT EXISTS ${q}${table}${q} ('
|
||||
mut str := 'CREATE TABLE IF NOT EXISTS ${q}${table.name}${q} ('
|
||||
|
||||
if alternative {
|
||||
str = 'IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=${q}${table}${q} and xtype=${q}U${q}) CREATE TABLE ${q}${table}${q} ('
|
||||
str = 'IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=${q}${table.name}${q} and xtype=${q}U${q}) CREATE TABLE ${q}${table.name}${q} ('
|
||||
}
|
||||
|
||||
mut fs := []string{}
|
||||
@ -461,6 +469,19 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
|
||||
mut unique := map[string][]string{}
|
||||
mut primary := ''
|
||||
mut primary_typ := 0
|
||||
mut table_comment := ''
|
||||
mut field_comments := map[string]string{}
|
||||
|
||||
for attr in table.attrs {
|
||||
match attr.name {
|
||||
'comment' {
|
||||
if attr.arg != '' && attr.kind == .string {
|
||||
table_comment = attr.arg.replace('"', '\\"')
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
for field in fields {
|
||||
if field.is_arr {
|
||||
@ -473,6 +494,7 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
|
||||
mut unique_len := 0
|
||||
mut references_table := ''
|
||||
mut references_field := ''
|
||||
mut field_comment := ''
|
||||
mut field_name := sql_field_name(field)
|
||||
mut col_typ := sql_from_v(sql_field_type(field)) or {
|
||||
field_name = '${field_name}_id'
|
||||
@ -540,6 +562,12 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
|
||||
}
|
||||
}
|
||||
}
|
||||
'comment' {
|
||||
if attr.arg != '' && attr.kind == .string {
|
||||
field_comment = attr.arg.replace("'", "\\'")
|
||||
field_comments[field_name] = field_comment
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
@ -548,12 +576,15 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
|
||||
}
|
||||
mut stmt := ''
|
||||
if col_typ == '' {
|
||||
return error('Unknown type (${field.typ}) for field ${field.name} in struct ${table}')
|
||||
return error('Unknown type (${field.typ}) for field ${field.name} in struct ${table.name}')
|
||||
}
|
||||
stmt = '${q}${field_name}${q} ${col_typ}'
|
||||
if defaults && default_val != '' {
|
||||
stmt += ' DEFAULT ${default_val}'
|
||||
}
|
||||
if sql_dialect == .mysql && field_comment != '' {
|
||||
stmt += " COMMENT '${field_comment}'"
|
||||
}
|
||||
if !nullable {
|
||||
stmt += ' NOT NULL'
|
||||
}
|
||||
@ -591,9 +622,22 @@ pub fn orm_table_gen(table string, q string, defaults bool, def_unique_len int,
|
||||
|
||||
fs << unique_fields
|
||||
str += fs.join(', ')
|
||||
str += ');'
|
||||
str += ')'
|
||||
if sql_dialect == .mysql && table_comment != '' {
|
||||
str += " COMMENT = '${table_comment}'"
|
||||
}
|
||||
str += ';'
|
||||
|
||||
if sql_dialect == .pg {
|
||||
if table_comment != '' {
|
||||
str += "\nCOMMENT ON TABLE \"${table.name}\" IS '${table_comment}';"
|
||||
}
|
||||
for f, c in field_comments {
|
||||
str += "\nCOMMENT ON COLUMN \"${table.name}\".\"${f}\" IS '${c}';"
|
||||
}
|
||||
}
|
||||
$if trace_orm_create ? {
|
||||
eprintln('> orm_create table: ${table} | query: ${str}')
|
||||
eprintln('> orm_create table: ${table.name} | query: ${str}')
|
||||
}
|
||||
$if trace_orm ? {
|
||||
eprintln('> orm: ${str}')
|
||||
|
@ -3,7 +3,10 @@
|
||||
import orm
|
||||
|
||||
fn test_orm_stmt_gen_update() {
|
||||
query_and, _ := orm.orm_stmt_gen(.default, 'Test', "'", .update, true, '?', 0, orm.QueryData{
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
query_and, _ := orm.orm_stmt_gen(.default, table, "'", .update, true, '?', 0, orm.QueryData{
|
||||
fields: ['test', 'a']
|
||||
data: []
|
||||
types: []
|
||||
@ -17,7 +20,7 @@ fn test_orm_stmt_gen_update() {
|
||||
})
|
||||
assert query_and == "UPDATE 'Test' SET 'test' = ?0, 'a' = ?1 WHERE 'id' >= ?2 AND 'name' = ?3;"
|
||||
|
||||
query_or, _ := orm.orm_stmt_gen(.default, 'Test', "'", .update, true, '?', 0, orm.QueryData{
|
||||
query_or, _ := orm.orm_stmt_gen(.default, table, "'", .update, true, '?', 0, orm.QueryData{
|
||||
fields: ['test', 'a']
|
||||
data: []
|
||||
types: []
|
||||
@ -33,7 +36,10 @@ fn test_orm_stmt_gen_update() {
|
||||
}
|
||||
|
||||
fn test_orm_stmt_gen_insert() {
|
||||
query, _ := orm.orm_stmt_gen(.default, 'Test', "'", .insert, true, '?', 0, orm.QueryData{
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
query, _ := orm.orm_stmt_gen(.default, table, "'", .insert, true, '?', 0, orm.QueryData{
|
||||
fields: ['test', 'a']
|
||||
data: []
|
||||
types: []
|
||||
@ -43,7 +49,10 @@ fn test_orm_stmt_gen_insert() {
|
||||
}
|
||||
|
||||
fn test_orm_stmt_gen_delete() {
|
||||
query_and, _ := orm.orm_stmt_gen(.default, 'Test', "'", .delete, true, '?', 0, orm.QueryData{
|
||||
table := orm.Table{
|
||||
name: 'Test'
|
||||
}
|
||||
query_and, _ := orm.orm_stmt_gen(.default, table, "'", .delete, true, '?', 0, orm.QueryData{
|
||||
fields: ['test', 'a']
|
||||
data: []
|
||||
types: []
|
||||
@ -57,7 +66,7 @@ fn test_orm_stmt_gen_delete() {
|
||||
})
|
||||
assert query_and == "DELETE FROM 'Test' WHERE 'id' >= ?0 AND 'name' = ?1;"
|
||||
|
||||
query_or, _ := orm.orm_stmt_gen(.default, 'Test', "'", .delete, true, '?', 0, orm.QueryData{
|
||||
query_or, _ := orm.orm_stmt_gen(.default, table, "'", .delete, true, '?', 0, orm.QueryData{
|
||||
fields: ['test', 'a']
|
||||
data: []
|
||||
types: []
|
||||
@ -78,7 +87,9 @@ fn get_select_fields() []string {
|
||||
|
||||
fn test_orm_select_gen() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
}, "'", true, '?', 0, orm.QueryData{})
|
||||
|
||||
@ -87,7 +98,9 @@ fn test_orm_select_gen() {
|
||||
|
||||
fn test_orm_select_gen_with_limit() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
has_limit: true
|
||||
}, "'", true, '?', 0, orm.QueryData{})
|
||||
@ -97,7 +110,9 @@ fn test_orm_select_gen_with_limit() {
|
||||
|
||||
fn test_orm_select_gen_with_where() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
has_where: true
|
||||
}, "'", true, '?', 0, orm.QueryData{
|
||||
@ -111,7 +126,9 @@ fn test_orm_select_gen_with_where() {
|
||||
|
||||
fn test_orm_select_gen_with_order() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
has_order: true
|
||||
order_type: .desc
|
||||
@ -122,7 +139,9 @@ fn test_orm_select_gen_with_order() {
|
||||
|
||||
fn test_orm_select_gen_with_offset() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
has_offset: true
|
||||
}, "'", true, '?', 0, orm.QueryData{})
|
||||
@ -132,7 +151,9 @@ fn test_orm_select_gen_with_offset() {
|
||||
|
||||
fn test_orm_select_gen_with_all() {
|
||||
query := orm.orm_select_gen(orm.SelectConfig{
|
||||
table: 'test_table'
|
||||
table: orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
fields: get_select_fields()
|
||||
has_limit: true
|
||||
has_order: true
|
||||
@ -149,7 +170,10 @@ fn test_orm_select_gen_with_all() {
|
||||
}
|
||||
|
||||
fn test_orm_table_gen() {
|
||||
query := orm.orm_table_gen('test_table', "'", true, 0, [
|
||||
table := orm.Table{
|
||||
name: 'test_table'
|
||||
}
|
||||
query := orm.orm_table_gen(.default, table, "'", true, 0, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
@ -181,7 +205,7 @@ fn test_orm_table_gen() {
|
||||
], sql_type_from_v, false) or { panic(err) }
|
||||
assert query == "CREATE TABLE IF NOT EXISTS 'test_table' ('id' SERIAL DEFAULT 10, 'test' TEXT, 'abc' INT64 DEFAULT 6754, PRIMARY KEY('id'));"
|
||||
|
||||
alt_query := orm.orm_table_gen('test_table', "'", true, 0, [
|
||||
alt_query := orm.orm_table_gen(.default, table, "'", true, 0, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
@ -213,7 +237,7 @@ fn test_orm_table_gen() {
|
||||
], sql_type_from_v, true) or { panic(err) }
|
||||
assert alt_query == "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='test_table' and xtype='U') CREATE TABLE 'test_table' ('id' SERIAL DEFAULT 10, 'test' TEXT, 'abc' INT64 DEFAULT 6754, PRIMARY KEY('id'));"
|
||||
|
||||
unique_query := orm.orm_table_gen('test_table', "'", true, 0, [
|
||||
unique_query := orm.orm_table_gen(.default, table, "'", true, 0, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
@ -248,7 +272,7 @@ fn test_orm_table_gen() {
|
||||
], sql_type_from_v, false) or { panic(err) }
|
||||
assert unique_query == "CREATE TABLE IF NOT EXISTS 'test_table' ('id' SERIAL DEFAULT 10, 'test' TEXT NOT NULL, 'abc' INT64 DEFAULT 6754 NOT NULL, PRIMARY KEY('id'), UNIQUE('test'));"
|
||||
|
||||
mult_unique_query := orm.orm_table_gen('test_table', "'", true, 0, [
|
||||
mult_unique_query := orm.orm_table_gen(.default, table, "'", true, 0, [
|
||||
orm.TableField{
|
||||
name: 'id'
|
||||
typ: typeof[int]().idx
|
||||
|
@ -25,7 +25,7 @@ pub fn new_query[T](conn Connection) &QueryBuilder[T] {
|
||||
valid_sql_field_names: meta.map(sql_field_name(it))
|
||||
conn: conn
|
||||
config: SelectConfig{
|
||||
table: table_name_from_struct[T]()
|
||||
table: table_from_struct[T]()
|
||||
}
|
||||
data: QueryData{}
|
||||
where: QueryData{}
|
||||
@ -35,9 +35,9 @@ pub fn new_query[T](conn Connection) &QueryBuilder[T] {
|
||||
// reset reset a query object, but keep the connection and table name
|
||||
pub fn (qb_ &QueryBuilder[T]) reset() &QueryBuilder[T] {
|
||||
mut qb := unsafe { qb_ }
|
||||
old_table_name := qb.config.table
|
||||
old_table := qb.config.table
|
||||
qb.config = SelectConfig{
|
||||
table: old_table_name
|
||||
table: old_table
|
||||
}
|
||||
qb.data = QueryData{}
|
||||
qb.where = QueryData{}
|
||||
@ -366,15 +366,20 @@ pub fn (qb_ &QueryBuilder[T]) set(assign string, values ...Primitive) !&QueryBui
|
||||
return qb
|
||||
}
|
||||
|
||||
// table_name_from_struct get table name from struct
|
||||
fn table_name_from_struct[T]() string {
|
||||
// table_from_struct get table from struct
|
||||
fn table_from_struct[T]() Table {
|
||||
mut table_name := T.name
|
||||
mut attrs := []VAttribute{}
|
||||
$for a in T.attributes {
|
||||
$if a.name == 'table' && a.has_arg {
|
||||
table_name = a.arg
|
||||
}
|
||||
attrs << a
|
||||
}
|
||||
return Table{
|
||||
name: table_name
|
||||
attrs: attrs
|
||||
}
|
||||
return table_name
|
||||
}
|
||||
|
||||
// struct_meta return a struct's fields info
|
||||
|
@ -25,14 +25,14 @@ fn (mut db Database) select(config orm.SelectConfig, data orm.QueryData, where o
|
||||
}
|
||||
|
||||
// insert is used internally by V's ORM for processing `INSERT` queries
|
||||
fn (mut db Database) insert(table string, data orm.QueryData) ! {
|
||||
fn (mut db Database) insert(table orm.Table, data orm.QueryData) ! {
|
||||
query, _ := orm.orm_stmt_gen(.sqlite, table, '', .insert, false, '?', 1, data, orm.QueryData{})
|
||||
|
||||
db.query(query)!
|
||||
}
|
||||
|
||||
// update is used internally by V's ORM for processing `UPDATE` queries
|
||||
fn (mut db Database) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
fn (mut db Database) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
|
||||
mut query, _ := orm.orm_stmt_gen(.sqlite, table, '', .update, true, ':', 1, data,
|
||||
where)
|
||||
|
||||
@ -40,7 +40,7 @@ fn (mut db Database) update(table string, data orm.QueryData, where orm.QueryDat
|
||||
}
|
||||
|
||||
// delete is used internally by V's ORM for processing `DELETE ` queries
|
||||
fn (mut db Database) delete(table string, where orm.QueryData) ! {
|
||||
fn (mut db Database) delete(table orm.Table, where orm.QueryData) ! {
|
||||
query, converted := orm.orm_stmt_gen(.sqlite, table, '', .delete, true, ':', 1, orm.QueryData{},
|
||||
where)
|
||||
|
||||
@ -66,16 +66,15 @@ fn sqlite_type_from_v(typ int) !string {
|
||||
}
|
||||
|
||||
// create is used internally by V's ORM for processing table creation queries (DDL)
|
||||
fn (mut db Database) create(table string, fields []orm.TableField) ! {
|
||||
mut query := orm.orm_table_gen(table, '', true, 0, fields, sqlite_type_from_v, false) or {
|
||||
return err
|
||||
}
|
||||
fn (mut db Database) create(table orm.Table, fields []orm.TableField) ! {
|
||||
mut query := orm.orm_table_gen(.sqlite, table, '', true, 0, fields, sqlite_type_from_v,
|
||||
false) or { return err }
|
||||
db.query(query)!
|
||||
}
|
||||
|
||||
// drop is used internally by V's ORM for processing table destroying queries (DDL)
|
||||
fn (mut db Database) drop(table string) ! {
|
||||
query := 'DROP TABLE ${table};'
|
||||
fn (mut db Database) drop(table orm.Table) ! {
|
||||
query := 'DROP TABLE ${table.name};'
|
||||
$if trace_orm ? {
|
||||
eprintln('> vsql drop: ${query}')
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ fn (db MockDB) select(config orm.SelectConfig, data orm.QueryData, where orm.Que
|
||||
return db.db.select(config, data, where)
|
||||
}
|
||||
|
||||
fn (db MockDB) insert(table string, data orm.QueryData) ! {
|
||||
fn (db MockDB) insert(table orm.Table, data orm.QueryData) ! {
|
||||
mut st := db.st
|
||||
last, qdata := orm.orm_stmt_gen(.sqlite, table, '`', .insert, false, '?', 1, data,
|
||||
orm.QueryData{})
|
||||
@ -41,7 +41,7 @@ fn (db MockDB) insert(table string, data orm.QueryData) ! {
|
||||
return db.db.insert(table, data)
|
||||
}
|
||||
|
||||
fn (db MockDB) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
fn (db MockDB) update(table orm.Table, data orm.QueryData, where orm.QueryData) ! {
|
||||
mut st := db.st
|
||||
st.last, _ = orm.orm_stmt_gen(.sqlite, table, '`', .update, false, '?', 1, data, where)
|
||||
st.data = data.data
|
||||
@ -49,7 +49,7 @@ fn (db MockDB) update(table string, data orm.QueryData, where orm.QueryData) ! {
|
||||
return db.db.update(table, data, where)
|
||||
}
|
||||
|
||||
fn (db MockDB) delete(table string, where orm.QueryData) ! {
|
||||
fn (db MockDB) delete(table orm.Table, where orm.QueryData) ! {
|
||||
mut st := db.st
|
||||
st.last, _ = orm.orm_stmt_gen(.sqlite, table, '`', .delete, false, '?', 1, orm.QueryData{},
|
||||
where)
|
||||
@ -82,13 +82,14 @@ fn mock_type_from_v(typ int) !string {
|
||||
}
|
||||
}
|
||||
|
||||
fn (db MockDB) create(table string, fields []orm.TableField) ! {
|
||||
fn (db MockDB) create(table orm.Table, fields []orm.TableField) ! {
|
||||
mut st := db.st
|
||||
st.last = orm.orm_table_gen(table, '`', true, 0, fields, mock_type_from_v, false)!
|
||||
st.last = orm.orm_table_gen(.sqlite, table, '`', true, 0, fields, mock_type_from_v,
|
||||
false)!
|
||||
return db.db.create(table, fields)
|
||||
}
|
||||
|
||||
fn (db MockDB) drop(table string) ! {
|
||||
fn (db MockDB) drop(table orm.Table) ! {
|
||||
return db.db.drop(table)
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ fn (mut g Gen) sql_insert_expr(node ast.SqlExpr) {
|
||||
connection_var_name := g.new_tmp_var()
|
||||
g.write_orm_connection_init(connection_var_name, &node.db_expr)
|
||||
table_name := g.get_table_name_by_struct_type(node.table_expr.typ)
|
||||
table_attrs := g.get_table_attrs_by_struct_type(node.table_expr.typ)
|
||||
result_var_name := g.new_tmp_var()
|
||||
g.sql_table_name = g.table.sym(node.table_expr.typ).name
|
||||
|
||||
@ -55,10 +56,11 @@ fn (mut g Gen) sql_insert_expr(node ast.SqlExpr) {
|
||||
hack_stmt_line := ast.SqlStmtLine{
|
||||
object_var: node.inserted_var
|
||||
fields: node.fields
|
||||
table_expr: node.table_expr
|
||||
// sub_structs: node.sub_structs
|
||||
}
|
||||
g.write_orm_insert(hack_stmt_line, table_name, connection_var_name, result_var_name,
|
||||
node.or_expr)
|
||||
node.or_expr, table_attrs)
|
||||
|
||||
g.write2(left, 'orm__Connection_name_table[${connection_var_name}._typ]._method_last_id(${connection_var_name}._object)')
|
||||
}
|
||||
@ -93,6 +95,7 @@ fn (mut g Gen) sql_stmt_line(stmt_line ast.SqlStmtLine, connection_var_name stri
|
||||
g.sql_last_stmt_out_len = g.out.len
|
||||
mut node := stmt_line
|
||||
table_name := g.get_table_name_by_struct_type(node.table_expr.typ)
|
||||
table_attrs := g.get_table_attrs_by_struct_type(node.table_expr.typ)
|
||||
result_var_name := g.new_tmp_var()
|
||||
g.sql_table_name = g.table.sym(node.table_expr.typ).name
|
||||
|
||||
@ -101,15 +104,18 @@ fn (mut g Gen) sql_stmt_line(stmt_line ast.SqlStmtLine, connection_var_name stri
|
||||
}
|
||||
|
||||
if node.kind == .create {
|
||||
g.write_orm_create_table(node, table_name, connection_var_name, result_var_name)
|
||||
g.write_orm_create_table(node, table_name, connection_var_name, result_var_name,
|
||||
table_attrs)
|
||||
} else if node.kind == .drop {
|
||||
g.write_orm_drop_table(table_name, connection_var_name, result_var_name)
|
||||
g.write_orm_drop_table(node, table_name, connection_var_name, result_var_name,
|
||||
table_attrs)
|
||||
} else if node.kind == .insert {
|
||||
g.write_orm_insert(node, table_name, connection_var_name, result_var_name, or_expr)
|
||||
g.write_orm_insert(node, table_name, connection_var_name, result_var_name, or_expr,
|
||||
table_attrs)
|
||||
} else if node.kind == .update {
|
||||
g.write_orm_update(node, table_name, connection_var_name, result_var_name)
|
||||
g.write_orm_update(node, table_name, connection_var_name, result_var_name, table_attrs)
|
||||
} else if node.kind == .delete {
|
||||
g.write_orm_delete(node, table_name, connection_var_name, result_var_name)
|
||||
g.write_orm_delete(node, table_name, connection_var_name, result_var_name, table_attrs)
|
||||
}
|
||||
|
||||
g.or_block(result_var_name, or_expr, ast.int_type.set_flag(.result))
|
||||
@ -138,14 +144,54 @@ fn (mut g Gen) write_orm_connection_init(connection_var_name string, db_expr &as
|
||||
}
|
||||
}
|
||||
|
||||
// write_orm_table_struct writes C code for the orm.Table struct
|
||||
fn (mut g Gen) write_orm_table_struct(typ ast.Type) {
|
||||
table_name := g.get_table_name_by_struct_type(typ)
|
||||
table_attrs := g.get_table_attrs_by_struct_type(typ)
|
||||
|
||||
g.writeln('((orm__Table){')
|
||||
g.indent++
|
||||
g.writeln('.name = _S("${table_name}"),')
|
||||
g.writeln('.attrs = new_array_from_c_array(${table_attrs.len}, ${table_attrs.len}, sizeof(VAttribute),')
|
||||
g.indent++
|
||||
|
||||
if table_attrs.len > 0 {
|
||||
g.write('_MOV((VAttribute[${table_attrs.len}]){')
|
||||
g.indent++
|
||||
for attr in table_attrs {
|
||||
g.write('(VAttribute){')
|
||||
g.indent++
|
||||
name1 := util.smart_quote(attr.name, false)
|
||||
name := cescape_nonascii(name1)
|
||||
g.write(' .name = _S("${name}"),')
|
||||
g.write(' .has_arg = ${attr.has_arg},')
|
||||
arg1 := util.smart_quote(attr.arg, false)
|
||||
arg := cescape_nonascii(arg1)
|
||||
g.write(' .arg = _S("${arg}"),')
|
||||
g.write(' .kind = ${int(attr.kind)},')
|
||||
g.indent--
|
||||
g.write('},')
|
||||
}
|
||||
g.indent--
|
||||
g.writeln('})')
|
||||
} else {
|
||||
g.writeln('NULL // No attrs')
|
||||
}
|
||||
g.indent--
|
||||
g.writeln(')')
|
||||
g.indent--
|
||||
g.write('})')
|
||||
}
|
||||
|
||||
// write_orm_create_table writes C code that calls ORM functions for creating tables.
|
||||
fn (mut g Gen) write_orm_create_table(node ast.SqlStmtLine, table_name string, connection_var_name string,
|
||||
result_var_name string) {
|
||||
result_var_name string, table_attrs []ast.Attr) {
|
||||
g.writeln('// sql { create table `${table_name}` }')
|
||||
g.writeln('${result_name}_void ${result_var_name} = orm__Connection_name_table[${connection_var_name}._typ]._method_create(')
|
||||
g.indent++
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('_S("${table_name}"),')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.writeln(',')
|
||||
g.writeln('new_array_from_c_array(${node.fields.len}, ${node.fields.len}, sizeof(orm__TableField),')
|
||||
g.indent++
|
||||
|
||||
@ -213,19 +259,19 @@ fn (mut g Gen) write_orm_create_table(node ast.SqlStmtLine, table_name string, c
|
||||
}
|
||||
|
||||
// write_orm_drop_table writes C code that calls ORM functions for dropping tables.
|
||||
fn (mut g Gen) write_orm_drop_table(table_name string, connection_var_name string, result_var_name string) {
|
||||
fn (mut g Gen) write_orm_drop_table(node ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string, table_attrs []ast.Attr) {
|
||||
g.writeln('// sql { drop table `${table_name}` }')
|
||||
g.writeln('${result_name}_void ${result_var_name} = orm__Connection_name_table[${connection_var_name}._typ]._method_drop(')
|
||||
g.indent++
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('_S("${table_name}")')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.indent--
|
||||
g.writeln(');')
|
||||
}
|
||||
|
||||
// write_orm_insert writes C code that calls ORM functions for inserting structs into a table.
|
||||
fn (mut g Gen) write_orm_insert(node &ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string,
|
||||
or_expr &ast.OrExpr) {
|
||||
or_expr &ast.OrExpr, table_attrs []ast.Attr) {
|
||||
last_ids_variable_name := g.new_tmp_var()
|
||||
|
||||
g.writeln('Array_orm__Primitive ${last_ids_variable_name} = __new_array_with_default_noscan(0, 0, sizeof(orm__Primitive), 0);')
|
||||
@ -234,12 +280,13 @@ fn (mut g Gen) write_orm_insert(node &ast.SqlStmtLine, table_name string, connec
|
||||
}
|
||||
|
||||
// write_orm_update writes C code that calls ORM functions for updating rows.
|
||||
fn (mut g Gen) write_orm_update(node &ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string) {
|
||||
fn (mut g Gen) write_orm_update(node &ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string, table_attrs []ast.Attr) {
|
||||
g.writeln('// sql { update `${table_name}` }')
|
||||
g.writeln('${result_name}_void ${result_var_name} = orm__Connection_name_table[${connection_var_name}._typ]._method_update(')
|
||||
g.indent++
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('_S("${table_name}"),')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.writeln(',')
|
||||
g.writeln('(orm__QueryData){')
|
||||
g.indent++
|
||||
g.writeln('.kinds = __new_array_with_default_noscan(0, 0, sizeof(orm__OperationKind), 0),')
|
||||
@ -285,12 +332,13 @@ fn (mut g Gen) write_orm_update(node &ast.SqlStmtLine, table_name string, connec
|
||||
}
|
||||
|
||||
// write_orm_delete writes C code that calls ORM functions for deleting rows.
|
||||
fn (mut g Gen) write_orm_delete(node &ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string) {
|
||||
fn (mut g Gen) write_orm_delete(node &ast.SqlStmtLine, table_name string, connection_var_name string, result_var_name string, table_attrs []ast.Attr) {
|
||||
g.writeln('// sql { delete from `${table_name}` }')
|
||||
g.writeln('${result_name}_void ${result_var_name} = orm__Connection_name_table[${connection_var_name}._typ]._method__v_delete(')
|
||||
g.indent++
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('_S("${table_name}"),')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.writeln(',')
|
||||
g.write_orm_where(node.where_expr)
|
||||
g.indent--
|
||||
g.writeln(');')
|
||||
@ -381,7 +429,8 @@ fn (mut g Gen) write_orm_insert_with_last_ids(node ast.SqlStmtLine, connection_v
|
||||
g.writeln('${result_name}_void ${res} = orm__Connection_name_table[${connection_var_name}._typ]._method_insert(')
|
||||
g.indent++
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('_S("${table_name}"),')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.writeln(',')
|
||||
g.writeln('(orm__QueryData){')
|
||||
g.indent++
|
||||
g.writeln('.fields = new_array_from_c_array(${fields.len}, ${fields.len}, sizeof(string),')
|
||||
@ -880,7 +929,6 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, re
|
||||
|
||||
select_result_var_name := g.new_tmp_var()
|
||||
table_name := g.get_table_name_by_struct_type(node.table_expr.typ)
|
||||
escaped_table_name := cescape_nonascii(util.smart_quote(table_name, false))
|
||||
g.sql_table_name = g.table.sym(node.table_expr.typ).name
|
||||
|
||||
g.writeln('// sql { select from `${table_name}` }')
|
||||
@ -889,7 +937,9 @@ fn (mut g Gen) write_orm_select(node ast.SqlExpr, connection_var_name string, re
|
||||
g.writeln('${connection_var_name}._object, // Connection object')
|
||||
g.writeln('(orm__SelectConfig){')
|
||||
g.indent++
|
||||
g.writeln('.table = _S("${escaped_table_name}"),')
|
||||
g.writeln('.table = ')
|
||||
g.write_orm_table_struct(node.table_expr.typ)
|
||||
g.writeln(',')
|
||||
g.writeln('.is_count = ${node.is_count},')
|
||||
g.writeln('.has_where = ${node.has_where},')
|
||||
g.writeln('.has_order = ${node.has_order},')
|
||||
@ -1246,6 +1296,13 @@ fn (g &Gen) get_db_expr_type(expr ast.Expr) ?ast.Type {
|
||||
return none
|
||||
}
|
||||
|
||||
// get_table_attrs_by_struct_type returns the struct attrs.
|
||||
fn (g &Gen) get_table_attrs_by_struct_type(typ ast.Type) []ast.Attr {
|
||||
sym := g.table.sym(typ)
|
||||
info := sym.struct_info()
|
||||
return info.attrs
|
||||
}
|
||||
|
||||
// get_table_name_by_struct_type converts the struct type to a table name.
|
||||
fn (g &Gen) get_table_name_by_struct_type(typ ast.Type) string {
|
||||
sym := g.table.sym(typ)
|
||||
@ -1255,8 +1312,8 @@ fn (g &Gen) get_table_name_by_struct_type(typ ast.Type) string {
|
||||
if attr := info.attrs.find_first('table') {
|
||||
table_name = attr.arg
|
||||
}
|
||||
|
||||
return table_name
|
||||
escaped_table_name := cescape_nonascii(util.smart_quote(table_name, false))
|
||||
return escaped_table_name
|
||||
}
|
||||
|
||||
// get_orm_current_table_field returns the current processing table's struct field by name.
|
||||
|
Loading…
x
Reference in New Issue
Block a user