diff --git a/Makefile b/Makefile index a194e11..b499469 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,9 @@ btree-test: oldv sql-test: oldv $(V) -stats $(BUILD_OPTIONS) vsql/sql_test.v +orm-test: oldv + $(V) -stats $(BUILD_OPTIONS) vsql/orm_test.v + # CLI Tests cli-test: bin/vsql diff --git a/cmd/vsql/bench.v b/cmd/vsql/bench.v index 7ae2889..ece3686 100644 --- a/cmd/vsql/bench.v +++ b/cmd/vsql/bench.v @@ -5,14 +5,14 @@ import vsql fn register_bench_command(mut cmd cli.Command) { mut bench_cmd := cli.Command{ - name: 'bench' + name: 'bench' description: 'Run benchmark' - execute: bench_command + execute: bench_command } bench_cmd.add_flag(cli.Flag{ - flag: .string - name: 'file' - abbrev: 'f' + flag: .string + name: 'file' + abbrev: 'f' description: 'File path that will be deleted and created for the test. You can use :memory: as well (default bench.vsql)' }) cmd.add_command(bench_cmd) diff --git a/cmd/vsql/cli.v b/cmd/vsql/cli.v index 09d4fec..0ac3217 100644 --- a/cmd/vsql/cli.v +++ b/cmd/vsql/cli.v @@ -7,11 +7,11 @@ import vsql fn register_cli_command(mut cmd cli.Command) { mut cli_cmd := cli.Command{ - name: 'cli' - usage: '' + name: 'cli' + usage: '' required_args: 1 - description: 'Run SQL in a vsql file' - execute: cli_command + description: 'Run SQL in a vsql file' + execute: cli_command } cmd.add_command(cli_cmd) } diff --git a/cmd/vsql/in.v b/cmd/vsql/in.v index 2fce7e9..65edf80 100644 --- a/cmd/vsql/in.v +++ b/cmd/vsql/in.v @@ -6,23 +6,23 @@ import vsql fn register_in_command(mut cmd cli.Command) { mut in_cmd := cli.Command{ - name: 'in' - usage: '' + name: 'in' + usage: '' required_args: 1 - description: 'Import schema and data' - execute: in_command + description: 'Import schema and data' + execute: in_command } in_cmd.add_flag(cli.Flag{ - flag: .bool - name: 'continue-on-error' + flag: .bool + name: 'continue-on-error' description: 'Continue when errors occur' }) in_cmd.add_flag(cli.Flag{ - flag: .bool - name: 'verbose' - abbrev: 'v' + flag: .bool + name: 'verbose' + abbrev: 'v' description: 'Show result of each command' }) diff --git a/cmd/vsql/main.v b/cmd/vsql/main.v index 1d5c087..23bd8db 100644 --- a/cmd/vsql/main.v +++ b/cmd/vsql/main.v @@ -5,9 +5,9 @@ import os fn main() { mut cmd := cli.Command{ - name: 'vsql' + name: 'vsql' description: 'vsql is a single-file or PostgeSQL-compatible SQL database written in V.\nhttps://github.com/elliotchance/vsql' - execute: unknown_command + execute: unknown_command } register_bench_command(mut cmd) diff --git a/cmd/vsql/out.v b/cmd/vsql/out.v index 738493a..53f1d9b 100644 --- a/cmd/vsql/out.v +++ b/cmd/vsql/out.v @@ -5,16 +5,16 @@ import vsql fn register_out_command(mut cmd cli.Command) { mut out_cmd := cli.Command{ - name: 'out' - usage: '' + name: 'out' + usage: '' required_args: 1 - description: 'Export schema and data' - execute: out_command + description: 'Export schema and data' + execute: out_command } out_cmd.add_flag(cli.Flag{ - flag: .bool - name: 'create-public-schema' + flag: .bool + name: 'create-public-schema' description: 'Include "CREATE SCHEMA PUBLIC"' }) diff --git a/cmd/vsql/server.v b/cmd/vsql/server.v index 232d59a..04ec58e 100644 --- a/cmd/vsql/server.v +++ b/cmd/vsql/server.v @@ -5,22 +5,22 @@ import vsql fn register_server_command(mut cmd cli.Command) { mut server_cmd := cli.Command{ - name: 'server' - description: 'Run as a server for PostgreSQL clients' - usage: '' + name: 'server' + description: 'Run as a server for PostgreSQL clients' + usage: '' required_args: 1 - execute: server_command + execute: server_command } server_cmd.add_flag(cli.Flag{ - flag: .bool - name: 'verbose' - abbrev: 'v' + flag: .bool + name: 'verbose' + abbrev: 'v' description: 'Verbose (show all messages in and out of the server)' }) server_cmd.add_flag(cli.Flag{ - flag: .int - name: 'port' - abbrev: 'p' + flag: .int + name: 'port' + abbrev: 'p' description: 'Port number (default 3210)' }) cmd.add_command(server_cmd) @@ -36,7 +36,7 @@ fn server_command(cmd cli.Command) ! { mut server := vsql.new_server(vsql.ServerOptions{ db_file: cmd.args[0] - port: port + port: port verbose: cmd.flags.get_bool('verbose') or { false } }) diff --git a/cmd/vsql/version.v b/cmd/vsql/version.v index 6b739b7..daf055d 100644 --- a/cmd/vsql/version.v +++ b/cmd/vsql/version.v @@ -4,9 +4,9 @@ import cli fn register_version_command(mut cmd cli.Command) { mut version_cmd := cli.Command{ - name: 'version' + name: 'version' description: 'Show version' - execute: version_command + execute: version_command } cmd.add_command(version_cmd) } diff --git a/examples/orm.v b/examples/orm.v new file mode 100644 index 0000000..91d4f66 --- /dev/null +++ b/examples/orm.v @@ -0,0 +1,61 @@ +import os +import vsql +import time + +// CHECK ./vsql/orm_test.v for more advanced usage + +fn main() { + os.rm('test.vsql') or {} + + example() or { panic(err) } +} + +// NOTE for some reason if we declare a @[primary] on a struct field, we can not do delete queries on the tables... +// https://github.com/elliotchance/vsql/issues/200 +struct Product { + id int //@[primary] + product_name string @[sql_type: 'varchar(100)'] + price f64 +} + +fn example() ! { + timer := time.new_stopwatch() + mut db := vsql.open('test.vsql')! + + sql db { + create table Product + }! + + products := [ + Product{1, 'Ice Cream', 5.99}, + Product{2, 'Ham Sandwhich', 3.47}, + Product{3, 'Bagel', 1.25}, + ] + + for product in products { + sql db { + insert product into Product + } or { panic(err) } + } + sql db { + update Product set product_name = 'Cereal' where id == 1 + } or { panic(err) } + + prod_one := sql db { + select from Product where id == 1 + }! + + assert prod_one.len == 1 + + sql db { + delete from Product where product_name == 'Cereal' + } or { panic(err) } + + all := sql db { + select from Product + }! + + assert all.len == 2 + + println(timer.elapsed()) +} diff --git a/vsql/bench.v b/vsql/bench.v index 68b9bfb..599e318 100644 --- a/vsql/bench.v +++ b/vsql/bench.v @@ -25,10 +25,10 @@ pub mut: pub fn new_benchmark(conn &Connection) Benchmark { return Benchmark{ account_rows: 100000 - teller_rows: 10 - branch_rows: 1 - run_for: time.minute - conn: conn + teller_rows: 10 + branch_rows: 1 + run_for: time.minute + conn: conn } } diff --git a/vsql/btree.v b/vsql/btree.v index d0675d8..16ff54f 100644 --- a/vsql/btree.v +++ b/vsql/btree.v @@ -30,7 +30,7 @@ mut: fn new_btree(pager Pager, page_size int) &Btree { return &Btree{ - pager: pager + pager: pager page_size: page_size } } @@ -383,8 +383,8 @@ fn (mut p Btree) split_page(path []int, page Page, obj PageObject, kind u8) ! { fn (p Btree) new_range_iterator(min []u8, max []u8) PageIterator { return PageIterator{ btree: p - min: min - max: max + min: min + max: max } } diff --git a/vsql/btree_test.v b/vsql/btree_test.v index 3cbf1dd..858ee6a 100644 --- a/vsql/btree_test.v +++ b/vsql/btree_test.v @@ -29,7 +29,7 @@ fn test_btree_test() ! { page_size := 256 file_name := 'btree.vsql' - for tt in 0 .. vsql.times { + for tt in 0 .. times { for size := 1; size <= 1000; size *= 10 { for blob_size in blob_sizes { if os.exists(file_name) { diff --git a/vsql/compiler.v b/vsql/compiler.v index 7e59110..8bf60bd 100644 --- a/vsql/compiler.v +++ b/vsql/compiler.v @@ -24,8 +24,8 @@ struct CompileResult { fn (c CompileResult) with_agg(contains_agg bool) CompileResult { return CompileResult{ - run: c.run - typ: c.typ + run: c.run + typ: c.typ contains_agg: contains_agg } } diff --git a/vsql/connection.v b/vsql/connection.v index 858e3aa..b85b6c7 100644 --- a/vsql/connection.v +++ b/vsql/connection.v @@ -113,10 +113,10 @@ fn open_connection(path string, options ConnectionOptions) !&Connection { catalog_name := catalog_name_from_path(path) mut conn := &Connection{ - query_cache: options.query_cache + query_cache: options.query_cache current_catalog: catalog_name - current_schema: vsql.default_schema_name - now: default_now + current_schema: default_schema_name + now: default_now } register_builtin_funcs(mut conn)! @@ -140,9 +140,9 @@ pub fn (mut conn Connection) add_catalog(catalog_name string, path string, optio catalog := &CatalogConnection{ catalog_name: catalog_name - path: path - storage: new_storage(btree) - options: options + path: path + storage: new_storage(btree) + options: options } conn.catalogs[catalog_name] = catalog @@ -350,9 +350,9 @@ pub fn (mut conn Connection) register_virtual_table(create_table string, data Vi mut table_name := conn.resolve_schema_identifier(stmt.table_name)! conn.catalogs[conn.current_catalog].virtual_tables[table_name.storage_id()] = VirtualTable{ - create_table_sql: create_table + create_table_sql: create_table create_table_stmt: stmt - data: data + data: data } return @@ -416,19 +416,20 @@ pub fn (mut conn CatalogConnection) schema_tables(schema string) ![]Table { // canonical (fully qualified) form. fn (conn Connection) resolve_identifier(identifier Identifier) Identifier { return Identifier{ - custom_id: identifier.custom_id - custom_typ: identifier.custom_typ - catalog_name: if identifier.catalog_name == '' && !identifier.entity_name.starts_with('$') { + custom_id: identifier.custom_id + custom_typ: identifier.custom_typ + catalog_name: if identifier.catalog_name == '' + && !identifier.entity_name.starts_with('$') { conn.current_catalog } else { identifier.catalog_name } - schema_name: if identifier.schema_name == '' && !identifier.entity_name.starts_with('$') { + schema_name: if identifier.schema_name == '' && !identifier.entity_name.starts_with('$') { conn.current_schema } else { identifier.schema_name } - entity_name: identifier.entity_name + entity_name: identifier.entity_name sub_entity_name: identifier.sub_entity_name } } @@ -518,8 +519,8 @@ pub mut: pub fn default_connection_options() ConnectionOptions { return ConnectionOptions{ query_cache: new_query_cache() - page_size: 4096 - mutex: sync.new_rwmutex() + page_size: 4096 + mutex: sync.new_rwmutex() } } diff --git a/vsql/connection_test.v b/vsql/connection_test.v index ec6110f..0690ecd 100644 --- a/vsql/connection_test.v +++ b/vsql/connection_test.v @@ -24,11 +24,11 @@ fn test_concurrent_writes() ! { waits << spawn fn (file_name string, i int, options ConnectionOptions) { mut db := open_database(file_name, options) or { panic(err) } for j in 0 .. 100 { - if vsql.verbose { + if verbose { println('${i}.${j}: INSERT start') } db.query('INSERT INTO foo (x) VALUES (1)') or { panic(err) } - if vsql.verbose { + if verbose { println('${i}.${j}: INSERT done') } } diff --git a/vsql/earley.v b/vsql/earley.v index b97a0d5..20455e0 100644 --- a/vsql/earley.v +++ b/vsql/earley.v @@ -63,12 +63,12 @@ fn new_earley_state(name string, production &EarleyProduction, dot_index int, st } return &EarleyState{ - name: name - production: production + name: name + production: production start_column: start_column - dot_index: dot_index - rules: rules - end_column: unsafe { 0 } + dot_index: dot_index + rules: rules + end_column: unsafe { 0 } } } @@ -136,9 +136,9 @@ mut: fn new_earley_column(index int, token string, value string) &EarleyColumn { return &EarleyColumn{ - index: index - token: token - value: value + index: index + token: token + value: value unique: &Set{} } } diff --git a/vsql/header.v b/vsql/header.v index fddc851..c164921 100644 --- a/vsql/header.v +++ b/vsql/header.v @@ -49,10 +49,10 @@ mut: fn new_header(page_size int) Header { return Header{ // Set all default here - even if they are zero - to be explicit. - version: vsql.current_version + version: current_version schema_version: 0 - page_size: page_size - root_page: 0 + page_size: page_size + root_page: 0 // 2 is a reserved number for freezing rows, but the transaction_is is // always incremented before returning the next value. transaction_id: 2 @@ -73,8 +73,8 @@ fn read_header(mut file os.File) !Header { header := file.read_raw[Header]() or { return error('unable to read raw header: ${err}') } // Check file version compatibility. - if header.version != vsql.current_version { - return error('need version ${vsql.current_version} but database is ${header.version}') + if header.version != current_version { + return error('need version ${current_version} but database is ${header.version}') } return header diff --git a/vsql/lexer.v b/vsql/lexer.v index fc15be0..97510ca 100644 --- a/vsql/lexer.v +++ b/vsql/lexer.v @@ -6,27 +6,27 @@ module vsql // Except for the eof and the keywords, the other tokens use the names described // in the SQL standard. enum TokenKind { - asterisk // ::= * - colon // ::= : - comma // ::= , - concatenation_operator // ::= || - equals_operator // ::= = - greater_than_operator // ::= > + asterisk // ::= * + colon // ::= : + comma // ::= , + concatenation_operator // ::= || + equals_operator // ::= = + greater_than_operator // ::= > greater_than_or_equals_operator // ::= >= keyword - left_paren // ::= ( - less_than_operator // ::= < + left_paren // ::= ( + less_than_operator // ::= < less_than_or_equals_operator // ::= <= - literal_identifier // foo or "foo" (delimited) - literal_number // 123 - literal_string // 'hello' - minus_sign // ::= - - not_equals_operator // ::= <> - period // ::= . - plus_sign // ::= + - right_paren // ::= ) - semicolon // ::= ; - solidus // ::= / + literal_identifier // foo or "foo" (delimited) + literal_number // 123 + literal_string // 'hello' + minus_sign // ::= - + not_equals_operator // ::= <> + period // ::= . + plus_sign // ::= + + right_paren // ::= ) + semicolon // ::= ; + solidus // ::= / } struct Token { diff --git a/vsql/numeric.v b/vsql/numeric.v index 16ed1c3..dcf8606 100644 --- a/vsql/numeric.v +++ b/vsql/numeric.v @@ -24,15 +24,15 @@ struct Numeric { fn new_numeric(typ Type, numerator big.Integer, denominator big.Integer) Numeric { return Numeric{ - typ: typ - numerator: numerator + typ: typ + numerator: numerator denominator: denominator } } fn new_null_numeric(typ Type) Numeric { return Numeric{ - typ: typ + typ: typ is_null: true } } @@ -110,18 +110,18 @@ fn (n Numeric) bytes() []u8 { mut buf := new_bytes([]u8{}) mut flags := u8(0) if n.is_null { - flags |= vsql.numeric_is_null + flags |= numeric_is_null } if n.is_zero() { - flags |= vsql.numeric_is_zero + flags |= numeric_is_zero } if n.is_negative() { - flags |= vsql.numeric_is_negative + flags |= numeric_is_negative } buf.write_u8(flags) // If the value is NULL or 0 we don't need to encode anything further. - if flags & vsql.numeric_is_null != 0 || flags & vsql.numeric_is_zero != 0 { + if flags & numeric_is_null != 0 || flags & numeric_is_zero != 0 { return buf.bytes() } @@ -140,11 +140,11 @@ fn new_numeric_from_bytes(typ Type, data []u8) Numeric { mut buf := new_bytes(data) flags := buf.read_u8() - if flags & vsql.numeric_is_null != 0 { + if flags & numeric_is_null != 0 { return new_null_numeric(typ) } - if flags & vsql.numeric_is_zero != 0 { + if flags & numeric_is_zero != 0 { return new_numeric(typ, big.zero_int, big.zero_int) } @@ -154,7 +154,7 @@ fn new_numeric_from_bytes(typ Type, data []u8) Numeric { denominator_len := buf.read_i16() denominator := big.integer_from_bytes(buf.read_u8s(denominator_len), big.IntegerConfig{}) - if flags & vsql.numeric_is_negative != 0 { + if flags & numeric_is_negative != 0 { numerator = numerator.neg() } @@ -214,9 +214,9 @@ fn (n Numeric) round(scale i16) Numeric { denominator := n.denominator / big.integer_from_int(10).pow(u32(-(scale - n.denominator.str().len) - 1)) return new_numeric(Type{ - typ: n.typ.typ - size: n.typ.size - scale: scale + typ: n.typ.typ + size: n.typ.size + scale: scale not_null: n.typ.not_null }, numerator, denominator) } diff --git a/vsql/orm.v b/vsql/orm.v new file mode 100644 index 0000000..9a76e54 --- /dev/null +++ b/vsql/orm.v @@ -0,0 +1,371 @@ +module vsql + +import orm +import time + +pub const varchar_default_len = 255 + +// Returns a string of the vsql type based on the v type index +fn vsql_type_from_v(typ int) !string { + return if typ == orm.type_idx['i8'] || typ == orm.type_idx['i16'] || typ == orm.type_idx['u8'] { + 'SMALLINT' + } else if typ == orm.type_idx['bool'] { + 'BOOLEAN' + } else if typ == orm.type_idx['int'] || typ == orm.type_idx['u16'] || typ == 8 { + 'INTEGER' + } else if typ == orm.type_idx['i64'] || typ == orm.type_idx['u32'] { + 'BIGINT' + } else if typ == orm.type_idx['f32'] { + 'REAL' + } else if typ == orm.type_idx['u64'] { + 'BIGINT' + } else if typ == orm.type_idx['f64'] { + 'DOUBLE PRECISION' + } else if typ == orm.type_idx['string'] { + 'VARCHAR(${varchar_default_len})' + } else if typ == orm.time_ { + 'TIMESTAMP(6) WITHOUT TIME ZONE' + } else if typ == -1 { + // -1 is a field with @[sql: serial] + 'INTEGER' + } else { + error('Unknown type ${typ}') + } +} + +// primitive_to_value returns the Value of a Primitive based on the intended +// destination type. Primitives are used by the ORM. +// +// It's important to note that while types may be compatible, they can still be +// out of range, such as assigning an overflowing integer value to SMALLINT. +fn primitive_to_value(typ Type, p orm.Primitive) !Value { + // The match should be exhaustive for typ and p so that we can make sure we + // cover all combinations now and in the future. + match p { + orm.Null { + // In standard SQL, NULL's must be typed. + return new_null_value(typ.typ) + } + bool { + match typ.typ { + .is_boolean { + return new_boolean_value(p) + } + else {} + } + } + f32, f64 { + match typ.typ { + .is_real { + return new_real_value(f32(p)) + } + .is_double_precision { + return new_double_precision_value(f64(p)) + } + else {} + } + } + i16, i8, u8 { + match typ.typ { + .is_smallint { + return new_smallint_value(i16(p)) + } + else {} + } + } + int, u16 { + match typ.typ { + .is_smallint { + return new_smallint_value(i16(p)) + } + .is_integer { + return new_integer_value(int(p)) + } + else {} + } + } + u32, i64 { + match typ.typ { + .is_bigint { + return new_bigint_value(i64(p)) + } + else {} + } + } + u64 { + match typ.typ { + .is_smallint { + return new_smallint_value(i16(p)) + } + .is_bigint { + return new_bigint_value(i64(p)) + } + else {} + } + } + string { + match typ.typ { + .is_varchar { + return new_varchar_value(p) + } + .is_numeric { + return new_numeric_value(p) + } + else {} + } + } + time.Time { + match typ.typ { + .is_timestamp_with_time_zone, .is_timestamp_without_time_zone { + return new_timestamp_value(p.str())! + } + else {} + } + } + orm.InfixType {} + } + + return error('cannot assign ${p} to ${typ}') +} + +fn serial_name(table string) string { + return '${table}_SERIAL' +} + +fn reformat_table_name(table string) string { + mut new_table := table + if is_reserved_word(table) { + new_table = '"${table}"' + } + return new_table +} + +fn get_table_values_map(mut db Connection, table string, data []orm.QueryData) !map[string]Value { + mut mp := map[string]Value{} + mut tbl := Table{} + mut cat := db.catalog() + tables := cat.schema_tables('PUBLIC') or { [] } + + for t in tables { + if t.name.entity_name == table.to_upper() { + tbl = t + break + } + } + if tbl.name.entity_name != table.to_upper() { + return error('Table ${table} not found') + } + mut field_counter := 1 + for d in data { + for i, f in d.fields { + for c in tbl.columns { + if c.name.sub_entity_name == f.to_upper() { + if mp.keys().contains(f) { + field_key := '${f}_${field_counter.str()}' + mp[field_key] = primitive_to_value(c.typ, d.data[i])! + field_counter++ + } else { + mp[f] = primitive_to_value(c.typ, d.data[i])! + } + } + } + } + } + + return mp +} + +// `query_reformatter` converts a statement like `INSERT INTO Product (id, product_name, price) VALUES (:1, :2, :3)` to `INSERT INTO Product (id, product_name, price) VALUES (:id, :product_name, :price)` +fn query_reformatter(query string, query_data []orm.QueryData) string { + mut counter := 1 + mut field_counter := 1 + mut new_query := query + for data in query_data { + for field in data.fields { + // this if check is for if there are multiple of the same field being checked for + if new_query.contains(':${field}') { + new_query = new_query.replace(':${counter}', ':${field}_${field_counter.str()}') + field_counter++ + counter++ + } else { + new_query = new_query.replace(':${counter}', ':${field}') + counter++ + } + } + } + return new_query +} + +fn check_for_not_supported(mut db Connection, table string, fields []orm.TableField) ! { + for field in fields { + if field.typ == orm.enum_ { + return error('enum is not supported in vsql') + } + if is_reserved_word(field.name) { + return error('reserved word ${field.name} cannot be used as a field name at ${table}.${field.name}') + } + for attr in field.attrs { + if attr.name == 'sql' { + if attr.arg == 'serial' { + db.query('CREATE SEQUENCE "${serial_name(table)}"')! + } + if is_reserved_word(attr.arg) { + return error('${attr.arg} is a reserved word in vsql') + } + } + if attr.name == 'default' { + return error('default is not supported in vsql') + } + if attr.name == 'unique' { + return error('unique is not supported in vsql') + } + } + } +} + +// select is used internally by V's ORM for processing `SELECT` queries +pub fn (mut db Connection) select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive { + conf := orm.SelectConfig{ + ...config + table: reformat_table_name(config.table) + } + mut query := orm.orm_select_gen(conf, '', true, ':', 1, where) + query = query_reformatter(query, [data, where]) + mut rows := Result{} + if data.data.len == 0 && where.data.len == 0 { + rows = db.query(query) or { return err } + } else { + values := get_table_values_map(mut db, config.table, [data, where]) or { return err } + mut stmt := db.prepare(query) or { return err } + rows = stmt.query(values) or { return err } + } + + mut ret := [][]orm.Primitive{} + for row in rows { + mut row_primitives := []orm.Primitive{} + keys := row.data.keys() + for _, key in keys { + prim := row.get(key)! + row_primitives << prim.primitive() or { return err } + } + ret << row_primitives + } + + return ret +} + +// insert is used internally by V's ORM for processing `INSERT` queries +pub fn (mut db Connection) insert(table string, data orm.QueryData) ! { + new_table := reformat_table_name(table) + mut tbl := get_table_values_map(mut db, table, [data]) or { return err } + mut query := 'INSERT INTO ${new_table} (${data.fields.join(', ')}) VALUES (:${data.fields.join(', :')})' + // if a table has a serial field, we need to remove it from the insert statement + // only allows one serial field per table, as do most RDBMS + if data.auto_fields.len > 1 { + return error('multiple AUTO fields are not supported') + } else if data.auto_fields.len == 1 { + autofield_idx := data.auto_fields[0] + autofield := data.fields[autofield_idx] + tbl.delete(autofield) + query = query.replace(':${autofield}', 'NEXT VALUE FOR "${serial_name(table)}"') + } + mut stmt := db.prepare(query) or { return err } + stmt.query(tbl) or { return err } +} + +// update is used internally by V's ORM for processing `UPDATE` queries +pub fn (mut db Connection) update(table string, data orm.QueryData, where orm.QueryData) ! { + new_table := reformat_table_name(table) + mut query, _ := orm.orm_stmt_gen(.sqlite, new_table, '', .update, true, ':', 1, data, + where) + values := get_table_values_map(mut db, table, [data, where]) or { return err } + query = query_reformatter(query, [data, where]) + mut stmt := db.prepare(query) or { return err } + stmt.query(values) or { return err } +} + +// delete is used internally by V's ORM for processing `DELETE ` queries +pub fn (mut db Connection) delete(table string, where orm.QueryData) ! { + new_table := reformat_table_name(table) + mut query, _ := orm.orm_stmt_gen(.sqlite, new_table, '', .delete, true, ':', 1, orm.QueryData{}, + where) + query = query_reformatter(query, [where]) + values := get_table_values_map(mut db, table, [where]) or { return err } + mut stmt := db.prepare(query) or { return err } + stmt.query(values) or { return err } +} + +// `last_id` is used internally by V's ORM for post-processing `INSERT` queries +//
    TODO i dont think vsql supports this +pub fn (mut db Connection) last_id() int { + return 0 +} + +// create is used internally by V's ORM for processing table creation queries (DDL) +pub fn (mut db Connection) create(table string, fields []orm.TableField) ! { + check_for_not_supported(mut db, table, fields) or { return err } + new_table := reformat_table_name(table) + mut query := orm.orm_table_gen(new_table, '', true, 0, fields, vsql_type_from_v, false) or { + return err + } + // 'IF NOT EXISTS' is not supported in vsql, so we remove it + query = query.replace(' IF NOT EXISTS ', ' ') + // `TEXT` is not supported in vsql, so we replace it with `VARCHAR(255) if its somehow used` + query = query.replace('TEXT', 'VARCHAR(${varchar_default_len})') + db.query(query) or { return err } +} + +// drop is used internally by V's ORM for processing table destroying queries (DDL) +pub fn (mut db Connection) drop(table string) ! { + new_table := reformat_table_name(table) + mut query := 'DROP TABLE ${new_table};' + db.query(query) or { return err } + + // check to see if there is a SEQUENCE for the table (for the @[sql: 'serial'] attribute) + // if there is, drop it + mut cat := db.catalog() + seqs := cat.sequences('PUBLIC') or { [] } + for sequence in seqs { + if sequence.name.entity_name == serial_name(table).to_upper() { + query = 'DROP SEQUENCE "${serial_name(table)}"' + db.query(query) or { return err } + } + } +} + +// convert a vsql row value to orm.Primitive +fn (v Value) primitive() !orm.Primitive { + if v.is_null { + return orm.Null{} + } + return match v.typ.typ { + .is_boolean { + orm.Primitive(v.bool_value() == .is_true) + } + .is_smallint { + orm.Primitive(i16(v.int_value())) + } + .is_integer { + orm.Primitive(int(v.int_value())) + } + .is_bigint { + orm.Primitive(i64(v.int_value())) + } + .is_varchar, .is_character { + orm.Primitive(v.string_value()) + } + .is_real { + orm.Primitive(f32(v.f64_value())) + } + .is_double_precision { + orm.Primitive(v.f64_value()) + } + .is_decimal, .is_numeric { + orm.Primitive(v.str()) + } + .is_date, .is_time_with_time_zone, .is_timestamp_without_time_zone, + .is_timestamp_with_time_zone, .is_time_without_time_zone { + orm.Primitive(v.str()) + } + } +} diff --git a/vsql/orm_test.v b/vsql/orm_test.v new file mode 100644 index 0000000..aa9e4c9 --- /dev/null +++ b/vsql/orm_test.v @@ -0,0 +1,404 @@ +module vsql + +// Structs intentionally have less than 6 fields, any more then inserts queries get exponentially slower. +// https://github.com/elliotchance/vsql/issues/199 +import time + +@[table: 'testcustomtable'] +struct TestCustomTableAndSerial { + id int @[sql: serial] + an_bool bool +} + +struct TestPrimaryBroken { + id int @[primary; sql: serial] +} + +struct TestDefaultAttribute { + id int @[sql: serial] + name string + created_at string @[default: 'CURRENT_TIMESTAMP(6)'; sql_type: 'TIMESTAMP(3) WITHOUT TIME ZONE'] +} + +struct TestUniqueAttribute { + attribute string @[unique] +} + +struct TestReservedWordField { + where string +} + +struct TestReservedWordSqlAttribute { + ok string @[sql: 'ORDER'] +} + +struct TestOrmValuesOne { + an_f32 f32 // REAL + an_f64 f64 // DOUBLE PRECISION + an_i16 i16 // SMALLINT + an_i64 i64 // BIGINT +} + +struct TestOrmValuesTwo { + an_i8 i8 // SMALLINT + an_int int // INTEGER + a_string string // CHARACTER VARYING(255) / VARCHAR(255) +} + +struct TestOrmValuesThree { + an_u16 u16 // INTEGER + an_u32 u32 // BIGINT + an_u64 u64 // BIGINT + an_u8 u8 // SMALLINT +} + +struct TestOrmValuesFour { + a_time time.Time // TIMESTAMP(6) WITH TIME ZONE + a_bool bool // BOOLEAN + int_or_null ?int // optional INTEGER +} + +// ORMTableEnum is not supported. +struct ORMTableEnum { + an_enum Colors +} + +enum Colors { + red + green + blue +} + +@[table: 'GROUP'] +struct ORMTable2 { + dummy int +} + +struct Product { + id int + product_name string + price string @[sql_type: 'NUMERIC(5,2)'] + quantity ?i16 +} + +fn test_orm_create_table_with_reserved_word() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table ORMTable2 + } or { error = err.str() } + assert error == '' + dumm := ORMTable2{ + dummy: 1 + } + sql db { + insert dumm into ORMTable2 + } or { error = err.str() } + assert error == '' + + sql db { + update ORMTable2 set dummy = 2 where dummy == 1 + }! + + all := sql db { + select from ORMTable2 + }! + assert all[0].dummy == 2 + + sql db { + delete from ORMTable2 where dummy == 2 + } or { error = err.str() } + assert error == '' + sql db { + drop table ORMTable2 + } or { error = err.str() } + + assert error == '' +} + +fn test_custom_table_name_and_serial_crud() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table TestCustomTableAndSerial + } or { error = err.str() } + assert error == '' + + test_custom_sql := TestCustomTableAndSerial{ + an_bool: true + } + test_custom_sql2 := TestCustomTableAndSerial{ + an_bool: false + } + + sql db { + insert test_custom_sql into TestCustomTableAndSerial + insert test_custom_sql2 into TestCustomTableAndSerial + } or { error = err.str() } + + assert error == '' + mut all := sql db { + select from TestCustomTableAndSerial + }! + assert all[0].id != 0 + + sql db { + update TestCustomTableAndSerial set an_bool = false where id == all[0].id + } or { error = err.str() } + assert error == '' + + sql db { + delete from TestCustomTableAndSerial where id == all[1].id + } or { error = err.str() } + assert error == '' + + all = sql db { + select from TestCustomTableAndSerial + }! + assert all.len == 1 + assert all[0].an_bool == false + + sql db { + drop table TestCustomTableAndSerial + } or { error = err.str() } + + assert error == '' +} + +fn test_reserved_words() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table TestReservedWordField + } or { error = err.str() } + assert error == 'reserved word where cannot be used as a field name at TestReservedWordField.where' + sql db { + create table TestReservedWordSqlAttribute + } or { error = err.str() } + assert error == 'ORDER is a reserved word in vsql' +} + +fn test_unsupported_attributes() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table TestDefaultAttribute + } or { error = err.str() } + assert error == 'default is not supported in vsql' + sql db { + create table TestUniqueAttribute + } or { error = err.str() } + assert error == 'unique is not supported in vsql' +} + +fn test_default_orm_values() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table TestOrmValuesOne + create table TestOrmValuesTwo + create table TestOrmValuesThree + create table TestOrmValuesFour + } or { error = err.str() } + assert error == '' + + values_one := TestOrmValuesOne{ + an_f32: 3.14 + an_f64: 2.718281828459 + an_i16: 12345 + an_i64: 123456789012345 + } + values_two := TestOrmValuesTwo{ + an_i8: 12 + an_int: 123456 + a_string: 'Hello, World!' + } + values_three := TestOrmValuesThree{ + an_u16: 54321 + an_u32: 1234567890 + an_u64: 1234 + an_u8: 255 + } + + values_four := TestOrmValuesFour{ + a_time: time.now() + a_bool: true + // int_or_null: 123 + } + values_four_b := TestOrmValuesFour{ + a_time: time.now() + a_bool: false + int_or_null: 123 + } + + sql db { + insert values_one into TestOrmValuesOne + insert values_two into TestOrmValuesTwo + insert values_three into TestOrmValuesThree + insert values_four into TestOrmValuesFour + insert values_four_b into TestOrmValuesFour + } or { error = err.str() } + assert error == '' + + result_values_one := sql db { + select from TestOrmValuesOne + }! + one := result_values_one[0] + + assert typeof(one.an_f32).idx == typeof[f32]().idx + assert one.an_f32 == 3.14 + assert typeof(one.an_f64).idx == typeof[f64]().idx + assert one.an_f64 == 2.718281828459 + assert typeof(one.an_i16).idx == typeof[i16]().idx + assert one.an_i16 == 12345 + assert typeof(one.an_i64).idx == typeof[i64]().idx + assert one.an_i64 == 123456789012345 + + result_values_two := sql db { + select from TestOrmValuesTwo + }! + + two := result_values_two[0] + + assert typeof(two.an_i8).idx == typeof[i8]().idx + assert two.an_i8 == 12 + assert typeof(two.an_int).idx == typeof[int]().idx + assert two.an_int == 123456 + assert typeof(two.a_string).idx == typeof[string]().idx + assert two.a_string == 'Hello, World!' + + result_values_three := sql db { + select from TestOrmValuesThree + }! + + three := result_values_three[0] + + assert typeof(three.an_u16).idx == typeof[u16]().idx + assert three.an_u16 == 54321 + assert typeof(three.an_u32).idx == typeof[u32]().idx + assert three.an_u32 == 1234567890 + assert typeof(three.an_u64).idx == typeof[u64]().idx + assert three.an_u64 == 1234 + assert typeof(three.an_u8).idx == typeof[u8]().idx + assert three.an_u8 == 255 + + result_values_four := sql db { + select from TestOrmValuesFour + }! + + four := result_values_four[0] + + assert typeof(four.a_time).idx == typeof[time.Time]().idx + assert typeof(four.a_bool).idx == typeof[bool]().idx + assert four.a_bool == true + assert typeof(four.int_or_null).idx == typeof[?int]().idx + unwrapped_option_one := four.int_or_null or { 0 } + assert unwrapped_option_one == 0 + unwrapped_option_two := result_values_four[1].int_or_null or { 0 } + assert unwrapped_option_two == 123 +} + +fn test_orm_create_enum_is_not_supported() { + mut db := open(':memory:')! + mut error := '' + sql db { + create table ORMTableEnum + } or { error = err.str() } + assert error == 'enum is not supported in vsql' +} + +fn test_orm_select_where() { + mut db := open(':memory:')! + mut error := '' + + sql db { + create table Product + } or { panic(err) } + + prods := [ + Product{1, 'Ice Cream', '5.99', 17}, + Product{2, 'Ham Sandwhich', '3.47', none}, + Product{3, 'Bagel', '1.25', 45}, + ] + for product in prods { + sql db { + insert product into Product + } or { panic(err) } + } + mut products := sql db { + select from Product where id == 2 + }! + + assert products == [Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where id == 5 + }! + + assert products == [] + + products = sql db { + select from Product where id != 3 + }! + + assert products == [Product{1, 'Ice Cream', '5.99', 17}, + Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where price > '3.47' + }! + + assert products == [Product{1, 'Ice Cream', '5.99', 17}] + + products = sql db { + select from Product where price >= '3' + }! + + assert products == [Product{1, 'Ice Cream', '5.99', 17}, + Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where price < '3.47' + }! + + assert products == [Product{3, 'Bagel', '1.25', 45}] + + products = sql db { + select from Product where price <= '5' + }! + + assert products == [Product{2, 'Ham Sandwhich', '3.47', none}, + Product{3, 'Bagel', '1.25', 45}] + + // TODO (daniel-le97): The ORM does not support a "not like" constraint right now. + + products = sql db { + select from Product where product_name like 'Ham%' + }! + + assert products == [Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where quantity is none + }! + + assert products == [Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where quantity !is none + }! + + assert products == [Product{1, 'Ice Cream', '5.99', 17}, Product{3, 'Bagel', '1.25', 45}] + + products = sql db { + select from Product where price > '3' && price < '3.50' + }! + + assert products == [Product{2, 'Ham Sandwhich', '3.47', none}] + + products = sql db { + select from Product where price < '2.000' || price >= '5' + }! + + assert products == [Product{1, 'Ice Cream', '5.99', 17}, Product{3, 'Bagel', '1.25', 45}] +} diff --git a/vsql/page.v b/vsql/page.v index 4de7bfd..e10da57 100644 --- a/vsql/page.v +++ b/vsql/page.v @@ -80,7 +80,7 @@ fn new_reference_object(key []u8, tid int, xid int, blob_peices int, has_fragmen } fn (o PageObject) length() int { - return vsql.page_object_prefix_length + o.key.len + o.value.len + return page_object_prefix_length + o.key.len + o.value.len } // blob_info only applies to blob objects. @@ -113,7 +113,7 @@ fn parse_page_object(data []u8) (int, PageObject) { key_len := buf.read_i16() key := buf.read_u8s(key_len) is_blob_ref := buf.read_bool() - value := buf.read_u8s(total_len - vsql.page_object_prefix_length - key_len) + value := buf.read_u8s(total_len - page_object_prefix_length - key_len) return total_len, PageObject{key, value, is_blob_ref, tid, xid} } @@ -132,17 +132,17 @@ mut: fn new_page(kind u8, page_size int) &Page { return &Page{ kind: kind - used: vsql.page_header_size // includes kind and self - data: []u8{len: page_size - vsql.page_header_size} + used: page_header_size // includes kind and self + data: []u8{len: page_size - page_header_size} } } fn (p Page) is_empty() bool { - return p.used == vsql.page_header_size + return p.used == page_header_size } fn (p Page) page_size() int { - return p.data.len + vsql.page_header_size + return p.data.len + page_header_size } // TODO(elliotchance): This really isn't the most efficient way to do this. Make @@ -307,7 +307,7 @@ fn (p Page) objects() []PageObject { mut objects := []PageObject{} mut n := 0 - for n < p.used - vsql.page_header_size { + for n < p.used - page_header_size { // Be careful to clone the size as the underlying data might get moved // around. m, object := parse_page_object(p.data[n..].clone()) diff --git a/vsql/pager.v b/vsql/pager.v index 3f875ba..1637eda 100644 --- a/vsql/pager.v +++ b/vsql/pager.v @@ -85,7 +85,7 @@ fn new_file_pager(mut file os.File, page_size int, root_page int) !&FilePager { file_len := file.tell() or { return error('unable to get file length: ${err}') } return &FilePager{ - file: file + file: file page_size: page_size root_page: root_page // The first page is reserved for header information. We do not include diff --git a/vsql/planner.v b/vsql/planner.v index e11b125..0fc23ac 100644 --- a/vsql/planner.v +++ b/vsql/planner.v @@ -162,7 +162,7 @@ fn create_select_plan_without_join(body QuerySpecification, from_clause TablePri mut subplan_columns := []Column{} for col in subplan.columns() { subplan_columns << Column{Identifier{ - entity_name: table_name.id() + entity_name: table_name.id() sub_entity_name: col.name.sub_entity_name }, col.typ, col.not_null} } @@ -170,7 +170,7 @@ fn create_select_plan_without_join(body QuerySpecification, from_clause TablePri // NOTE: This has to be assigned to a variable otherwise the value // is lost. This must be a bug in V. table = Table{ - name: table_name + name: table_name columns: subplan_columns } @@ -209,7 +209,7 @@ fn add_group_by_plan(mut plan Plan, group_clause []Identifier, select_exprs []De // expressions contain an aggregate function we need to have an implicit // GROUP BY for the whole set. mut c := Compiler{ - conn: conn + conn: conn params: params tables: tables } @@ -228,7 +228,7 @@ fn add_group_by_plan(mut plan Plan, group_clause []Identifier, select_exprs []De mut order := []SortSpecification{} for col in group_clause { order << SortSpecification{ - expr: ValueExpression(BooleanValueExpression{ + expr: ValueExpression(BooleanValueExpression{ term: BooleanTerm{ factor: BooleanTest{ expr: BooleanPrimary(BooleanPredicand(NonparenthesizedValueExpressionPrimary(col))) @@ -250,9 +250,9 @@ fn add_group_by_plan(mut plan Plan, group_clause []Identifier, select_exprs []De fn create_delete_plan(stmt DeleteStatementSearched, params map[string]Value, mut conn Connection) !Plan { select_stmt := QuerySpecification{ - exprs: AsteriskExpr(true) + exprs: AsteriskExpr(true) table_expression: TableExpression{ - from_clause: TablePrimary{ + from_clause: TablePrimary{ body: stmt.table_name } where_clause: stmt.where @@ -266,9 +266,9 @@ fn create_delete_plan(stmt DeleteStatementSearched, params map[string]Value, mut fn create_update_plan(stmt UpdateStatementSearched, params map[string]Value, mut conn Connection) !Plan { select_stmt := QuerySpecification{ - exprs: AsteriskExpr(true) + exprs: AsteriskExpr(true) table_expression: TableExpression{ - from_clause: TablePrimary{ + from_clause: TablePrimary{ body: stmt.table_name } where_clause: stmt.where @@ -288,7 +288,7 @@ fn create_query_expression_plan(stmt QueryExpression, params map[string]Value, m mut order := []SortSpecification{} for spec in stmt.order { order << SortSpecification{ - expr: spec.expr + expr: spec.expr is_asc: spec.is_asc } } @@ -427,7 +427,7 @@ fn new_expr_operation(mut conn Connection, params map[string]Value, select_list sub_entity_name: column_name } mut c := Compiler{ - conn: conn + conn: conn params: params tables: tables } @@ -452,7 +452,7 @@ fn (o ExprOperation) columns() Columns { fn (mut o ExprOperation) execute(rows []Row) ![]Row { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params tables: o.tables } diff --git a/vsql/result.v b/vsql/result.v index 323db15..460ad08 100644 --- a/vsql/result.v +++ b/vsql/result.v @@ -25,10 +25,10 @@ mut: pub fn new_result(columns Columns, rows []Row, elapsed_parse time.Duration, elapsed_exec time.Duration) Result { return Result{ - columns: columns - rows: rows + columns: columns + rows: rows elapsed_parse: elapsed_parse - elapsed_exec: elapsed_exec + elapsed_exec: elapsed_exec } } diff --git a/vsql/server.v b/vsql/server.v index c1b75a9..691733a 100644 --- a/vsql/server.v +++ b/vsql/server.v @@ -29,14 +29,14 @@ pub fn new_server(options ServerOptions) Server { catalog := &CatalogConnection{ catalog_name: catalog_name - storage: new_storage(btree) - options: default_connection_options() + storage: new_storage(btree) + options: default_connection_options() } return Server{options, &Connection{ query_cache: new_query_cache() - now: default_now - catalogs: { + now: default_now + catalogs: { catalog_name: catalog } }} diff --git a/vsql/sql_test.v b/vsql/sql_test.v index 415ca1e..aa4d539 100644 --- a/vsql/sql_test.v +++ b/vsql/sql_test.v @@ -177,12 +177,12 @@ fn run_single_test(test SQLTest, query_cache &QueryCache, verbose bool, filter_l mut db := open_database(':memory:', options)! db.now = fn () (time.Time, i16) { return time.new(time.Time{ - year: 2022 - month: 7 - day: 4 - hour: 14 - minute: 5 - second: 3 + year: 2022 + month: 7 + day: 4 + hour: 14 + minute: 5 + second: 3 nanosecond: 120056000 }), 300 } diff --git a/vsql/std_aggregate_function.v b/vsql/std_aggregate_function.v index 9dcff17..9a3a531 100644 --- a/vsql/std_aggregate_function.v +++ b/vsql/std_aggregate_function.v @@ -39,15 +39,15 @@ fn (e AggregateFunction) compile(mut c Compiler) !CompileResult { match e { AggregateFunctionCount { compiled := Identifier{ - custom_id: 'COUNT(*)' + custom_id: 'COUNT(*)' custom_typ: new_type('INTEGER', 0, 0) }.compile(mut c)! return CompileResult{ - run: fn [compiled] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled] (mut conn Connection, data Row, params map[string]Value) !Value { return compiled.run(mut conn, data, params)! } - typ: new_type('INTEGER', 0, 0) + typ: new_type('INTEGER', 0, 0) contains_agg: true } } diff --git a/vsql/std_alter_sequence_generator_statement.v b/vsql/std_alter_sequence_generator_statement.v index a63316d..2c577b4 100644 --- a/vsql/std_alter_sequence_generator_statement.v +++ b/vsql/std_alter_sequence_generator_statement.v @@ -39,7 +39,7 @@ struct AlterSequenceGeneratorStatement { fn parse_alter_sequence_generator_statement(generator_name Identifier, options []SequenceGeneratorOption) !AlterSequenceGeneratorStatement { return AlterSequenceGeneratorStatement{ - name: generator_name + name: generator_name options: options } } @@ -79,7 +79,7 @@ fn (stmt AlterSequenceGeneratorStatement) execute(mut conn Connection, params ma old_sequence := catalog.storage.sequence(name)! mut sequence := old_sequence.copy() mut c := Compiler{ - conn: conn + conn: conn params: params } diff --git a/vsql/std_between_predicate.v b/vsql/std_between_predicate.v index 26c9e87..bee8900 100644 --- a/vsql/std_between_predicate.v +++ b/vsql/std_between_predicate.v @@ -53,7 +53,7 @@ fn (e BetweenPredicate) compile(mut c Compiler) !CompileResult { compiled_right := e.right.compile(mut c)! return CompileResult{ - run: fn [e, compiled_expr, compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_expr, compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { expr := compiled_expr.run(mut conn, data, params)! mut left := compiled_left.run(mut conn, data, params)! mut right := compiled_right.run(mut conn, data, params)! @@ -80,7 +80,7 @@ fn (e BetweenPredicate) compile(mut c Compiler) !CompileResult { return new_boolean_value(result) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_expr.contains_agg || compiled_left.contains_agg || compiled_left.contains_agg } @@ -88,11 +88,11 @@ fn (e BetweenPredicate) compile(mut c Compiler) !CompileResult { fn parse_between(expr RowValueConstructorPredicand, between BetweenPredicate) !BetweenPredicate { return BetweenPredicate{ - not: between.not + not: between.not symmetric: between.symmetric - expr: expr - left: between.left - right: between.right + expr: expr + left: between.left + right: between.right } } @@ -103,9 +103,9 @@ fn parse_between_1(is_true bool, left RowValueConstructorPredicand, right RowVal fn parse_between_2(is_true bool, symmetric bool, left RowValueConstructorPredicand, right RowValueConstructorPredicand) !BetweenPredicate { return BetweenPredicate{ - not: !is_true + not: !is_true symmetric: symmetric - left: left - right: right + left: left + right: right } } diff --git a/vsql/std_boolean_value_expression.v b/vsql/std_boolean_value_expression.v index b36ffd1..d93f650 100644 --- a/vsql/std_boolean_value_expression.v +++ b/vsql/std_boolean_value_expression.v @@ -96,7 +96,7 @@ fn (e BooleanValueExpression) compile(mut c Compiler) !CompileResult { compiled_b := e.term.compile(mut c)! return CompileResult{ - run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { a := compiled_a.run(mut conn, data, params)! b := compiled_b.run(mut conn, data, params)! @@ -117,7 +117,7 @@ fn (e BooleanValueExpression) compile(mut c Compiler) !CompileResult { return b } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_a.contains_agg || compiled_b.contains_agg } } @@ -144,7 +144,7 @@ fn (e BooleanTerm) compile(mut c Compiler) !CompileResult { compiled_b := e.factor.compile(mut c)! return CompileResult{ - run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { a := compiled_a.run(mut conn, data, params)! b := compiled_b.run(mut conn, data, params)! @@ -165,7 +165,7 @@ fn (e BooleanTerm) compile(mut c Compiler) !CompileResult { return new_boolean_value(false) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_a.contains_agg || compiled_b.contains_agg } } @@ -216,7 +216,7 @@ fn (e BooleanTest) compile(mut c Compiler) !CompileResult { if v := e.value { return CompileResult{ - run: fn [e, v, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, v, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { // See ISO/IEC 9075-2:2016(E), 6.39, , // "Table 15 — Truth table for the IS boolean operator" @@ -240,16 +240,16 @@ fn (e BooleanTest) compile(mut c Compiler) !CompileResult { return e.unary_not(result)! } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled.contains_agg } } return CompileResult{ - run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { return e.unary_not(compiled.run(mut conn, data, params)!)! } - typ: compiled.typ + typ: compiled.typ contains_agg: compiled.contains_agg } } diff --git a/vsql/std_case_expression.v b/vsql/std_case_expression.v index 6ad7f86..577384e 100644 --- a/vsql/std_case_expression.v +++ b/vsql/std_case_expression.v @@ -42,7 +42,7 @@ fn (e CaseExpression) compile(mut c Compiler) !CompileResult { compiled_b := e.b.compile(mut c)! return CompileResult{ - run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled_a, compiled_b] (mut conn Connection, data Row, params map[string]Value) !Value { a := compiled_a.run(mut conn, data, params)! b := compiled_b.run(mut conn, data, params)! @@ -57,7 +57,7 @@ fn (e CaseExpression) compile(mut c Compiler) !CompileResult { return a } - typ: compiled_a.typ + typ: compiled_a.typ contains_agg: compiled_a.contains_agg || compiled_b.contains_agg } } @@ -70,7 +70,7 @@ fn (e CaseExpression) compile(mut c Compiler) !CompileResult { } return CompileResult{ - run: fn [compiled_exprs] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled_exprs] (mut conn Connection, data Row, params map[string]Value) !Value { mut typ := SQLType.is_varchar mut first := true for i, compiled_expr in compiled_exprs { @@ -96,7 +96,7 @@ fn (e CaseExpression) compile(mut c Compiler) !CompileResult { return new_null_value(value.typ.typ) } - typ: compiled_exprs[0].typ + typ: compiled_exprs[0].typ contains_agg: contains_agg } } diff --git a/vsql/std_cast_specification.v b/vsql/std_cast_specification.v index e4f9443..3e18239 100644 --- a/vsql/std_cast_specification.v +++ b/vsql/std_cast_specification.v @@ -49,12 +49,12 @@ fn (e CastSpecification) compile(mut c Compiler) !CompileResult { compiled_expr := e.expr.compile(mut c)! return CompileResult{ - run: fn [e, compiled_expr] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_expr] (mut conn Connection, data Row, params map[string]Value) !Value { value := compiled_expr.run(mut conn, data, params)! return cast(mut conn, 'for CAST', value, e.target)! } - typ: e.target + typ: e.target contains_agg: compiled_expr.contains_agg } } diff --git a/vsql/std_comparison_predicate.v b/vsql/std_comparison_predicate.v index 4143719..a199073 100644 --- a/vsql/std_comparison_predicate.v +++ b/vsql/std_comparison_predicate.v @@ -39,7 +39,7 @@ fn (e ComparisonPredicate) compile(mut c Compiler) !CompileResult { compiled_right := e.right.compile(mut c)! return CompileResult{ - run: fn [e, compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { mut left := compiled_left.run(mut conn, data, params)! mut right := compiled_right.run(mut conn, data, params)! @@ -73,7 +73,7 @@ fn (e ComparisonPredicate) compile(mut c Compiler) !CompileResult { } }) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_left.contains_agg || compiled_right.contains_agg } } diff --git a/vsql/std_contextually_typed_value_specification.v b/vsql/std_contextually_typed_value_specification.v index dbd96aa..dbce09e 100644 --- a/vsql/std_contextually_typed_value_specification.v +++ b/vsql/std_contextually_typed_value_specification.v @@ -31,10 +31,10 @@ fn (e NullSpecification) pstr(params map[string]Value) string { fn (e NullSpecification) compile(mut c Compiler) !CompileResult { if null_type := c.null_type { return CompileResult{ - run: fn [null_type] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [null_type] (mut conn Connection, data Row, params map[string]Value) !Value { return new_null_value(null_type.typ) } - typ: null_type + typ: null_type contains_agg: false } } diff --git a/vsql/std_datetime_value_function.v b/vsql/std_datetime_value_function.v index e3c656a..23b8278 100644 --- a/vsql/std_datetime_value_function.v +++ b/vsql/std_datetime_value_function.v @@ -58,10 +58,10 @@ fn (e DatetimeValueFunction) compile(mut c Compiler) !CompileResult { now, _ := c.conn.now() return CompileResult{ - run: fn [now] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [now] (mut conn Connection, data Row, params map[string]Value) !Value { return new_date_value(now.strftime('%Y-%m-%d'))! } - typ: new_type('DATE', 0, 0) + typ: new_type('DATE', 0, 0) contains_agg: false } } @@ -75,10 +75,10 @@ fn (e DatetimeValueFunction) compile(mut c Compiler) !CompileResult { e2 := e return CompileResult{ - run: fn [e2] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e2] (mut conn Connection, data Row, params map[string]Value) !Value { return new_time_value(time_value(conn, e2.prec, true))! } - typ: new_type('TIME WITH TIME ZONE', 0, 0) + typ: new_type('TIME WITH TIME ZONE', 0, 0) contains_agg: false } } @@ -94,11 +94,11 @@ fn (e DatetimeValueFunction) compile(mut c Compiler) !CompileResult { e2 := e return CompileResult{ - run: fn [e2, now] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e2, now] (mut conn Connection, data Row, params map[string]Value) !Value { return new_timestamp_value(now.strftime('%Y-%m-%d ') + time_value(conn, e2.prec, true))! } - typ: new_type('TIMESTAMP WITH TIME ZONE', 0, 0) + typ: new_type('TIMESTAMP WITH TIME ZONE', 0, 0) contains_agg: false } } @@ -112,10 +112,10 @@ fn (e DatetimeValueFunction) compile(mut c Compiler) !CompileResult { e2 := e return CompileResult{ - run: fn [e2] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e2] (mut conn Connection, data Row, params map[string]Value) !Value { return new_time_value(time_value(conn, e2.prec, false))! } - typ: new_type('TIME WITHOUT TIME ZONE', 0, 0) + typ: new_type('TIME WITHOUT TIME ZONE', 0, 0) contains_agg: false } } @@ -131,11 +131,11 @@ fn (e DatetimeValueFunction) compile(mut c Compiler) !CompileResult { e2 := e return CompileResult{ - run: fn [e2, now] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e2, now] (mut conn Connection, data Row, params map[string]Value) !Value { return new_timestamp_value(now.strftime('%Y-%m-%d ') + time_value(conn, e2.prec, false))! } - typ: new_type('TIMESTAMP WITHOUT TIME ZONE', 0, 0) + typ: new_type('TIMESTAMP WITHOUT TIME ZONE', 0, 0) contains_agg: false } } diff --git a/vsql/std_group_by_clause.v b/vsql/std_group_by_clause.v index 9164022..8ab1b6c 100644 --- a/vsql/std_group_by_clause.v +++ b/vsql/std_group_by_clause.v @@ -72,14 +72,14 @@ fn new_group_operation(select_exprs []DerivedColumn, group_exprs []Identifier, p } mut c := Compiler{ - conn: conn + conn: conn params: params } for expr in select_exprs { compiled_expr := expr.expr.compile(mut c)! if compiled_expr.contains_agg { columns << Column{Identifier{ - custom_id: expr.expr.pstr(params) + custom_id: expr.expr.pstr(params) custom_typ: compiled_expr.typ }, compiled_expr.typ, false} @@ -115,7 +115,7 @@ fn (o &GroupOperation) columns() Columns { fn (mut o GroupOperation) execute(rows []Row) ![]Row { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params } diff --git a/vsql/std_insert_statement.v b/vsql/std_insert_statement.v index a91163a..a238cc0 100644 --- a/vsql/std_insert_statement.v +++ b/vsql/std_insert_statement.v @@ -41,7 +41,7 @@ fn parse_insert_statement(insertion_target Identifier, stmt InsertStatement) !St fn parse_from_constructor(columns []Identifier, values []ContextuallyTypedRowValueConstructor) !InsertStatement { return InsertStatement{ columns: columns - values: values + values: values } } @@ -96,8 +96,8 @@ fn (stmt InsertStatement) execute(mut conn Connection, params map[string]Value, table_column := table.column(column_name)! mut c := Compiler{ - conn: conn - params: params + conn: conn + params: params null_type: table_column.typ } raw_value := values[i].compile(mut c)!.run(mut conn, Row{}, params)! diff --git a/vsql/std_like_predicate.v b/vsql/std_like_predicate.v index d22b97c..33c8ee1 100644 --- a/vsql/std_like_predicate.v +++ b/vsql/std_like_predicate.v @@ -49,7 +49,7 @@ fn (e CharacterLikePredicate) compile(mut c Compiler) !CompileResult { compiled_l := l.compile(mut c)! return CompileResult{ - run: fn [e, compiled_l, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_l, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { left := compiled_l.run(mut conn, data, params)! right := compiled_right.run(mut conn, data, params)! @@ -70,7 +70,7 @@ fn (e CharacterLikePredicate) compile(mut c Compiler) !CompileResult { return new_boolean_value(result) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_right.contains_agg || compiled_l.contains_agg } } diff --git a/vsql/std_names_and_identifiers.v b/vsql/std_names_and_identifiers.v index 9ec7f3b..10174c9 100644 --- a/vsql/std_names_and_identifiers.v +++ b/vsql/std_names_and_identifiers.v @@ -138,7 +138,7 @@ fn new_identifier1(s string) !Identifier { 2 { return Identifier{ catalog_name: parts[0] - schema_name: parts[1] + schema_name: parts[1] } } else { @@ -165,8 +165,8 @@ fn new_identifier2(s string) !Identifier { 3 { return Identifier{ catalog_name: parts[0] - schema_name: parts[1] - entity_name: parts[2] + schema_name: parts[1] + entity_name: parts[2] } } else { @@ -209,22 +209,22 @@ fn new_identifier3(s string) !Identifier { } 2 { return Identifier{ - entity_name: parts[0] + entity_name: parts[0] sub_entity_name: parts[1] } } 3 { return Identifier{ - schema_name: parts[0] - entity_name: parts[1] + schema_name: parts[0] + entity_name: parts[1] sub_entity_name: parts[2] } } 4 { return Identifier{ - catalog_name: parts[0] - schema_name: parts[1] - entity_name: parts[2] + catalog_name: parts[0] + schema_name: parts[1] + entity_name: parts[2] sub_entity_name: parts[3] } } @@ -289,10 +289,10 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { // removed in the future. if e.custom_id != '' { return CompileResult{ - run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[e.id()] or { return sqlstate_42601('unknown column: ${e}') } } - typ: e.custom_typ + typ: e.custom_typ contains_agg: false } } @@ -302,10 +302,10 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { column := table.column(e.sub_entity_name) or { Column{} } if column.name.sub_entity_name == e.sub_entity_name { return CompileResult{ - run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[e.id()] or { return sqlstate_42601('unknown column: ${e}') } } - typ: column.typ + typ: column.typ contains_agg: false } } @@ -313,13 +313,21 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { // 3. Try to use the context. mut ident := c.conn.resolve_identifier(Identifier{ - catalog_name: if c.context.catalog_name != '' { + catalog_name: if c.context.catalog_name != '' { c.context.catalog_name } else { e.catalog_name } - schema_name: if c.context.schema_name != '' { c.context.schema_name } else { e.schema_name } - entity_name: if c.context.entity_name != '' { c.context.entity_name } else { e.entity_name } + schema_name: if c.context.schema_name != '' { + c.context.schema_name + } else { + e.schema_name + } + entity_name: if c.context.entity_name != '' { + c.context.entity_name + } else { + e.entity_name + } sub_entity_name: e.sub_entity_name }) mut catalog := c.conn.catalogs[ident.catalog_name] or { @@ -331,12 +339,12 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { column := table.column(ident.sub_entity_name) or { Column{} } if column.name.sub_entity_name == ident.sub_entity_name { return CompileResult{ - run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[ident.id()] or { return sqlstate_42601('unknown column: ${ident}') } } - typ: column.typ + typ: column.typ contains_agg: false } } @@ -351,12 +359,12 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { ident = column.name return CompileResult{ - run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[ident.id()] or { return sqlstate_42601('unknown column: ${ident}') } } - typ: column.typ + typ: column.typ contains_agg: false } } @@ -370,12 +378,12 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { column := table.column(ident.sub_entity_name) or { Column{} } if column.name.sub_entity_name == ident.sub_entity_name { return CompileResult{ - run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[ident.id()] or { return sqlstate_42601('unknown column: ${ident}') } } - typ: column.typ + typ: column.typ contains_agg: false } } @@ -393,12 +401,12 @@ fn (e Identifier) compile(mut c Compiler) !CompileResult { ident = column.name return CompileResult{ - run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [ident] (mut conn Connection, data Row, params map[string]Value) !Value { return data.data[ident.id()] or { return sqlstate_42601('unknown column: ${ident}') } } - typ: column.typ + typ: column.typ contains_agg: false } } @@ -513,10 +521,10 @@ fn (e HostParameterName) compile(mut c Compiler) !CompileResult { p := c.params[e.name] or { return sqlstate_42p02(e.name) } return CompileResult{ - run: fn [p] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [p] (mut conn Connection, data Row, params map[string]Value) !Value { return p } - typ: p.typ + typ: p.typ contains_agg: false } } diff --git a/vsql/std_next_value_expression.v b/vsql/std_next_value_expression.v index 9c8384e..50171f5 100644 --- a/vsql/std_next_value_expression.v +++ b/vsql/std_next_value_expression.v @@ -25,12 +25,12 @@ fn (e NextValueExpression) compile(mut c Compiler) !CompileResult { name := c.conn.resolve_identifier(e.name) return CompileResult{ - run: fn [name, mut catalog] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [name, mut catalog] (mut conn Connection, data Row, params map[string]Value) !Value { next := catalog.storage.sequence_next_value(name)! return new_bigint_value(next) } - typ: new_type('INTEGER', 0, 0) + typ: new_type('INTEGER', 0, 0) contains_agg: false } } diff --git a/vsql/std_null_predicate.v b/vsql/std_null_predicate.v index e80cba1..b645545 100644 --- a/vsql/std_null_predicate.v +++ b/vsql/std_null_predicate.v @@ -33,7 +33,7 @@ fn (e NullPredicate) compile(mut c Compiler) !CompileResult { compiled := e.expr.compile(mut c)! return CompileResult{ - run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { value := compiled.run(mut conn, data, params)! if e.not { @@ -42,7 +42,7 @@ fn (e NullPredicate) compile(mut c Compiler) !CompileResult { return new_boolean_value(value.is_null) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled.contains_agg } } diff --git a/vsql/std_numeric_value_expression.v b/vsql/std_numeric_value_expression.v index 80cd83a..05d8fdb 100644 --- a/vsql/std_numeric_value_expression.v +++ b/vsql/std_numeric_value_expression.v @@ -56,7 +56,7 @@ fn (e NumericValueExpression) compile(mut c Compiler) !CompileResult { // TODO(elliotchance): This is not correct, we would have to return // the highest resolution type (need to check the SQL standard about // this behavior). - typ: compiled_n.typ + typ: compiled_n.typ contains_agg: compiled_term.contains_agg || compiled_n.contains_agg } } @@ -85,13 +85,13 @@ fn (e Term) compile(mut c Compiler) !CompileResult { compiled_term := term.compile(mut c)! return CompileResult{ - run: fn [e, compiled_term, compiled_factor] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_term, compiled_factor] (mut conn Connection, data Row, params map[string]Value) !Value { mut left := compiled_term.run(mut conn, data, params)! mut right := compiled_factor.run(mut conn, data, params)! return eval_binary(mut conn, data, left, e.op, right, params)! } - typ: compiled_term.typ + typ: compiled_term.typ contains_agg: compiled_factor.contains_agg || compiled_term.contains_agg } } @@ -112,7 +112,7 @@ fn (e SignedValueExpressionPrimary) compile(mut c Compiler) !CompileResult { compiled := e.e.compile(mut c)! return CompileResult{ - run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled] (mut conn Connection, data Row, params map[string]Value) !Value { value := compiled.run(mut conn, data, params)! key := '${e.sign} ${value.typ.typ}' @@ -123,7 +123,7 @@ fn (e SignedValueExpressionPrimary) compile(mut c Compiler) !CompileResult { return sqlstate_42883('operator does not exist: ${key}') } - typ: compiled.typ + typ: compiled.typ contains_agg: compiled.contains_agg } } diff --git a/vsql/std_query_expression.v b/vsql/std_query_expression.v index 4034d1e..cef2b84 100644 --- a/vsql/std_query_expression.v +++ b/vsql/std_query_expression.v @@ -87,36 +87,36 @@ fn parse_query_expression(body SimpleTable) !QueryExpression { fn parse_query_expression_order(body SimpleTable, order []SortSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body order: order } } fn parse_query_expression_offset(body SimpleTable, offset ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body offset: offset } } fn parse_query_expression_order_offset(body SimpleTable, order []SortSpecification, offset ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body offset: offset - order: order + order: order } } fn parse_query_expression_fetch(body SimpleTable, fetch ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body fetch: fetch } } fn parse_query_expression_order_fetch(body SimpleTable, order []SortSpecification, fetch ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body fetch: fetch order: order } @@ -124,18 +124,18 @@ fn parse_query_expression_order_fetch(body SimpleTable, order []SortSpecificatio fn parse_query_expression_offset_fetch(body SimpleTable, offset ValueSpecification, fetch ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body offset: offset - fetch: fetch + fetch: fetch } } fn parse_query_expression_order_offset_fetch(body SimpleTable, order []SortSpecification, offset ValueSpecification, fetch ValueSpecification) !QueryExpression { return QueryExpression{ - body: body + body: body offset: offset - fetch: fetch - order: order + fetch: fetch + order: order } } @@ -231,7 +231,7 @@ fn (mut o OrderOperation) execute(rows []Row) ![]Row { head_cmp := row_cmp(mut o.conn, o.params, row, head.row, o.order)! if head_cmp < 0 { head = &RowLink{ - row: row + row: row next: head } continue @@ -244,7 +244,7 @@ fn (mut o OrderOperation) execute(rows []Row) ![]Row { cmp := row_cmp(mut o.conn, o.params, row, cursor.next.row, o.order)! if cmp < 0 { cursor.next = &RowLink{ - row: row + row: row next: cursor.next } inserted = true @@ -291,7 +291,7 @@ fn (l &RowLink) rows() []Row { fn row_cmp(mut conn Connection, params map[string]Value, r1 Row, r2 Row, specs []SortSpecification) !int { mut c := Compiler{ - conn: conn + conn: conn params: params } @@ -436,7 +436,7 @@ fn (o &LimitOperation) columns() Columns { fn (mut o LimitOperation) execute(rows []Row) ![]Row { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params } mut offset := i64(0) diff --git a/vsql/std_query_specification.v b/vsql/std_query_specification.v index 1ab8a38..2264f02 100644 --- a/vsql/std_query_specification.v +++ b/vsql/std_query_specification.v @@ -65,7 +65,7 @@ struct QuerySpecification { fn parse_query_specification(select_list SelectList, table_expression TableExpression) !SimpleTable { return QuerySpecification{ - exprs: select_list + exprs: select_list table_expression: table_expression } } diff --git a/vsql/std_routine_invocation.v b/vsql/std_routine_invocation.v index 45fa376..12834a8 100644 --- a/vsql/std_routine_invocation.v +++ b/vsql/std_routine_invocation.v @@ -45,7 +45,7 @@ fn (e RoutineInvocation) compile(mut c Compiler) !CompileResult { if found_func.is_agg { return Identifier{ - custom_id: e.pstr(c.params) + custom_id: e.pstr(c.params) custom_typ: found_func.return_type }.compile(mut c)!.with_agg(true) } @@ -62,7 +62,7 @@ fn (e RoutineInvocation) compile(mut c Compiler) !CompileResult { } return CompileResult{ - run: fn [found_func, func_name, arg_types, compiled_args] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [found_func, func_name, arg_types, compiled_args] (mut conn Connection, data Row, params map[string]Value) !Value { mut args := []Value{} mut i := 0 for typ in arg_types { @@ -73,7 +73,7 @@ fn (e RoutineInvocation) compile(mut c Compiler) !CompileResult { return found_func.func(args)! } - typ: found_func.return_type + typ: found_func.return_type contains_agg: found_func.is_agg } } diff --git a/vsql/std_row_value_constructor.v b/vsql/std_row_value_constructor.v index be93d06..67c17ce 100644 --- a/vsql/std_row_value_constructor.v +++ b/vsql/std_row_value_constructor.v @@ -158,7 +158,7 @@ fn (r RowValueConstructor) eval_row(mut conn Connection, data Row, params map[st mut col_number := 1 mut row := map[string]Value{} mut c := Compiler{ - conn: conn + conn: conn params: params } match r { diff --git a/vsql/std_search_condition.v b/vsql/std_search_condition.v index d993e92..987e9fe 100644 --- a/vsql/std_search_condition.v +++ b/vsql/std_search_condition.v @@ -52,7 +52,7 @@ fn (mut o WhereOperation) execute(rows []Row) ![]Row { fn eval_as_bool(mut conn Connection, data Row, e BooleanValueExpression, params map[string]Value, tables map[string]Table) !bool { mut c := Compiler{ - conn: conn + conn: conn params: params tables: tables } diff --git a/vsql/std_sequence_generator_definition.v b/vsql/std_sequence_generator_definition.v index bb2bf08..3815834 100644 --- a/vsql/std_sequence_generator_definition.v +++ b/vsql/std_sequence_generator_definition.v @@ -116,7 +116,7 @@ fn parse_sequence_generator_definition_1(generator_name Identifier) !Stmt { fn parse_sequence_generator_definition_2(generator_name Identifier, options []SequenceGeneratorOption) !Stmt { return SequenceGeneratorDefinition{ - name: generator_name + name: generator_name options: options } } @@ -174,7 +174,7 @@ fn (stmt SequenceGeneratorDefinition) execute(mut conn Connection, params map[st } mut c := Compiler{ - conn: conn + conn: conn params: params } mut catalog := conn.catalog() @@ -236,14 +236,14 @@ fn (stmt SequenceGeneratorDefinition) execute(mut conn Connection, params map[st } sequence := Sequence{ - name: sequence_name + name: sequence_name current_value: current_value - increment_by: increment_by - cycle: cycle + increment_by: increment_by + cycle: cycle has_min_value: has_min_value - min_value: min_value + min_value: min_value has_max_value: has_max_value - max_value: max_value + max_value: max_value } catalog.storage.create_sequence(sequence)! diff --git a/vsql/std_set_catalog_statement.v b/vsql/std_set_catalog_statement.v index 71eb7d3..715e0c2 100644 --- a/vsql/std_set_catalog_statement.v +++ b/vsql/std_set_catalog_statement.v @@ -41,7 +41,7 @@ fn (stmt SetCatalogStatement) execute(mut conn Connection, params map[string]Val // This does not need to hold a write connection with the file. mut c := Compiler{ - conn: conn + conn: conn params: params } new_catalog := stmt.catalog_name.compile(mut c)!.run(mut conn, Row{}, map[string]Value{})!.str() diff --git a/vsql/std_set_schema_statement.v b/vsql/std_set_schema_statement.v index ed6d75a..4e00813 100644 --- a/vsql/std_set_schema_statement.v +++ b/vsql/std_set_schema_statement.v @@ -41,7 +41,7 @@ fn (stmt SetSchemaStatement) execute(mut conn Connection, params map[string]Valu // This does not need to hold a write connection with the file. mut c := Compiler{ - conn: conn + conn: conn params: params } new_schema := stmt.schema_name.compile(mut c)!.run(mut conn, Row{}, map[string]Value{})!.str() diff --git a/vsql/std_similar_predicate.v b/vsql/std_similar_predicate.v index af7373f..9814de2 100644 --- a/vsql/std_similar_predicate.v +++ b/vsql/std_similar_predicate.v @@ -45,7 +45,7 @@ fn (e SimilarPredicate) compile(mut c Compiler) !CompileResult { compiled_right := e.right.compile(mut c)! return CompileResult{ - run: fn [e, compiled_l, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_l, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { left := compiled_l.run(mut conn, data, params)! right := compiled_right.run(mut conn, data, params)! @@ -62,7 +62,7 @@ fn (e SimilarPredicate) compile(mut c Compiler) !CompileResult { return new_boolean_value(result) } - typ: new_type('BOOLEAN', 0, 0) + typ: new_type('BOOLEAN', 0, 0) contains_agg: compiled_l.contains_agg || compiled_right.contains_agg } } diff --git a/vsql/std_sqlstate.v b/vsql/std_sqlstate.v index b53ed65..9e4fafd 100644 --- a/vsql/std_sqlstate.v +++ b/vsql/std_sqlstate.v @@ -79,8 +79,8 @@ struct SQLState22001 { fn sqlstate_22001(to Type) IError { return SQLState22001{ code: sqlstate_to_int('22001') - msg: 'string data right truncation for ${to}' - to: to + msg: 'string data right truncation for ${to}' + to: to } } @@ -92,7 +92,7 @@ struct SQLState22003 { fn sqlstate_22003() IError { return SQLState22003{ code: sqlstate_to_int('22003') - msg: 'numeric value out of range' + msg: 'numeric value out of range' } } @@ -105,7 +105,7 @@ struct SQLState2200H { fn sqlstate_2200h(generator_name string) IError { return SQLState2200H{ code: sqlstate_to_int('2200H') - msg: 'sequence generator limit exceeded: ${generator_name}' + msg: 'sequence generator limit exceeded: ${generator_name}' } } @@ -117,7 +117,7 @@ struct SQLState22012 { fn sqlstate_22012() IError { return SQLState22012{ code: sqlstate_to_int('22012') - msg: 'division by zero' + msg: 'division by zero' } } @@ -129,7 +129,7 @@ struct SQLState23502 { fn sqlstate_23502(msg string) IError { return SQLState23502{ code: sqlstate_to_int('23502') - msg: 'violates non-null constraint: ${msg}' + msg: 'violates non-null constraint: ${msg}' } } @@ -142,8 +142,8 @@ pub: fn sqlstate_2bp01(object_name string) IError { return SQLState2BP01{ - code: sqlstate_to_int('2BP01') - msg: 'dependent objects still exist on ${object_name}' + code: sqlstate_to_int('2BP01') + msg: 'dependent objects still exist on ${object_name}' object_name: object_name } } @@ -157,8 +157,8 @@ pub: fn sqlstate_3d000(catalog_name string) IError { return SQLState3D000{ - code: sqlstate_to_int('3D000') - msg: 'invalid catalog name: ${catalog_name}' + code: sqlstate_to_int('3D000') + msg: 'invalid catalog name: ${catalog_name}' catalog_name: catalog_name } } @@ -172,8 +172,8 @@ pub: fn sqlstate_3f000(schema_name string) IError { return SQLState3F000{ - code: sqlstate_to_int('3F000') - msg: 'invalid schema name: ${schema_name}' + code: sqlstate_to_int('3F000') + msg: 'invalid schema name: ${schema_name}' schema_name: schema_name } } @@ -186,7 +186,7 @@ struct SQLState42601 { fn sqlstate_42601(message string) IError { return SQLState42601{ code: sqlstate_to_int('42601') - msg: 'syntax error: ${message}' + msg: 'syntax error: ${message}' } } @@ -199,8 +199,8 @@ pub: fn sqlstate_42703(column_name string) IError { return SQLState42703{ - code: sqlstate_to_int('42703') - msg: 'no such column: ${column_name}' + code: sqlstate_to_int('42703') + msg: 'no such column: ${column_name}' column_name: column_name } } @@ -214,10 +214,10 @@ struct SQLState42804 { fn sqlstate_42804(msg string, expected string, actual string) IError { return SQLState42804{ - code: sqlstate_to_int('42804') - msg: 'data type mismatch ${msg}: expected ${expected} but got ${actual}' + code: sqlstate_to_int('42804') + msg: 'data type mismatch ${msg}: expected ${expected} but got ${actual}' expected: expected - actual: actual + actual: actual } } @@ -231,9 +231,9 @@ struct SQLState42846 { fn sqlstate_42846(from Type, to Type) IError { return SQLState42846{ code: sqlstate_to_int('42846') - msg: 'cannot coerce ${from} to ${to}' + msg: 'cannot coerce ${from} to ${to}' from: from - to: to + to: to } } @@ -249,8 +249,8 @@ pub: fn sqlstate_42p01(entity_type string, entity_name string) IError { return SQLState42P01{ - code: sqlstate_to_int('42P01') - msg: 'no such ${entity_type}: ${entity_name}' + code: sqlstate_to_int('42P01') + msg: 'no such ${entity_type}: ${entity_name}' entity_type: entity_type entity_name: entity_name } @@ -265,8 +265,8 @@ pub: fn sqlstate_42p06(schema_name string) IError { return SQLState42P06{ - code: sqlstate_to_int('42P06') - msg: 'duplicate schema: ${schema_name}' + code: sqlstate_to_int('42P06') + msg: 'duplicate schema: ${schema_name}' schema_name: schema_name } } @@ -280,8 +280,8 @@ pub: fn sqlstate_42p07(table_name string) IError { return SQLState42P07{ - code: sqlstate_to_int('42P07') - msg: 'duplicate table: ${table_name}' + code: sqlstate_to_int('42P07') + msg: 'duplicate table: ${table_name}' table_name: table_name } } @@ -294,7 +294,7 @@ struct SQLState42883 { fn sqlstate_42883(msg string) IError { return SQLState42883{ code: sqlstate_to_int('42883') - msg: msg + msg: msg } } @@ -307,8 +307,8 @@ pub: fn sqlstate_42p02(parameter_name string) IError { return SQLState42P02{ - code: sqlstate_to_int('42P02') - msg: 'parameter does not exist: ${parameter_name}' + code: sqlstate_to_int('42P02') + msg: 'parameter does not exist: ${parameter_name}' parameter_name: parameter_name } } @@ -321,7 +321,7 @@ struct SQLState25001 { fn sqlstate_25001() IError { return SQLState25001{ code: sqlstate_to_int('25001') - msg: 'invalid transaction state: active sql transaction' + msg: 'invalid transaction state: active sql transaction' } } @@ -333,7 +333,7 @@ struct SQLState2D000 { fn sqlstate_2d000() IError { return SQLState2D000{ code: sqlstate_to_int('2D000') - msg: 'invalid transaction termination' + msg: 'invalid transaction termination' } } @@ -345,7 +345,7 @@ struct SQLState0B000 { fn sqlstate_0b000(msg string) IError { return SQLState0B000{ code: sqlstate_to_int('0B000') - msg: 'invalid transaction initiation: ${msg}' + msg: 'invalid transaction initiation: ${msg}' } } @@ -357,7 +357,7 @@ struct SQLState40001 { fn sqlstate_40001(message string) IError { return SQLState40001{ code: sqlstate_to_int('40001') - msg: 'serialization failure: ${message}' + msg: 'serialization failure: ${message}' } } @@ -369,6 +369,6 @@ struct SQLState25P02 { fn sqlstate_25p02() IError { return SQLState25P02{ code: sqlstate_to_int('25P02') - msg: 'transaction is aborted, commands ignored until end of transaction block' + msg: 'transaction is aborted, commands ignored until end of transaction block' } } diff --git a/vsql/std_store_assignment.v b/vsql/std_store_assignment.v index 096bdc2..8336f8e 100644 --- a/vsql/std_store_assignment.v +++ b/vsql/std_store_assignment.v @@ -557,17 +557,17 @@ fn cast_timestamp_without_to_timestamp_without(conn &Connection, v Value, to Typ fn check_numeric_range(x Numeric, typ SQLType) ! { match typ { .is_smallint { - if x.less_than(vsql.min_smallint) || x.greater_than(vsql.max_smallint) { + if x.less_than(min_smallint) || x.greater_than(max_smallint) { return sqlstate_22003() } } .is_integer { - if x.less_than(vsql.min_integer) || x.greater_than(vsql.max_integer) { + if x.less_than(min_integer) || x.greater_than(max_integer) { return sqlstate_22003() } } .is_bigint { - if x.less_than(vsql.min_bigint) || x.greater_than(vsql.max_bigint) { + if x.less_than(min_bigint) || x.greater_than(max_bigint) { return sqlstate_22003() } } diff --git a/vsql/std_string_value_expression.v b/vsql/std_string_value_expression.v index 5e23839..8fad73b 100644 --- a/vsql/std_string_value_expression.v +++ b/vsql/std_string_value_expression.v @@ -77,7 +77,7 @@ fn (e Concatenation) compile(mut c Compiler) !CompileResult { compiled_right := e.right.compile(mut c)! return CompileResult{ - run: fn [compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [compiled_left, compiled_right] (mut conn Connection, data Row, params map[string]Value) !Value { mut left := compiled_left.run(mut conn, data, params)! mut right := compiled_right.run(mut conn, data, params)! @@ -88,7 +88,7 @@ fn (e Concatenation) compile(mut c Compiler) !CompileResult { return sqlstate_42883('operator does not exist: ${left.typ.typ} || ${right.typ.typ}') } - typ: new_type('CHARACTER VARYING', 0, 0) + typ: new_type('CHARACTER VARYING', 0, 0) contains_agg: compiled_left.contains_agg || compiled_right.contains_agg } } diff --git a/vsql/std_string_value_function.v b/vsql/std_string_value_function.v index dddb84d..ccc07bb 100644 --- a/vsql/std_string_value_function.v +++ b/vsql/std_string_value_function.v @@ -108,8 +108,8 @@ fn (e CharacterSubstringFunction) compile(mut c Compiler) !CompileResult { f.compile(mut c)! } else { CompileResult{ - run: unsafe { nil } - typ: Type{} + run: unsafe { nil } + typ: Type{} contains_agg: false } } @@ -117,14 +117,14 @@ fn (e CharacterSubstringFunction) compile(mut c Compiler) !CompileResult { f.compile(mut c)! } else { CompileResult{ - run: unsafe { nil } - typ: Type{} + run: unsafe { nil } + typ: Type{} contains_agg: false } } return CompileResult{ - run: fn [e, compiled_value, compiled_from, compiled_for] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_value, compiled_from, compiled_for] (mut conn Connection, data Row, params map[string]Value) !Value { value := compiled_value.run(mut conn, data, params)! mut from := 0 @@ -158,7 +158,7 @@ fn (e CharacterSubstringFunction) compile(mut c Compiler) !CompileResult { return new_varchar_value(value.string_value().substr(from, from + @for)) } - typ: new_type('CHARACTER VARYING', 0, 0) + typ: new_type('CHARACTER VARYING', 0, 0) contains_agg: compiled_value.contains_agg } } @@ -180,7 +180,7 @@ fn (e TrimFunction) compile(mut c Compiler) !CompileResult { compiled_character := e.character.compile(mut c)! return CompileResult{ - run: fn [e, compiled_source, compiled_character] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e, compiled_source, compiled_character] (mut conn Connection, data Row, params map[string]Value) !Value { source := compiled_source.run(mut conn, data, params)! character := compiled_character.run(mut conn, data, params)! @@ -194,7 +194,7 @@ fn (e TrimFunction) compile(mut c Compiler) !CompileResult { return new_varchar_value(source.string_value().trim(character.string_value())) } - typ: new_type('CHARACTER VARYING', 0, 0) + typ: new_type('CHARACTER VARYING', 0, 0) contains_agg: compiled_source.contains_agg || compiled_character.contains_agg } } diff --git a/vsql/std_table_definition.v b/vsql/std_table_definition.v index ee0e6cd..8e8de11 100644 --- a/vsql/std_table_definition.v +++ b/vsql/std_table_definition.v @@ -95,9 +95,9 @@ fn (stmt TableDefinition) execute(mut conn Connection, params map[string]Value, } columns << Column{Identifier{ - catalog_name: table_name.catalog_name - schema_name: table_name.schema_name - entity_name: table_name.entity_name + catalog_name: table_name.catalog_name + schema_name: table_name.schema_name + entity_name: table_name.entity_name sub_entity_name: table_element.name.sub_entity_name }, table_element.typ, table_element.not_null} } diff --git a/vsql/std_table_reference.v b/vsql/std_table_reference.v index facadcd..7afb706 100644 --- a/vsql/std_table_reference.v +++ b/vsql/std_table_reference.v @@ -105,7 +105,7 @@ fn parse_table_primary_identifier(name Identifier) !TablePrimary { fn parse_table_primary_derived_2(body TablePrimary, correlation Correlation) !TablePrimary { return TablePrimary{ - body: body.body + body: body.body correlation: correlation } } @@ -128,7 +128,7 @@ fn parse_correlation_1(name Identifier) !Correlation { fn parse_correlation_2(name Identifier, columns []Identifier) !Correlation { return Correlation{ - name: name + name: name columns: columns } } diff --git a/vsql/std_table_value_constructor.v b/vsql/std_table_value_constructor.v index 31a1c2b..68a75f8 100644 --- a/vsql/std_table_value_constructor.v +++ b/vsql/std_table_value_constructor.v @@ -124,7 +124,7 @@ fn (o &ValuesOperation) str() string { fn (o &ValuesOperation) columns() Columns { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params } e := o.rows[0] @@ -138,7 +138,7 @@ fn (o &ValuesOperation) columns() Columns { typ := (e.exprs[i].compile(mut c) or { panic(err) }).typ columns << Column{ name: column - typ: typ + typ: typ } } QueryExpression { @@ -149,7 +149,7 @@ fn (o &ValuesOperation) columns() Columns { CommonValueExpression, BooleanValueExpression { columns << Column{ name: column - typ: (e.compile(mut c) or { panic(err) }).typ + typ: (e.compile(mut c) or { panic(err) }).typ } } } @@ -172,7 +172,7 @@ fn (o &ValuesOperation) columns() Columns { name: Identifier{ sub_entity_name: 'COL${i}' } - typ: typ + typ: typ } } } @@ -186,7 +186,7 @@ fn (o &ValuesOperation) columns() Columns { name: Identifier{ sub_entity_name: 'COL1' } - typ: (e.compile(mut c) or { panic(err) }).typ + typ: (e.compile(mut c) or { panic(err) }).typ } } } @@ -196,7 +196,7 @@ fn (o &ValuesOperation) columns() Columns { fn (mut o ValuesOperation) execute(_ []Row) ![]Row { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params } offset := int((o.offset.compile(mut c)!.run(mut o.conn, Row{}, o.params)!).f64_value()) diff --git a/vsql/std_update_statement_searched.v b/vsql/std_update_statement_searched.v index e8a0434..94f0139 100644 --- a/vsql/std_update_statement_searched.v +++ b/vsql/std_update_statement_searched.v @@ -52,7 +52,7 @@ fn (stmt UpdateStatementSearched) execute(mut conn Connection, params map[string } mut c := Compiler{ - conn: conn + conn: conn params: params } mut catalog := conn.catalog() @@ -77,8 +77,8 @@ fn (stmt UpdateStatementSearched) execute(mut conn Connection, params map[string table_column := table.column(column_name)! c.context = Identifier{ catalog_name: table_column.name.catalog_name - schema_name: table_column.name.schema_name - entity_name: table.name.entity_name + schema_name: table_column.name.schema_name + entity_name: table.name.entity_name } raw_value := match v { diff --git a/vsql/std_value_specification_and_target_specification.v b/vsql/std_value_specification_and_target_specification.v index dc7409c..4390ffb 100644 --- a/vsql/std_value_specification_and_target_specification.v +++ b/vsql/std_value_specification_and_target_specification.v @@ -74,19 +74,19 @@ fn (e GeneralValueSpecification) compile(mut c Compiler) !CompileResult { } CurrentCatalog { return CompileResult{ - run: fn (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn (mut conn Connection, data Row, params map[string]Value) !Value { return new_varchar_value(conn.current_catalog) } - typ: new_type('CHARACTER VARYING', 0, 0) + typ: new_type('CHARACTER VARYING', 0, 0) contains_agg: false } } CurrentSchema { return CompileResult{ - run: fn (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn (mut conn Connection, data Row, params map[string]Value) !Value { return new_varchar_value(conn.current_schema) } - typ: new_type('CHARACTER VARYING', 0, 0) + typ: new_type('CHARACTER VARYING', 0, 0) contains_agg: false } } diff --git a/vsql/table.v b/vsql/table.v index 6fda268..8308948 100644 --- a/vsql/table.v +++ b/vsql/table.v @@ -117,9 +117,9 @@ fn new_table_from_bytes(data []u8, tid int, catalog_name string) Table { scale := b.read_i16() columns << Column{Identifier{ - catalog_name: catalog_name - schema_name: table_name.schema_name - entity_name: table_name.entity_name + catalog_name: catalog_name + schema_name: table_name.schema_name + entity_name: table_name.entity_name sub_entity_name: column_name }, type_from_number(column_type, size, scale), is_not_null} } diff --git a/vsql/time.v b/vsql/time.v index de9874d..571a831 100644 --- a/vsql/time.v +++ b/vsql/time.v @@ -65,8 +65,8 @@ fn new_timestamp_from_string(s string) !Time { expects_time_zone := s.len > 6 && (s[s.len - 6] == `+` || s[s.len - 6] == `-`) mut re := regex.regex_opt(match expects_time_zone { - true { vsql.unquoted_timestamp_with_time_zone_string } - false { vsql.unquoted_timestamp_without_time_zone_string } + true { unquoted_timestamp_with_time_zone_string } + false { unquoted_timestamp_without_time_zone_string } }) or { return error('cannot compile regex for timestamp: ${err}') } if !re.matches_string(s) { return sqlstate_42601('TIMESTAMP \'${s}\' is not valid') @@ -93,7 +93,7 @@ fn new_timestamp_from_string(s string) !Time { } mut typ := Type{ - typ: if expects_time_zone { + typ: if expects_time_zone { .is_timestamp_with_time_zone } else { .is_timestamp_without_time_zone @@ -142,12 +142,12 @@ fn new_date_from_string(s string) !Time { fn new_time_from_components(typ Type, year int, month int, day int, hour int, minute int, second int, microsecond int, time_zone i16) Time { return Time{typ, time_zone, time.new(time.Time{ - year: year - month: month - day: day - hour: hour - minute: minute - second: second + year: year + month: month + day: day + hour: hour + minute: minute + second: second nanosecond: microsecond * 1000 })} } @@ -156,23 +156,23 @@ fn new_time_from_bytes(typ Type, bytes []u8) Time { mut buf := new_bytes(bytes) mut ts_i64 := buf.read_i64() - year := int(ts_i64 / vsql.year_period) - ts_i64 -= year * vsql.year_period + year := int(ts_i64 / year_period) + ts_i64 -= year * year_period - month := int(ts_i64 / vsql.month_period) - ts_i64 -= month * vsql.month_period + month := int(ts_i64 / month_period) + ts_i64 -= month * month_period - day := int(ts_i64 / vsql.day_period) - ts_i64 -= day * vsql.day_period + day := int(ts_i64 / day_period) + ts_i64 -= day * day_period - hour := int(ts_i64 / vsql.hour_period) - ts_i64 -= hour * vsql.hour_period + hour := int(ts_i64 / hour_period) + ts_i64 -= hour * hour_period - minute := int(ts_i64 / vsql.minute_period) - ts_i64 -= minute * vsql.minute_period + minute := int(ts_i64 / minute_period) + ts_i64 -= minute * minute_period - second := int(ts_i64 / vsql.second_period) - ts_i64 -= second * vsql.second_period + second := int(ts_i64 / second_period) + ts_i64 -= second * second_period mut time_zone := i16(0) if typ.typ == .is_time_with_time_zone || typ.typ == .is_timestamp_with_time_zone { @@ -230,13 +230,13 @@ fn (t Time) i64() i64 { // See i64() for details. fn (t Time) time_i64() i64 { - return t.t.hour * vsql.hour_period + t.t.minute * vsql.minute_period + - t.t.second * vsql.second_period + int(t.t.nanosecond / 1000) + return t.t.hour * hour_period + t.t.minute * minute_period + t.t.second * second_period + + int(t.t.nanosecond / 1000) } // See i64() for details. fn (t Time) date_i64() i64 { - return t.t.year * vsql.year_period + t.t.month * vsql.month_period + t.t.day * vsql.day_period + return t.t.year * year_period + t.t.month * month_period + t.t.day * day_period } // Returns the Time formatted based on its type. diff --git a/vsql/type.v b/vsql/type.v index b75ccb1..f6f6af9 100644 --- a/vsql/type.v +++ b/vsql/type.v @@ -17,21 +17,21 @@ mut: // Represents the fundamental SQL type. enum SQLType { - is_bigint // BIGINT - is_boolean // BOOLEAN - is_character // CHARACTER(n), CHAR(n), CHARACTER and CHAR - is_double_precision // DOUBLE PRECISION, FLOAT and FLOAT(n) - is_integer // INTEGER and INT - is_real // REAL - is_smallint // SMALLINT - is_varchar // CHARACTER VARYING, CHAR VARYING and VARCHAR - is_date // DATE - is_time_without_time_zone // TIME, TIME WITHOUT TIME ZONE - is_time_with_time_zone // TIME WITH TIME ZONE + is_bigint // BIGINT + is_boolean // BOOLEAN + is_character // CHARACTER(n), CHAR(n), CHARACTER and CHAR + is_double_precision // DOUBLE PRECISION, FLOAT and FLOAT(n) + is_integer // INTEGER and INT + is_real // REAL + is_smallint // SMALLINT + is_varchar // CHARACTER VARYING, CHAR VARYING and VARCHAR + is_date // DATE + is_time_without_time_zone // TIME, TIME WITHOUT TIME ZONE + is_time_with_time_zone // TIME WITH TIME ZONE is_timestamp_without_time_zone // TIMESTAMP, TIMESTAMP WITHOUT TIME ZONE - is_timestamp_with_time_zone // TIMESTAMP WITH TIME ZONE - is_decimal // DECIMAL - is_numeric // NUMERIC + is_timestamp_with_time_zone // TIMESTAMP WITH TIME ZONE + is_decimal // DECIMAL + is_numeric // NUMERIC } // The SQL representation, such as ``TIME WITHOUT TIME ZONE``. diff --git a/vsql/value.v b/vsql/value.v index 0295d9f..1acfe24 100644 --- a/vsql/value.v +++ b/vsql/value.v @@ -38,10 +38,10 @@ pub mut: fn (e Value) compile(mut c Compiler) !CompileResult { return CompileResult{ - run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { + run: fn [e] (mut conn Connection, data Row, params map[string]Value) !Value { return e } - typ: e.typ + typ: e.typ contains_agg: false } } @@ -70,7 +70,7 @@ mut: // values need to have a type. pub fn new_null_value(typ SQLType) Value { return Value{ - typ: Type{typ, 0, 0, false} + typ: Type{typ, 0, 0, false} is_null: true } } @@ -80,7 +80,7 @@ pub fn new_null_value(typ SQLType) Value { pub fn new_boolean_value(b bool) Value { return Value{ typ: Type{.is_boolean, 0, 0, false} - v: InternalValue{ + v: InternalValue{ bool_value: if b { .is_true } else { .is_false } } } @@ -90,7 +90,7 @@ pub fn new_boolean_value(b bool) Value { // representation of ``BOOLEAN``. pub fn new_unknown_value() Value { return Value{ - typ: Type{.is_boolean, 0, 0, false} + typ: Type{.is_boolean, 0, 0, false} is_null: true } } @@ -99,7 +99,7 @@ pub fn new_unknown_value() Value { pub fn new_double_precision_value(x f64) Value { return Value{ typ: Type{.is_double_precision, 0, 0, false} - v: InternalValue{ + v: InternalValue{ f64_value: x } } @@ -109,7 +109,7 @@ pub fn new_double_precision_value(x f64) Value { pub fn new_integer_value(x int) Value { return Value{ typ: Type{.is_integer, 0, 0, false} - v: InternalValue{ + v: InternalValue{ int_value: x } } @@ -119,7 +119,7 @@ pub fn new_integer_value(x int) Value { pub fn new_bigint_value(x i64) Value { return Value{ typ: Type{.is_bigint, 0, 0, false} - v: InternalValue{ + v: InternalValue{ int_value: x } } @@ -129,7 +129,7 @@ pub fn new_bigint_value(x i64) Value { pub fn new_real_value(x f32) Value { return Value{ typ: Type{.is_real, 0, 0, false} - v: InternalValue{ + v: InternalValue{ f64_value: x } } @@ -139,7 +139,7 @@ pub fn new_real_value(x f32) Value { pub fn new_smallint_value(x i16) Value { return Value{ typ: Type{.is_smallint, 0, 0, false} - v: InternalValue{ + v: InternalValue{ int_value: x } } @@ -149,7 +149,7 @@ pub fn new_smallint_value(x i16) Value { pub fn new_varchar_value(x string) Value { return Value{ typ: Type{.is_varchar, x.len, 0, false} - v: InternalValue{ + v: InternalValue{ string_value: x } } @@ -160,7 +160,7 @@ pub fn new_varchar_value(x string) Value { pub fn new_character_value(x string) Value { return Value{ typ: Type{.is_character, x.len, 0, false} - v: InternalValue{ + v: InternalValue{ string_value: x } } @@ -180,7 +180,7 @@ pub fn new_numeric_value(x string) Value { return Value{ typ: n.typ - v: InternalValue{ + v: InternalValue{ numeric_value: n.normalize_denominator(n.typ) } } @@ -201,7 +201,7 @@ pub fn new_decimal_value(x string) Value { return Value{ typ: typ - v: InternalValue{ + v: InternalValue{ numeric_value: n.normalize_denominator(typ) } } @@ -210,7 +210,7 @@ pub fn new_decimal_value(x string) Value { fn new_numeric_value_from_numeric(n Numeric) Value { return Value{ typ: n.typ - v: InternalValue{ + v: InternalValue{ numeric_value: n.normalize_denominator(n.typ) } } @@ -221,7 +221,7 @@ fn new_decimal_value_from_numeric(n Numeric) Value { return Value{ typ: typ - v: InternalValue{ + v: InternalValue{ numeric_value: n.normalize_denominator(n.typ) } } @@ -233,7 +233,7 @@ pub fn new_timestamp_value(ts string) !Value { return Value{ typ: t.typ - v: InternalValue{ + v: InternalValue{ time_value: t } } @@ -245,7 +245,7 @@ pub fn new_time_value(ts string) !Value { return Value{ typ: t.typ - v: InternalValue{ + v: InternalValue{ time_value: t } } @@ -257,7 +257,7 @@ pub fn new_date_value(ts string) !Value { return Value{ typ: t.typ - v: InternalValue{ + v: InternalValue{ time_value: t } } diff --git a/vsql/virtual_table.v b/vsql/virtual_table.v index 0bdd9d2..1dc30d2 100644 --- a/vsql/virtual_table.v +++ b/vsql/virtual_table.v @@ -35,8 +35,8 @@ pub fn (mut v VirtualTable) done() { pub fn (v VirtualTable) table() Table { return Table{ - name: v.create_table_stmt.table_name - columns: v.create_table_stmt.columns() + name: v.create_table_stmt.table_name + columns: v.create_table_stmt.columns() is_virtual: true } } diff --git a/vsql/walk.v b/vsql/walk.v index 34998b5..b1f8995 100644 --- a/vsql/walk.v +++ b/vsql/walk.v @@ -127,7 +127,7 @@ fn (o &PrimaryKeyOperation) columns() Columns { fn (mut o PrimaryKeyOperation) execute(_ []Row) ![]Row { mut c := Compiler{ - conn: o.conn + conn: o.conn params: o.params } mut lower := o.lower.compile(mut c)!.run(mut o.conn, Row{}, o.params)!