diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs index 5a0e5ef941ad4e0922e9c8953b01be1a5b3872c9..463c67a79b9daf2e52809d6c831b8514e973e6b5 100644 --- a/sbroad-core/src/frontend/sql.rs +++ b/sbroad-core/src/frontend/sql.rs @@ -1843,12 +1843,14 @@ impl Ast for AbstractSyntaxTree { let ast_child = self.nodes.get_node(*ast_child_id)?; let plan_insert_id = if let Type::TargetColumns = ast_child.rule { // insert into t (a, b, c) ... - let mut selected_col_names: Vec<&str> = + let mut selected_col_names: Vec<String> = Vec::with_capacity(ast_child.children.len()); for col_id in &ast_child.children { let col = self.nodes.get_node(*col_id)?; if let Type::ColumnName = col.rule { - selected_col_names.push(parse_string_value_node(self, *col_id)?); + selected_col_names.push(normalize_name_from_sql( + parse_string_value_node(self, *col_id)?, + )); } else { return Err(SbroadError::Invalid( Entity::Type, @@ -1867,9 +1869,7 @@ impl Ast for AbstractSyntaxTree { if let ColumnRole::Sharding = column.get_role() { continue; } - if !column.is_nullable - && !selected_col_names.contains(&column.name.as_str()) - { + if !column.is_nullable && !selected_col_names.contains(&column.name) { return Err(SbroadError::Invalid( Entity::Column, Some(format!( diff --git a/sbroad-core/src/frontend/sql/ir/tests.rs b/sbroad-core/src/frontend/sql/ir/tests.rs index f025ea88a2611511fd94f90dac2088f93f29d447..ab733f6cded6793b56aec5d1aa098b4df50ce726 100644 --- a/sbroad-core/src/frontend/sql/ir/tests.rs +++ b/sbroad-core/src/frontend/sql/ir/tests.rs @@ -2812,9 +2812,13 @@ fn assert_explain_eq(query: &str, params: Vec<Value>, expected: &str) { assert_eq!(expected, actual); } +#[cfg(test)] mod global; #[cfg(test)] +mod insert; +#[cfg(test)] mod params; +#[cfg(test)] mod single; #[cfg(test)] mod update; diff --git a/sbroad-core/src/frontend/sql/ir/tests/insert.rs b/sbroad-core/src/frontend/sql/ir/tests/insert.rs new file mode 100644 index 0000000000000000000000000000000000000000..43c1707ff704cf4f367f05148951cc9f3f8a439b --- /dev/null +++ b/sbroad-core/src/frontend/sql/ir/tests/insert.rs @@ -0,0 +1,61 @@ +use crate::ir::transformation::helpers::sql_to_optimized_ir; +use crate::ir::value::Value; +use pretty_assertions::assert_eq; + +#[test] +fn insert1() { + 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( + r#"insert "test_space" on conflict: fail + motion [policy: segment([ref("COLUMN_1")])] + values + value row (data=ROW(1::integer, 'test'::string)) +execution options: +sql_vdbe_max_steps = 45000 +vtable_max_rows = 5000 +"#, + ); + + assert_eq!(expected_explain, plan.as_explain().unwrap()); +} + +#[test] +fn insert2() { + let pattern = r#"INSERT INTO "test_space"("id", "FIRST_NAME") VALUES(1, 'test')"#; + let plan = sql_to_optimized_ir(pattern, vec![]); + + let expected_explain = String::from( + r#"insert "test_space" on conflict: fail + motion [policy: segment([ref("COLUMN_1")])] + values + value row (data=ROW(1::unsigned, 'test'::string)) +execution options: +sql_vdbe_max_steps = 45000 +vtable_max_rows = 5000 +"#, + ); + + assert_eq!(expected_explain, plan.as_explain().unwrap()); +} + +#[test] +fn insert3() { + let pattern = r#"INSERT INTO "test_space"("id", "sys_op") + SELECT "id", "id" FROM "test_space""#; + let plan = sql_to_optimized_ir(pattern, vec![]); + + let expected_explain = String::from( + r#"insert "test_space" on conflict: fail + motion [policy: segment([ref("id")])] + projection ("test_space"."id"::unsigned -> "id", "test_space"."id"::unsigned -> "id") + scan "test_space" +execution options: +sql_vdbe_max_steps = 45000 +vtable_max_rows = 5000 +"#, + ); + + assert_eq!(expected_explain, plan.as_explain().unwrap()); +} diff --git a/sbroad-core/src/ir/api/parameter.rs b/sbroad-core/src/ir/api/parameter.rs index 7dbe18b7e34f342a926b0f3e3744d57458f98c22..4d56bec13ac0631c8a9028649068f5856f58cf3a 100644 --- a/sbroad-core/src/ir/api/parameter.rs +++ b/sbroad-core/src/ir/api/parameter.rs @@ -181,7 +181,6 @@ impl Plan { } } Expression::Reference { .. } => { - println!("expr: {expr:?}, id: {id}"); // Remember to recalculate type. new_types.insert(id, expr.recalculate_type(self)?); } diff --git a/sbroad-core/src/ir/operator.rs b/sbroad-core/src/ir/operator.rs index 98056533bb46a18859750fb81f43fdc497ae021a..80f11632c2830bb74975861c69f39e7da91f4370 100644 --- a/sbroad-core/src/ir/operator.rs +++ b/sbroad-core/src/ir/operator.rs @@ -1105,7 +1105,7 @@ impl Plan { &mut self, relation: &str, child: usize, - columns: &[&str], + columns: &[String], conflict_strategy: ConflictStrategy, ) -> Result<usize, SbroadError> { let rel = self.relations.get(relation).ok_or_else(|| { @@ -1126,7 +1126,7 @@ impl Plan { }); let mut cols: Vec<usize> = Vec::with_capacity(names.len()); for name in columns { - match names.get(name) { + match names.get(name.as_str()) { Some((&ColumnRole::User, pos)) => cols.push(*pos), Some((&ColumnRole::Sharding, _)) => { return Err(SbroadError::FailedTo( diff --git a/sbroad-core/src/ir/operator/tests.rs b/sbroad-core/src/ir/operator/tests.rs index 72026e8d5b67d82f925d5bac7f5b4a816326c778..43c3a4358e6e9c9f7a534a1597408d6078541e28 100644 --- a/sbroad-core/src/ir/operator/tests.rs +++ b/sbroad-core/src/ir/operator/tests.rs @@ -299,7 +299,7 @@ fn insert() { assert_eq!( SbroadError::NotFound(Entity::Table, "t4 among plan relations".into()), - plan.add_insert("t4", scan_t1_id, &["a"], ConflictStrategy::default()) + plan.add_insert("t4", scan_t1_id, &["a".into()], ConflictStrategy::default()) .unwrap_err() ); @@ -312,7 +312,7 @@ fn insert() { plan.add_insert( "t2", scan_t1_id, - &["a", "b", "c"], + &["a".into(), "b".into(), "c".into()], ConflictStrategy::default() ) .unwrap_err() @@ -322,11 +322,16 @@ fn insert() { SbroadError::UnexpectedNumberOfValues( "invalid number of values: 1. Table t2 expects 2 column(s).".into() ), - plan.add_insert("t2", scan_t1_id, &["a", "b"], ConflictStrategy::default()) - .unwrap_err() + plan.add_insert( + "t2", + scan_t1_id, + &["a".into(), "b".into()], + ConflictStrategy::default() + ) + .unwrap_err() ); - plan.add_insert("t1", scan_t1_id, &["a"], ConflictStrategy::default()) + plan.add_insert("t1", scan_t1_id, &["a".into()], ConflictStrategy::default()) .unwrap(); }