From 4e2e0a680c2df3c72df727b7dca78690923eb8c5 Mon Sep 17 00:00:00 2001 From: Arseniy Volynets <vol0ncar@yandex.ru> Date: Mon, 29 Jul 2024 14:37:32 +0300 Subject: [PATCH] feat!: normalize identifiers to lowercase - Normalize name to lowercase from parser - Identifiers are stored as normalized strings without quotes - During conversion to local SQL we wrap identifiers in quotes, because tarantool normalizes names without quotes to uppercase - For errors and explain, we also need to wrap names into quotes for better readability --- sbroad-cartridge/src/cartridge/config.rs | 23 +- .../src/cartridge/config/tests.rs | 152 ++--- sbroad-cartridge/src/cartridge/router.rs | 8 +- .../test_app/test/integration/api_test.lua | 20 +- .../arbitrary_expressions_test.lua | 6 +- .../test/integration/arithmetic_test.lua | 8 +- .../test_app/test/integration/cte_test.lua | 33 +- .../test/integration/groupby_test.lua | 45 +- .../test/integration/large_query_test.lua | 4 +- .../test/integration/left_outer_join_test.lua | 105 ++-- .../test_app/test/integration/limit_test.lua | 4 +- .../test/integration/operators_test.lua | 8 +- sbroad-core/src/backend/sql/ir.rs | 66 +- .../src/backend/sql/ir/tests/selection.rs | 2 +- .../src/backend/sql/ir/tests/sub_query.rs | 8 +- sbroad-core/src/backend/sql/tree.rs | 14 +- sbroad-core/src/builtins.lua | 4 +- sbroad-core/src/cbo/histogram/tests.rs | 2 +- sbroad-core/src/cbo/selectivity.rs | 10 +- sbroad-core/src/cbo/selectivity/tests.rs | 2 +- sbroad-core/src/executor.rs | 5 +- sbroad-core/src/executor/bucket/tests.rs | 2 +- sbroad-core/src/executor/engine.rs | 8 +- sbroad-core/src/executor/engine/helpers.rs | 57 +- sbroad-core/src/executor/engine/mock.rs | 595 +++++++----------- sbroad-core/src/executor/tests.rs | 24 +- sbroad-core/src/executor/tests/bucket_id.rs | 2 +- sbroad-core/src/executor/tests/cast.rs | 2 +- sbroad-core/src/executor/tests/concat.rs | 4 +- .../src/executor/tests/empty_motion.rs | 4 +- sbroad-core/src/executor/tests/exec_plan.rs | 83 +-- sbroad-core/src/executor/tests/frontend.rs | 6 +- sbroad-core/src/frontend/sql.rs | 44 +- sbroad-core/src/frontend/sql/ir/tests.rs | 280 +++++---- sbroad-core/src/frontend/sql/ir/tests/cte.rs | 178 +++--- sbroad-core/src/frontend/sql/ir/tests/ddl.rs | 12 +- .../src/frontend/sql/ir/tests/global.rs | 79 +-- .../src/frontend/sql/ir/tests/insert.rs | 2 +- sbroad-core/src/frontend/sql/ir/tests/join.rs | 14 +- .../src/frontend/sql/ir/tests/single.rs | 8 +- .../src/frontend/sql/ir/tests/update.rs | 12 +- sbroad-core/src/ir.rs | 6 +- sbroad-core/src/ir/aggregates.rs | 5 +- sbroad-core/src/ir/explain.rs | 36 +- sbroad-core/src/ir/explain/tests.rs | 6 +- sbroad-core/src/ir/explain/tests/concat.rs | 2 +- sbroad-core/src/ir/explain/tests/delete.rs | 6 +- sbroad-core/src/ir/expression.rs | 18 +- sbroad-core/src/ir/function.rs | 17 +- sbroad-core/src/ir/helpers/tests.rs | 123 ++-- sbroad-core/src/ir/operator.rs | 5 +- sbroad-core/src/ir/operator/tests.rs | 4 +- sbroad-core/src/ir/relation.rs | 4 +- .../src/ir/transformation/bool_in/tests.rs | 2 +- .../transformation/redistribution/groupby.rs | 14 +- 55 files changed, 1063 insertions(+), 1130 deletions(-) diff --git a/sbroad-cartridge/src/cartridge/config.rs b/sbroad-cartridge/src/cartridge/config.rs index e8b0667f0..376e1d13c 100644 --- a/sbroad-cartridge/src/cartridge/config.rs +++ b/sbroad-cartridge/src/cartridge/config.rs @@ -2,12 +2,12 @@ extern crate yaml_rust; -use smol_str::{format_smolstr, SmolStr}; +use smol_str::{format_smolstr, SmolStr, ToSmolStr}; use std::collections::HashMap; use yaml_rust::{Yaml, YamlLoader}; use sbroad::errors::{Entity, SbroadError}; -use sbroad::executor::engine::helpers::{normalize_name_from_schema, normalize_name_from_sql}; +use sbroad::executor::engine::helpers::normalize_name_from_sql; use sbroad::executor::engine::{get_builtin_functions, Metadata}; use sbroad::executor::lru::DEFAULT_CAPACITY; use sbroad::ir::function::Function; @@ -131,19 +131,12 @@ impl RouterConfiguration { )) } }; - let qualified_name = normalize_name_from_schema(name); - debug!( - Option::from("configuration parsing"), - &format!( - "Column's original name: {name}, qualified name {qualified_name}" - ), - ); - let role = if self.sharding_column().eq(&qualified_name) { + let role = if self.sharding_column().eq(name) { ColumnRole::Sharding } else { ColumnRole::User }; - let col = Column::new(&qualified_name, t, role, is_nullable); + let col = Column::new(name, t, role, is_nullable); result.push(col); } result @@ -171,7 +164,7 @@ impl RouterConfiguration { ); continue; }; - result.push(normalize_name_from_schema(key)); + result.push(key.to_smolstr()); } result } else { @@ -203,7 +196,7 @@ impl RouterConfiguration { Entity::PrimaryKey, Some(format_smolstr!("for space {current_space_name}: failed to get index part field"))) )?; - Ok(normalize_name_from_schema(name)) + Ok(name.to_smolstr()) }).collect::<Result<Vec<SmolStr>, SbroadError>>()? } else { warn!( @@ -231,7 +224,7 @@ impl RouterConfiguration { continue; }; - let table_name: SmolStr = normalize_name_from_schema(current_space_name); + let table_name: SmolStr = current_space_name.to_smolstr(); debug!( Option::from("configuration parsing"), &format!( @@ -289,7 +282,7 @@ impl Metadata for RouterConfiguration { /// Returns `SbroadError` when table was not found. #[allow(dead_code)] fn table(&self, table_name: &str) -> Result<Table, SbroadError> { - let name = normalize_name_from_sql(table_name); + let name = table_name.to_smolstr(); match self.tables.get(&name) { Some(v) => Ok(v.clone()), None => Err(SbroadError::NotFound(Entity::Space, name)), diff --git a/sbroad-cartridge/src/cartridge/config/tests.rs b/sbroad-cartridge/src/cartridge/config/tests.rs index f8d8da996..661ae9ed4 100644 --- a/sbroad-cartridge/src/cartridge/config/tests.rs +++ b/sbroad-cartridge/src/cartridge/config/tests.rs @@ -5,89 +5,89 @@ use pretty_assertions::assert_eq; fn test_yaml_schema_parser() { let test_schema = "spaces: EMPLOYEES: - engine: \"memtx\" + engine: memtx is_local: false temporary: false format: - - name: \"ID\" + - name: ID is_nullable: false - type: \"number\" - - name: \"sysFrom\" + type: number + - name: sysFrom is_nullable: false - type: \"number\" - - name: \"FIRST_NAME\" + type: number + - name: FIRST_NAME is_nullable: false - type: \"string\" - - name: \"sysOp\" + type: string + - name: sysOp is_nullable: false - type: \"number\" - - name: \"bucket_id\" + type: number + - name: bucket_id is_nullable: true - type: \"unsigned\" + type: unsigned indexes: - - type: \"TREE\" - name: \"ID\" + - type: TREE + name: ID unique: true parts: - - path: \"ID\" - type: \"number\" + - path: ID + type: number is_nullable: false - - path: \"sysFrom\" - type: \"number\" + - path: sysFrom + type: number is_nullable: false - - type: \"TREE\" - name: \"bucket_id\" + - type: TREE + name: bucket_id unique: false parts: - - path: \"bucket_id\" - type: \"unsigned\" + - path: bucket_id + type: unsigned is_nullable: true sharding_key: - - \"ID\" + - ID hash_testing: is_local: false temporary: false - engine: \"memtx\" + engine: memtx format: - - name: \"identification_number\" - type: \"integer\" + - name: identification_number + type: integer is_nullable: false - - name: \"product_code\" - type: \"string\" + - name: product_code + type: string is_nullable: false - - name: \"product_units\" - type: \"integer\" + - name: product_units + type: integer is_nullable: false - - name: \"sys_op\" - type: \"number\" + - name: sys_op + type: number is_nullable: false - - name: \"bucket_id\" - type: \"unsigned\" + - name: bucket_id + type: unsigned is_nullable: true indexes: - - name: \"id\" + - name: id unique: true - type: \"TREE\" + type: TREE parts: - - path: \"identification_number\" + - path: identification_number is_nullable: false - type: \"integer\" + type: integer - name: bucket_id unique: false parts: - - path: \"bucket_id\" + - path: bucket_id is_nullable: true - type: \"unsigned\" - type: \"TREE\" + type: unsigned + type: TREE sharding_key: - - \"identification_number\" - - \"product_code\""; + - identification_number + - product_code"; let mut s = RouterConfiguration::new(); s.load_schema(test_schema).unwrap(); - let expected_keys = vec!["\"identification_number\"", "\"product_code\""]; - let actual_keys = s.sharding_key_by_space("\"hash_testing\"").unwrap(); + let expected_keys = vec!["identification_number", "product_code"]; + let actual_keys = s.sharding_key_by_space("hash_testing").unwrap(); assert_eq!(actual_keys, expected_keys); } @@ -97,75 +97,75 @@ fn test_getting_table_segment() { hash_testing: is_local: false temporary: false - engine: \"memtx\" + engine: memtx format: - - name: \"identification_number\" - type: \"integer\" + - name: identification_number + type: integer is_nullable: false - - name: \"product_code\" - type: \"string\" + - name: product_code + type: string is_nullable: false - - name: \"product_units\" - type: \"boolean\" + - name: product_units + type: boolean is_nullable: false - - name: \"sys_op\" - type: \"number\" + - name: sys_op + type: number is_nullable: false - name: detail type: array is_nullable: false - - name: \"bucket_id\" - type: \"unsigned\" + - name: bucket_id + type: unsigned is_nullable: true indexes: - - name: \"id\" + - name: id unique: true - type: \"TREE\" + type: TREE parts: - - path: \"identification_number\" + - path: identification_number is_nullable: false - type: \"integer\" + type: integer - name: bucket_id unique: false parts: - - path: \"bucket_id\" + - path: bucket_id is_nullable: true - type: \"unsigned\" - type: \"TREE\" + type: unsigned + type: TREE sharding_key: - - \"identification_number\" - - \"product_code\""; + - identification_number + - product_code"; let mut s = RouterConfiguration::new(); - s.set_sharding_column("\"bucket_id\"".into()); + s.set_sharding_column("bucket_id".into()); s.load_schema(test_schema).unwrap(); let expected = Table::new_sharded( - "\"hash_testing\"", + "hash_testing", vec![ Column::new( - "\"identification_number\"", + "identification_number", Type::Integer, ColumnRole::User, false, ), - Column::new("\"product_code\"", Type::String, ColumnRole::User, false), - Column::new("\"product_units\"", Type::Boolean, ColumnRole::User, false), - Column::new("\"sys_op\"", Type::Number, ColumnRole::User, false), - Column::new("\"detail\"", Type::Array, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("product_code", Type::String, ColumnRole::User, false), + Column::new("product_units", Type::Boolean, ColumnRole::User, false), + Column::new("sys_op", Type::Number, ColumnRole::User, false), + Column::new("detail", Type::Array, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ], - &["\"identification_number\"", "\"product_code\""], - &["\"identification_number\""], + &["identification_number", "product_code"], + &["identification_number"], SpaceEngine::Memtx, ) .unwrap(); assert_eq!( s.table("invalid_table").unwrap_err(), - SbroadError::NotFound(Entity::Space, r#""INVALID_TABLE""#.into()) + SbroadError::NotFound(Entity::Space, r#"invalid_table"#.into()) ); - assert_eq!(s.table("\"hash_testing\"").unwrap(), expected); + assert_eq!(s.table("hash_testing").unwrap(), expected); } #[test] diff --git a/sbroad-cartridge/src/cartridge/router.rs b/sbroad-cartridge/src/cartridge/router.rs index 13be89e21..61ccb267c 100644 --- a/sbroad-cartridge/src/cartridge/router.rs +++ b/sbroad-cartridge/src/cartridge/router.rs @@ -6,7 +6,7 @@ use sbroad::executor::engine::helpers::vshard::{ }; use sbroad::executor::engine::{QueryCache, Vshard}; use sbroad::utils::MutexLike; -use smol_str::{format_smolstr, SmolStr}; +use smol_str::{format_smolstr, SmolStr, ToSmolStr}; use tarantool::fiber::Mutex; use std::any::Any; @@ -28,8 +28,8 @@ use sbroad::errors::{Entity, SbroadError}; use sbroad::executor::bucket::Buckets; use sbroad::executor::engine::{ helpers::{ - dispatch_impl, explain_format, materialize_motion, normalize_name_from_schema, - sharding_key_from_map, sharding_key_from_tuple, + dispatch_impl, explain_format, materialize_motion, sharding_key_from_map, + sharding_key_from_tuple, }, Router, Statistics, }; @@ -130,7 +130,7 @@ impl ConfigurationProvider for RouterRuntime { let mut metadata = RouterConfiguration::new(); metadata.set_waiting_timeout(timeout); metadata.set_cache_capacity(router_capacity); - metadata.set_sharding_column(normalize_name_from_schema(column.as_str())); + metadata.set_sharding_column(column.to_smolstr()); // We should always load the schema **after** setting the sharding column. metadata.load_schema(&schema)?; diff --git a/sbroad-cartridge/test_app/test/integration/api_test.lua b/sbroad-cartridge/test_app/test/integration/api_test.lua index a066f4667..f0f87cd83 100644 --- a/sbroad-cartridge/test_app/test/integration/api_test.lua +++ b/sbroad-cartridge/test_app/test/integration/api_test.lua @@ -178,7 +178,7 @@ g.test_bucket_id_calculation = function() t.assert_equals(r, nil) t.assert_equals( tostring(err), - [[Sbroad Error: sharding key (quoted) column "\"name\"" in the quoted map {"\"id\"": "id"} (original map: {"id": Integer(1)}) not found]] + [[Sbroad Error: sharding key (quoted) column "name" in the quoted map {"id": "id"} (original map: {"id": Integer(1)}) not found]] ) r, err = api:call("sbroad.calculate_bucket_id", { { id = 1, "123" }, "testing_space" }) @@ -393,7 +393,7 @@ g.test_uppercase1 = function() local api = cluster:server("api-1").net_box local r, err = api:call("sbroad.execute", { [[ - SELECT "id" FROM broken + SELECT "id" FROM "BROKEN" ]], {} }) t.assert_equals(err, nil) @@ -409,7 +409,7 @@ g.test_uppercase2 = function() local api = cluster:server("api-1").net_box local r, err = api:call("sbroad.execute", { [[ - SELECT "id" FROM BROKEN + SELECT "id" FROM "BROKEN" ]], {} }) t.assert_equals(err, nil) @@ -504,8 +504,8 @@ g.test_datetime_insert = function () local api = cluster:server("api-1").net_box local r, err = api:call("sbroad.execute", { [[ - insert into "datetime_t" select to_date(COLUMN_1, '%c'), - cast(COLUMN_2 as int) from + insert into "datetime_t" select to_date("COLUMN_1", '%c'), + cast("COLUMN_2" as int) from (values ('Thu Jan 1 03:44:00 1970', 100)) ]]}) t.assert_equals(err, nil) @@ -577,7 +577,7 @@ g.test_to_char = function () -- second argument is optional -- FIXME: https://git.picodata.io/picodata/picodata/sbroad/-/issues/645 r, err = api:call("sbroad.execute", { [[ - select to_char(to_date(COLUMN_1, '%Y %d'), null) + select to_char(to_date("COLUMN_1", '%Y %d'), null) from (values ('2020 20')) ]]}) @@ -593,7 +593,7 @@ g.test_to_char = function () -- check we can use expressions inside to_char r, err = api:call("sbroad.execute", { [[ - select to_char(to_date(COLUMN_1, '%Y %d'), '%Y-%m-%d' || '-%H-%M-%S-%z') + select to_char(to_date("COLUMN_1", '%Y %d'), '%Y-%m-%d' || '-%H-%M-%S-%z') from (values ('2020 20')) ]]}) @@ -609,7 +609,7 @@ g.test_to_char = function () -- invalid modifier used r, err = api:call("sbroad.execute", { [[ - select to_char(to_date(COLUMN_1, '%Y %d'), '%i-%m-%d') + select to_char(to_date("COLUMN_1", '%Y %d'), '%i-%m-%d') from (values ('2020 20')) ]]}) @@ -655,10 +655,10 @@ g.test_current_date = function () }) r, err = api:call("sbroad.execute", { [[ - select to_char(COL_1, '%Y') from (select to_date(COLUMN_2, '%Y.%m.%d') from ( + select to_char("COL_1", '%Y') from (select to_date("COLUMN_2", '%Y.%m.%d') from ( values ('2077.1.1'), ('2000.10.10') )) - where COL_1 > CURRENT_DATE + where "COL_1" > CURRENT_DATE ]]}) t.assert_equals(err, nil) t.assert_equals(r, { diff --git a/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua b/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua index 7f0157687..4dcc432db 100644 --- a/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua +++ b/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua @@ -149,7 +149,7 @@ arbitrary_projection.test_arbitrary_valid = function() -- column selection from values -- results in type erasing local r, err = api:call("sbroad.execute", { [[ - SELECT COLUMN_1 FROM (VALUES (1)) + SELECT "COLUMN_1" FROM (VALUES (1)) ]], {} }) t.assert_equals(err, nil) @@ -164,7 +164,7 @@ arbitrary_projection.test_arbitrary_valid = function() -- column selection from values with cast r, err = api:call("sbroad.execute", { [[ - SELECT CAST(COLUMN_1 as int) FROM (VALUES (1)) + SELECT CAST("COLUMN_1" as int) FROM (VALUES (1)) ]], {} }) t.assert_equals(err, nil) @@ -179,7 +179,7 @@ arbitrary_projection.test_arbitrary_valid = function() -- using cyrillic symbols in identifiers is okay local r, err = api:call("sbroad.execute", { [[ - SELECT COLUMN_1 as "колонка" FROM (VALUES (1)) + SELECT "COLUMN_1" as "колонка" FROM (VALUES (1)) ]], {} }) t.assert_equals(err, nil) t.assert_equals(r, { diff --git a/sbroad-cartridge/test_app/test/integration/arithmetic_test.lua b/sbroad-cartridge/test_app/test/integration/arithmetic_test.lua index 3d75bd18b..0a2541f0a 100644 --- a/sbroad-cartridge/test_app/test/integration/arithmetic_test.lua +++ b/sbroad-cartridge/test_app/test/integration/arithmetic_test.lua @@ -887,8 +887,8 @@ g1.test_arithmetic_in_parens = function() t.assert_items_equals( without_parens.metadata, { - {name = "A1", type = "integer"}, - {name = "A2", type = "integer"}, + {name = "a1", type = "integer"}, + {name = "a2", type = "integer"}, } ) @@ -901,8 +901,8 @@ g1.test_arithmetic_in_parens = function() t.assert_items_equals( with_parens.metadata, { - {name = "A1", type = "integer"}, - {name = "A2", type = "integer"}, + {name = "a1", type = "integer"}, + {name = "a2", type = "integer"}, } ) diff --git a/sbroad-cartridge/test_app/test/integration/cte_test.lua b/sbroad-cartridge/test_app/test/integration/cte_test.lua index 42e8bf436..11a38c9ee 100644 --- a/sbroad-cartridge/test_app/test/integration/cte_test.lua +++ b/sbroad-cartridge/test_app/test/integration/cte_test.lua @@ -31,7 +31,7 @@ g.test_cte = function () SELECT b FROM cte ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {4}, {5} }) -- nested cte @@ -41,7 +41,7 @@ g.test_cte = function () SELECT * FROM cte2 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {4}, {5} }) -- reuse cte @@ -52,7 +52,7 @@ g.test_cte = function () SELECT b FROM cte ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {4}, {5}, {4}, {5} }) -- inner join table with cte @@ -63,7 +63,7 @@ g.test_cte = function () t.assert_equals(err, nil) t.assert_items_equals( r["metadata"], - { {name = "B", type = "number"}, {name = "a", type = "number"} } + { {name = "b", type = "number"}, {name = "a", type = "number"} } ) t.assert_items_equals(r["rows"], { {1, 1}, {2, 2} }) @@ -75,7 +75,7 @@ g.test_cte = function () t.assert_equals(err, nil) t.assert_items_equals( r["metadata"], - { {name = "B", type = "number"}, {name = "a", type = "number"} } + { {name = "b", type = "number"}, {name = "a", type = "number"} } ) t.assert_items_equals( r["rows"], { {1, 1}, {2, 2} }) @@ -89,8 +89,7 @@ g.test_cte = function () t.assert_equals(err, nil) t.assert_items_equals( r["metadata"], - -- TODO: this should be simply B? - { {name = "B", type = "number"} } + { {name = "b", type = "number"} } ) t.assert_items_equals( r["rows"], { {1}, {2} }) @@ -122,7 +121,7 @@ g.test_cte = function () ]], }) t.assert_equals(err, nil) -- FIXME: metadata type from tarantool is not correct - t.assert_items_equals(r["metadata"], { {name = "B", type = "unsigned"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "unsigned"} }) t.assert_items_equals(r["rows"], { {1}, {2}, {3} }) -- union in cte @@ -132,7 +131,7 @@ g.test_cte = function () SELECT a FROM c2 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "A", type = "unsigned"} }) + t.assert_items_equals(r["metadata"], { {name = "a", type = "unsigned"} }) t.assert_items_equals(r["rows"], { {1}, {2} }) -- union all in cte @@ -142,7 +141,7 @@ g.test_cte = function () SELECT b FROM cte2 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {1}, {2} }) -- join in cte @@ -155,7 +154,7 @@ g.test_cte = function () SELECT c FROM cte ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "C", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "c", type = "number"} }) t.assert_items_equals(r["rows"], { {1} }) -- order by in cte @@ -164,7 +163,7 @@ g.test_cte = function () SELECT b FROM cte ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {5}, {4} }) -- randomly distributed cte, used multiple times @@ -174,7 +173,7 @@ g.test_cte = function () JOIN cte ON true ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "C", type = "integer"} }) + t.assert_items_equals(r["metadata"], { {name = "c", type = "integer"} }) t.assert_items_equals(r["rows"], { {4}, {4} }) -- cte with segment distributed, used multiple times @@ -184,7 +183,7 @@ g.test_cte = function () JOIN cte ON true ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "C", type = "integer"} }) + t.assert_items_equals(r["metadata"], { {name = "c", type = "integer"} }) t.assert_items_equals(r["rows"], { {1} }) -- globally distributed cte, used multiple times @@ -194,7 +193,7 @@ g.test_cte = function () JOIN cte ON true ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "C", type = "integer"} }) + t.assert_items_equals(r["metadata"], { {name = "c", type = "integer"} }) t.assert_items_equals(r["rows"], { {1} }) -- cte with "serialize as empty table" opcode in motion @@ -204,7 +203,7 @@ g.test_cte = function () SELECT * FROM cte2 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "A", type = "unsigned"} }) + t.assert_items_equals(r["metadata"], { {name = "a", type = "unsigned"} }) t.assert_items_equals(r["rows"], { {1} }) r, err = api:call("sbroad.execute", { [[ @@ -219,7 +218,7 @@ g.test_cte = function () SELECT * FROM cte2 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "A", type = "unsigned"} }) + t.assert_items_equals(r["metadata"], { {name = "a", type = "unsigned"} }) t.assert_items_equals(r["rows"], { {1}, {1}, {1} }) end diff --git a/sbroad-cartridge/test_app/test/integration/groupby_test.lua b/sbroad-cartridge/test_app/test/integration/groupby_test.lua index 437c90618..04427e80e 100644 --- a/sbroad-cartridge/test_app/test/integration/groupby_test.lua +++ b/sbroad-cartridge/test_app/test/integration/groupby_test.lua @@ -401,7 +401,7 @@ groupby_queries.test_with_join2 = function () t.assert_equals(err, nil) t.assert_equals(r.metadata, { { name = "c", type = "integer" }, - { name = "A1", type = "integer" }, + { name = "a1", type = "integer" }, }) t.assert_items_equals(r.rows, { @@ -420,7 +420,7 @@ groupby_queries.test_with_join2 = function () t.assert_equals(err, nil) t.assert_equals(r.metadata, { { name = "c", type = "integer" }, - { name = "A1", type = "integer" }, + { name = "a1", type = "integer" }, }) t.assert_items_equals(r.rows, { @@ -651,7 +651,7 @@ groupby_queries.test_with_subquery_2 = function () t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "K", type = "integer" }, + { name = "k", type = "integer" }, }) t.assert_items_equals(r.rows, { { 2 }, @@ -865,7 +865,7 @@ groupby_queries.test_count = function() t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "CS", type = "integer" }, + { name = "cs", type = "integer" }, { name = "COL_1" , type = "decimal" } }) @@ -893,7 +893,7 @@ groupby_queries.test_groupby_arith_expression = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "U", type = "decimal" }, + { name = "u", type = "decimal" }, }) t.assert_items_equals(r.rows, { {1}, {1}, {1}, @@ -913,7 +913,7 @@ groupby_queries.test_grouping_by_concat = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "U", type = "string" }, + { name = "u", type = "string" }, }) t.assert_items_equals(r.rows, { {"aa"}, {"cb"}, @@ -1059,7 +1059,7 @@ groupby_queries.test_aggr_valid = function() t.assert_equals(err, nil) t.assert_equals(r.metadata, { { name = "c", type = "integer" }, - { name = "SS", type = "decimal" } + { name = "ss", type = "decimal" } }) t.assert_items_equals(r.rows, { {1, 4}, @@ -1274,10 +1274,10 @@ groupby_queries.test_join_single6 = function() local api = cluster:server("api-1").net_box local expected_metadata = { - { name = "A", type = "decimal" }, - { name = "B", type = "integer" }, - { name = "C", type = "integer" }, - { name = "D", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "b", type = "integer" }, + { name = "c", type = "integer" }, + { name = "d", type = "integer" }, } local expected_rows = { { 6, 4, 4, 6 }, @@ -1317,8 +1317,8 @@ groupby_queries.test_join_single7 = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "D", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "d", type = "integer" }, }) t.assert_items_equals(r.rows, { { 6, 6 }, @@ -1337,8 +1337,8 @@ groupby_queries.test_join_single8 = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "D", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "d", type = "integer" }, }) t.assert_items_equals(r.rows, { { 6, 6 }, @@ -1358,8 +1358,8 @@ groupby_queries.test_join_single9 = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "D", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "d", type = "integer" }, }) t.assert_items_equals(r.rows, { { 6, 2 }, @@ -1376,8 +1376,8 @@ groupby_queries.test_join_single10 = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "D", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "d", type = "integer" }, }) t.assert_items_equals(r.rows, { { 6, 2 }, @@ -2059,7 +2059,7 @@ groupby_queries.test_having_join = function() t.assert_equals(r.metadata, { { name = "COL_1", type = "decimal" }, { name = "b", type = "integer" }, - { name = "S", type = "integer" } + { name = "s", type = "integer" } }) t.assert_items_equals(r.rows, { { 2, 3, 1 } @@ -2082,8 +2082,8 @@ groupby_queries.test_having_full_query = function() t.assert_equals(err, nil) t.assert_equals(r.metadata, { { name = "a", type = "integer" }, - { name = "B", type = "integer" }, - { name = "S", type = "string" }, + { name = "b", type = "integer" }, + { name = "s", type = "string" }, { name = "d", type = "integer" }, }) t.assert_items_equals(r.rows, { @@ -2227,4 +2227,3 @@ groupby_queries.test_sum_on_decimal_col = function() }) t.assert_str_contains(tostring(err), "can't compute avg on argument with type number") end - diff --git a/sbroad-cartridge/test_app/test/integration/large_query_test.lua b/sbroad-cartridge/test_app/test/integration/large_query_test.lua index ca0a42478..e296f18a4 100644 --- a/sbroad-cartridge/test_app/test/integration/large_query_test.lua +++ b/sbroad-cartridge/test_app/test/integration/large_query_test.lua @@ -141,12 +141,12 @@ g.test_schema_invalid = function () "a"."common_text" AS "common_text1", "b1"."common_text2", "a"."date_start" AS "date_sort1", "a"."date_end" AS "date_end1", "b1"."date_sort2", "b1"."date_end2", "a"."common_detail" AS "common_detail1", "b1"."common_detail2", "a"."typology_type", "a"."typology_id" - FROM VSA_PROXY as "a" + FROM "VSA_PROXY" as "a" INNER JOIN (SELECT "b"."common_id" AS "common_id2", "b"."fid" AS "fid2", "b"."exclude_id" AS "exclude_id2", "b"."common_text" AS "common_text2", "b"."date_start" AS "date_sort2", "b"."date_end" AS "date_end2", "b"."common_detail" AS "common_detail2" - FROM VSA_PROXY as "b") as "b1" ON "a"."common_id" = "b1"."common_id2" + FROM "VSA_PROXY" as "b") as "b1" ON "a"."common_id" = "b1"."common_id2" WHERE "a"."fid" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717) AND "b1"."fid2" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717) AND "a"."fid" < "b1"."fid2" diff --git a/sbroad-cartridge/test_app/test/integration/left_outer_join_test.lua b/sbroad-cartridge/test_app/test/integration/left_outer_join_test.lua index a707e9872..8d7b1d3a3 100644 --- a/sbroad-cartridge/test_app/test/integration/left_outer_join_test.lua +++ b/sbroad-cartridge/test_app/test/integration/left_outer_join_test.lua @@ -161,8 +161,8 @@ left_join.test_left_join_false_condition = function() }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "decimal" }, + { name = "a", type = "integer" }, + { name = "b", type = "decimal" }, }) t.assert_items_equals(r.rows, { { 1, nil }, @@ -175,12 +175,13 @@ end left_join.test_left_join_local_execution = function() local api = cluster:server("api-1").net_box + local query = [[ + select * from (select "id" as "A" from "arithmetic_space") as "T1" + left outer join (select "id" as "B" from "arithmetic_space2") as "T2" + on "T1"."A" = "T2"."B" + ]] local r, err = api:call("sbroad.execute", { - [[ - select * from (select "id" as a from "arithmetic_space") as t1 - left outer join (select "id" as b from "arithmetic_space2") as t2 - on t1.a = t2.b - ]], {} + query, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { @@ -196,11 +197,7 @@ left_join.test_left_join_local_execution = function() -- check there is really no motion for join in plan r, err = api:call("sbroad.execute", { - [[ - explain select * from (select "id" as a from "arithmetic_space") as t1 - left join (select "id" as b from "arithmetic_space2") as t2 - on t1.a = t2.b - ]], {} + [[explain ]] .. query, {} }) t.assert_equals(err, nil) t.assert_items_equals(r, { @@ -221,9 +218,9 @@ end left_join.test_inner_segment_motion = function() local api = cluster:server("api-1").net_box local query_str = [[ - select * from (select "id" as a from "arithmetic_space") as t1 - left join (select "a" as b from "arithmetic_space2") as t2 - on t1.a = t2.b + select * from (select "id" as "A" from "arithmetic_space") as "T1" + left join (select "a" as "B" from "arithmetic_space2") as "T2" + on "T1"."A" = "T2"."B" ]]; local r, err = api:call("sbroad.execute", { query_str, {} }) @@ -263,9 +260,9 @@ end left_join.test_inner_full_motion = function() local api = cluster:server("api-1").net_box local query_str = [[ - select * from (select "id" as a from "arithmetic_space") as t1 - left join (select "a" as b from "arithmetic_space2") as t2 - on t1.a < t2.b + select * from (select "id" as "A" from "arithmetic_space") as "T1" + left join (select "a" as "B" from "arithmetic_space2") as "T2" + on "T1"."A" < "T2"."B" ]]; local r, err = api:call("sbroad.execute", { query_str, {} }) @@ -317,8 +314,8 @@ left_join.test_outer_segment_motion = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "B", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { { 2, 2 }, @@ -338,8 +335,8 @@ left_join.test_single_dist_outer = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "decimal" }, - { name = "B", type = "integer" }, + { name = "a", type = "decimal" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { { 2, 3 }, @@ -358,8 +355,8 @@ left_join.test_single_dist_both = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { { 1, 4 }, @@ -377,9 +374,9 @@ left_join.test_sq_with_full_motion = function() -- explain test can be found in sbroad explain tests local api = cluster:server("api-1").net_box local query_str = [[ - select * from (select "a" as a from "arithmetic_space") as t1 - left join (select "id" as b from "arithmetic_space2") as t2 - on t1.a in (select "a" + 1 from "arithmetic_space") + select * from (select "a" as "A" from "arithmetic_space") as "T1" + left join (select "id" as "B" from "arithmetic_space2") as "T2" + on "T1"."A" in (select "a" + 1 from "arithmetic_space") ]]; local r, err = api:call("sbroad.execute", { query_str, {} }) @@ -428,9 +425,9 @@ end left_join.test_sq_with_segment_motion = function() local api = cluster:server("api-1").net_box local query_str = [[ - select * from (select "id" as a from "arithmetic_space") as t1 - left join (select "id" as b from "arithmetic_space2") as t2 - on t1.a in (select "c" from "arithmetic_space") + select * from (select "id" as "A" from "arithmetic_space") as t1 + left join (select "id" as "B" from "arithmetic_space2") as t2 + on t1."A" in (select "c" from "arithmetic_space") ]]; local r, err = api:call("sbroad.execute", { query_str, {} }) @@ -453,13 +450,13 @@ left_join.test_sq_with_segment_motion = function() r, err = api:call("sbroad.execute", { "explain " .. query_str, {} }) t.assert_equals(err, nil) t.assert_items_equals(r, { - "projection (\"T1\".\"A\"::integer -> \"A\", \"T2\".\"B\"::integer -> \"B\")", - " left join on ROW(\"T1\".\"A\"::integer) in ROW($0)", - " scan \"T1\"", + "projection (\"t1\".\"A\"::integer -> \"A\", \"t2\".\"B\"::integer -> \"B\")", + " left join on ROW(\"t1\".\"A\"::integer) in ROW($0)", + " scan \"t1\"", " projection (\"arithmetic_space\".\"id\"::integer -> \"A\")", " scan \"arithmetic_space\"", " motion [policy: full]", - " scan \"T2\"", + " scan \"t2\"", " projection (\"arithmetic_space2\".\"id\"::integer -> \"B\")", " scan \"arithmetic_space2\"", "subquery $0:", @@ -526,8 +523,8 @@ left_join.test_table_with_nulls1 = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { { nil, nil }, @@ -550,8 +547,8 @@ left_join.test_table_with_nulls2 = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { { nil, nil }, @@ -577,8 +574,8 @@ left_join.test_empty_left_table = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, {}) end @@ -594,8 +591,8 @@ left_join.test_empty_right_table = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { {nil, nil}, @@ -618,7 +615,7 @@ left_join.test_groupby_after_join = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, + { name = "a", type = "integer" }, { name = "COL_1", type = "decimal" }, }) t.assert_items_equals(r.rows, { @@ -638,8 +635,8 @@ left_join.test_groupby_under_outer_child = function() local r, err = api:call("sbroad.execute", { query_str, {} }) t.assert_equals(err, nil) t.assert_equals(r.metadata, { - { name = "A", type = "integer" }, - { name = "B", type = "integer" }, + { name = "a", type = "integer" }, + { name = "b", type = "integer" }, }) t.assert_items_equals(r.rows, { {nil, nil}, @@ -666,7 +663,7 @@ SELECT sp2."name" FROM (select "yearquarter", "a_to", "b_to", "d_by_ab", "c_by_ab", "a_from", "b_from" - from SPACE1) AS sp1 + from "SPACE1") AS sp1 LEFT JOIN ( SELECT sp2_1."id" AS "sp2_id", @@ -687,7 +684,7 @@ FROM sp2_1."count_from", sp2_1."count_to" FROM - SPACE2 AS sp2_1 + "SPACE2" AS sp2_1 ) AS sp2 ON sp1."a_to" = sp2."sp2_a" AND sp1."b_to" = sp2."sp2_b" AND sp1."yearquarter" = sp2."sp2_yearquarter"]], {} }) t.assert_equals(err, nil) @@ -713,13 +710,13 @@ left_join.test_left_multi_join= function() local api = cluster:server("api-1").net_box local r, err = api:call("sbroad.execute", { [[ - SELECT space1."yearquarter", space2."name" FROM space1 - LEFT JOIN space2 - ON space1."a_to" = space2."a" AND space1."b_to" = space2."b" - AND space1."yearquarter" = space2."yearquarter" - LEFT JOIN space2 as space3 - ON space1."a_to" = space3."a" AND space1."b_to" = space3."b" - WHERE space2."yearquarter" = 4 + SELECT "SPACE1"."yearquarter", "SPACE2"."name" FROM "SPACE1" + LEFT JOIN "SPACE2" + ON "SPACE1"."a_to" = "SPACE2"."a" AND "SPACE1"."b_to" = "SPACE2"."b" + AND "SPACE1"."yearquarter" = "SPACE2"."yearquarter" + LEFT JOIN "SPACE2" as space3 + ON "SPACE1"."a_to" = space3."a" AND "SPACE1"."b_to" = space3."b" + WHERE "SPACE2"."yearquarter" = 4 ]], {} }) t.assert_equals(err, nil) diff --git a/sbroad-cartridge/test_app/test/integration/limit_test.lua b/sbroad-cartridge/test_app/test/integration/limit_test.lua index 6a4643e25..cecb0d5dc 100644 --- a/sbroad-cartridge/test_app/test/integration/limit_test.lua +++ b/sbroad-cartridge/test_app/test/integration/limit_test.lua @@ -57,7 +57,7 @@ g.test_limit = function() SELECT b FROM cte ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_items_equals(r["rows"], { {1}, {2}, {1}, {2} }) -- cte with limit @@ -69,7 +69,7 @@ g.test_limit = function() LIMIT 1 ]], }) t.assert_equals(err, nil) - t.assert_items_equals(r["metadata"], { {name = "B", type = "number"} }) + t.assert_items_equals(r["metadata"], { {name = "b", type = "number"} }) t.assert_equals(#r["rows"], 1) -- limit in a subquery diff --git a/sbroad-cartridge/test_app/test/integration/operators_test.lua b/sbroad-cartridge/test_app/test/integration/operators_test.lua index 1fc8221d7..ce4342ade 100644 --- a/sbroad-cartridge/test_app/test/integration/operators_test.lua +++ b/sbroad-cartridge/test_app/test/integration/operators_test.lua @@ -196,7 +196,7 @@ g.test_not_eq2 = function() t.assert_items_equals(r, { metadata = { {name = "id", type = "integer"}, - {name = "U", type = "integer"} + {name = "u", type = "integer"} }, rows = { {1, 2}, {1, 3}, {1, 4}, @@ -377,7 +377,7 @@ g.test_not_in_subquery_select_from_values = function() local r, err = api:call("sbroad.execute", { [[ SELECT "id" FROM "space_simple_shard_key" - WHERE "id" NOT IN (SELECT cast(COLUMN_2 as int) FROM (VALUES (1), (3))) + WHERE "id" NOT IN (SELECT cast("COLUMN_2" as int) FROM (VALUES (1), (3))) ]], {} }) t.assert_equals(err, nil) @@ -395,7 +395,7 @@ g.test_in_subquery_select_from_values = function() local api = cluster:server("api-1").net_box local r, err = api:call("sbroad.execute", { [[ - SELECT "id" FROM "space_simple_shard_key_hist" WHERE "id" IN (SELECT cast(COLUMN_1 as int) FROM (VALUES (1))) + SELECT "id" FROM "space_simple_shard_key_hist" WHERE "id" IN (SELECT cast("COLUMN_1" as int) FROM (VALUES (1))) ]], {1} }) t.assert_equals(err, nil) @@ -435,7 +435,7 @@ g.test_not_exists_subquery_select_from_values = function() -- NotExists condition should return false on each row from t -- as soon as it's subquery always returns one row. local r, err = api:call("sbroad.execute", { [[ - SELECT "id" FROM "t" WHERE NOT EXISTS (SELECT cast(COLUMN_1 as int) FROM (VALUES (1))) + SELECT "id" FROM "t" WHERE NOT EXISTS (SELECT cast("COLUMN_1" as int) FROM (VALUES (1))) ]], {} }) t.assert_equals(err, nil) diff --git a/sbroad-core/src/backend/sql/ir.rs b/sbroad-core/src/backend/sql/ir.rs index 1bcd1478e..b8a736077 100644 --- a/sbroad-core/src/backend/sql/ir.rs +++ b/sbroad-core/src/backend/sql/ir.rs @@ -238,6 +238,15 @@ impl ExecutionPlan { let vtable_engine = self.vtable_engine()?; let capacity = self.get_vtables().map_or(1, HashMap::len); let mut tmp_spaces = TmpSpaceMap::with_capacity(capacity); + // In our data structures, we store plan identifiers without + // quotes in normalized form, but tarantool local sql has + // different normalizing rules (to uppercase), so we need + // to wrap all names in quotes. + let push_identifier = |sql: &mut String, identifier: &str| { + sql.push('\"'); + sql.push_str(identifier); + sql.push('\"'); + }; let (sql, params) = child_span("\"syntax.ordered.sql\"", || { let mut params: Vec<Value> = Vec::new(); @@ -278,6 +287,10 @@ impl ExecutionPlan { // TODO: should we care about plans without projections? // Or they should be treated as invalid? SyntaxData::Alias(s) => { + sql.push_str("as "); + push_identifier(&mut sql, s); + } + SyntaxData::UnquotedAlias(s) => { sql.push_str("as "); sql.push_str(s); } @@ -355,14 +368,14 @@ impl ExecutionPlan { } Relational::Insert { relation, .. } => { sql.push_str("INSERT INTO "); - sql.push_str(relation.as_str()); + push_identifier(&mut sql, relation); } Relational::Join { kind, .. } => sql.push_str( format!("{} JOIN", kind.to_string().to_uppercase()).as_str(), ), Relational::Projection { .. } => sql.push_str("SELECT"), Relational::ScanRelation { relation, .. } => { - sql.push_str(relation); + push_identifier(&mut sql, relation); } Relational::ScanSubQuery { .. } | Relational::ScanCte { .. } @@ -416,9 +429,9 @@ impl ExecutionPlan { ) })?; if let Some(name) = (*vt).get_alias() { - sql.push_str(name); + push_identifier(&mut sql, name); sql.push('.'); - sql.push_str(alias); + push_identifier(&mut sql, alias); continue; } } @@ -428,21 +441,28 @@ impl ExecutionPlan { if rel_node.is_insert() { // We expect `INSERT INTO t(a, b) VALUES(1, 2)` // rather then `INSERT INTO t(t.a, t.b) VALUES(1, 2)`. - sql.push_str(alias); + push_identifier(&mut sql, alias); continue; } if let Some(name) = rel_node.scan_name(ir_plan, *position)? { - sql.push_str(name); + push_identifier(&mut sql, name); sql.push('.'); - sql.push_str(alias); + push_identifier(&mut sql, alias); + continue; } - sql.push_str(alias); + push_identifier(&mut sql, alias); } - Expression::StableFunction { name, .. } => { - sql.push_str(name.as_str()); + Expression::StableFunction { + name, is_system, .. + } => { + if *is_system { + sql.push_str(name); + } else { + push_identifier(&mut sql, name); + } } Expression::CountAsterisk => { sql.push('*'); @@ -466,20 +486,18 @@ impl ExecutionPlan { SyntaxData::VTable(motion_id) => { let name = TmpSpace::generate_space_name(name_base, *motion_id); let vtable = self.get_motion_vtable(*motion_id)?; - let col_names = vtable - .get_columns() - .iter() - .map(|c| { - if let (Some('"'), Some('"')) = - (c.name.chars().next(), c.name.chars().last()) - { - c.name.clone() - } else { - format_smolstr!("\"{}\"", c.name) - } - }) - .collect::<Vec<_>>() - .join(","); + + // for each name we wrap it in quotes and add a comma (except last name): 2 + 1 + let cp: usize = vtable.get_columns().iter().map(|c| c.name.len() + 3).sum(); + let mut col_names = String::with_capacity(cp.saturating_sub(1)); + if let Some((last, other)) = vtable.get_columns().split_last() { + for col in other { + push_identifier(&mut col_names, &col.name); + col_names.push(','); + } + push_identifier(&mut col_names, &last.name); + } + write!(sql, "SELECT {col_names} FROM \"{name}\"").map_err(|e| { SbroadError::FailedTo( Action::Serialize, diff --git a/sbroad-core/src/backend/sql/ir/tests/selection.rs b/sbroad-core/src/backend/sql/ir/tests/selection.rs index 889ecbba2..7e1b97e2c 100644 --- a/sbroad-core/src/backend/sql/ir/tests/selection.rs +++ b/sbroad-core/src/backend/sql/ir/tests/selection.rs @@ -5,7 +5,7 @@ use crate::ir::value::Value; #[test] fn selection_column_from_values() { let query = r#" - SELECT COLUMN_1 FROM (VALUES (1)) + SELECT "COLUMN_1" FROM (VALUES (1)) "#; let expected = PatternWithParams::new( diff --git a/sbroad-core/src/backend/sql/ir/tests/sub_query.rs b/sbroad-core/src/backend/sql/ir/tests/sub_query.rs index 917595f9d..7a9fbf0bf 100644 --- a/sbroad-core/src/backend/sql/ir/tests/sub_query.rs +++ b/sbroad-core/src/backend/sql/ir/tests/sub_query.rs @@ -13,10 +13,10 @@ fn sub_query1_latest() { let expected = PatternWithParams::new( format!( "{} {} {} {}", - r#"SELECT "T1"."product_code" FROM"#, + r#"SELECT "t1"."product_code" FROM"#, r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#, - r#"WHERE ("hash_testing"."identification_number") = (?)) as "T1""#, - r#"WHERE ("T1"."product_code") = (?)"# + r#"WHERE ("hash_testing"."identification_number") = (?)) as "t1""#, + r#"WHERE ("t1"."product_code") = (?)"# ), vec![Value::from(1_u64), Value::from("a")], ); @@ -28,7 +28,7 @@ fn sub_query1_oldest() { let query = r#"SELECT "product_code" FROM (SELECT "product_code" FROM "hash_testing" - WHERE "identification_number" = 1) as t1 + WHERE "identification_number" = 1) as "T1" WHERE "product_code" = 'a'"#; let expected = PatternWithParams::new( diff --git a/sbroad-core/src/backend/sql/tree.rs b/sbroad-core/src/backend/sql/tree.rs index bbc828489..7e34f212e 100644 --- a/sbroad-core/src/backend/sql/tree.rs +++ b/sbroad-core/src/backend/sql/tree.rs @@ -16,8 +16,10 @@ use sbroad_proc::otm_child_span; /// Payload of the syntax tree node. #[derive(Clone, Deserialize, Debug, PartialEq, Eq, Serialize)] pub enum SyntaxData { - /// "as alias_name" + /// "as \"alias_name\"" Alias(SmolStr), + /// "as alias_name" + UnquotedAlias(SmolStr), /// "cast" Cast, // "case" @@ -114,6 +116,14 @@ impl SyntaxNode { } } + fn new_unquoted_alias(name: SmolStr) -> Self { + SyntaxNode { + data: SyntaxData::UnquotedAlias(name), + left: None, + right: Vec::new(), + } + } + fn new_cast() -> Self { SyntaxNode { data: SyntaxData::Cast, @@ -1199,7 +1209,7 @@ impl<'p> SyntaxPlan<'p> { let children = vec![ arena.push_sn_non_plan(SyntaxNode::new_open()), child_sn_id, - arena.push_sn_non_plan(SyntaxNode::new_alias(to_alias)), + arena.push_sn_non_plan(SyntaxNode::new_unquoted_alias(to_alias)), arena.push_sn_non_plan(SyntaxNode::new_close()), ]; let cast_sn_id = arena.push_sn_non_plan(SyntaxNode::new_cast()); diff --git a/sbroad-core/src/builtins.lua b/sbroad-core/src/builtins.lua index 0127a328c..d2411fb2e 100644 --- a/sbroad-core/src/builtins.lua +++ b/sbroad-core/src/builtins.lua @@ -46,7 +46,7 @@ local function init() -- name, so for each func we provide a body. local body = string.format("function(...) return %s.builtins.TO_DATE(...) end", module) - box.schema.func.create("TO_DATE", { + box.schema.func.create("to_date", { language = 'LUA', returns = 'datetime', body = body, @@ -58,7 +58,7 @@ local function init() body = string.format("function(...) return %s.builtins.TO_CHAR(...) end", module) - box.schema.func.create("TO_CHAR", { + box.schema.func.create("to_char", { language = 'LUA', returns = 'string', body = body, diff --git a/sbroad-core/src/cbo/histogram/tests.rs b/sbroad-core/src/cbo/histogram/tests.rs index ea6c46dbe..739697ff3 100644 --- a/sbroad-core/src/cbo/histogram/tests.rs +++ b/sbroad-core/src/cbo/histogram/tests.rs @@ -13,7 +13,7 @@ fn stats_merge() { let coordinator = RouterRuntimeMock::new(); let (table_stats, sys_from_stats_wrapped) = - get_table_column_stats_downcasted::<i64>(&coordinator, &String::from("\"test_space\""), 1); + get_table_column_stats_downcasted::<i64>(&coordinator, &String::from("test_space"), 1); let test_space_rows_count = 25000.0; let column_stats_unwrapped = ColumnStatsUnwrapped::from_column_stats(&sys_from_stats_wrapped); diff --git a/sbroad-core/src/cbo/selectivity.rs b/sbroad-core/src/cbo/selectivity.rs index 5dc6b85b8..2ffe84bb2 100644 --- a/sbroad-core/src/cbo/selectivity.rs +++ b/sbroad-core/src/cbo/selectivity.rs @@ -6,6 +6,7 @@ use crate::cbo::histogram::Scalar; use crate::cbo::{ColumnStats, TableColumnPair, TableStats}; use crate::errors::{Entity, SbroadError}; +use crate::executor::engine::helpers::to_user; use crate::executor::engine::{Metadata, Router, Statistics}; use crate::ir::operator::Bool; use crate::ir::relation::{Column, Type}; @@ -249,7 +250,8 @@ pub fn calculate_filter_selectivity( SbroadError::Invalid( Entity::Statistics, Some(format_smolstr!( - "Column with name {table_name} is not found in metadata", + "Column with name {} is not found in metadata", + to_user(table_name) )), ) })?; @@ -373,7 +375,8 @@ pub fn calculate_condition_selectivity( SbroadError::Invalid( Entity::Statistics, Some(format_smolstr!( - "Column with name {left_table_name} is not found in metadata", + "Column with name {} is not found in metadata", + to_user(left_table_name) )), ) })?; @@ -395,7 +398,8 @@ pub fn calculate_condition_selectivity( SbroadError::Invalid( Entity::Statistics, Some(format_smolstr!( - "Column with name {right_table_name} is not found in metadata", + "Column with name {} is not found in metadata", + to_user(right_table_name), )), ) })?; diff --git a/sbroad-core/src/cbo/selectivity/tests.rs b/sbroad-core/src/cbo/selectivity/tests.rs index 39b316829..d52348e15 100644 --- a/sbroad-core/src/cbo/selectivity/tests.rs +++ b/sbroad-core/src/cbo/selectivity/tests.rs @@ -10,7 +10,7 @@ use tarantool::decimal; #[test] fn numeric_filter_eq_selectivity() { let runtime = RouterRuntimeMock::new(); - let table_name = SmolStr::from("\"test_space\""); + let table_name = SmolStr::from("test_space"); let column_index = 0; let constant = Value::from(4u64); diff --git a/sbroad-core/src/executor.rs b/sbroad-core/src/executor.rs index a306d9b02..24e90d088 100644 --- a/sbroad-core/src/executor.rs +++ b/sbroad-core/src/executor.rs @@ -29,7 +29,6 @@ use std::rc::Rc; use crate::errors::{Entity, SbroadError}; use crate::executor::bucket::Buckets; -use crate::executor::engine::helpers::normalize_name_for_space_api; use crate::executor::engine::{helpers::materialize_values, Router, TableVersionMap, Vshard}; use crate::executor::ir::ExecutionPlan; use crate::executor::lru::Cache; @@ -135,9 +134,9 @@ where if tbl.is_system() { continue; } - let normalized = normalize_name_for_space_api(tbl_name); + let normalized = tbl_name; let version = coordinator.get_table_version(normalized.as_str())?; - table_version_map.insert(normalized, version); + table_version_map.insert(normalized.clone(), version); } plan.version_map = table_version_map; } diff --git a/sbroad-core/src/executor/bucket/tests.rs b/sbroad-core/src/executor/bucket/tests.rs index 8fb990485..8b43ed12f 100644 --- a/sbroad-core/src/executor/bucket/tests.rs +++ b/sbroad-core/src/executor/bucket/tests.rs @@ -365,7 +365,7 @@ fn global_tbl_join2() { // we have an "A" aliased column. let query = r#" select * from "global_t" - inner join (select "a" as a from "global_t") + inner join (select "a" as q from "global_t") on ("a", "b") in (select "e", "f" from "t2") "#; diff --git a/sbroad-core/src/executor/engine.rs b/sbroad-core/src/executor/engine.rs index 9cdafb074..554035e3f 100644 --- a/sbroad-core/src/executor/engine.rs +++ b/sbroad-core/src/executor/engine.rs @@ -33,7 +33,7 @@ pub mod mock; /// A metadata trait of the cluster (getters for tables, functions, etc.). pub trait Metadata: Sized { - /// Get a table by name that contains: + /// Get a table by normalized name that contains: /// * list of the columns, /// * distribution key of the output tuples (column positions), /// * table name. @@ -75,9 +75,9 @@ pub fn get_builtin_functions() -> &'static [Function] { unsafe { BUILTINS.get_or_init(|| { vec![ - Function::new_stable("\"TO_DATE\"".into(), Type::Datetime), - Function::new_stable("\"TO_CHAR\"".into(), Type::String), - Function::new_stable("\"SUBSTR\"".into(), Type::String), + Function::new_stable("to_date".into(), Type::Datetime, false), + Function::new_stable("to_char".into(), Type::String, false), + Function::new_stable("substr".into(), Type::String, true), ] }) } diff --git a/sbroad-core/src/executor/engine/helpers.rs b/sbroad-core/src/executor/engine/helpers.rs index c0e00ba3e..df47e3740 100644 --- a/sbroad-core/src/executor/engine/helpers.rs +++ b/sbroad-core/src/executor/engine/helpers.rs @@ -60,31 +60,32 @@ use super::{Metadata, Router, Vshard}; pub mod storage; pub mod vshard; -#[must_use] -pub fn normalize_name_from_schema(s: &str) -> SmolStr { - format_smolstr!("\"{s}\"") -} - /// Transform: -/// * "s" -> "s" (same cased, quoted) -/// * s -> "S" (uppercased, quoted) +/// +/// ```text +/// * "AbC" -> AbC (same cased, unquoted) +/// * AbC -> abc (lowercased, unquoted) +/// ``` #[must_use] pub fn normalize_name_from_sql(s: &str) -> SmolStr { if let (Some('"'), Some('"')) = (s.chars().next(), s.chars().last()) { - return s.to_smolstr(); + return SmolStr::from(&s[1..s.len() - 1]); } - format_smolstr!("\"{}\"", s.to_uppercase()) + SmolStr::new(s.to_lowercase()) } /// Transform: -/// * "s" -> s (same cased, unquoted) -/// * s -> S (uppercased, unquoted) +/// * s -> "s" (same cased, quoted) +/// +/// This function is used to convert identifiers +/// to user-friendly format for errors and explain +/// query. +/// +/// # Panics +/// - never #[must_use] -pub fn normalize_name_for_space_api(s: &str) -> SmolStr { - if let (Some('"'), Some('"')) = (s.chars().next(), s.chars().last()) { - return SmolStr::from(&s[1..s.len() - 1]); - } - s.to_uppercase().to_smolstr() +pub fn to_user<T: std::fmt::Display>(from: T) -> SmolStr { + format_smolstr!("\"{from}\"") } /// A helper function to encode the execution plan into a pair of binary data (see `Message`): @@ -1003,10 +1004,9 @@ pub fn sharding_key_from_tuple<'tuple>( space: &str, tuple: &'tuple [Value], ) -> Result<Vec<&'tuple Value>, SbroadError> { - let quoted_space = normalize_name_from_schema(space); - let sharding_positions = conf.sharding_positions_by_space("ed_space)?; + let sharding_positions = conf.sharding_positions_by_space(space)?; let mut sharding_tuple = Vec::with_capacity(sharding_positions.len()); - let table_col_amount = conf.table("ed_space)?.columns.len(); + let table_col_amount = conf.table(space)?.columns.len(); if table_col_amount == tuple.len() { // The tuple contains a "bucket_id" column. for position in &sharding_positions { @@ -1021,7 +1021,7 @@ pub fn sharding_key_from_tuple<'tuple>( Ok(sharding_tuple) } else if table_col_amount == tuple.len() + 1 { // The tuple doesn't contain the "bucket_id" column. - let table = conf.table("ed_space)?; + let table = conf.table(space)?; let bucket_position = table.get_bucket_id_position()?.ok_or_else(|| { SbroadError::Invalid( Entity::Space, @@ -1335,7 +1335,7 @@ where let plan = optional.exec_plan.get_ir_plan(); let update_id = plan.get_top()?; let update_child_id = plan.dml_child_id(update_id)?; - let space_name = normalize_name_for_space_api(plan.dml_node_table(update_id)?.name()); + let space_name = plan.dml_node_table(update_id)?.name().clone(); let mut result = ConsumerResult::default(); let is_sharded = plan.is_sharded_update(update_id)?; let build_vtable_locally = optional @@ -1618,7 +1618,7 @@ where let delete_id = plan.get_top()?; let delete_child_id = plan.dml_child_id(delete_id)?; let builder = init_delete_tuple_builder(plan, delete_id)?; - let space_name = normalize_name_for_space_api(plan.dml_node_table(delete_id)?.name()); + let space_name = plan.dml_node_table(delete_id)?.name().clone(); let mut result = ConsumerResult::default(); let build_vtable_locally = optional .exec_plan @@ -1667,7 +1667,7 @@ where let plan = optional.exec_plan.get_ir_plan(); let insert_id = plan.get_top()?; let insert_child_id = plan.dml_child_id(insert_id)?; - let space_name = normalize_name_for_space_api(plan.dml_node_table(insert_id)?.name()); + let space_name = plan.dml_node_table(insert_id)?.name().clone(); let mut result = ConsumerResult::default(); // There are two ways to execute an `INSERT` query: @@ -1893,11 +1893,10 @@ pub fn sharding_key_from_map<'rec, S: ::std::hash::BuildHasher>( space: &str, map: &'rec HashMap<SmolStr, Value, S>, ) -> Result<Vec<&'rec Value>, SbroadError> { - let quoted_space = normalize_name_from_schema(space); - let sharding_key = conf.sharding_key_by_space("ed_space)?; + let sharding_key = conf.sharding_key_by_space(space)?; let quoted_map = map .iter() - .map(|(k, _)| (normalize_name_from_schema(k).to_smolstr(), k.as_str())) + .map(|(k, _)| (k.to_smolstr(), k.as_str())) .collect::<HashMap<SmolStr, &str>>(); let mut tuple = Vec::with_capacity(sharding_key.len()); for quoted_column in &sharding_key { @@ -1946,11 +1945,7 @@ pub fn try_get_metadata_from_plan( let column = ir.get_expression_node(*col_id)?; let column_type = column.calculate_type(ir)?.to_string(); let column_name = if let Expression::Alias { name, .. } = column { - let mut chars = name.chars(); - // remove quotes from the name - chars.next(); - chars.next_back(); - chars.as_str().to_owned() + name.to_string() } else { return Err(SbroadError::Invalid( Entity::Expression, diff --git a/sbroad-core/src/executor/engine/mock.rs b/sbroad-core/src/executor/engine/mock.rs index d9cdaac96..f886b1e89 100644 --- a/sbroad-core/src/executor/engine/mock.rs +++ b/sbroad-core/src/executor/engine/mock.rs @@ -55,8 +55,7 @@ pub struct RouterConfigurationMock { impl Metadata for RouterConfigurationMock { fn table(&self, table_name: &str) -> Result<Table, SbroadError> { - let name = normalize_name_from_sql(table_name); - match self.tables.get(&name) { + match self.tables.get(table_name) { Some(v) => Ok(v.clone()), None => Err(SbroadError::NotFound( Entity::Space, @@ -107,9 +106,9 @@ impl RouterConfigurationMock { #[must_use] pub fn new() -> Self { let name_func = normalize_name_from_sql("func"); - let fn_func = Function::new_stable(name_func.clone(), Type::Integer); + let fn_func = Function::new_stable(name_func.clone(), Type::Integer, false); let name_trim = normalize_name_from_sql("trim"); - let trim_func = Function::new_stable(name_trim.clone(), Type::String); + let trim_func = Function::new_stable(name_trim.clone(), Type::String, false); let mut functions = HashMap::new(); functions.insert(name_func, fn_func); functions.insert(name_trim, trim_func); @@ -121,22 +120,22 @@ impl RouterConfigurationMock { let columns = vec![ Column::new( - "\"identification_number\"", + "identification_number", Type::Integer, ColumnRole::User, false, ), - Column::new("\"product_code\"", Type::String, ColumnRole::User, false), - Column::new("\"product_units\"", Type::Boolean, ColumnRole::User, true), - Column::new("\"sys_op\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("product_code", Type::String, ColumnRole::User, false), + Column::new("product_units", Type::Boolean, ColumnRole::User, true), + Column::new("sys_op", Type::Unsigned, ColumnRole::User, true), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key = &["\"identification_number\"", "\"product_code\""]; - let primary_key = &["\"product_code\"", "\"identification_number\""]; + let sharding_key = &["identification_number", "product_code"]; + let primary_key = &["product_code", "identification_number"]; tables.insert( - "\"hash_testing\"".to_smolstr(), + "hash_testing".to_smolstr(), Table::new_sharded( - "\"hash_testing\"", + "hash_testing", columns.clone(), sharding_key, primary_key, @@ -146,9 +145,9 @@ impl RouterConfigurationMock { ); tables.insert( - "\"hash_testing_hist\"".to_smolstr(), + "hash_testing_hist".to_smolstr(), Table::new_sharded( - "\"hash_testing_hist\"", + "hash_testing_hist", columns.clone(), sharding_key, primary_key, @@ -157,11 +156,11 @@ impl RouterConfigurationMock { .unwrap(), ); - let sharding_key = &["\"identification_number\""]; + let sharding_key = &["identification_number"]; tables.insert( - "\"hash_single_testing\"".to_smolstr(), + "hash_single_testing".to_smolstr(), Table::new_sharded( - "\"hash_single_testing\"", + "hash_single_testing", columns.clone(), sharding_key, primary_key, @@ -171,9 +170,9 @@ impl RouterConfigurationMock { ); tables.insert( - "\"hash_single_testing_hist\"".to_smolstr(), + "hash_single_testing_hist".to_smolstr(), Table::new_sharded( - "\"hash_single_testing_hist\"", + "hash_single_testing_hist", columns, sharding_key, primary_key, @@ -183,19 +182,19 @@ impl RouterConfigurationMock { ); let columns = vec![ - Column::new("\"id\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"sysFrom\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"FIRST_NAME\"", Type::String, ColumnRole::User, true), - Column::new("\"sys_op\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("id", Type::Unsigned, ColumnRole::User, false), + Column::new("sysFrom", Type::Unsigned, ColumnRole::User, true), + Column::new("FIRST_NAME", Type::String, ColumnRole::User, true), + Column::new("sys_op", Type::Unsigned, ColumnRole::User, true), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key = &["\"id\""]; - let primary_key = &["\"id\""]; + let sharding_key = &["id"]; + let primary_key = &["id"]; tables.insert( - "\"test_space\"".to_smolstr(), + "test_space".to_smolstr(), Table::new_sharded( - "\"test_space\"", + "test_space", columns.clone(), sharding_key, primary_key, @@ -205,9 +204,9 @@ impl RouterConfigurationMock { ); tables.insert( - "\"test_space_hist\"".to_smolstr(), + "test_space_hist".to_smolstr(), Table::new_sharded( - "\"test_space_hist\"", + "test_space_hist", columns, sharding_key, primary_key, @@ -217,15 +216,15 @@ impl RouterConfigurationMock { ); let columns = vec![ - Column::new("\"id\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("id", Type::Unsigned, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key: &[&str] = &["\"id\""]; - let primary_key: &[&str] = &["\"id\""]; + let sharding_key: &[&str] = &["id"]; + let primary_key: &[&str] = &["id"]; tables.insert( - "\"history\"".to_smolstr(), + "history".to_smolstr(), Table::new_sharded( - "\"history\"", + "history", columns, sharding_key, primary_key, @@ -235,16 +234,16 @@ impl RouterConfigurationMock { ); let columns = vec![ - Column::new("\"A\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"B\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("A", Type::Unsigned, ColumnRole::User, true), + Column::new("B", Type::Unsigned, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key: &[&str] = &["\"A\"", "\"B\""]; - let primary_key: &[&str] = &["\"B\""]; + let sharding_key: &[&str] = &["A", "B"]; + let primary_key: &[&str] = &["B"]; tables.insert( - "\"TBL\"".to_smolstr(), + "TBL".to_smolstr(), Table::new_sharded( - "\"TBL\"", + "TBL", columns, sharding_key, primary_key, @@ -254,622 +253,452 @@ impl RouterConfigurationMock { ); let columns = vec![ - Column::new("\"a\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"b\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"c\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"d\"", Type::Unsigned, ColumnRole::User, true), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("a", Type::Unsigned, ColumnRole::User, true), + Column::new("b", Type::Unsigned, ColumnRole::User, false), + Column::new("c", Type::Unsigned, ColumnRole::User, true), + Column::new("d", Type::Unsigned, ColumnRole::User, true), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key: &[&str] = &["\"a\"", "\"b\""]; - let primary_key: &[&str] = &["\"b\""]; + let sharding_key: &[&str] = &["a", "b"]; + let primary_key: &[&str] = &["b"]; tables.insert( - "\"t\"".to_smolstr(), - Table::new_sharded( - "\"t\"", - columns, - sharding_key, - primary_key, - SpaceEngine::Memtx, - ) - .unwrap(), + "t".to_smolstr(), + Table::new_sharded("t", columns, sharding_key, primary_key, SpaceEngine::Memtx) + .unwrap(), ); let columns = vec![ - Column::new("\"a\"", Type::String, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), - Column::new("\"b\"", Type::Integer, ColumnRole::User, false), + Column::new("a", Type::String, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("b", Type::Integer, ColumnRole::User, false), ]; - let sharding_key: &[&str] = &["\"a\"", "\"b\""]; - let primary_key: &[&str] = &["\"a\"", "\"b\""]; + let sharding_key: &[&str] = &["a", "b"]; + let primary_key: &[&str] = &["a", "b"]; tables.insert( - "\"t1\"".to_smolstr(), - Table::new_sharded( - "\"t1\"", - columns, - sharding_key, - primary_key, - SpaceEngine::Memtx, - ) - .unwrap(), + "t1".to_smolstr(), + Table::new_sharded("t1", columns, sharding_key, primary_key, SpaceEngine::Memtx) + .unwrap(), ); let columns = vec![ - Column::new("\"e\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"f\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"g\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"h\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("e", Type::Unsigned, ColumnRole::User, false), + Column::new("f", Type::Unsigned, ColumnRole::User, false), + Column::new("g", Type::Unsigned, ColumnRole::User, false), + Column::new("h", Type::Unsigned, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key: &[&str] = &["\"e\"", "\"f\""]; - let primary_key: &[&str] = &["\"g\"", "\"h\""]; + let sharding_key: &[&str] = &["e", "f"]; + let primary_key: &[&str] = &["g", "h"]; tables.insert( - "\"t2\"".to_smolstr(), - Table::new_sharded( - "\"t2\"", - columns, - sharding_key, - primary_key, - SpaceEngine::Memtx, - ) - .unwrap(), + "t2".to_smolstr(), + Table::new_sharded("t2", columns, sharding_key, primary_key, SpaceEngine::Memtx) + .unwrap(), ); let columns = vec![ - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), - Column::new("\"a\"", Type::String, ColumnRole::User, false), - Column::new("\"b\"", Type::Integer, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("a", Type::String, ColumnRole::User, false), + Column::new("b", Type::Integer, ColumnRole::User, false), ]; - let sharding_key: &[&str] = &["\"a\""]; - let primary_key: &[&str] = &["\"a\""]; + let sharding_key: &[&str] = &["a"]; + let primary_key: &[&str] = &["a"]; tables.insert( - "\"t3\"".to_smolstr(), - Table::new_sharded( - "\"t3\"", - columns, - sharding_key, - primary_key, - SpaceEngine::Memtx, - ) - .unwrap(), + "t3".to_smolstr(), + Table::new_sharded("t3", columns, sharding_key, primary_key, SpaceEngine::Memtx) + .unwrap(), ); let columns = vec![ - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), - Column::new("\"c\"", Type::String, ColumnRole::User, false), - Column::new("\"d\"", Type::Integer, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("c", Type::String, ColumnRole::User, false), + Column::new("d", Type::Integer, ColumnRole::User, false), ]; - let sharding_key: &[&str] = &["\"c\""]; - let primary_key: &[&str] = &["\"d\""]; + let sharding_key: &[&str] = &["c"]; + let primary_key: &[&str] = &["d"]; tables.insert( - "\"t4\"".to_smolstr(), - Table::new_sharded( - "\"t4\"", - columns, - sharding_key, - primary_key, - SpaceEngine::Memtx, - ) - .unwrap(), + "t4".to_smolstr(), + Table::new_sharded("t4", columns, sharding_key, primary_key, SpaceEngine::Memtx) + .unwrap(), ); let columns = vec![ - Column::new("\"a\"", Type::Integer, ColumnRole::User, false), - Column::new("\"b\"", Type::Integer, ColumnRole::User, false), + Column::new("a", Type::Integer, ColumnRole::User, false), + Column::new("b", Type::Integer, ColumnRole::User, false), ]; - let primary_key: &[&str] = &["\"a\""]; + let primary_key: &[&str] = &["a"]; tables.insert( - "\"global_t\"".to_smolstr(), - Table::new_global("\"global_t\"", columns, primary_key).unwrap(), + "global_t".to_smolstr(), + Table::new_global("global_t", columns, primary_key).unwrap(), ); // Table for sbroad-benches let columns = vec![ - Column::new("\"vehicleguid\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"reestrid\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"reestrstatus\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"vehicleregno\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"vehiclevin\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"vehiclevin2\"", Type::Unsigned, ColumnRole::User, false), - Column::new( - "\"vehiclechassisnum\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclereleaseyear\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"operationregdoctypename\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"operationregdoc\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"operationregdocissuedate\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"operationregdoccomments\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleptstypename\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new("\"vehicleptsnum\"", Type::Unsigned, ColumnRole::User, false), - Column::new( - "\"vehicleptsissuedate\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleptsissuer\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleptscomments\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclebodycolor\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new("\"vehiclebrand\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"vehiclemodel\"", Type::Unsigned, ColumnRole::User, false), - Column::new( - "\"vehiclebrandmodel\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclebodynum\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new("\"vehiclecost\"", Type::Unsigned, ColumnRole::User, false), - Column::new( - "\"vehiclegasequip\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleproducername\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclegrossmass\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new("\"vehiclemass\"", Type::Unsigned, ColumnRole::User, false), - Column::new( - "\"vehiclesteeringwheeltypeid\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclekpptype\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicletransmissiontype\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicletypename\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclecategory\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicletypeunit\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleecoclass\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehiclespecfuncname\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleenclosedvolume\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleenginemodel\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleenginenum\"", - Type::Unsigned, - ColumnRole::User, - false, - ), - Column::new( - "\"vehicleenginepower\"", - Type::Unsigned, - ColumnRole::User, - false, - ), + Column::new("vehicleguid", Type::Unsigned, ColumnRole::User, false), + Column::new("reestrid", Type::Unsigned, ColumnRole::User, false), + Column::new("reestrstatus", Type::Unsigned, ColumnRole::User, false), + Column::new("vehicleregno", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclevin", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclevin2", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclechassisnum", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"vehicleenginepowerkw\"", + "vehiclereleaseyear", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"vehicleenginetype\"", + "operationregdoctypename", Type::Unsigned, ColumnRole::User, false, ), + Column::new("operationregdoc", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holdrestrictiondate\"", + "operationregdocissuedate", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"approvalnum\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"approvaldate\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"approvaltype\"", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"utilizationfeename\"", + "operationregdoccomments", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"customsdoc\"", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"customsdocdate\"", + "vehicleptstypename", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehicleptsnum", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"customsdocissue\"", + "vehicleptsissuedate", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehicleptsissuer", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"customsdocrestriction\"", + "vehicleptscomments", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehiclebodycolor", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclebrand", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclemodel", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclebrandmodel", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclebodynum", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclecost", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclegasequip", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"customscountryremovalid\"", + "vehicleproducername", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehiclegrossmass", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclemass", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"customscountryremovalname\"", + "vehiclesteeringwheeltypeid", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"ownerorgname\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"ownerinn\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"ownerogrn\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"ownerkpp\"", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclekpptype", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"ownerpersonlastname\"", + "vehicletransmissiontype", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehicletypename", Type::Unsigned, ColumnRole::User, false), + Column::new("vehiclecategory", Type::Unsigned, ColumnRole::User, false), + Column::new("vehicletypeunit", Type::Unsigned, ColumnRole::User, false), + Column::new("vehicleecoclass", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"ownerpersonfirstname\"", + "vehiclespecfuncname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersonmiddlename\"", + "vehicleenclosedvolume", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersonbirthdate\"", + "vehicleenginemodel", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehicleenginenum", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"ownerbirthplace\"", + "vehicleenginepower", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersonogrnip\"", + "vehicleenginepowerkw", Type::Unsigned, ColumnRole::User, false, ), + Column::new("vehicleenginetype", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"owneraddressindex\"", + "holdrestrictiondate", Type::Unsigned, ColumnRole::User, false, ), + Column::new("approvalnum", Type::Unsigned, ColumnRole::User, false), + Column::new("approvaldate", Type::Unsigned, ColumnRole::User, false), + Column::new("approvaltype", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"owneraddressmundistrict\"", + "utilizationfeename", Type::Unsigned, ColumnRole::User, false, ), + Column::new("customsdoc", Type::Unsigned, ColumnRole::User, false), + Column::new("customsdocdate", Type::Unsigned, ColumnRole::User, false), + Column::new("customsdocissue", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"owneraddresssettlement\"", + "customsdocrestriction", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"owneraddressstreet\"", + "customscountryremovalid", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersoninn\"", + "customscountryremovalname", Type::Unsigned, ColumnRole::User, false, ), + Column::new("ownerorgname", Type::Unsigned, ColumnRole::User, false), + Column::new("ownerinn", Type::Unsigned, ColumnRole::User, false), + Column::new("ownerogrn", Type::Unsigned, ColumnRole::User, false), + Column::new("ownerkpp", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"ownerpersondoccode\"", + "ownerpersonlastname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersondocnum\"", + "ownerpersonfirstname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"ownerpersondocdate\"", + "ownerpersonmiddlename", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"operationname\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"operationdate\"", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"operationdepartmentname\"", + "ownerpersonbirthdate", Type::Unsigned, ColumnRole::User, false, ), + Column::new("ownerbirthplace", Type::Unsigned, ColumnRole::User, false), + Column::new("ownerpersonogrnip", Type::Unsigned, ColumnRole::User, false), + Column::new("owneraddressindex", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"operationattorney\"", + "owneraddressmundistrict", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"operationlising\"", + "owneraddresssettlement", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"holdertypeid\"", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersondoccode\"", + "owneraddressstreet", Type::Unsigned, ColumnRole::User, false, ), + Column::new("ownerpersoninn", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersondocnum\"", + "ownerpersondoccode", Type::Unsigned, ColumnRole::User, false, ), + Column::new("ownerpersondocnum", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersondocdate\"", + "ownerpersondocdate", Type::Unsigned, ColumnRole::User, false, ), + Column::new("operationname", Type::Unsigned, ColumnRole::User, false), + Column::new("operationdate", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersondocissuer\"", + "operationdepartmentname", Type::Unsigned, ColumnRole::User, false, ), + Column::new("operationattorney", Type::Unsigned, ColumnRole::User, false), + Column::new("operationlising", Type::Unsigned, ColumnRole::User, false), + Column::new("holdertypeid", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersonlastname\"", + "holderpersondoccode", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonfirstname\"", + "holderpersondocnum", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonmiddlename\"", + "holderpersondocdate", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonbirthdate\"", + "holderpersondocissuer", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonbirthregionid\"", + "holderpersonlastname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonsex\"", + "holderpersonfirstname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonbirthplace\"", + "holderpersonmiddlename", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersoninn\"", + "holderpersonbirthdate", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderpersonsnils\"", + "holderpersonbirthregionid", Type::Unsigned, ColumnRole::User, false, ), + Column::new("holderpersonsex", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderpersonogrnip\"", + "holderpersonbirthplace", Type::Unsigned, ColumnRole::User, false, ), + Column::new("holderpersoninn", Type::Unsigned, ColumnRole::User, false), + Column::new("holderpersonsnils", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderaddressguid\"", + "holderpersonogrnip", Type::Unsigned, ColumnRole::User, false, ), + Column::new("holderaddressguid", Type::Unsigned, ColumnRole::User, false), Column::new( - "\"holderaddressregionid\"", + "holderaddressregionid", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressregionname\"", + "holderaddressregionname", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressdistrict\"", + "holderaddressdistrict", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressmundistrict\"", + "holderaddressmundistrict", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddresssettlement\"", + "holderaddresssettlement", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressstreet\"", + "holderaddressstreet", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressbuilding\"", + "holderaddressbuilding", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressstructureid\"", + "holderaddressstructureid", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressstructurename\"", + "holderaddressstructurename", Type::Unsigned, ColumnRole::User, false, ), Column::new( - "\"holderaddressstructure\"", + "holderaddressstructure", Type::Unsigned, ColumnRole::User, false, ), - Column::new("\"sys_from\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"sys_to\"", Type::Unsigned, ColumnRole::User, false), - Column::new("\"bucket_id\"", Type::Unsigned, ColumnRole::Sharding, true), + Column::new("sys_from", Type::Unsigned, ColumnRole::User, false), + Column::new("sys_to", Type::Unsigned, ColumnRole::User, false), + Column::new("bucket_id", Type::Unsigned, ColumnRole::Sharding, true), ]; - let sharding_key: &[&str] = &["\"reestrid\""]; - let primary_key: &[&str] = &["\"reestrid\""]; + let sharding_key: &[&str] = &["reestrid"]; + let primary_key: &[&str] = &["reestrid"]; tables.insert( - "\"test__gibdd_db__vehicle_reg_and_res100_actual\"".to_smolstr(), + "test__gibdd_db__vehicle_reg_and_res100_actual".to_smolstr(), Table::new_sharded( - "\"test__gibdd_db__vehicle_reg_and_res100_actual\"", + "test__gibdd_db__vehicle_reg_and_res100_actual", columns.clone(), sharding_key, primary_key, @@ -878,9 +707,9 @@ impl RouterConfigurationMock { .unwrap(), ); tables.insert( - "\"test__gibdd_db__vehicle_reg_and_res100_history\"".to_smolstr(), + "test__gibdd_db__vehicle_reg_and_res100_history".to_smolstr(), Table::new_sharded( - "\"test__gibdd_db__vehicle_reg_and_res100_history\"", + "test__gibdd_db__vehicle_reg_and_res100_history", columns, sharding_key, primary_key, @@ -893,7 +722,7 @@ impl RouterConfigurationMock { functions, tables, bucket_count: 10000, - sharding_column: "\"bucket_id\"".into(), + sharding_column: "bucket_id".into(), } } } @@ -1183,17 +1012,17 @@ impl RouterRuntimeMock { let mut table_statistics_cache = HashMap::new(); let hash_testing_hist_rows_number = 1000.0; table_statistics_cache.insert( - "\"hash_testing_hist\"".to_smolstr(), + "hash_testing_hist".to_smolstr(), Rc::new(TableStats::new(hash_testing_hist_rows_number as u64)), ); let hash_testing_rows_number = 10000.0; table_statistics_cache.insert( - "\"hash_testing\"".to_smolstr(), + "hash_testing".to_smolstr(), Rc::new(TableStats::new(hash_testing_rows_number as u64)), ); let test_space_rows_number = 25000.0; table_statistics_cache.insert( - "\"test_space\"".to_smolstr(), + "test_space".to_smolstr(), Rc::new(TableStats::new(test_space_rows_number as u64)), ); @@ -1224,7 +1053,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"hash_testing_hist\"".to_smolstr(), 0), + TableColumnPair::new("hash_testing_hist".to_smolstr(), 0), Rc::new(boxed_column_stats), ); @@ -1287,7 +1116,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"hash_testing\"".to_smolstr(), 0), + TableColumnPair::new("hash_testing".to_smolstr(), 0), Rc::new(boxed_column_stats), ); @@ -1320,7 +1149,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"hash_testing\"".to_smolstr(), 3), + TableColumnPair::new("hash_testing".to_smolstr(), 3), Rc::new(boxed_column_stats), ); @@ -1379,7 +1208,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"test_space\"".to_smolstr(), 0), + TableColumnPair::new("test_space".to_smolstr(), 0), Rc::new(boxed_column_stats), ); @@ -1410,7 +1239,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"test_space\"".to_smolstr(), 1), + TableColumnPair::new("test_space".to_smolstr(), 1), Rc::new(boxed_column_stats), ); @@ -1469,7 +1298,7 @@ impl RouterRuntimeMock { )), )); column_statistics_cache.insert( - TableColumnPair::new("\"test_space\"".to_smolstr(), 2), + TableColumnPair::new("test_space".to_smolstr(), 2), Rc::new(boxed_column_stats), ); diff --git a/sbroad-core/src/executor/tests.rs b/sbroad-core/src/executor/tests.rs index 36b35101e..4ceca6001 100644 --- a/sbroad-core/src/executor/tests.rs +++ b/sbroad-core/src/executor/tests.rs @@ -332,7 +332,7 @@ WHERE "t3"."id" = 2 AND "t8"."identification_number" = 2"#; .unwrap() .position(0) .unwrap(); - let mut virtual_table = virtual_table_23(Some("\"t8\"")); + let mut virtual_table = virtual_table_23(Some("t8")); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_id) { virtual_table.reshard(key, &query.coordinator).unwrap(); @@ -411,7 +411,7 @@ fn join_linker2_test() { virtual_table.add_column(column_integer_user_non_null(SmolStr::from("id2"))); virtual_table.add_tuple(vec![Value::from(1_u64), Value::from(1_u64)]); virtual_table.add_tuple(vec![Value::from(2_u64), Value::from(2_u64)]); - virtual_table.set_alias("\"t2\"").unwrap(); + virtual_table.set_alias("t2").unwrap(); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_id) { virtual_table.reshard(key, &query.coordinator).unwrap(); @@ -475,7 +475,7 @@ fn join_linker3_test() { virtual_table.add_column(column_integer_user_non_null(SmolStr::from("FIRST_NAME"))); virtual_table.add_tuple(vec![Value::from(1_u64), Value::from(1_u64)]); virtual_table.add_tuple(vec![Value::from(2_u64), Value::from(2_u64)]); - virtual_table.set_alias("\"t2\"").unwrap(); + virtual_table.set_alias("t2").unwrap(); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_id) { virtual_table.reshard(key, &query.coordinator).unwrap(); @@ -516,10 +516,10 @@ fn join_linker3_test() { #[test] #[allow(clippy::too_many_lines)] fn join_linker4_test() { - let sql = r#"SELECT t1."id" FROM "test_space" as t1 JOIN - (SELECT "FIRST_NAME" as "r_id" FROM "test_space") as t2 - on t1."id" = t2."r_id" and - t1."FIRST_NAME" = (SELECT "FIRST_NAME" as "fn" FROM "test_space" WHERE "id" = 1)"#; + let sql = r#"SELECT "T1"."id" FROM "test_space" as "T1" JOIN + (SELECT "FIRST_NAME" as "r_id" FROM "test_space") as "T2" + on "T1"."id" = "T2"."r_id" and + "T1"."FIRST_NAME" = (SELECT "FIRST_NAME" as "fn" FROM "test_space" WHERE "id" = 1)"#; let coordinator = RouterRuntimeMock::new(); @@ -537,7 +537,7 @@ fn join_linker4_test() { virtual_t2.add_column(column_integer_user_non_null(SmolStr::from("r_id"))); virtual_t2.add_tuple(vec![Value::from(1_u64)]); virtual_t2.add_tuple(vec![Value::from(2_u64)]); - virtual_t2.set_alias("\"T2\"").unwrap(); + virtual_t2.set_alias("T2").unwrap(); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_t2_id) { @@ -640,7 +640,7 @@ on q."f" = "t1"."a""#; .unwrap(); let mut virtual_t2 = VirtualTable::new(); virtual_t2.add_column(column_integer_user_non_null(SmolStr::from("b"))); - virtual_t2.set_alias("\"t3\"").unwrap(); + virtual_t2.set_alias("t3").unwrap(); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_t2_id) { @@ -661,7 +661,7 @@ on q."f" = "t1"."a""#; let mut virtual_sq = VirtualTable::new(); virtual_sq.add_column(column_integer_user_non_null(SmolStr::from("f"))); virtual_sq.add_column(column_integer_user_non_null(SmolStr::from("B"))); - virtual_sq.set_alias("Q").unwrap(); + virtual_sq.set_alias("q").unwrap(); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_sq_id) { @@ -684,10 +684,10 @@ on q."f" = "t1"."a""#; LuaValue::String(String::from(PatternWithParams::new( format!( "{} {} {} {}", - r#"SELECT "t1"."a", "t1"."b", "Q"."f", "Q"."B" FROM"#, + r#"SELECT "t1"."a", "t1"."b", "q"."f", "q"."b" FROM"#, r#"(SELECT "t1"."a", "t1"."b" FROM "t1") as "t1""#, r#"INNER JOIN (SELECT "f","B" FROM "TMP_test_146")"#, - r#"as Q ON ("Q"."f") = ("t1"."a")"#, + r#"as "q" ON ("q"."f") = ("t1"."a")"#, ), vec![], ))), diff --git a/sbroad-core/src/executor/tests/bucket_id.rs b/sbroad-core/src/executor/tests/bucket_id.rs index 9f89a8de6..bb1231fd0 100644 --- a/sbroad-core/src/executor/tests/bucket_id.rs +++ b/sbroad-core/src/executor/tests/bucket_id.rs @@ -83,7 +83,7 @@ fn bucket3_test() { expected.rows.push(vec![ LuaValue::String("Execute query on all buckets".to_string()), LuaValue::String(String::from(PatternWithParams::new( - r#"SELECT "t1"."a", "t1"."b", "FUNC" (?) as "COL_1" FROM "t1""#.to_string(), + r#"SELECT "t1"."a", "t1"."b", "func" (?) as "COL_1" FROM "t1""#.to_string(), vec![Value::from("111".to_string())], ))), ]); diff --git a/sbroad-core/src/executor/tests/cast.rs b/sbroad-core/src/executor/tests/cast.rs index 2b4e3928c..b068c3543 100644 --- a/sbroad-core/src/executor/tests/cast.rs +++ b/sbroad-core/src/executor/tests/cast.rs @@ -122,7 +122,7 @@ fn cast13_test() { fn cast14_test() { broadcast_check( r#"SELECT CAST(func("a") as varchar(100)) FROM "t1""#, - r#"SELECT CAST ("FUNC" ("t1"."a") as varchar(100)) as "COL_1" FROM "t1""#, + r#"SELECT CAST ("func" ("t1"."a") as varchar(100)) as "COL_1" FROM "t1""#, vec![], ); } diff --git a/sbroad-core/src/executor/tests/concat.rs b/sbroad-core/src/executor/tests/concat.rs index 7aa1f6c18..b74fac81b 100644 --- a/sbroad-core/src/executor/tests/concat.rs +++ b/sbroad-core/src/executor/tests/concat.rs @@ -14,7 +14,7 @@ fn concat1_test() { fn concat2_test() { broadcast_check( r#"SELECT func('hello') || CAST(42 as string) FROM "t1""#, - r#"SELECT ("FUNC" (?)) || (CAST (? as string)) as "COL_1" FROM "t1""#, + r#"SELECT ("func" (?)) || (CAST (? as string)) as "COL_1" FROM "t1""#, vec![Value::from("hello"), Value::from(42_u64)], ); } @@ -32,7 +32,7 @@ fn concat3_test() { fn concat4_test() { broadcast_check( r#"SELECT "a" FROM "t1" WHERE "a" || 'a' = CAST(42 as string) || FUNC('b') || 'a'"#, - r#"SELECT "t1"."a" FROM "t1" WHERE (("t1"."a") || (?)) = (((CAST (? as string)) || ("FUNC" (?))) || (?))"#, + r#"SELECT "t1"."a" FROM "t1" WHERE (("t1"."a") || (?)) = (((CAST (? as string)) || ("func" (?))) || (?))"#, vec![ Value::from("a"), Value::from(42_u64), diff --git a/sbroad-core/src/executor/tests/empty_motion.rs b/sbroad-core/src/executor/tests/empty_motion.rs index b2932032b..3b4e531a3 100644 --- a/sbroad-core/src/executor/tests/empty_motion.rs +++ b/sbroad-core/src/executor/tests/empty_motion.rs @@ -19,7 +19,7 @@ fn empty_motion1_test() { EXCEPT SELECT "t"."a", "t"."b" FROM "t" INNER JOIN "t2" ON "t"."a" = "t2"."g" and "t"."b" = "t2"."h" WHERE "t"."a" = 1 - ) as q"#; + ) as "Q""#; let coordinator = RouterRuntimeMock::new(); @@ -94,7 +94,7 @@ fn t2_empty() -> VirtualTable { virtual_table.add_column(column_integer_user_non_null(SmolStr::from("h"))); - virtual_table.set_alias("\"t2\"").unwrap(); + virtual_table.set_alias("t2").unwrap(); virtual_table } diff --git a/sbroad-core/src/executor/tests/exec_plan.rs b/sbroad-core/src/executor/tests/exec_plan.rs index 603314b7f..bda487faa 100644 --- a/sbroad-core/src/executor/tests/exec_plan.rs +++ b/sbroad-core/src/executor/tests/exec_plan.rs @@ -15,6 +15,15 @@ use crate::ir::{Node, Slice}; use super::*; +// Helper function to format back sql. +// The local sql we produce doesn't contain line breaks, +// but in code it's hard to read such long string, so +// we insert line breaks and remove them back for +// string comparison with expected pattern. +fn f_sql(s: &str) -> String { + s.replace("\n", " ") +} + /// Helper function to generate sql from `exec_plan` from given `top_id` node. /// Used for testing. fn get_sql_from_execution_plan( @@ -89,7 +98,7 @@ fn exec_plan_subtree_test() { #[test] fn exec_plan_subtree_two_stage_groupby_test() { - let sql = r#"SELECT t1."FIRST_NAME" FROM "test_space" as t1 group by t1."FIRST_NAME""#; + let sql = r#"SELECT "T1"."FIRST_NAME" FROM "test_space" as "T1" group by "T1"."FIRST_NAME""#; let coordinator = RouterRuntimeMock::new(); let mut query = Query::new(&coordinator, sql, vec![]).unwrap(); @@ -155,7 +164,7 @@ fn exec_plan_subtree_two_stage_groupby_test() { #[test] fn exec_plan_subtree_two_stage_groupby_test_2() { - let sql = r#"SELECT t1."FIRST_NAME", t1."sys_op", t1."sysFrom" FROM "test_space" as t1 GROUP BY t1."FIRST_NAME", t1."sys_op", t1."sysFrom""#; + let sql = r#"SELECT "T1"."FIRST_NAME", "T1"."sys_op", "T1"."sysFrom" FROM "test_space" as "T1" GROUP BY "T1"."FIRST_NAME", "T1"."sys_op", "T1"."sysFrom""#; let coordinator = RouterRuntimeMock::new(); let mut query = Query::new(&coordinator, sql, vec![]).unwrap(); @@ -208,11 +217,12 @@ fn exec_plan_subtree_two_stage_groupby_test_2() { assert_eq!( sql, PatternWithParams::new( - format!( - "{} {} {}", - r#"SELECT "T1"."FIRST_NAME" as "column_12", "T1"."sysFrom" as "column_14","#, - r#""T1"."sys_op" as "column_13" FROM "test_space" as "T1""#, - r#"GROUP BY "T1"."sys_op", "T1"."FIRST_NAME", "T1"."sysFrom""#, + f_sql( + r#"SELECT "T1"."FIRST_NAME" as "column_12", +"T1"."sysFrom" as "column_14", +"T1"."sys_op" as "column_13" +FROM "test_space" as "T1" +GROUP BY "T1"."FIRST_NAME", "T1"."sys_op", "T1"."sysFrom""# ), vec![] ) @@ -224,12 +234,11 @@ fn exec_plan_subtree_two_stage_groupby_test_2() { assert_eq!( sql, PatternWithParams::new( - format!( - "{} {} {} {}", - r#"SELECT "column_12" as "FIRST_NAME", "column_13" as "sys_op","#, - r#""column_14" as "sysFrom" FROM"#, - r#"(SELECT "column_12","column_13","column_14" FROM "TMP_test_14")"#, - r#"GROUP BY "column_13", "column_12", "column_14""#, + f_sql( + r#"SELECT "column_12" as "FIRST_NAME", +"column_13" as "sys_op", "column_14" as "sysFrom" +FROM (SELECT "column_12","column_13","column_14" FROM "TMP_test_14") +GROUP BY "column_12", "column_13", "column_14""# ), vec![] ) @@ -238,10 +247,10 @@ fn exec_plan_subtree_two_stage_groupby_test_2() { #[test] fn exec_plan_subtree_aggregates() { - let sql = r#"SELECT t1."sys_op" || t1."sys_op", t1."sys_op"*2 + count(t1."sysFrom"), - sum(t1."id"), sum(distinct t1."id"*t1."sys_op") / count(distinct "id"), - group_concat(t1."FIRST_NAME", 'o'), avg(t1."id"), total(t1."id"), min(t1."id"), max(t1."id") - FROM "test_space" as t1 group by t1."sys_op""#; + let sql = r#"SELECT "T1"."sys_op" || "T1"."sys_op", "T1"."sys_op"*2 + count("T1"."sysFrom"), + sum("T1"."id"), sum(distinct "T1"."id"*"T1"."sys_op") / count(distinct "id"), + group_concat("T1"."FIRST_NAME", 'o'), avg("T1"."id"), total("T1"."id"), min("T1"."id"), max("T1"."id") + FROM "test_space" as "T1" group by "T1"."sys_op""#; let coordinator = RouterRuntimeMock::new(); let mut query = Query::new(&coordinator, sql, vec![]).unwrap(); @@ -295,14 +304,16 @@ fn exec_plan_subtree_aggregates() { assert_eq!( sql, PatternWithParams::new( - format!( - "{} {} {} {} {} {}", - r#"SELECT "T1"."sys_op" as "column_12", ("T1"."id") * ("T1"."sys_op") as "column_49","#, - r#""T1"."id" as "column_46", count ("T1"."sysFrom") as "count_37","#, - r#"sum ("T1"."id") as "sum_42", count ("T1"."id") as "count_61", total ("T1"."id") as "total_64","#, - r#"min ("T1"."id") as "min_67", max ("T1"."id") as "max_70", group_concat ("T1"."FIRST_NAME", ?) as "group_concat_58""#, - r#"FROM "test_space" as "T1""#, - r#"GROUP BY "T1"."sys_op", ("T1"."id") * ("T1"."sys_op"), "T1"."id""#, + f_sql( + r#"SELECT "T1"."sys_op" as "column_12", +("T1"."id") * ("T1"."sys_op") as "column_49", +"T1"."id" as "column_46", +group_concat ("T1"."FIRST_NAME", ?) as "group_concat_58", +count ("T1"."sysFrom") as "count_37", total ("T1"."id") as "total_64", +min ("T1"."id") as "min_67", count ("T1"."id") as "count_61", +max ("T1"."id") as "max_70", sum ("T1"."id") as "sum_42" +FROM "test_space" as "T1" +GROUP BY "T1"."sys_op", ("T1"."id") * ("T1"."sys_op"), "T1"."id""# ), vec![Value::from("o")] ) @@ -332,7 +343,7 @@ fn exec_plan_subtree_aggregates() { #[test] fn exec_plan_subtree_aggregates_no_groupby() { - let sql = r#"SELECT count(t1."sysFrom"), sum(distinct t1."id" + t1."sysFrom") FROM "test_space" as t1"#; + let sql = r#"SELECT count("T1"."sysFrom"), sum(distinct "T1"."id" + "T1"."sysFrom") FROM "test_space" as "T1""#; let coordinator = RouterRuntimeMock::new(); let mut query = Query::new(&coordinator, sql, vec![]).unwrap(); @@ -452,7 +463,7 @@ fn exec_plan_subquery_under_motion_with_alias() { .unwrap() .position(0) .unwrap(); - let mut virtual_table = virtual_table_23(Some("\"hti\"")); + let mut virtual_table = virtual_table_23(Some("hti")); if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_id) { virtual_table.reshard(key, &query.coordinator).unwrap(); @@ -617,9 +628,9 @@ fn exec_plan_subtree_count_asterisk() { fn exec_plan_subtree_having() { let sql = format!( "{} {} {}", - r#"SELECT t1."sys_op" || t1."sys_op", count(t1."sys_op"*2) + count(distinct t1."sys_op"*2)"#, - r#"FROM "test_space" as t1 group by t1."sys_op""#, - r#"HAVING sum(distinct t1."sys_op"*2) > 1"# + r#"SELECT "T1"."sys_op" || "T1"."sys_op", count("T1"."sys_op"*2) + count(distinct "T1"."sys_op"*2)"#, + r#"FROM "test_space" as "T1" group by "T1"."sys_op""#, + r#"HAVING sum(distinct "T1"."sys_op"*2) > 1"# ); let coordinator = RouterRuntimeMock::new(); @@ -699,9 +710,9 @@ fn exec_plan_subtree_having() { fn exec_plan_subtree_having_without_groupby() { let sql = format!( "{} {} {}", - r#"SELECT count(t1."sys_op"*2) + count(distinct t1."sys_op"*2)"#, - r#"FROM "test_space" as t1"#, - r#"HAVING sum(distinct t1."sys_op"*2) > 1"# + r#"SELECT count("T1"."sys_op"*2) + count(distinct "T1"."sys_op"*2)"#, + r#"FROM "test_space" as "T1""#, + r#"HAVING sum(distinct "T1"."sys_op"*2) > 1"# ); let coordinator = RouterRuntimeMock::new(); @@ -929,7 +940,7 @@ fn global_union_all3() { let sql = r#" select "a" from "global_t" where "b" in (select "e" from "t2") - union all + union all select "f" from "t2" group by "f""#; let mut coordinator = RouterRuntimeMock::new(); @@ -1050,10 +1061,10 @@ fn global_union_all3() { fn global_union_all4() { let sql = r#" select "b" from "global_t" - union all + union all select * from ( select "a" from "global_t" - union all + union all select "f" from "t2" ) "#; diff --git a/sbroad-core/src/executor/tests/frontend.rs b/sbroad-core/src/executor/tests/frontend.rs index 668fb61cb..fef876e5c 100644 --- a/sbroad-core/src/executor/tests/frontend.rs +++ b/sbroad-core/src/executor/tests/frontend.rs @@ -27,7 +27,7 @@ fn front_invalid_sql2() { assert_eq!( SbroadError::UnexpectedNumberOfValues( - r#"invalid number of values: 4. Table "t" expects 3 column(s)."#.into() + r#"invalid number of values: 4. Table t expects 3 column(s)."#.into() ), plan_err ); @@ -42,7 +42,7 @@ fn front_invalid_sql3() { assert_eq!( SbroadError::UnexpectedNumberOfValues( - r#"invalid number of values: 2. Table "t" expects 4 column(s)."#.into() + r#"invalid number of values: 2. Table t expects 4 column(s)."#.into() ), plan_err ); @@ -57,7 +57,7 @@ fn front_invalid_sql4() { assert_eq!( SbroadError::UnexpectedNumberOfValues( - r#"invalid number of values: 2. Table "t" expects 4 column(s)."#.into() + r#"invalid number of values: 2. Table t expects 4 column(s)."#.into() ), plan_err ); diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs index 8eca4ed72..c68b70620 100644 --- a/sbroad-core/src/frontend/sql.rs +++ b/sbroad-core/src/frontend/sql.rs @@ -20,7 +20,7 @@ use tarantool::index::{IndexType, RtreeIndexDistanceType}; use time::{OffsetDateTime, Time}; use crate::errors::{Action, Entity, SbroadError}; -use crate::executor::engine::{helpers::normalize_name_for_space_api, Metadata}; +use crate::executor::engine::Metadata; use crate::frontend::sql::ast::{ AbstractSyntaxTree, ParseNode, ParseNodes, ParseTree, Rule, StackParseNode, }; @@ -44,7 +44,7 @@ use crate::ir::{Node, NodeId, OptionKind, OptionParamValue, OptionSpec, Plan}; use crate::otm::child_span; use crate::errors::Entity::AST; -use crate::executor::engine::helpers::normalize_name_from_sql; +use crate::executor::engine::helpers::{normalize_name_from_sql, to_user}; use crate::ir::acl::AlterOption; use crate::ir::acl::{Acl, GrantRevokeType, Privilege}; use crate::ir::aggregates::AggregateKind; @@ -926,7 +926,8 @@ where return Err(SbroadError::Invalid( Entity::Table, Some(format_smolstr!( - "table with name {scan_name} is already defined as a CTE", + "table with name {} is already defined as a CTE", + to_user(scan_name) )), )); } @@ -937,7 +938,10 @@ where Err(SbroadError::NotFound(..)) => { // If the table is not found, we try to find a CTE with the given name. let cte_id = *ctes.get(&scan_name).ok_or_else(|| { - SbroadError::NotFound(Entity::Table, format_smolstr!("with name {scan_name}")) + SbroadError::NotFound( + Entity::Table, + format_smolstr!("with name {}", to_user(scan_name)), + ) })?; map.add(node_id, cte_id); } @@ -984,7 +988,10 @@ fn parse_cte( if ctes.get(&name).is_some() { return Err(SbroadError::Invalid( Entity::Cte, - Some(format_smolstr!("CTE with name {name} is already defined")), + Some(format_smolstr!( + "CTE with name {} is already defined", + to_user(name) + )), )); } let cte_id = plan.add_cte(child_id, name.clone(), columns)?; @@ -996,7 +1003,9 @@ fn parse_cte( /// Get String value under node that is considered to be an identifier /// (on which rules on name normalization should be applied). fn parse_identifier(ast: &AbstractSyntaxTree, node_id: usize) -> Result<SmolStr, SbroadError> { - Ok(normalize_name_for_space_api(parse_string_value_node(ast, node_id)?).to_smolstr()) + Ok(normalize_name_from_sql(parse_string_value_node( + ast, node_id, + )?)) } fn parse_normalized_identifier( @@ -2799,8 +2808,8 @@ impl AbstractSyntaxTree { Rule::Table => { // The thing is we don't want to normalize name. // Should we fix `parse_identifier` or `table` logic? - let table_name = parse_string_value_node(self, id)?; - let t = metadata.table(table_name)?; + let table_name = parse_identifier(self, id)?; + let t = metadata.table(&table_name)?; plan.add_rel(t); } Rule::SubQuery => { @@ -3001,17 +3010,15 @@ impl AbstractSyntaxTree { .reference_to_name_map .get(&expr_plan_node_id) .expect("reference must be in a map"); - normalize_name_from_sql(col_name.as_str()) + col_name.clone() } else { unnamed_col_pos += 1; get_unnamed_column_alias(unnamed_col_pos) } }; - let plan_alias_id = plan.nodes.add_alias( - &normalize_name_from_sql(&alias_name), - expr_plan_node_id, - )?; + let plan_alias_id = + plan.nodes.add_alias(&alias_name, expr_plan_node_id)?; proj_columns.push(plan_alias_id); } Rule::Asterisk => { @@ -3158,7 +3165,7 @@ impl AbstractSyntaxTree { Entity::Query, Some(format_smolstr!( "it is illegal to update primary key column: {}", - col_name + to_user(col_name) )), )); } @@ -3167,7 +3174,7 @@ impl AbstractSyntaxTree { Entity::Query, Some(format_smolstr!( "The same column is specified twice in update list: {}", - col_name + to_user(col_name) )), )); } @@ -3177,7 +3184,10 @@ impl AbstractSyntaxTree { return Err(SbroadError::FailedTo( Action::Update, Some(Entity::Column), - format_smolstr!("system column {col_name} cannot be updated"), + format_smolstr!( + "system column {} cannot be updated", + to_user(col_name) + ), )) } None => { @@ -3342,7 +3352,7 @@ impl AbstractSyntaxTree { Entity::Column, Some(format_smolstr!( "NonNull column {} must be specified", - column.name + to_user(&column.name) )), )); } diff --git a/sbroad-core/src/frontend/sql/ir/tests.rs b/sbroad-core/src/frontend/sql/ir/tests.rs index 14a19919e..d859d866f 100644 --- a/sbroad-core/src/frontend/sql/ir/tests.rs +++ b/sbroad-core/src/frontend/sql/ir/tests.rs @@ -172,14 +172,14 @@ fn front_sql6() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T"."id"::unsigned -> "id", "hash_testing"."product_units"::boolean -> "product_units") + r#"projection ("t"."id"::unsigned -> "id", "hash_testing"."product_units"::boolean -> "product_units") selection ROW("hash_testing"."identification_number"::integer) = ROW(5::unsigned) and ROW("hash_testing"."product_code"::string) = ROW('123'::string) - join on ROW("hash_testing"."identification_number"::integer) = ROW("T"."id"::unsigned) + join on ROW("hash_testing"."identification_number"::integer) = ROW("t"."id"::unsigned) scan "hash_testing" projection ("hash_testing"."identification_number"::integer -> "identification_number", "hash_testing"."product_code"::string -> "product_code", "hash_testing"."product_units"::boolean -> "product_units", "hash_testing"."sys_op"::unsigned -> "sys_op") scan "hash_testing" motion [policy: full] - scan "T" + scan "t" projection ("test_space"."id"::unsigned -> "id") scan "test_space" execution options: @@ -199,9 +199,9 @@ fn front_sql8() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T"."identification_number"::integer -> "identification_number", "T"."product_code"::string -> "product_code") - selection ROW("T"."identification_number"::integer) = ROW(1::unsigned) - scan "hash_testing" -> "T" + r#"projection ("t"."identification_number"::integer -> "identification_number", "t"."product_code"::string -> "product_code") + selection ROW("t"."identification_number"::integer) = ROW(1::unsigned) + scan "hash_testing" -> "t" execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -576,8 +576,8 @@ fn front_sql_check_arbitraty_utf_in_identifiers() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("&%ښ۞@ƵǕ"."id"::unsigned -> "from", "&%ښ۞@ƵǕ"."id"::unsigned -> "select", "&%ښ۞@ƵǕ"."id"::unsigned -> "123»&%ښ۞@Ƶǖselect.""''\\", "&%ښ۞@ƵǕ"."id"::unsigned -> "AЦ1&@$ƵǕ%^&«»§&%ښ۞@ƵǕ") - scan "test_space" -> "&%ښ۞@ƵǕ" + r#"projection ("&%ښ۞@ƶǖ"."id"::unsigned -> "from", "&%ښ۞@ƶǖ"."id"::unsigned -> "select", "&%ښ۞@ƶǖ"."id"::unsigned -> "123»&%ښ۞@Ƶǖselect.""''\\", "&%ښ۞@ƶǖ"."id"::unsigned -> "aц1&@$ƶǖ%^&«»§&%ښ۞@ƶǖ") + scan "test_space" -> "&%ښ۞@ƶǖ" execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -590,8 +590,8 @@ vtable_max_rows = 5000 #[test] fn front_sql_check_inapplicatable_symbols() { let input = r#" - SELECT a*a, B+B, a-a - FROM TBL + SELECT "A"*"A", "B"+"B", "A"-"A" + FROM "TBL" "#; let plan = sql_to_optimized_ir(input, vec![]); @@ -1055,11 +1055,11 @@ fn front_sql_join_on_bucket_id1() { let expected_explain = String::from( r#"projection ("t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h") - join on ROW("T_MV"."bucket_id"::unsigned) = ROW("t2"."bucket_id"::unsigned) + join on ROW("t_mv"."bucket_id"::unsigned) = ROW("t2"."bucket_id"::unsigned) scan "t2" projection ("t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h", "t2"."bucket_id"::unsigned -> "bucket_id") scan "t2" - scan "T_MV" + scan "t_mv" projection ("test_space"."bucket_id"::unsigned -> "bucket_id") selection ROW("test_space"."id"::unsigned) = ROW(1::unsigned) scan "test_space" @@ -1084,12 +1084,12 @@ fn front_sql_join_on_bucket_id2() { let expected_explain = String::from( r#"projection ("t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h") - join on ROW("T_MV"."bucket_id"::unsigned) = ROW("t2"."bucket_id"::unsigned) or ROW("t2"."e"::unsigned) = ROW("t2"."f"::unsigned) + join on ROW("t_mv"."bucket_id"::unsigned) = ROW("t2"."bucket_id"::unsigned) or ROW("t2"."e"::unsigned) = ROW("t2"."f"::unsigned) scan "t2" projection ("t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h", "t2"."bucket_id"::unsigned -> "bucket_id") scan "t2" motion [policy: full] - scan "T_MV" + scan "t_mv" projection ("test_space"."bucket_id"::unsigned -> "bucket_id") selection ROW("test_space"."id"::unsigned) = ROW(1::unsigned) scan "test_space" @@ -1112,10 +1112,10 @@ fn front_sql_groupby_on_bucket_id() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T"."B"::unsigned -> "B", count((*::integer))::integer -> "COL_1") - group by ("T"."B"::unsigned) output: ("T"."B"::unsigned -> "B") - scan "T" - projection ("t2"."bucket_id"::unsigned -> "B") + r#"projection ("t"."b"::unsigned -> "b", count((*::integer))::integer -> "COL_1") + group by ("t"."b"::unsigned) output: ("t"."b"::unsigned -> "b") + scan "t" + projection ("t2"."bucket_id"::unsigned -> "b") scan "t2" execution options: sql_vdbe_max_steps = 45000 @@ -1136,10 +1136,10 @@ fn front_sql_sq_on_bucket_id() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T"."B"::unsigned -> "B", "T"."E"::unsigned -> "E") - selection ROW("T"."B"::unsigned, "T"."E"::unsigned) in ROW($0, $0) - scan "T" - projection ("t2"."bucket_id"::unsigned -> "B", "t2"."e"::unsigned -> "E") + r#"projection ("t"."b"::unsigned -> "b", "t"."e"::unsigned -> "e") + selection ROW("t"."b"::unsigned, "t"."e"::unsigned) in ROW($0, $0) + scan "t" + projection ("t2"."bucket_id"::unsigned -> "b", "t2"."e"::unsigned -> "e") scan "t2" subquery $0: scan @@ -1257,13 +1257,14 @@ fn front_sql_groupby() { let input = r#"SELECT "identification_number", "product_code" FROM "hash_testing" group by "identification_number", "product_code""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_12"::integer -> "identification_number", "column_13"::string -> "product_code") - group by ("column_13"::string, "column_12"::integer) output: ("column_12"::integer -> "column_12", "column_13"::string -> "column_13") - motion [policy: segment([ref("column_13"), ref("column_12")])] + group by ("column_12"::integer, "column_13"::string) output: ("column_12"::integer -> "column_12", "column_13"::string -> "column_13") + motion [policy: segment([ref("column_12"), ref("column_13")])] scan projection ("hash_testing"."identification_number"::integer -> "column_12", "hash_testing"."product_code"::string -> "column_13") - group by ("hash_testing"."product_code"::string, "hash_testing"."identification_number"::integer) output: ("hash_testing"."identification_number"::integer -> "identification_number", "hash_testing"."product_code"::string -> "product_code", "hash_testing"."product_units"::boolean -> "product_units", "hash_testing"."sys_op"::unsigned -> "sys_op", "hash_testing"."bucket_id"::unsigned -> "bucket_id") + group by ("hash_testing"."identification_number"::integer, "hash_testing"."product_code"::string) output: ("hash_testing"."identification_number"::integer -> "identification_number", "hash_testing"."product_code"::string -> "product_code", "hash_testing"."product_units"::boolean -> "product_units", "hash_testing"."sys_op"::unsigned -> "sys_op", "hash_testing"."bucket_id"::unsigned -> "bucket_id") scan "hash_testing" execution options: sql_vdbe_max_steps = 45000 @@ -1374,19 +1375,20 @@ fn front_sql_groupby_join_1() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_63"::string -> "product_code", "column_64"::boolean -> "product_units") group by ("column_63"::string, "column_64"::boolean) output: ("column_64"::boolean -> "column_64", "column_63"::string -> "column_63") motion [policy: segment([ref("column_63"), ref("column_64")])] scan - projection ("T2"."product_units"::boolean -> "column_64", "T2"."product_code"::string -> "column_63") - group by ("T2"."product_code"::string, "T2"."product_units"::boolean) output: ("T2"."product_units"::boolean -> "product_units", "T2"."product_code"::string -> "product_code", "T2"."identification_number"::integer -> "identification_number", "T"."id"::unsigned -> "id") - join on ROW("T2"."identification_number"::integer) = ROW("T"."id"::unsigned) - scan "T2" + projection ("t2"."product_units"::boolean -> "column_64", "t2"."product_code"::string -> "column_63") + group by ("t2"."product_code"::string, "t2"."product_units"::boolean) output: ("t2"."product_units"::boolean -> "product_units", "t2"."product_code"::string -> "product_code", "t2"."identification_number"::integer -> "identification_number", "t"."id"::unsigned -> "id") + join on ROW("t2"."identification_number"::integer) = ROW("t"."id"::unsigned) + scan "t2" projection ("hash_testing"."product_units"::boolean -> "product_units", "hash_testing"."product_code"::string -> "product_code", "hash_testing"."identification_number"::integer -> "identification_number") scan "hash_testing" motion [policy: full] - scan "T" + scan "t" projection ("test_space"."id"::unsigned -> "id") scan "test_space" execution options: @@ -1408,13 +1410,13 @@ fn front_sql_join() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T2"."product_code"::string -> "product_code", "T2"."product_units"::boolean -> "product_units") - join on ROW("T2"."identification_number"::integer) = ROW("T"."id"::unsigned) and not ROW("T"."id"::unsigned) is null - scan "T2" + r#"projection ("t2"."product_code"::string -> "product_code", "t2"."product_units"::boolean -> "product_units") + join on ROW("t2"."identification_number"::integer) = ROW("t"."id"::unsigned) and not ROW("t"."id"::unsigned) is null + scan "t2" projection ("hash_testing"."product_units"::boolean -> "product_units", "hash_testing"."product_code"::string -> "product_code", "hash_testing"."identification_number"::integer -> "identification_number") scan "hash_testing" motion [policy: full] - scan "T" + scan "t" projection ("test_space"."id"::unsigned -> "id") scan "test_space" execution options: @@ -1433,12 +1435,12 @@ vtable_max_rows = 5000 let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T1"."product_code"::string -> "product_code", "T1"."product_units"::boolean -> "product_units") - join on ROW("T1"."identification_number"::integer) = ROW("T2"."id"::unsigned) and not ROW("T2"."id"::unsigned) is null - scan "T1" + r#"projection ("t1"."product_code"::string -> "product_code", "t1"."product_units"::boolean -> "product_units") + join on ROW("t1"."identification_number"::integer) = ROW("t2"."id"::unsigned) and not ROW("t2"."id"::unsigned) is null + scan "t1" projection ("hash_single_testing"."product_units"::boolean -> "product_units", "hash_single_testing"."product_code"::string -> "product_code", "hash_single_testing"."identification_number"::integer -> "identification_number") scan "hash_single_testing" - scan "T2" + scan "t2" projection ("test_space"."id"::unsigned -> "id") scan "test_space" execution options: @@ -1455,17 +1457,18 @@ vtable_max_rows = 5000 "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); // TODO: For the hash function in the cartrisge runtime we can apply // `motion [policy: segment([ref("id")])]` instead of the `motion [policy: full]`. let expected_explain = String::from( - r#"projection ("T1"."product_code"::string -> "product_code", "T1"."product_units"::boolean -> "product_units") - join on ROW("T1"."identification_number"::integer) = ROW("T2"."id"::decimal) and not ROW("T2"."id"::decimal) is null - scan "T1" + r#"projection ("t1"."product_code"::string -> "product_code", "t1"."product_units"::boolean -> "product_units") + join on ROW("t1"."identification_number"::integer) = ROW("t2"."id"::decimal) and not ROW("t2"."id"::decimal) is null + scan "t1" projection ("hash_single_testing"."product_units"::boolean -> "product_units", "hash_single_testing"."product_code"::string -> "product_code", "hash_single_testing"."identification_number"::integer -> "identification_number") scan "hash_single_testing" motion [policy: full] - scan "T2" + scan "t2" projection (sum(("sum_41"::decimal))::decimal -> "id") motion [policy: full] scan @@ -1485,15 +1488,16 @@ fn front_sql_groupby_insert() { SELECT "b", "d" FROM "t" group by "b", "d" ON CONFLICT DO FAIL"#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"insert "t" on conflict: fail motion [policy: segment([value(NULL), ref("d")])] projection ("column_12"::unsigned -> "b", "column_13"::unsigned -> "d") - group by ("column_12"::unsigned, "column_13"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_13"::unsigned -> "column_13") - motion [policy: segment([ref("column_12"), ref("column_13")])] + group by ("column_13"::unsigned, "column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_13"::unsigned -> "column_13") + motion [policy: segment([ref("column_13"), ref("column_12")])] scan projection ("t"."b"::unsigned -> "column_12", "t"."d"::unsigned -> "column_13") - group by ("t"."b"::unsigned, "t"."d"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") + group by ("t"."d"::unsigned, "t"."b"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -1536,13 +1540,14 @@ fn front_sql_aggregates() { group by "b""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_12"::unsigned -> "b", ROW(sum(("count_29"::integer))::decimal) + ROW(sum(("count_31"::integer))::decimal) -> "COL_1") - group by ("column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "count_29"::integer -> "count_29", "count_31"::integer -> "count_31") + group by ("column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "count_31"::integer -> "count_31", "count_29"::integer -> "count_29") motion [policy: segment([ref("column_12")])] scan - projection ("t"."b"::unsigned -> "column_12", count(("t"."a"::unsigned))::integer -> "count_29", count(("t"."b"::unsigned))::integer -> "count_31") + projection ("t"."b"::unsigned -> "column_12", count(("t"."b"::unsigned))::integer -> "count_31", count(("t"."a"::unsigned))::integer -> "count_29") group by ("t"."b"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: @@ -1559,12 +1564,13 @@ fn front_sql_avg_aggregate() { let input = r#"SELECT avg("b"), avg(distinct "b"), avg("b") * avg("b") FROM "t""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection (sum(("sum_13"::decimal::double))::decimal / sum(("count_13"::decimal::double))::decimal -> "COL_1", avg(distinct ("column_15"::decimal::double))::decimal -> "COL_2", ROW(sum(("sum_13"::decimal::double))::decimal / sum(("count_13"::decimal::double))::decimal) * ROW(sum(("sum_13"::decimal::double))::decimal / sum(("count_13"::decimal::double))::decimal) -> "COL_3") motion [policy: full] scan - projection ("t"."b"::unsigned -> "column_15", sum(("t"."b"::unsigned))::decimal -> "sum_13", count(("t"."b"::unsigned))::integer -> "count_13") + projection ("t"."b"::unsigned -> "column_15", count(("t"."b"::unsigned))::integer -> "count_13", sum(("t"."b"::unsigned))::decimal -> "sum_13") group by ("t"."b"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: @@ -1752,13 +1758,14 @@ fn front_sql_aggregates_with_subexpressions() { group by "b""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_12"::unsigned -> "b", sum(("count_35"::integer))::decimal -> "COL_1", sum(("count_39"::integer))::decimal -> "COL_2") group by ("column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "count_39"::integer -> "count_39", "count_35"::integer -> "count_35") motion [policy: segment([ref("column_12")])] scan - projection ("t"."b"::unsigned -> "column_12", count(("FUNC"(("t"."a"::unsigned))::integer))::integer -> "count_39", count((ROW("t"."a"::unsigned) * ROW("t"."b"::unsigned) + ROW(1::unsigned)))::integer -> "count_35") + projection ("t"."b"::unsigned -> "column_12", count(("func"(("t"."a"::unsigned))::integer))::integer -> "count_39", count((ROW("t"."a"::unsigned) * ROW("t"."b"::unsigned) + ROW(1::unsigned)))::integer -> "count_35") group by ("t"."b"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: @@ -2077,11 +2084,12 @@ fn front_sql_aggregate_on_aggregate() { let input = r#"SELECT max(c) FROM (SELECT count("id") as c FROM "test_space") as "t1""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( - r#"projection (max(("t1"."C"::integer))::scalar -> "COL_1") + r#"projection (max(("t1"."c"::integer))::scalar -> "COL_1") scan "t1" - projection (sum(("count_13"::integer))::decimal -> "C") + projection (sum(("count_13"::integer))::decimal -> "c") motion [policy: full] scan projection (count(("test_space"."id"::unsigned))::integer -> "count_13") @@ -2198,7 +2206,7 @@ fn front_sql_insert_single() { projection (sum(("sum_13"::decimal))::decimal -> "COL_1", sum(("count_16"::integer))::decimal -> "COL_2") motion [policy: full] scan - projection (sum(("t"."b"::unsigned))::decimal -> "sum_13", count(("t"."d"::unsigned))::integer -> "count_16") + projection (count(("t"."d"::unsigned))::integer -> "count_16", sum(("t"."b"::unsigned))::decimal -> "sum_13") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2296,6 +2304,7 @@ fn front_sql_except_single_both() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"except motion [policy: segment([ref("COL_1")])] @@ -2308,7 +2317,7 @@ fn front_sql_except_single_both() { projection (sum(("sum_33"::decimal))::decimal -> "COL_1", sum(("sum_36"::decimal))::decimal -> "COL_2") motion [policy: full] scan - projection (sum(("t"."b"::unsigned))::decimal -> "sum_36", sum(("t"."a"::unsigned))::decimal -> "sum_33") + projection (sum(("t"."a"::unsigned))::decimal -> "sum_33", sum(("t"."b"::unsigned))::decimal -> "sum_36") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2373,13 +2382,14 @@ fn front_sql_groupby_expression3() { group by "a"+"b", "a"+"b", ("c"*"d")"#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_16"::unsigned -> "COL_1", "column_27"::unsigned * ROW(sum(("sum_59"::decimal))::decimal) / ROW(sum(("count_65"::integer))::decimal) -> "COL_2") - group by ("column_27"::unsigned, "column_16"::unsigned) output: ("column_16"::unsigned -> "column_16", "column_27"::unsigned -> "column_27", "count_65"::integer -> "count_65", "sum_59"::decimal -> "sum_59") - motion [policy: segment([ref("column_27"), ref("column_16")])] + group by ("column_16"::unsigned, "column_27"::unsigned) output: ("column_27"::unsigned -> "column_27", "column_16"::unsigned -> "column_16", "count_65"::integer -> "count_65", "sum_59"::decimal -> "sum_59") + motion [policy: segment([ref("column_16"), ref("column_27")])] scan - projection (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "column_16", (ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned)) -> "column_27", count((ROW("t"."a"::unsigned) * ROW("t"."b"::unsigned)))::integer -> "count_65", sum((ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned)))::decimal -> "sum_59") - group by ((ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned)), ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned)) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") + projection ((ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned)) -> "column_27", ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "column_16", count((ROW("t"."a"::unsigned) * ROW("t"."b"::unsigned)))::integer -> "count_65", sum((ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned)))::decimal -> "sum_59") + group by (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned), (ROW("t"."c"::unsigned) * ROW("t"."d"::unsigned))) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2396,13 +2406,14 @@ fn front_sql_groupby_expression4() { group by "a"+"b", "a""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_16"::unsigned -> "COL_1", "column_17"::unsigned -> "a") - group by ("column_17"::unsigned, "column_16"::unsigned) output: ("column_17"::unsigned -> "column_17", "column_16"::unsigned -> "column_16") - motion [policy: segment([ref("column_17"), ref("column_16")])] + group by ("column_16"::unsigned, "column_17"::unsigned) output: ("column_17"::unsigned -> "column_17", "column_16"::unsigned -> "column_16") + motion [policy: segment([ref("column_16"), ref("column_17")])] scan projection ("t"."a"::unsigned -> "column_17", ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "column_16") - group by ("t"."a"::unsigned, ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned)) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") + group by (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned), "t"."a"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2421,10 +2432,11 @@ fn front_sql_groupby_with_aggregates() { on (t1."a", t2."g") = (t2."e", t1."b")"#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( - r#"projection ("T1"."a"::unsigned -> "a", "T1"."b"::unsigned -> "b", "T1"."c"::decimal -> "c", "T2"."g"::unsigned -> "g", "T2"."e"::unsigned -> "e", "T2"."f"::decimal -> "f") - join on ROW("T1"."a"::unsigned, "T2"."g"::unsigned) = ROW("T2"."e"::unsigned, "T1"."b"::unsigned) - scan "T1" + r#"projection ("t1"."a"::unsigned -> "a", "t1"."b"::unsigned -> "b", "t1"."c"::decimal -> "c", "t2"."g"::unsigned -> "g", "t2"."e"::unsigned -> "e", "t2"."f"::decimal -> "f") + join on ROW("t1"."a"::unsigned, "t2"."g"::unsigned) = ROW("t2"."e"::unsigned, "t1"."b"::unsigned) + scan "t1" projection ("column_12"::unsigned -> "a", "column_13"::unsigned -> "b", sum(("sum_31"::decimal))::decimal -> "c") group by ("column_13"::unsigned, "column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_13"::unsigned -> "column_13", "sum_31"::decimal -> "sum_31") motion [policy: segment([ref("column_13"), ref("column_12")])] @@ -2433,7 +2445,7 @@ fn front_sql_groupby_with_aggregates() { group by ("t"."b"::unsigned, "t"."a"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" motion [policy: full] - scan "T2" + scan "t2" projection ("column_55"::unsigned -> "g", "column_56"::unsigned -> "e", sum(("sum_74"::decimal))::decimal -> "f") group by ("column_55"::unsigned, "column_56"::unsigned) output: ("column_56"::unsigned -> "column_56", "column_55"::unsigned -> "column_55", "sum_74"::decimal -> "sum_74") motion [policy: segment([ref("column_55"), ref("column_56")])] @@ -2460,14 +2472,14 @@ fn front_sql_left_join() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("O"."A"::unsigned -> "A", "I"."C"::unsigned -> "C", "I"."D"::unsigned -> "D") - left join on ROW("O"."A"::unsigned) = ROW("I"."C"::unsigned) - scan "O" - projection ("t"."a"::unsigned -> "A") + r#"projection ("o"."a"::unsigned -> "a", "i"."c"::unsigned -> "c", "i"."d"::unsigned -> "d") + left join on ROW("o"."a"::unsigned) = ROW("i"."c"::unsigned) + scan "o" + projection ("t"."a"::unsigned -> "a") scan "t" motion [policy: full] - scan "I" - projection ("t"."b"::unsigned -> "C", "t"."d"::unsigned -> "D") + scan "i" + projection ("t"."b"::unsigned -> "c", "t"."d"::unsigned -> "d") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2487,20 +2499,21 @@ fn front_sql_left_join_single_left() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( - r#"projection ("T1"."A"::decimal -> "A", "T2"."B"::unsigned -> "B") - left join on ROW("T1"."A"::decimal) = ROW("T2"."B"::unsigned) - motion [policy: segment([ref("A")])] - scan "T1" - projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "A") + r#"projection ("t1"."a"::decimal -> "a", "t2"."b"::unsigned -> "b") + left join on ROW("t1"."a"::decimal) = ROW("t2"."b"::unsigned) + motion [policy: segment([ref("a")])] + scan "t1" + projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "a") motion [policy: full] scan projection (sum(("test_space"."id"::unsigned))::decimal -> "sum_14") scan "test_space" motion [policy: full] - scan "T2" - projection ("test_space"."id"::unsigned -> "B") + scan "t2" + projection ("test_space"."id"::unsigned -> "b") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -2520,21 +2533,22 @@ fn front_sql_left_join_single_left2() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); // full motion should be under outer child let expected_explain = String::from( - r#"projection ("T1"."A"::decimal -> "A", "T2"."B"::unsigned -> "B") - left join on ROW("T1"."A"::decimal) + ROW(3::unsigned) <> ROW("T2"."B"::unsigned) - motion [policy: segment([ref("A")])] - scan "T1" - projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "A") + r#"projection ("t1"."a"::decimal -> "a", "t2"."b"::unsigned -> "b") + left join on ROW("t1"."a"::decimal) + ROW(3::unsigned) <> ROW("t2"."b"::unsigned) + motion [policy: segment([ref("a")])] + scan "t1" + projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "a") motion [policy: full] scan projection (sum(("test_space"."id"::unsigned))::decimal -> "sum_14") scan "test_space" motion [policy: full] - scan "T2" - projection ("test_space"."id"::unsigned -> "B") + scan "t2" + projection ("test_space"."id"::unsigned -> "b") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -2554,19 +2568,20 @@ fn front_sql_left_join_single_both() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); // full motion should be under outer child let expected_explain = String::from( - r#"projection ("T1"."A"::decimal -> "A", "T2"."B"::integer -> "B") - left join on ROW("T1"."A"::decimal) <> ROW("T2"."B"::integer) - scan "T1" - projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "A") + r#"projection ("t1"."a"::decimal -> "a", "t2"."b"::integer -> "b") + left join on ROW("t1"."a"::decimal) <> ROW("t2"."b"::integer) + scan "t1" + projection (ROW(sum(("sum_14"::decimal))::decimal) / ROW(3::unsigned) -> "a") motion [policy: full] scan projection (sum(("test_space"."id"::unsigned))::decimal -> "sum_14") scan "test_space" - scan "T2" - projection (sum(("count_38"::integer))::decimal -> "B") + scan "t2" + projection (sum(("count_38"::integer))::decimal -> "b") motion [policy: full] scan projection (count(("test_space"."id"::unsigned))::integer -> "count_38") @@ -2759,18 +2774,19 @@ fn front_sql_having_with_sq_segment_motion() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_12"::unsigned -> "sysFrom", "column_13"::unsigned -> "sys_op", sum(distinct ("column_70"::decimal))::decimal -> "sum", count(distinct ("column_70"::integer))::integer -> "count") having ROW("column_12"::unsigned, "column_13"::unsigned) in ROW($0, $0) - group by ("column_12"::unsigned, "column_13"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_70"::unsigned -> "column_70", "column_13"::unsigned -> "column_13") - motion [policy: segment([ref("column_12"), ref("column_13")])] + group by ("column_13"::unsigned, "column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_70"::unsigned -> "column_70", "column_13"::unsigned -> "column_13") + motion [policy: segment([ref("column_13"), ref("column_12")])] scan projection ("test_space"."sysFrom"::unsigned -> "column_12", "test_space"."id"::unsigned -> "column_70", "test_space"."sys_op"::unsigned -> "column_13") - group by ("test_space"."sysFrom"::unsigned, "test_space"."sys_op"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id") + group by ("test_space"."sys_op"::unsigned, "test_space"."sysFrom"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id") scan "test_space" subquery $0: -motion [policy: segment([ref("a"), ref("d")])] +motion [policy: segment([ref("d"), ref("a")])] scan projection ("t"."a"::unsigned -> "a", "t"."d"::unsigned -> "d") scan "t" @@ -2794,20 +2810,22 @@ fn front_sql_having_with_sq_segment_local_motion() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_12"::unsigned -> "sysFrom", "column_13"::unsigned -> "sys_op", sum(distinct ("column_70"::decimal))::decimal -> "sum", count(distinct ("column_70"::integer))::integer -> "count") having ROW("column_12"::unsigned, "column_13"::unsigned) in ROW($0, $0) - group by ("column_12"::unsigned, "column_13"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_70"::unsigned -> "column_70", "column_13"::unsigned -> "column_13") - motion [policy: segment([ref("column_12"), ref("column_13")])] + group by ("column_13"::unsigned, "column_12"::unsigned) output: ("column_12"::unsigned -> "column_12", "column_70"::unsigned -> "column_70", "column_13"::unsigned -> "column_13") + motion [policy: segment([ref("column_13"), ref("column_12")])] scan projection ("test_space"."sysFrom"::unsigned -> "column_12", "test_space"."id"::unsigned -> "column_70", "test_space"."sys_op"::unsigned -> "column_13") - group by ("test_space"."sysFrom"::unsigned, "test_space"."sys_op"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id") + group by ("test_space"."sys_op"::unsigned, "test_space"."sysFrom"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id") scan "test_space" subquery $0: -scan - projection ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b") - scan "t" +motion [policy: segment([ref("b"), ref("a")])] + scan + projection ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b") + scan "t" execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -2823,12 +2841,13 @@ fn front_sql_unique_local_aggregates() { let input = r#"SELECT sum("a"), count("a"), sum("a") + count("a") FROM "t""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); // here we must compute only two aggregates at local stage: sum(a), count(a) let expected_explain = String::from( r#"projection (sum(("sum_13"::decimal))::decimal -> "COL_1", sum(("count_16"::integer))::decimal -> "COL_2", ROW(sum(("sum_13"::decimal))::decimal) + ROW(sum(("count_16"::integer))::decimal) -> "COL_3") motion [policy: full] scan - projection (count(("t"."a"::unsigned))::integer -> "count_16", sum(("t"."a"::unsigned))::decimal -> "sum_13") + projection (sum(("t"."a"::unsigned))::decimal -> "sum_13", count(("t"."a"::unsigned))::integer -> "count_16") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2911,14 +2930,15 @@ fn front_sql_select_distinct() { let input = r#"SELECT distinct "a", "a" + "b" FROM "t""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); // here we must compute only two groupby columns at local stage: a, b let expected_explain = String::from( r#"projection ("column_22"::unsigned -> "a", "column_27"::unsigned -> "COL_1") - group by ("column_22"::unsigned, "column_27"::unsigned) output: ("column_22"::unsigned -> "column_22", "column_27"::unsigned -> "column_27") - motion [policy: segment([ref("column_22"), ref("column_27")])] + group by ("column_27"::unsigned, "column_22"::unsigned) output: ("column_22"::unsigned -> "column_22", "column_27"::unsigned -> "column_27") + motion [policy: segment([ref("column_27"), ref("column_22")])] scan projection ("t"."a"::unsigned -> "column_22", ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "column_27") - group by ("t"."a"::unsigned, ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned)) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") + group by (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned), "t"."a"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -2934,13 +2954,14 @@ fn front_sql_select_distinct_asterisk() { let input = r#"SELECT distinct * FROM "t""#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_23"::unsigned -> "a", "column_24"::unsigned -> "b", "column_25"::unsigned -> "c", "column_26"::unsigned -> "d") - group by ("column_24"::unsigned, "column_26"::unsigned, "column_23"::unsigned, "column_25"::unsigned) output: ("column_24"::unsigned -> "column_24", "column_23"::unsigned -> "column_23", "column_26"::unsigned -> "column_26", "column_25"::unsigned -> "column_25") - motion [policy: segment([ref("column_24"), ref("column_26"), ref("column_23"), ref("column_25")])] + group by ("column_24"::unsigned, "column_23"::unsigned, "column_25"::unsigned, "column_26"::unsigned) output: ("column_24"::unsigned -> "column_24", "column_23"::unsigned -> "column_23", "column_25"::unsigned -> "column_25", "column_26"::unsigned -> "column_26") + motion [policy: segment([ref("column_24"), ref("column_23"), ref("column_25"), ref("column_26")])] scan - projection ("t"."b"::unsigned -> "column_24", "t"."a"::unsigned -> "column_23", "t"."d"::unsigned -> "column_26", "t"."c"::unsigned -> "column_25") - group by ("t"."b"::unsigned, "t"."d"::unsigned, "t"."a"::unsigned, "t"."c"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") + projection ("t"."b"::unsigned -> "column_24", "t"."a"::unsigned -> "column_23", "t"."c"::unsigned -> "column_25", "t"."d"::unsigned -> "column_26") + group by ("t"."b"::unsigned, "t"."a"::unsigned, "t"."c"::unsigned, "t"."d"::unsigned) output: ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d", "t"."bucket_id"::unsigned -> "bucket_id") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -3225,12 +3246,12 @@ fn front_sql_update1() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( r#"update "t" -"b" = COL_1 -"d" = COL_3 -"a" = COL_0 -"c" = COL_2 +"b" = "COL_1" +"d" = "COL_3" +"a" = "COL_0" +"c" = "COL_2" motion [policy: segment([])] - projection (1::unsigned -> COL_0, "t"."b"::unsigned -> COL_1, "t"."c"::unsigned -> COL_2, "t"."d"::unsigned -> COL_3, "t"."a"::unsigned -> COL_4, "t"."b"::unsigned -> COL_5) + projection (1::unsigned -> "COL_0", "t"."b"::unsigned -> "COL_1", "t"."c"::unsigned -> "COL_2", "t"."d"::unsigned -> "COL_3", "t"."a"::unsigned -> "COL_4", "t"."b"::unsigned -> "COL_5") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -3247,9 +3268,9 @@ fn front_sql_update2() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( r#"update "t" -"c" = COL_0 +"c" = "COL_0" motion [policy: local] - projection (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> COL_0, "t"."b"::unsigned -> COL_1) + projection (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "COL_0", "t"."b"::unsigned -> "COL_1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -3266,9 +3287,9 @@ fn front_sql_update3() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( r#"update "t" -"c" = COL_0 +"c" = "COL_0" motion [policy: local] - projection (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> COL_0, "t"."b"::unsigned -> COL_1) + projection (ROW("t"."a"::unsigned) + ROW("t"."b"::unsigned) -> "COL_0", "t"."b"::unsigned -> "COL_1") selection ROW("t"."c"::unsigned) = ROW(1::unsigned) scan "t" execution options: @@ -3290,10 +3311,10 @@ fn front_sql_update4() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( r#"update "t" -"d" = COL_0 -"c" = COL_0 +"d" = "COL_0" +"c" = "COL_0" motion [policy: local] - projection (ROW("b1"::integer) * ROW(2::unsigned) -> COL_0, "t"."b"::unsigned -> COL_1) + projection (ROW("b1"::integer) * ROW(2::unsigned) -> "COL_0", "t"."b"::unsigned -> "COL_1") join on ROW("t"."c"::unsigned) = ROW("b1"::integer) scan "t" projection ("t"."a"::unsigned -> "a", "t"."b"::unsigned -> "b", "t"."c"::unsigned -> "c", "t"."d"::unsigned -> "d") @@ -3320,9 +3341,9 @@ fn front_sql_update5() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( r#"update "t3" -"b" = COL_0 +"b" = "COL_0" motion [policy: local] - projection ("test_space"."id"::unsigned -> COL_0, "t3"."a"::string -> COL_1) + projection ("test_space"."id"::unsigned -> "COL_0", "t3"."a"::string -> "COL_1") join on ROW("t3"."a"::string) = ROW("test_space"."id"::unsigned) scan "t3" projection ("t3"."a"::string -> "a", "t3"."b"::integer -> "b") @@ -3345,17 +3366,18 @@ fn front_sql_update6() { where "b" in (select sum("b") as s from "t3")"#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"update "t3" -"b" = COL_0 +"b" = "COL_0" motion [policy: local] - projection (2::unsigned -> COL_0, "t3"."a"::string -> COL_1) + projection (2::unsigned -> "COL_0", "t3"."a"::string -> "COL_1") selection ROW("t3"."b"::integer) in ROW($0) scan "t3" subquery $0: motion [policy: full] scan - projection (sum(("sum_17"::decimal))::decimal -> "S") + projection (sum(("sum_17"::decimal))::decimal -> "s") motion [policy: full] scan projection (sum(("t3"."b"::integer))::decimal -> "sum_17") @@ -3608,10 +3630,10 @@ vtable_max_rows = 5000 fn front_sql_to_date() { assert_explain_eq( r#" - SELECT to_date(COLUMN_1, '%Y/%d/%m') FROM (values ('2010/10/10')) + SELECT to_date("COLUMN_1", '%Y/%d/%m') FROM (values ('2010/10/10')) "#, vec![], - r#"projection ("TO_DATE"(("COLUMN_1"::string, '%Y/%d/%m'::string))::datetime -> "COL_1") + r#"projection ("to_date"(("COLUMN_1"::string, '%Y/%d/%m'::string))::datetime -> "COL_1") scan values value row (data=ROW('2010/10/10'::string)) @@ -3633,7 +3655,7 @@ fn front_sql_current_date() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = format!( r#"projection ({today} 0:00:00.0 +00:00:00::datetime -> "COL_1") - selection ROW("TO_DATE"(('2010/10/10'::string, '%Y/%d/%m'::string))::datetime) < ROW({today} 0:00:00.0 +00:00:00::datetime) + selection ROW("to_date"(('2010/10/10'::string, '%Y/%d/%m'::string))::datetime) < ROW({today} 0:00:00.0 +00:00:00::datetime) scan values value row (data=ROW('2010/10/10'::string)) @@ -3692,7 +3714,7 @@ fn front_count_no_params() { assert_eq!( true, err.to_string() - .contains("invalid query: Expected one argument for aggregate: count") + .contains("invalid query: Expected one argument for aggregate: \"count\"") ); } diff --git a/sbroad-core/src/frontend/sql/ir/tests/cte.rs b/sbroad-core/src/frontend/sql/ir/tests/cte.rs index 2d612e183..0f39c4324 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/cte.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/cte.rs @@ -7,15 +7,15 @@ use pretty_assertions::assert_eq; #[test] fn cte() { - let sql = r#"WITH cte (a) AS (SELECT first_name FROM "test_space") SELECT * FROM cte"#; + let sql = r#"WITH cte (a) AS (SELECT "FIRST_NAME" FROM "test_space") SELECT * FROM cte"#; let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) + r#"projection ("cte"."a"::string -> "a") + scan cte cte($0) subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -31,10 +31,10 @@ fn global_cte() { let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE"."A"::integer -> "A") - scan cte "CTE"($0) + r#"projection ("cte"."a"::integer -> "a") + scan cte cte($0) subquery $0: -projection ("global_t"."a"::integer -> "A") +projection ("global_t"."a"::integer -> "a") scan "global_t" execution options: sql_vdbe_max_steps = 45000 @@ -47,22 +47,22 @@ vtable_max_rows = 5000 #[test] fn nested_cte() { let sql = r#" - WITH cte1 (a) AS (SELECT first_name FROM "test_space"), + WITH cte1 (a) AS (SELECT "FIRST_NAME" FROM "test_space"), cte2 AS (SELECT * FROM cte1) SELECT * FROM cte2 "#; let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE2"."A"::string -> "A") - scan cte "CTE2"($1) + r#"projection ("cte2"."a"::string -> "a") + scan cte cte2($1) subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") scan "test_space" subquery $1: -projection ("CTE1"."A"::string -> "A") - scan cte "CTE1"($0) +projection ("cte1"."a"::string -> "a") + scan cte cte1($0) execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -74,7 +74,7 @@ vtable_max_rows = 5000 #[test] fn reuse_cte_union_all() { let sql = r#" - WITH cte (a) AS (SELECT first_name FROM "test_space") + WITH cte (a) AS (SELECT "FIRST_NAME" FROM "test_space") SELECT * FROM cte UNION ALL SELECT * FROM cte @@ -83,13 +83,13 @@ fn reuse_cte_union_all() { let expected_explain = String::from( r#"union all - projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) - projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) + projection ("cte"."a"::string -> "a") + scan cte cte($0) + projection ("cte"."a"::string -> "a") + scan cte cte($0) subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -103,9 +103,9 @@ vtable_max_rows = 5000 fn reuse_union_in_cte() { let sql = r#" WITH cte (a) AS ( - SELECT first_name FROM "test_space" + SELECT "FIRST_NAME" FROM "test_space" UNION - SELECT first_name FROM "test_space" + SELECT "FIRST_NAME" FROM "test_space" ) SELECT * FROM cte UNION @@ -116,13 +116,13 @@ fn reuse_union_in_cte() { let expected_explain = String::from( r#"motion [policy: full] union - projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) - projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) + projection ("cte"."a"::string -> "a") + scan cte cte($0) + projection ("cte"."a"::string -> "a") + scan cte cte($0) subquery $0: -projection ("CTE"."FIRST_NAME"::string -> "A") - scan "CTE" +projection ("cte"."FIRST_NAME"::string -> "a") + scan "cte" motion [policy: full] union projection ("test_space"."FIRST_NAME"::string -> "FIRST_NAME") @@ -147,18 +147,18 @@ fn reuse_cte_values() { let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("T"."C"::integer -> "C") + r#"projection ("t"."c"::integer -> "c") join on true::boolean - scan "T" - projection (count((*::integer))::integer -> "C") + scan "t" + projection (count((*::integer))::integer -> "c") join on true::boolean - scan cte "C1"($0) - scan cte "C2"($0) - scan cte "CTE"($0) + scan cte c1($0) + scan cte c2($0) + scan cte cte($0) subquery $0: motion [policy: full] - projection ("CTE"."COLUMN_1"::unsigned -> "B") - scan "CTE" + projection ("cte"."COLUMN_1"::unsigned -> "b") + scan "cte" values value row (data=ROW(1::unsigned)) execution options: @@ -172,22 +172,22 @@ vtable_max_rows = 5000 #[test] fn join_cte() { let sql = r#" - WITH cte (a) AS (SELECT first_name FROM "test_space") - SELECT t.first_name FROM "test_space" t - JOIN cte ON t.first_name = cte.a + WITH cte (a) AS (SELECT "FIRST_NAME" FROM "test_space") + SELECT t."FIRST_NAME" FROM "test_space" t + JOIN cte ON t."FIRST_NAME" = cte.a "#; let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("T"."FIRST_NAME"::string -> "FIRST_NAME") - join on ROW("T"."FIRST_NAME"::string) = ROW("CTE"."A"::string) - scan "T" - projection ("T"."id"::unsigned -> "id", "T"."sysFrom"::unsigned -> "sysFrom", "T"."FIRST_NAME"::string -> "FIRST_NAME", "T"."sys_op"::unsigned -> "sys_op") - scan "test_space" -> "T" - scan cte "CTE"($0) + r#"projection ("t"."FIRST_NAME"::string -> "FIRST_NAME") + join on ROW("t"."FIRST_NAME"::string) = ROW("cte"."a"::string) + scan "t" + projection ("t"."id"::unsigned -> "id", "t"."sysFrom"::unsigned -> "sysFrom", "t"."FIRST_NAME"::string -> "FIRST_NAME", "t"."sys_op"::unsigned -> "sys_op") + scan "test_space" -> "t" + scan cte cte($0) subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -200,17 +200,17 @@ vtable_max_rows = 5000 #[test] fn agg_cte() { let sql = r#" - WITH cte (a) AS (SELECT first_name FROM "test_space") + WITH cte (a) AS (SELECT "FIRST_NAME" FROM "test_space") SELECT count(a) FROM cte "#; let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection (count(("CTE"."A"::string))::integer -> "COL_1") - scan cte "CTE"($0) + r#"projection (count(("cte"."a"::string))::integer -> "COL_1") + scan cte cte($0) subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -223,8 +223,8 @@ vtable_max_rows = 5000 #[test] fn sq_cte() { let sql = r#" - WITH cte (a) AS (SELECT first_name FROM "test_space" WHERE first_name = 'hi') - SELECT first_name FROM "test_space" WHERE first_name IN (SELECT a FROM cte) + WITH cte (a) AS (SELECT "FIRST_NAME" FROM "test_space" WHERE "FIRST_NAME" = 'hi') + SELECT "FIRST_NAME" FROM "test_space" WHERE "FIRST_NAME" IN (SELECT a FROM cte) "#; let plan = sql_to_optimized_ir(sql, vec![]); @@ -234,13 +234,13 @@ fn sq_cte() { scan "test_space" subquery $0: motion [policy: full] - projection ("test_space"."FIRST_NAME"::string -> "A") + projection ("test_space"."FIRST_NAME"::string -> "a") selection ROW("test_space"."FIRST_NAME"::string) = ROW('hi'::string) scan "test_space" subquery $1: scan - projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) + projection ("cte"."a"::string -> "a") + scan cte cte($0) execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -258,12 +258,12 @@ fn values_in_cte() { let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE"."A"::string -> "A") - scan cte "CTE"($0) + r#"projection ("cte"."a"::string -> "a") + scan cte cte($0) subquery $0: motion [policy: full] - projection ("CTE"."COLUMN_1"::string -> "A") - scan "CTE" + projection ("cte"."COLUMN_1"::string -> "a") + scan "cte" values value row (data=ROW('a'::string)) execution options: @@ -284,21 +284,21 @@ fn union_all_in_cte() { let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE2"."A"::string -> "A") - scan cte "CTE2"($1) + r#"projection ("cte2"."a"::string -> "a") + scan cte cte2($1) subquery $0: motion [policy: full] - projection ("CTE1"."COLUMN_1"::string -> "A") - scan "CTE1" + projection ("cte1"."COLUMN_1"::string -> "a") + scan "cte1" values value row (data=ROW('a'::string)) subquery $1: motion [policy: full] union all - projection ("CTE1"."A"::string -> "A") - scan cte "CTE1"($0) - projection ("CTE1"."A"::string -> "A") - scan cte "CTE1"($0) + projection ("cte1"."a"::string -> "a") + scan cte cte1($0) + projection ("cte1"."a"::string -> "a") + scan cte cte1($0) execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -311,27 +311,27 @@ vtable_max_rows = 5000 fn join_in_cte() { let sql = r#" WITH cte AS ( - SELECT t1.first_name FROM "test_space" t1 - JOIN "test_space" t2 ON t1.first_name = t2."id" + SELECT t1."FIRST_NAME" FROM "test_space" t1 + JOIN "test_space" t2 ON t1."FIRST_NAME" = t2."id" ) SELECT * FROM cte "#; let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE"."FIRST_NAME"::string -> "FIRST_NAME") - scan cte "CTE"($0) + r#"projection ("cte"."FIRST_NAME"::string -> "FIRST_NAME") + scan cte cte($0) subquery $0: motion [policy: full] - projection ("T1"."FIRST_NAME"::string -> "FIRST_NAME") - join on ROW("T1"."FIRST_NAME"::string) = ROW("T2"."id"::unsigned) - scan "T1" - projection ("T1"."id"::unsigned -> "id", "T1"."sysFrom"::unsigned -> "sysFrom", "T1"."FIRST_NAME"::string -> "FIRST_NAME", "T1"."sys_op"::unsigned -> "sys_op") - scan "test_space" -> "T1" + projection ("t1"."FIRST_NAME"::string -> "FIRST_NAME") + join on ROW("t1"."FIRST_NAME"::string) = ROW("t2"."id"::unsigned) + scan "t1" + projection ("t1"."id"::unsigned -> "id", "t1"."sysFrom"::unsigned -> "sysFrom", "t1"."FIRST_NAME"::string -> "FIRST_NAME", "t1"."sys_op"::unsigned -> "sys_op") + scan "test_space" -> "t1" motion [policy: full] - scan "T2" - projection ("T2"."id"::unsigned -> "id", "T2"."sysFrom"::unsigned -> "sysFrom", "T2"."FIRST_NAME"::string -> "FIRST_NAME", "T2"."sys_op"::unsigned -> "sys_op") - scan "test_space" -> "T2" + scan "t2" + projection ("t2"."id"::unsigned -> "id", "t2"."sysFrom"::unsigned -> "sysFrom", "t2"."FIRST_NAME"::string -> "FIRST_NAME", "t2"."sys_op"::unsigned -> "sys_op") + scan "test_space" -> "t2" execution options: sql_vdbe_max_steps = 45000 vtable_max_rows = 5000 @@ -344,7 +344,7 @@ vtable_max_rows = 5000 fn order_by_in_cte() { let sql = r#" WITH cte AS ( - SELECT first_name FROM "test_space" + SELECT "FIRST_NAME" FROM "test_space" ORDER BY 1 ) SELECT * FROM cte @@ -352,8 +352,8 @@ fn order_by_in_cte() { let plan = sql_to_optimized_ir(sql, vec![]); let expected_explain = String::from( - r#"projection ("CTE"."FIRST_NAME"::string -> "FIRST_NAME") - scan cte "CTE"($0) + r#"projection ("cte"."FIRST_NAME"::string -> "FIRST_NAME") + scan cte cte($0) subquery $0: projection ("FIRST_NAME"::string -> "FIRST_NAME") order by (1) @@ -372,7 +372,7 @@ vtable_max_rows = 5000 #[test] fn table_name_conflict() { let sql = r#" - WITH "test_space" AS (SELECT first_name FROM "test_space") + WITH "test_space" AS (SELECT "FIRST_NAME" FROM "test_space") SELECT * FROM "test_space" "#; let metadata = &RouterConfigurationMock::new(); @@ -389,7 +389,7 @@ fn table_name_conflict() { #[test] fn cte_name_conflict() { let sql = r#" - WITH cte AS (SELECT first_name FROM "test_space"), + WITH cte AS (SELECT "FIRST_NAME" FROM "test_space"), cte as (SELECT 'a' as a from "test_space") SELECT * FROM cte "#; @@ -399,7 +399,7 @@ fn cte_name_conflict() { plan_error, Err(SbroadError::Invalid( Entity::Cte, - Some(r#"CTE with name "CTE" is already defined"#.into()) + Some(r#"CTE with name "cte" is already defined"#.into()) )) ); } @@ -407,7 +407,7 @@ fn cte_name_conflict() { #[test] fn cte_column_mismatch() { let sql = r#" - WITH cte(a) AS (SELECT first_name, first_name FROM "test_space") + WITH cte(a) AS (SELECT "FIRST_NAME", "FIRST_NAME" FROM "test_space") SELECT * FROM cte "#; let metadata = &RouterConfigurationMock::new(); @@ -423,8 +423,8 @@ fn cte_column_mismatch() { #[test] fn cte_with_left_join() { let sql = r#" - with cte as (select "e" as e from "t2") - select e from cte left join "t2" + with cte as (select "e" as "E" from "t2") + select "E" from cte left join "t2" on true "#; @@ -434,9 +434,9 @@ fn cte_with_left_join() { r#"projection ("E"::unsigned -> "E") motion [policy: full] scan - projection ("CTE"."E"::unsigned -> "E", "t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h") + projection ("cte"."E"::unsigned -> "E", "t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h") join on true::boolean - scan cte "CTE"($0) + scan cte cte($0) scan "t2" projection ("t2"."e"::unsigned -> "e", "t2"."f"::unsigned -> "f", "t2"."g"::unsigned -> "g", "t2"."h"::unsigned -> "h") scan "t2" diff --git a/sbroad-core/src/frontend/sql/ir/tests/ddl.rs b/sbroad-core/src/frontend/sql/ir/tests/ddl.rs index c0c58a7d7..405e766d7 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/ddl.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/ddl.rs @@ -30,14 +30,14 @@ fn infer_not_null_on_pk1() { }; let def = ColumnDef { - name: "A".into(), + name: "a".into(), data_type: Type::Integer, is_nullable: false, }; assert_eq!(format, &vec![def]); - let expected_pk: Vec<SmolStr> = vec!["A".into()]; + let expected_pk: Vec<SmolStr> = vec!["a".into()]; assert_eq!(primary_key, &expected_pk); } @@ -61,26 +61,26 @@ fn infer_not_null_on_pk2() { }; let def_a = ColumnDef { - name: "A".into(), + name: "a".into(), data_type: Type::Integer, is_nullable: false, }; let def_b = ColumnDef { - name: "B".into(), + name: "b".into(), data_type: Type::Integer, is_nullable: false, }; let def_c = ColumnDef { - name: "C".into(), + name: "c".into(), data_type: Type::Integer, is_nullable: true, }; assert_eq!(format, &vec![def_a, def_b, def_c]); - let expected_pk: Vec<SmolStr> = vec!["A".into(), "B".into()]; + let expected_pk: Vec<SmolStr> = vec!["a".into(), "b".into()]; assert_eq!(primary_key, &expected_pk); } diff --git a/sbroad-core/src/frontend/sql/ir/tests/global.rs b/sbroad-core/src/frontend/sql/ir/tests/global.rs index cf8ea980a..2cdf46165 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/global.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/global.rs @@ -92,7 +92,7 @@ scan subquery $1: motion [policy: full] scan - projection ("t"."a"::unsigned -> "A1") + projection ("t"."a"::unsigned -> "a1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -128,7 +128,7 @@ scan scan "t" subquery $1: scan - projection ("t"."a"::unsigned -> "A1", "t"."b"::unsigned -> "B1") + projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -167,7 +167,7 @@ scan subquery $1: motion [policy: full] scan - projection ("t"."a"::unsigned -> "A1", "t"."b"::unsigned -> "B1") + projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -193,7 +193,7 @@ fn front_sql_global_tbl_sq2() { scan "global_t" subquery $0: scan - projection ("t"."a"::unsigned -> "A1", "t"."b"::unsigned -> "B1") + projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -221,12 +221,12 @@ fn front_sql_global_tbl_sq3() { subquery $0: motion [policy: full] scan - projection ("t"."a"::unsigned -> "A1", "t"."b"::unsigned -> "B1") + projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1") scan "t" subquery $1: motion [policy: full] scan - projection ("t"."a"::unsigned -> "A1", "t"."b"::unsigned -> "B1") + projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1") scan "t" execution options: sql_vdbe_max_steps = 45000 @@ -259,7 +259,7 @@ fn front_sql_global_tbl_sq4() { scan "hash_testing" subquery $0: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" execution options: sql_vdbe_max_steps = 45000 @@ -290,7 +290,7 @@ fn front_sql_global_tbl_sq5() { scan "t2" subquery $0: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" execution options: sql_vdbe_max_steps = 45000 @@ -326,16 +326,16 @@ fn front_sql_global_tbl_sq6() { scan "t2" subquery $0: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" subquery $1: scan - projection (ROW("global_t"."a"::integer) * ROW(20::unsigned) -> "A1") + projection (ROW("global_t"."a"::integer) * ROW(20::unsigned) -> "a1") selection ROW("global_t"."a"::integer) = ROW(1::unsigned) scan "global_t" subquery $2: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" subquery $3: scan @@ -372,11 +372,11 @@ fn front_sql_global_tbl_sq7() { scan "t2" subquery $0: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" subquery $1: scan - projection ("global_t"."a"::integer -> "A1") + projection ("global_t"."a"::integer -> "a1") scan "global_t" execution options: sql_vdbe_max_steps = 45000 @@ -493,10 +493,10 @@ fn front_sql_global_join4() { check_join_dist(&plan, &[DistMock::Single]); let expected_explain = String::from( - r#"projection ("S"."E"::decimal -> "E") + r#"projection ("s"."e"::decimal -> "e") left join on true::boolean - scan "S" - projection (sum(("sum_13"::decimal))::decimal -> "E") + scan "s" + projection (sum(("sum_13"::decimal))::decimal -> "e") motion [policy: full] scan projection (sum(("t2"."e"::unsigned))::decimal -> "sum_13") @@ -524,13 +524,13 @@ fn front_sql_global_join5() { check_join_dist(&plan, &[DistMock::Single]); let expected_explain = String::from( - r#"projection ("S"."E"::decimal -> "E") + r#"projection ("s"."e"::decimal -> "e") left join on true::boolean scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") scan "global_t" - scan "S" - projection (sum(("sum_19"::decimal))::decimal -> "E") + scan "s" + projection (sum(("sum_19"::decimal))::decimal -> "e") motion [policy: full] scan projection (sum(("t2"."e"::unsigned))::decimal -> "sum_19") @@ -555,13 +555,13 @@ fn front_sql_global_join6() { check_join_dist(&plan, &[DistMock::Any]); let expected_explain = String::from( - r#"projection ("S"."E"::unsigned -> "E") + r#"projection ("s"."e"::unsigned -> "e") join on true::boolean scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") scan "global_t" - scan "S" - projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "E") + scan "s" + projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "e") scan "t2" execution options: sql_vdbe_max_steps = 45000 @@ -583,10 +583,10 @@ fn front_sql_global_join7() { check_join_dist(&plan, &[DistMock::Any]); let expected_explain = String::from( - r#"projection ("S"."E"::unsigned -> "E") + r#"projection ("s"."e"::unsigned -> "e") join on true::boolean - scan "S" - projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "E") + scan "s" + projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "e") scan "t2" scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") @@ -611,10 +611,10 @@ fn front_sql_global_join8() { check_join_dist(&plan, &[DistMock::Global]); let expected_explain = String::from( - r#"projection ("E"::integer -> "E") + r#"projection ("e"::integer -> "e") join on true::boolean scan - projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "E") + projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "e") scan "global_t" scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") @@ -639,10 +639,10 @@ fn front_sql_global_join9() { check_join_dist(&plan, &[DistMock::Any]); let expected_explain = String::from( - r#"projection ("E"::unsigned -> "E") + r#"projection ("e"::unsigned -> "e") left join on true::boolean scan - projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "E") + projection (ROW("t2"."e"::unsigned) * ROW("t2"."e"::unsigned) -> "e") scan "t2" scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") @@ -667,10 +667,10 @@ fn front_sql_global_join10() { check_join_dist(&plan, &[DistMock::Global]); let expected_explain = String::from( - r#"projection ("E"::integer -> "E") - join on ROW("E"::integer) in ROW($0) + r#"projection ("e"::integer -> "e") + join on ROW("e"::integer) in ROW($0) scan - projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "E") + projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "e") scan "global_t" scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") @@ -700,10 +700,10 @@ fn front_sql_global_join11() { check_join_dist(&plan, &[DistMock::Any]); let expected_explain = String::from( - r#"projection ("E"::integer -> "E") - join on ROW("E"::integer, "E"::integer) in ROW($0, $0) + r#"projection ("e"::integer -> "e") + join on ROW("e"::integer, "e"::integer) in ROW($0, $0) scan - projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "E") + projection (ROW("global_t"."a"::integer) * ROW("global_t"."a"::integer) -> "e") scan "global_t" scan "global_t" projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") @@ -812,14 +812,15 @@ fn front_sql_global_aggregate5() { "#; let plan = sql_to_optimized_ir(input, vec![]); + println!("{}", plan.as_explain().unwrap()); let expected_explain = String::from( r#"projection ("column_44"::integer -> "COL_1", sum(("sum_70"::decimal))::decimal -> "COL_2") having ROW(sum(("sum_53"::decimal::double))::decimal / sum(("count_53"::decimal::double))::decimal) > ROW(3::unsigned) - group by ("column_44"::integer) output: ("column_44"::integer -> "column_44", "sum_53"::decimal -> "sum_53", "sum_70"::decimal -> "sum_70", "count_53"::integer -> "count_53") + group by ("column_44"::integer) output: ("column_44"::integer -> "column_44", "sum_70"::decimal -> "sum_70", "sum_53"::decimal -> "sum_53", "count_53"::integer -> "count_53") motion [policy: segment([ref("column_44")])] scan - projection (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer) -> "column_44", sum(("global_t"."b"::integer))::decimal -> "sum_53", sum(("global_t"."a"::integer))::decimal -> "sum_70", count(("global_t"."b"::integer))::integer -> "count_53") + projection (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer) -> "column_44", sum(("global_t"."a"::integer))::decimal -> "sum_70", sum(("global_t"."b"::integer))::decimal -> "sum_53", count(("global_t"."b"::integer))::integer -> "count_53") group by (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer)) output: ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b") selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($0, $0) scan "global_t" @@ -1425,8 +1426,8 @@ fn check_plan_except_non_trivial_global_subtree_vs_any() { // a global table let input = r#" select "b" from "global_t" - left join (select "b" as b from "global_t") - on "a" = b + left join (select "b" as "B" from "global_t") + on "a" = "B" where "a" = 1 except select "e" from "t2" diff --git a/sbroad-core/src/frontend/sql/ir/tests/insert.rs b/sbroad-core/src/frontend/sql/ir/tests/insert.rs index 43c1707ff..50560bbad 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/insert.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/insert.rs @@ -4,7 +4,7 @@ use pretty_assertions::assert_eq; #[test] fn insert1() { - let pattern = r#"INSERT INTO "test_space"("id", first_name) VALUES(?, ?)"#; + let pattern = r#"INSERT INTO "test_space"("id", "FIRST_NAME") VALUES(?, ?)"#; let plan = sql_to_optimized_ir(pattern, vec![Value::from(1_i64), Value::from("test")]); let expected_explain = String::from( diff --git a/sbroad-core/src/frontend/sql/ir/tests/join.rs b/sbroad-core/src/frontend/sql/ir/tests/join.rs index 9c0777e53..a6271a5c9 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/join.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/join.rs @@ -14,19 +14,19 @@ fn milti_join1() { let plan = sql_to_optimized_ir(input, vec![]); let expected_explain = String::from( - r#"projection ("T1"."identification_number"::integer -> "identification_number", "T1"."product_code"::string -> "product_code", "T2"."id"::unsigned -> "id", "T3"."id"::unsigned -> "id") - selection ROW("T1"."identification_number"::integer) = ROW(5::unsigned) and ROW("T1"."product_code"::string) = ROW('123'::string) - left join on ROW("T1"."identification_number"::integer) = ROW("T3"."id"::unsigned) - join on ROW("T1"."identification_number"::integer) = ROW("T2"."id"::unsigned) - scan "T1" + r#"projection ("t1"."identification_number"::integer -> "identification_number", "t1"."product_code"::string -> "product_code", "t2"."id"::unsigned -> "id", "t3"."id"::unsigned -> "id") + selection ROW("t1"."identification_number"::integer) = ROW(5::unsigned) and ROW("t1"."product_code"::string) = ROW('123'::string) + left join on ROW("t1"."identification_number"::integer) = ROW("t3"."id"::unsigned) + join on ROW("t1"."identification_number"::integer) = ROW("t2"."id"::unsigned) + scan "t1" projection ("hash_testing"."identification_number"::integer -> "identification_number", "hash_testing"."product_code"::string -> "product_code") scan "hash_testing" motion [policy: full] - scan "T2" + scan "t2" projection ("test_space"."id"::unsigned -> "id") scan "test_space" motion [policy: full] - scan "T3" + scan "t3" projection ("test_space"."id"::unsigned -> "id") scan "test_space" execution options: diff --git a/sbroad-core/src/frontend/sql/ir/tests/single.rs b/sbroad-core/src/frontend/sql/ir/tests/single.rs index 0759c1001..412d2bc72 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/single.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/single.rs @@ -243,7 +243,7 @@ fn front_sql_join_single_left_2() { on (o.a, o.b) = (i.c, i.d) "#; - check_join_motions(input, Policy::new_seg(&["A", "B"]), Policy::None, None); + check_join_motions(input, Policy::new_seg(&["a", "b"]), Policy::None, None); } #[test] @@ -267,7 +267,7 @@ fn front_sql_join_single_left_4() { check_join_motions( input, - Policy::new_seg(&["A", "B"]), + Policy::new_seg(&["a", "b"]), Policy::None, Some(vec![Policy::Full]), ); @@ -280,7 +280,7 @@ fn front_sql_join_single_left_5() { on o.a = i."id" and (i."sysFrom" = i."sys_op" and o.a = cast(o.a as number) + 1) "#; - check_join_motions(input, Policy::new_seg(&["A"]), Policy::None, None); + check_join_motions(input, Policy::new_seg(&["a"]), Policy::None, None); } #[test] @@ -292,7 +292,7 @@ fn front_sql_join_single_left_6() { check_join_motions( input, - Policy::new_seg(&["A"]), + Policy::new_seg(&["a"]), Policy::None, Some(vec![Policy::Full]), ); diff --git a/sbroad-core/src/frontend/sql/ir/tests/update.rs b/sbroad-core/src/frontend/sql/ir/tests/update.rs index c34210134..6bad29c01 100644 --- a/sbroad-core/src/frontend/sql/ir/tests/update.rs +++ b/sbroad-core/src/frontend/sql/ir/tests/update.rs @@ -4,14 +4,14 @@ use pretty_assertions::assert_eq; #[test] fn update1() { - let pattern = r#"UPDATE "test_space" SET first_name = 'test'"#; + let pattern = r#"UPDATE "test_space" SET "FIRST_NAME" = 'test'"#; let plan = sql_to_optimized_ir(pattern, vec![]); let expected_explain = String::from( r#"update "test_space" -"FIRST_NAME" = COL_0 +"FIRST_NAME" = "COL_0" motion [policy: local] - projection ('test'::string -> COL_0, "test_space"."id"::unsigned -> COL_1) + projection ('test'::string -> "COL_0", "test_space"."id"::unsigned -> "COL_1") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -24,14 +24,14 @@ vtable_max_rows = 5000 #[test] fn update2() { - let pattern = r#"UPDATE "test_space" SET first_name = ?"#; + let pattern = r#"UPDATE "test_space" SET "FIRST_NAME" = ?"#; let plan = sql_to_optimized_ir(pattern, vec![Value::from("test")]); let expected_explain = String::from( r#"update "test_space" -"FIRST_NAME" = COL_0 +"FIRST_NAME" = "COL_0" motion [policy: local] - projection ('test'::string -> COL_0, "test_space"."id"::unsigned -> COL_1) + projection ('test'::string -> "COL_0", "test_space"."id"::unsigned -> "COL_1") scan "test_space" execution options: sql_vdbe_max_steps = 45000 diff --git a/sbroad-core/src/ir.rs b/sbroad-core/src/ir.rs index c513e2ce0..ad2cbc2e1 100644 --- a/sbroad-core/src/ir.rs +++ b/sbroad-core/src/ir.rs @@ -22,6 +22,7 @@ use relation::{Table, Type}; use crate::errors::Entity::Query; use crate::errors::{Action, Entity, SbroadError, TypeError}; +use crate::executor::engine::helpers::to_user; use crate::executor::engine::TableVersionMap; use crate::ir::expression::Expression::StableFunction; use crate::ir::helpers::RepeatableState; @@ -670,7 +671,10 @@ impl Plan { /// - no relation with given name pub fn get_relation_or_error(&self, name: &str) -> Result<&Table, SbroadError> { self.relations.get(name).ok_or_else(|| { - SbroadError::NotFound(Entity::Table, format_smolstr!("with name {name}")) + SbroadError::NotFound( + Entity::Table, + format_smolstr!("with name {}", to_user(name)), + ) }) } diff --git a/sbroad-core/src/ir/aggregates.rs b/sbroad-core/src/ir/aggregates.rs index 5adeab519..f1ecee6ce 100644 --- a/sbroad-core/src/ir/aggregates.rs +++ b/sbroad-core/src/ir/aggregates.rs @@ -207,7 +207,7 @@ pub struct SimpleAggregate { #[must_use] pub fn generate_local_alias_for_aggr(kind: &AggregateKind, suffix: &str) -> String { format!( - "\"{}_{kind}_{suffix}\"", + "{}_{kind}_{suffix}", uuid::Uuid::new_v4().as_simple().to_string() ) } @@ -215,7 +215,7 @@ pub fn generate_local_alias_for_aggr(kind: &AggregateKind, suffix: &str) -> Stri #[cfg(feature = "mock")] #[must_use] pub fn generate_local_alias_for_aggr(kind: &AggregateKind, suffix: &str) -> String { - format!("\"{kind}_{suffix}\"") + format!("{kind}_{suffix}") } impl SimpleAggregate { @@ -356,6 +356,7 @@ impl SimpleAggregate { children, feature, func_type: RelType::from(final_func), + is_system: true, }; let aggr_id = plan.nodes.push(Node::Expression(final_aggr)); final_aggregates.insert(local_kind, aggr_id); diff --git a/sbroad-core/src/ir/explain.rs b/sbroad-core/src/ir/explain.rs index fb985e4df..53c1ddffe 100644 --- a/sbroad-core/src/ir/explain.rs +++ b/sbroad-core/src/ir/explain.rs @@ -7,6 +7,7 @@ use serde::Serialize; use smol_str::{format_smolstr, SmolStr, ToSmolStr}; use crate::errors::{Entity, SbroadError}; +use crate::executor::engine::helpers::to_user; use crate::ir::expression::cast::Type as CastType; use crate::ir::expression::{Expression, TrimKind}; use crate::ir::operator::{ @@ -38,7 +39,7 @@ enum ColExpr { Option<Box<ColExpr>>, ), Concat(Box<ColExpr>, Box<ColExpr>), - StableFunction(SmolStr, Vec<ColExpr>, Option<FunctionFeature>, Type), + StableFunction(SmolStr, Vec<ColExpr>, Option<FunctionFeature>, Type, bool), Trim(Option<TrimKind>, Option<Box<ColExpr>>, Box<ColExpr>), Row(Row), None, @@ -48,7 +49,7 @@ impl Display for ColExpr { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let s = match &self { ColExpr::Parentheses(child_expr) => format!("({child_expr})"), - ColExpr::Alias(expr, name) => format!("{expr} -> {name}"), + ColExpr::Alias(expr, name) => format!("{expr} -> \"{name}\""), ColExpr::Arithmetic(left, op, right) => format!("{left} {op} {right}"), ColExpr::Bool(left, op, right) => format!("{left} {op} {right}"), ColExpr::Unary(op, expr) => match op { @@ -80,7 +81,11 @@ impl Display for ColExpr { res } ColExpr::Concat(l, r) => format!("{l} || {r}"), - ColExpr::StableFunction(name, args, feature, func_type) => { + ColExpr::StableFunction(name, args, feature, func_type, is_aggr) => { + let mut name = name.clone(); + if !is_aggr { + name = to_user(name); + } let is_distinct = matches!(feature, Some(FunctionFeature::Distinct)); let formatted_args = format!("({})", args.iter().format(", ")); format!( @@ -191,12 +196,16 @@ impl ColExpr { let rel_node = plan.get_relation_node(rel_id)?; if let Some(name) = rel_node.scan_name(plan, *position)? { + col_name.push('"'); col_name.push_str(name); + col_name.push('"'); col_name.push('.'); } let alias = plan.get_alias_from_reference_node(current_node)?; + col_name.push('"'); col_name.push_str(alias); + col_name.push('"'); let ref_expr = ColExpr::Column(col_name, current_node.calculate_type(plan)?); stack.push((ref_expr, id)); @@ -233,6 +242,8 @@ impl ColExpr { children, feature, func_type, + is_system: is_aggr, + .. } => { let mut len = children.len(); let mut args: Vec<ColExpr> = Vec::with_capacity(len); @@ -251,6 +262,7 @@ impl ColExpr { args, feature.clone(), func_type.clone(), + *is_aggr, ); stack.push((func_expr, id)); } @@ -556,7 +568,7 @@ impl Update { let col_name = table .columns .get(*col_idx) - .map(|c| c.name.clone()) + .map(|c| to_user(&c.name)) .ok_or_else(|| { SbroadError::Invalid( Entity::Node, @@ -576,7 +588,7 @@ impl Update { })?; let node = plan.get_expression_node(alias_id)?; if let Expression::Alias { name, .. } = node { - name.clone() + to_user(name) } else { return Err(SbroadError::Invalid( Entity::Node, @@ -607,7 +619,7 @@ impl Display for Update { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut s = "update ".to_string(); - write!(s, "{}", &self.table)?; + write!(s, "\"{}\"", &self.table)?; let update_statements = self .update_statements .iter() @@ -638,10 +650,10 @@ impl Display for Scan { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut s = String::from("scan "); - s.push_str(&self.table); + write!(s, "\"{}\"", &self.table)?; if let Some(a) = &self.alias { - write!(s, " -> {a}")?; + write!(s, " -> \"{a}\"")?; } write!(f, "{s}") @@ -778,7 +790,7 @@ impl Display for SubQuery { let mut s = String::from("scan"); if let Some(a) = &self.alias { - write!(s, " {a}")?; + write!(s, " \"{a}\"")?; } write!(f, "{s}") } @@ -849,7 +861,7 @@ enum Target { impl Display for Target { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self { - Target::Reference(s) => write!(f, "ref({s})"), + Target::Reference(s) => write!(f, "ref(\"{s}\")"), Target::Value(v) => write!(f, "value({v})"), } } @@ -904,13 +916,13 @@ impl Display for ExplainNode { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let s = match &self { ExplainNode::Cte(s, r) => format_smolstr!("scan cte {s}({r})"), - ExplainNode::Delete(s) => format_smolstr!("delete {s}"), + ExplainNode::Delete(s) => format_smolstr!("delete \"{s}\""), ExplainNode::Except => "except".to_smolstr(), ExplainNode::InnerJoin(i) => i.to_smolstr(), ExplainNode::ValueRow(r) => format_smolstr!("value row (data={r})"), ExplainNode::Value => "values".to_smolstr(), ExplainNode::Insert(s, conflict) => { - format_smolstr!("insert {s} on conflict: {conflict}") + format_smolstr!("insert \"{s}\" on conflict: {conflict}") } ExplainNode::Projection(e) => e.to_smolstr(), ExplainNode::GroupBy(p) => p.to_smolstr(), diff --git a/sbroad-core/src/ir/explain/tests.rs b/sbroad-core/src/ir/explain/tests.rs index ecf324e31..1c9dba45b 100644 --- a/sbroad-core/src/ir/explain/tests.rs +++ b/sbroad-core/src/ir/explain/tests.rs @@ -488,7 +488,7 @@ fn select_cast_plan_nested() { let mut actual_explain = String::new(); actual_explain.push_str( - r#"projection ("FUNC"(("test_space"."id"::unsigned))::integer::string -> "COL_1") + r#"projection ("func"(("test_space"."id"::unsigned))::integer::string -> "COL_1") scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -511,7 +511,7 @@ fn select_cast_plan_nested_where() { let mut actual_explain = String::new(); actual_explain.push_str( r#"projection ("test_space"."id"::unsigned -> "id") - selection ROW("FUNC"(("test_space"."id"::unsigned))::integer::string) = ROW(1::unsigned) + selection ROW("func"(("test_space"."id"::unsigned))::integer::string) = ROW(1::unsigned) scan "test_space" execution options: sql_vdbe_max_steps = 45000 @@ -534,7 +534,7 @@ fn select_cast_plan_nested_where2() { let mut actual_explain = String::new(); actual_explain.push_str( r#"projection ("test_space"."id"::unsigned -> "id") - selection ROW("FUNC"((42::unsigned::string))::integer) = ROW(1::unsigned) + selection ROW("func"((42::unsigned::string))::integer) = ROW(1::unsigned) scan "test_space" execution options: sql_vdbe_max_steps = 45000 diff --git a/sbroad-core/src/ir/explain/tests/concat.rs b/sbroad-core/src/ir/explain/tests/concat.rs index b690c366c..e522079d5 100644 --- a/sbroad-core/src/ir/explain/tests/concat.rs +++ b/sbroad-core/src/ir/explain/tests/concat.rs @@ -22,7 +22,7 @@ fn concat2_test() { &format!( "{}\n{}\n{}\n{}\n{}\n{}\n", r#"projection ("t1"."a"::string -> "a")"#, - r#" selection ROW(ROW(ROW('1'::string::string) || ROW("FUNC"(('hello'::string))::integer)) || ROW('2'::string)) = ROW(42::unsigned)"#, + r#" selection ROW(ROW(ROW('1'::string::string) || ROW("func"(('hello'::string))::integer)) || ROW('2'::string)) = ROW(42::unsigned)"#, r#" scan "t1""#, r#"execution options:"#, r#"sql_vdbe_max_steps = 45000"#, diff --git a/sbroad-core/src/ir/explain/tests/delete.rs b/sbroad-core/src/ir/explain/tests/delete.rs index 5bd01bf2c..44185beb1 100644 --- a/sbroad-core/src/ir/explain/tests/delete.rs +++ b/sbroad-core/src/ir/explain/tests/delete.rs @@ -8,7 +8,7 @@ fn delete1_test() { "{}\n{}\n{}\n{}\n{}\n{}\n{}\n", r#"delete "t1""#, r#" motion [policy: local]"#, - r#" projection ("t1"."a"::string -> pk_col_0, "t1"."b"::integer -> pk_col_1)"#, + r#" projection ("t1"."a"::string -> "pk_col_0", "t1"."b"::integer -> "pk_col_1")"#, r#" scan "t1""#, r#"execution options:"#, r#"sql_vdbe_max_steps = 45000"#, @@ -25,7 +25,7 @@ fn delete2_test() { "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", r#"delete "t1""#, r#" motion [policy: local]"#, - r#" projection ("t1"."a"::string -> pk_col_0, "t1"."b"::integer -> pk_col_1)"#, + r#" projection ("t1"."a"::string -> "pk_col_0", "t1"."b"::integer -> "pk_col_1")"#, r#" selection ROW("t1"."a"::string) > ROW(3::unsigned)"#, r#" scan "t1""#, r#"execution options:"#, @@ -43,7 +43,7 @@ fn delete3_test() { "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", r#"delete "t1""#, r#" motion [policy: local]"#, - r#" projection ("t1"."a"::string -> pk_col_0, "t1"."b"::integer -> pk_col_1)"#, + r#" projection ("t1"."a"::string -> "pk_col_0", "t1"."b"::integer -> "pk_col_1")"#, r#" selection ROW("t1"."a"::string) in ROW($0)"#, r#" scan "t1""#, r#"subquery $0:"#, diff --git a/sbroad-core/src/ir/expression.rs b/sbroad-core/src/ir/expression.rs index 8dfd78f19..e9b9eeefe 100644 --- a/sbroad-core/src/ir/expression.rs +++ b/sbroad-core/src/ir/expression.rs @@ -14,6 +14,7 @@ use std::hash::{Hash, Hasher}; use std::ops::Bound::Included; use crate::errors::{Entity, SbroadError}; +use crate::executor::engine::helpers::to_user; use crate::ir::aggregates::AggregateKind; use crate::ir::operator::{Bool, Relational}; use crate::ir::relation::Type; @@ -150,6 +151,11 @@ pub enum Expression { feature: Option<FunctionFeature>, /// Function return type. func_type: Type, + /// Whether function is provided by tarantool, + /// when referencing these funcs from local + /// sql we must not use quotes. + /// Examples: aggregates, substr + is_system: bool, }, /// Trim expression. Trim { @@ -732,17 +738,20 @@ impl<'plan> Comparator<'plan> { children: children_left, feature: feature_left, func_type: func_type_left, + is_system: is_aggr_left, } => { if let Expression::StableFunction { name: name_right, children: children_right, feature: feature_right, func_type: func_type_right, + is_system: is_aggr_right, } = right { return Ok(name_left == name_right && feature_left == feature_right && func_type_left == func_type_right + && is_aggr_left == is_aggr_right && children_left.iter().zip(children_right.iter()).all( |(l, r)| self.are_subtrees_equal(*l, *r).unwrap_or(false), )); @@ -872,10 +881,12 @@ impl<'plan> Comparator<'plan> { children, func_type, feature, + is_system: is_aggr, } => { feature.hash(state); func_type.hash(state); name.hash(state); + is_aggr.hash(state); for child in children { self.hash_for_child_expr(*child, depth); } @@ -998,7 +1009,7 @@ impl ColumnPositionMap { } _ => Err(SbroadError::NotFound( Entity::Column, - format_smolstr!("with name {column}"), + format_smolstr!("with name {}", to_user(column)), )), } } @@ -1021,12 +1032,13 @@ impl ColumnPositionMap { // Even given `scan` we can't identify which of these two columns do we need to // refer to. return Err(SbroadError::DuplicatedValue(format_smolstr!( - "column name {column} is ambiguous" + "column name {} is ambiguous", + to_user(column) ))); } Err(SbroadError::NotFound( Entity::Column, - format_smolstr!("with name {column} and scan {scan:?}"), + format_smolstr!("with name {} and scan {scan:?}", to_user(column)), )) } diff --git a/sbroad-core/src/ir/function.rs b/sbroad-core/src/ir/function.rs index 0ee2e10e5..c7bea0939 100644 --- a/sbroad-core/src/ir/function.rs +++ b/sbroad-core/src/ir/function.rs @@ -1,4 +1,5 @@ use crate::errors::{Entity, SbroadError}; +use crate::executor::engine::helpers::to_user; use crate::ir::aggregates::AggregateKind; use crate::ir::expression::Expression; use crate::ir::relation::Type; @@ -23,21 +24,26 @@ pub struct Function { pub name: SmolStr, pub behavior: Behavior, pub func_type: Type, + /// True if this function is provided by tarantool, + /// when referencing this func in local sql, we must + /// not use quotes + pub is_system: bool, } impl Function { #[must_use] - pub fn new(name: SmolStr, behavior: Behavior, func_type: Type) -> Self { + pub fn new(name: SmolStr, behavior: Behavior, func_type: Type, is_system: bool) -> Self { Self { name, behavior, func_type, + is_system, } } #[must_use] - pub fn new_stable(name: SmolStr, func_type: Type) -> Self { - Self::new(name, Behavior::Stable, func_type) + pub fn new_stable(name: SmolStr, func_type: Type, is_system: bool) -> Self { + Self::new(name, Behavior::Stable, func_type, is_system) } #[must_use] @@ -69,6 +75,7 @@ impl Plan { children, feature, func_type: function.func_type.clone(), + is_system: function.is_system, }; let func_id = self.nodes.push(Node::Expression(func_expr)); Ok(func_id) @@ -112,7 +119,8 @@ impl Plan { return Err(SbroadError::Invalid( Entity::Query, Some(format_smolstr!( - "Expected one argument for aggregate: {function}." + "Expected one argument for aggregate: {}.", + to_user(function) )), )); } @@ -129,6 +137,7 @@ impl Plan { children, feature, func_type: Type::from(kind), + is_system: true, }; let id = self.nodes.push(Node::Expression(func_expr)); Ok(id) diff --git a/sbroad-core/src/ir/helpers/tests.rs b/sbroad-core/src/ir/helpers/tests.rs index aef55aa41..8be08bb6a 100644 --- a/sbroad-core/src/ir/helpers/tests.rs +++ b/sbroad-core/src/ir/helpers/tests.rs @@ -12,16 +12,16 @@ fn simple_select() { expected_arena.push_str( r#"--------------------------------------------- [id: 11] relation: ScanRelation - Relation: "hash_testing" + Relation: hash_testing [No children] Output_id: 10 [id: 10] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 1] expression: Alias [name = "identification_number", child = Reference { parent: Some(11), targets: None, position: 0, col_type: Integer }] - [id: 3] expression: Alias [name = "product_code", child = Reference { parent: Some(11), targets: None, position: 1, col_type: String }] - [id: 5] expression: Alias [name = "product_units", child = Reference { parent: Some(11), targets: None, position: 2, col_type: Boolean }] - [id: 7] expression: Alias [name = "sys_op", child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] - [id: 9] expression: Alias [name = "bucket_id", child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] + [id: 1] expression: Alias [name = identification_number, child = Reference { parent: Some(11), targets: None, position: 0, col_type: Integer }] + [id: 3] expression: Alias [name = product_code, child = Reference { parent: Some(11), targets: None, position: 1, col_type: String }] + [id: 5] expression: Alias [name = product_units, child = Reference { parent: Some(11), targets: None, position: 2, col_type: Boolean }] + [id: 7] expression: Alias [name = sys_op, child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] + [id: 9] expression: Alias [name = bucket_id, child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 15] relation: Projection @@ -30,7 +30,7 @@ fn simple_select() { Output_id: 14 [id: 14] expression: Row [distribution = Some(Any)] List: - [id: 13] expression: Alias [name = "product_code", child = Reference { parent: Some(15), targets: Some([0]), position: 1, col_type: String }] + [id: 13] expression: Alias [name = product_code, child = Reference { parent: Some(15), targets: Some([0]), position: 1, col_type: String }] --------------------------------------------- "#); @@ -51,16 +51,16 @@ fn simple_join() { expected_arena.push_str( r#"--------------------------------------------- [id: 11] relation: ScanRelation - Relation: "test_space" + Relation: test_space [No children] Output_id: 10 [id: 10] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1] expression: Alias [name = "id", child = Reference { parent: Some(11), targets: None, position: 0, col_type: Unsigned }] - [id: 3] expression: Alias [name = "sysFrom", child = Reference { parent: Some(11), targets: None, position: 1, col_type: Unsigned }] - [id: 5] expression: Alias [name = "FIRST_NAME", child = Reference { parent: Some(11), targets: None, position: 2, col_type: String }] - [id: 7] expression: Alias [name = "sys_op", child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] - [id: 9] expression: Alias [name = "bucket_id", child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] + [id: 1] expression: Alias [name = id, child = Reference { parent: Some(11), targets: None, position: 0, col_type: Unsigned }] + [id: 3] expression: Alias [name = sysFrom, child = Reference { parent: Some(11), targets: None, position: 1, col_type: Unsigned }] + [id: 5] expression: Alias [name = FIRST_NAME, child = Reference { parent: Some(11), targets: None, position: 2, col_type: String }] + [id: 7] expression: Alias [name = sys_op, child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] + [id: 9] expression: Alias [name = bucket_id, child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 15] relation: Projection @@ -69,30 +69,30 @@ fn simple_join() { Output_id: 14 [id: 14] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 13] expression: Alias [name = "id", child = Reference { parent: Some(15), targets: Some([0]), position: 0, col_type: Unsigned }] + [id: 13] expression: Alias [name = id, child = Reference { parent: Some(15), targets: Some([0]), position: 0, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 19] relation: ScanSubQuery - Alias: "t1" + Alias: t1 Children: Child_id = 15 Output_id: 18 [id: 18] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 17] expression: Alias [name = "id", child = Reference { parent: Some(19), targets: Some([0]), position: 0, col_type: Unsigned }] + [id: 17] expression: Alias [name = id, child = Reference { parent: Some(19), targets: Some([0]), position: 0, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 31] relation: ScanRelation - Relation: "hash_testing" + Relation: hash_testing [No children] Output_id: 30 [id: 30] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 21] expression: Alias [name = "identification_number", child = Reference { parent: Some(31), targets: None, position: 0, col_type: Integer }] - [id: 23] expression: Alias [name = "product_code", child = Reference { parent: Some(31), targets: None, position: 1, col_type: String }] - [id: 25] expression: Alias [name = "product_units", child = Reference { parent: Some(31), targets: None, position: 2, col_type: Boolean }] - [id: 27] expression: Alias [name = "sys_op", child = Reference { parent: Some(31), targets: None, position: 3, col_type: Unsigned }] - [id: 29] expression: Alias [name = "bucket_id", child = Reference { parent: Some(31), targets: None, position: 4, col_type: Unsigned }] + [id: 21] expression: Alias [name = identification_number, child = Reference { parent: Some(31), targets: None, position: 0, col_type: Integer }] + [id: 23] expression: Alias [name = product_code, child = Reference { parent: Some(31), targets: None, position: 1, col_type: String }] + [id: 25] expression: Alias [name = product_units, child = Reference { parent: Some(31), targets: None, position: 2, col_type: Boolean }] + [id: 27] expression: Alias [name = sys_op, child = Reference { parent: Some(31), targets: None, position: 3, col_type: Unsigned }] + [id: 29] expression: Alias [name = bucket_id, child = Reference { parent: Some(31), targets: None, position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 35] relation: Projection @@ -101,17 +101,17 @@ fn simple_join() { Output_id: 34 [id: 34] expression: Row [distribution = Some(Any)] List: - [id: 33] expression: Alias [name = "identification_number", child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: Integer }] + [id: 33] expression: Alias [name = identification_number, child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 39] relation: ScanSubQuery - Alias: "t2" + Alias: t2 Children: Child_id = 35 Output_id: 38 [id: 38] expression: Row [distribution = Some(Any)] List: - [id: 37] expression: Alias [name = "identification_number", child = Reference { parent: Some(39), targets: Some([0]), position: 0, col_type: Integer }] + [id: 37] expression: Alias [name = identification_number, child = Reference { parent: Some(39), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 61] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] })] @@ -120,7 +120,7 @@ fn simple_join() { Output_id: 60 [id: 60] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 59] expression: Alias [name = "identification_number", child = Reference { parent: Some(61), targets: Some([0]), position: 0, col_type: Integer }] + [id: 59] expression: Alias [name = identification_number, child = Reference { parent: Some(61), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 50] relation: InnerJoin @@ -130,8 +130,8 @@ fn simple_join() { [id: 55] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: [id: 40] expression: Reference - Alias: "id" - Referenced table name (or alias): "t1" + Alias: id + Referenced table name (or alias): t1 Parent: Some(50) target_id: 0 Column type: unsigned @@ -139,8 +139,8 @@ fn simple_join() { [id: 56] expression: Row [distribution = Some(Any)] List: [id: 42] expression: Reference - Alias: "identification_number" - Referenced table name (or alias): "t2" + Alias: identification_number + Referenced table name (or alias): t2 Parent: Some(50) target_id: 1 Column type: integer @@ -150,8 +150,8 @@ fn simple_join() { Output_id: 49 [id: 49] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [1] }, Key { positions: [0] }}) })] List: - [id: 46] expression: Alias [name = "id", child = Reference { parent: Some(50), targets: Some([0]), position: 0, col_type: Unsigned }] - [id: 48] expression: Alias [name = "identification_number", child = Reference { parent: Some(50), targets: Some([1]), position: 0, col_type: Integer }] + [id: 46] expression: Alias [name = id, child = Reference { parent: Some(50), targets: Some([0]), position: 0, col_type: Unsigned }] + [id: 48] expression: Alias [name = identification_number, child = Reference { parent: Some(50), targets: Some([1]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 54] relation: Projection @@ -160,7 +160,7 @@ fn simple_join() { Output_id: 53 [id: 53] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 52] expression: Alias [name = "id", child = Reference { parent: Some(54), targets: Some([0]), position: 0, col_type: Unsigned }] + [id: 52] expression: Alias [name = id, child = Reference { parent: Some(54), targets: Some([0]), position: 0, col_type: Unsigned }] --------------------------------------------- "#); @@ -185,18 +185,18 @@ fn simple_join_subtree() { let mut expected_arena_subtree = String::new(); expected_arena_subtree.push_str( - r#"--------------------------------------------- + r#"--------------------------------------------- [id: 31] relation: ScanRelation - Relation: "hash_testing" + Relation: hash_testing [No children] Output_id: 30 [id: 30] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 21] expression: Alias [name = "identification_number", child = Reference { parent: Some(31), targets: None, position: 0, col_type: Integer }] - [id: 23] expression: Alias [name = "product_code", child = Reference { parent: Some(31), targets: None, position: 1, col_type: String }] - [id: 25] expression: Alias [name = "product_units", child = Reference { parent: Some(31), targets: None, position: 2, col_type: Boolean }] - [id: 27] expression: Alias [name = "sys_op", child = Reference { parent: Some(31), targets: None, position: 3, col_type: Unsigned }] - [id: 29] expression: Alias [name = "bucket_id", child = Reference { parent: Some(31), targets: None, position: 4, col_type: Unsigned }] + [id: 21] expression: Alias [name = identification_number, child = Reference { parent: Some(31), targets: None, position: 0, col_type: Integer }] + [id: 23] expression: Alias [name = product_code, child = Reference { parent: Some(31), targets: None, position: 1, col_type: String }] + [id: 25] expression: Alias [name = product_units, child = Reference { parent: Some(31), targets: None, position: 2, col_type: Boolean }] + [id: 27] expression: Alias [name = sys_op, child = Reference { parent: Some(31), targets: None, position: 3, col_type: Unsigned }] + [id: 29] expression: Alias [name = bucket_id, child = Reference { parent: Some(31), targets: None, position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 35] relation: Projection @@ -205,17 +205,17 @@ fn simple_join_subtree() { Output_id: 34 [id: 34] expression: Row [distribution = Some(Any)] List: - [id: 33] expression: Alias [name = "identification_number", child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: Integer }] + [id: 33] expression: Alias [name = identification_number, child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 39] relation: ScanSubQuery - Alias: "t2" + Alias: t2 Children: Child_id = 35 Output_id: 38 [id: 38] expression: Row [distribution = Some(Any)] List: - [id: 37] expression: Alias [name = "identification_number", child = Reference { parent: Some(39), targets: Some([0]), position: 0, col_type: Integer }] + [id: 37] expression: Alias [name = identification_number, child = Reference { parent: Some(39), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- --------------------------------------------- [id: 61] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] })] @@ -224,9 +224,10 @@ fn simple_join_subtree() { Output_id: 60 [id: 60] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 59] expression: Alias [name = "identification_number", child = Reference { parent: Some(61), targets: Some([0]), position: 0, col_type: Integer }] + [id: 59] expression: Alias [name = identification_number, child = Reference { parent: Some(61), targets: Some([0]), position: 0, col_type: Integer }] --------------------------------------------- -"#); +"# + ); assert_eq!(expected_arena_subtree, actual_arena_subtree); } @@ -241,16 +242,16 @@ fn simple_aggregation_with_group_by() { expected_arena.push_str( r#"--------------------------------------------- [id: 11] relation: ScanRelation - Relation: "hash_testing" + Relation: hash_testing [No children] Output_id: 10 [id: 10] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 1] expression: Alias [name = "identification_number", child = Reference { parent: Some(11), targets: None, position: 0, col_type: Integer }] - [id: 3] expression: Alias [name = "product_code", child = Reference { parent: Some(11), targets: None, position: 1, col_type: String }] - [id: 5] expression: Alias [name = "product_units", child = Reference { parent: Some(11), targets: None, position: 2, col_type: Boolean }] - [id: 7] expression: Alias [name = "sys_op", child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] - [id: 9] expression: Alias [name = "bucket_id", child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] + [id: 1] expression: Alias [name = identification_number, child = Reference { parent: Some(11), targets: None, position: 0, col_type: Integer }] + [id: 3] expression: Alias [name = product_code, child = Reference { parent: Some(11), targets: None, position: 1, col_type: String }] + [id: 5] expression: Alias [name = product_units, child = Reference { parent: Some(11), targets: None, position: 2, col_type: Boolean }] + [id: 7] expression: Alias [name = sys_op, child = Reference { parent: Some(11), targets: None, position: 3, col_type: Unsigned }] + [id: 9] expression: Alias [name = bucket_id, child = Reference { parent: Some(11), targets: None, position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 24] relation: GroupBy [is_final = false] @@ -261,11 +262,11 @@ fn simple_aggregation_with_group_by() { Output_id: 23 [id: 23] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 14] expression: Alias [name = "identification_number", child = Reference { parent: Some(24), targets: Some([0]), position: 0, col_type: Integer }] - [id: 16] expression: Alias [name = "product_code", child = Reference { parent: Some(24), targets: Some([0]), position: 1, col_type: String }] - [id: 18] expression: Alias [name = "product_units", child = Reference { parent: Some(24), targets: Some([0]), position: 2, col_type: Boolean }] - [id: 20] expression: Alias [name = "sys_op", child = Reference { parent: Some(24), targets: Some([0]), position: 3, col_type: Unsigned }] - [id: 22] expression: Alias [name = "bucket_id", child = Reference { parent: Some(24), targets: Some([0]), position: 4, col_type: Unsigned }] + [id: 14] expression: Alias [name = identification_number, child = Reference { parent: Some(24), targets: Some([0]), position: 0, col_type: Integer }] + [id: 16] expression: Alias [name = product_code, child = Reference { parent: Some(24), targets: Some([0]), position: 1, col_type: String }] + [id: 18] expression: Alias [name = product_units, child = Reference { parent: Some(24), targets: Some([0]), position: 2, col_type: Boolean }] + [id: 20] expression: Alias [name = sys_op, child = Reference { parent: Some(24), targets: Some([0]), position: 3, col_type: Unsigned }] + [id: 22] expression: Alias [name = bucket_id, child = Reference { parent: Some(24), targets: Some([0]), position: 4, col_type: Unsigned }] --------------------------------------------- --------------------------------------------- [id: 31] relation: Projection @@ -274,7 +275,7 @@ fn simple_aggregation_with_group_by() { Output_id: 30 [id: 30] expression: Row [distribution = Some(Any)] List: - [id: 29] expression: Alias [name = "column_12", child = Reference { parent: Some(24), targets: Some([0]), position: 1, col_type: String }] + [id: 29] expression: Alias [name = column_12, child = Reference { parent: Some(24), targets: Some([0]), position: 1, col_type: String }] --------------------------------------------- --------------------------------------------- [id: 35] relation: ScanSubQuery @@ -283,7 +284,7 @@ fn simple_aggregation_with_group_by() { Output_id: 34 [id: 34] expression: Row [distribution = Some(Any)] List: - [id: 33] expression: Alias [name = "column_12", child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: String }] + [id: 33] expression: Alias [name = column_12, child = Reference { parent: Some(35), targets: Some([0]), position: 0, col_type: String }] --------------------------------------------- --------------------------------------------- [id: 45] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] })] @@ -292,7 +293,7 @@ fn simple_aggregation_with_group_by() { Output_id: 44 [id: 44] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 43] expression: Alias [name = "column_12", child = Reference { parent: Some(45), targets: Some([0]), position: 0, col_type: String }] + [id: 43] expression: Alias [name = column_12, child = Reference { parent: Some(45), targets: Some([0]), position: 0, col_type: String }] --------------------------------------------- --------------------------------------------- [id: 40] relation: GroupBy [is_final = true] @@ -303,7 +304,7 @@ fn simple_aggregation_with_group_by() { Output_id: 39 [id: 39] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 38] expression: Alias [name = "column_12", child = Reference { parent: Some(40), targets: Some([0]), position: 0, col_type: String }] + [id: 38] expression: Alias [name = column_12, child = Reference { parent: Some(40), targets: Some([0]), position: 0, col_type: String }] --------------------------------------------- --------------------------------------------- [id: 28] relation: Projection @@ -312,7 +313,7 @@ fn simple_aggregation_with_group_by() { Output_id: 27 [id: 27] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 26] expression: Alias [name = "product_code", child = Reference { parent: Some(28), targets: Some([0]), position: 0, col_type: String }] + [id: 26] expression: Alias [name = product_code, child = Reference { parent: Some(28), targets: Some([0]), position: 0, col_type: String }] --------------------------------------------- "#); diff --git a/sbroad-core/src/ir/operator.rs b/sbroad-core/src/ir/operator.rs index b841733d3..19973b548 100644 --- a/sbroad-core/src/ir/operator.rs +++ b/sbroad-core/src/ir/operator.rs @@ -2,6 +2,7 @@ //! //! Contains operator nodes that transform the tuples in IR tree. +use crate::executor::engine::helpers::to_user; use crate::frontend::sql::get_unnamed_column_alias; use ahash::RandomState; @@ -1267,7 +1268,7 @@ impl Plan { return Err(SbroadError::FailedTo( Action::Insert, Some(Entity::Column), - format_smolstr!("system column {name} cannot be inserted"), + format_smolstr!("system column {} cannot be inserted", to_user(name)), )) } None => { @@ -1887,7 +1888,7 @@ impl Plan { // Generate a row of aliases for the incoming row. *col_idx += 1; // The column names are generated according to tarantool naming of anonymous columns - let name = format!("\"COLUMN_{col_idx}\""); + let name = format!("COLUMN_{col_idx}"); let alias_id = self.nodes.add_alias(&name, col_id)?; aliases.push(alias_id); } diff --git a/sbroad-core/src/ir/operator/tests.rs b/sbroad-core/src/ir/operator/tests.rs index faf8643e3..3c7bd2fc8 100644 --- a/sbroad-core/src/ir/operator/tests.rs +++ b/sbroad-core/src/ir/operator/tests.rs @@ -114,7 +114,7 @@ fn projection() { // Invalid alias names in the output assert_eq!( - SbroadError::NotFound(Entity::Column, r#"with name e"#.into()), + SbroadError::NotFound(Entity::Column, r#"with name "e""#.into()), plan.add_proj(scan_id, &["a", "e"], false, false) .unwrap_err() ); @@ -299,7 +299,7 @@ fn insert() { SbroadError::FailedTo( Action::Insert, Some(Entity::Column), - "system column c cannot be inserted".into(), + "system column \"c\" cannot be inserted".into(), ), plan.add_insert( "t2", diff --git a/sbroad-core/src/ir/relation.rs b/sbroad-core/src/ir/relation.rs index 75b7a529f..b75c3df13 100644 --- a/sbroad-core/src/ir/relation.rs +++ b/sbroad-core/src/ir/relation.rs @@ -569,7 +569,7 @@ pub struct Table { impl Table { #[must_use] - pub fn name(&self) -> &str { + pub fn name(&self) -> &SmolStr { &self.name } @@ -857,7 +857,7 @@ impl Relations { } pub fn insert(&mut self, table: Table) { - self.tables.insert(table.name().into(), table); + self.tables.insert(table.name().clone(), table); } #[must_use] diff --git a/sbroad-core/src/ir/transformation/bool_in/tests.rs b/sbroad-core/src/ir/transformation/bool_in/tests.rs index 3c6f9ee41..d5a5a298d 100644 --- a/sbroad-core/src/ir/transformation/bool_in/tests.rs +++ b/sbroad-core/src/ir/transformation/bool_in/tests.rs @@ -106,7 +106,7 @@ fn bool_in5() { format!( "{} {}", r#"SELECT "t"."a" FROM "t""#, - r#"WHERE ("FUNC" (("t"."a") = (?) or ("t"."a") = (?))) < (?)"#, + r#"WHERE ("func" (("t"."a") = (?) or ("t"."a") = (?))) < (?)"#, ), vec![Value::from(1_u64), Value::from(2_u64), Value::from(1_u64)], ); diff --git a/sbroad-core/src/ir/transformation/redistribution/groupby.rs b/sbroad-core/src/ir/transformation/redistribution/groupby.rs index a534ca881..bb87f2532 100644 --- a/sbroad-core/src/ir/transformation/redistribution/groupby.rs +++ b/sbroad-core/src/ir/transformation/redistribution/groupby.rs @@ -1,6 +1,7 @@ use smol_str::{format_smolstr, ToSmolStr}; use crate::errors::{Entity, SbroadError}; +use crate::executor::engine::helpers::to_user; use crate::ir::aggregates::{generate_local_alias_for_aggr, AggregateKind, SimpleAggregate}; use crate::ir::distribution::Distribution; use crate::ir::expression::Expression::StableFunction; @@ -327,7 +328,8 @@ impl<'plan> ExpressionMapper<'plan> { return Err(SbroadError::Invalid( Entity::Query, Some(format_smolstr!( - "column {column_name} is not found in grouping expressions!" + "column {} is not found in grouping expressions!", + to_user(column_name) )), )); } @@ -347,9 +349,9 @@ impl Plan { fn generate_local_alias(id: usize) -> String { #[cfg(feature = "mock")] { - return format!("\"column_{id}\""); + return format!("column_{id}"); } - format!("\"{}_{id}\"", uuid::Uuid::new_v4().as_simple()) + format!("{}_{id}", uuid::Uuid::new_v4().as_simple()) } #[allow(clippy::too_many_lines)] @@ -562,17 +564,20 @@ impl Plan { children: children_left, feature: feature_left, func_type: func_type_left, + is_system: is_aggr_left, } => { if let Expression::StableFunction { name: name_right, children: children_right, feature: feature_right, func_type: func_type_right, + is_system: is_aggr_right, } = right { return Ok(name_left == name_right && feature_left == feature_right && func_type_left == func_type_right + && is_aggr_left == is_aggr_right && children_left.iter().zip(children_right.iter()).all( |(l, r)| { self.are_aggregate_subtrees_equal(*l, *r).unwrap_or(false) @@ -929,7 +934,7 @@ impl Plan { Err(e) => e.to_smolstr(), }; return Err(SbroadError::Invalid(Entity::Query, - Some(format_smolstr!("found column reference ({alias}) outside aggregate function")))); + Some(format_smolstr!("found column reference ({}) outside aggregate function", to_user(alias))))); } } } @@ -1078,6 +1083,7 @@ impl Plan { name: kind.to_smolstr(), behavior: Behavior::Stable, func_type: Type::from(kind), + is_system: true, }; // We can reuse aggregate expression between local aggregates, because // all local aggregates are located inside the same motion subtree and we -- GitLab