From 57cb5b4c8ada2a30669a441fe54d13f1846309de Mon Sep 17 00:00:00 2001
From: EmirVildanov <reddog201030@gmail.com>
Date: Tue, 29 Oct 2024 22:59:10 +0300
Subject: [PATCH] feat: mock PARTITION BY syntax

in case such a clause met we ignore it and return an error of it being unimplemented yet
---
 sbroad-core/src/frontend/sql.rs          |  9 +++++
 sbroad-core/src/frontend/sql/ir/tests.rs | 33 ++++++++++++++++++
 sbroad-core/src/frontend/sql/query.pest  | 44 +++++++++++++++++-------
 3 files changed, 73 insertions(+), 13 deletions(-)

diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs
index 8b2e29bc75..79a7fdaa43 100644
--- a/sbroad-core/src/frontend/sql.rs
+++ b/sbroad-core/src/frontend/sql.rs
@@ -901,6 +901,9 @@ fn parse_create_table(
             Rule::WaitAppliedLocally => {
                 wait_applied_globally = false;
             }
+            Rule::Partition => {
+                warn!(None, "PARTITION BY option is not supported yet.");
+            }
             _ => panic!("Unexpected rule met under CreateTable."),
         }
     }
@@ -4288,6 +4291,12 @@ impl AbstractSyntaxTree {
                     let plan_id = plan.nodes.push(create_sharded_table.into());
                     map.add(id, plan_id);
                 }
+                Rule::CreatePartition => {
+                    return Err(SbroadError::NotImplemented(
+                        Entity::Rule,
+                        format_smolstr!("PARTITION OF logic is not supported yet."),
+                    ));
+                }
                 Rule::GrantPrivilege => {
                     let (grant_type, grantee_name, timeout) = parse_grant_revoke(node, self)?;
                     let grant_privilege = GrantPrivilege {
diff --git a/sbroad-core/src/frontend/sql/ir/tests.rs b/sbroad-core/src/frontend/sql/ir/tests.rs
index a0d998a24a..2f20b757a3 100644
--- a/sbroad-core/src/frontend/sql/ir/tests.rs
+++ b/sbroad-core/src/frontend/sql/ir/tests.rs
@@ -3910,6 +3910,39 @@ fn front_mock_set_param_transaction() {
     }
 }
 
+#[test]
+fn front_mock_partition_by() {
+    let metadata = &RouterConfigurationMock::new();
+
+    let queries_to_check = vec![
+        r#"create table t(a int primary key) partition by list (a)"#,
+        r#"create table t(a int primary key) partition by hash (a, b)"#,
+        r#"create table t(a int primary key) partition by range (a, b, c)"#,
+    ];
+    for query in queries_to_check {
+        let plan = AbstractSyntaxTree::transform_into_plan(query, metadata);
+        assert!(plan.is_ok())
+    }
+
+    let queries_to_check = vec![
+        r#"create table tp partition of t default"#,
+        r#"create table tp partition of t default partition by range (a)"#,
+        r#"create table tp partition of t for values in (1)"#,
+        r#"create table tp partition of t for values in (1, 2)"#,
+        r#"create table tp partition of t for values from (1) to (2)"#,
+        r#"create table tp partition of t for values from (1, 3) to (2, 4)"#,
+        r#"create table tp partition of t for values from (1, MINVALUE) to (2, MAXVALUE)"#,
+        r#"create table tp partition of t for values with (modulus 1, remainder 2)"#,
+        r#"create table tp partition of t for values with (modulus 1, remainder 2) partition by range (a, b, c)"#,
+    ];
+    for query in queries_to_check {
+        let err = AbstractSyntaxTree::transform_into_plan(query, metadata).unwrap_err();
+        assert!(err
+            .to_string()
+            .contains("PARTITION OF logic is not supported yet"))
+    }
+}
+
 #[test]
 fn front_create_table_with_tier_syntax() {
     let query = r#"CREATE TABLE warehouse (
diff --git a/sbroad-core/src/frontend/sql/query.pest b/sbroad-core/src/frontend/sql/query.pest
index 43ee7474cc..3209ed3fd4 100644
--- a/sbroad-core/src/frontend/sql/query.pest
+++ b/sbroad-core/src/frontend/sql/query.pest
@@ -79,32 +79,50 @@ ACL = _{ DropRole | DropUser | CreateRole | CreateUser | AlterUser | GrantPrivil
             PrivilegeWrite = { ^"write" }
 
 DDL = _{ CreateTable | DropTable | CreateIndex | DropIndex
-         | CreateProc | DropProc | RenameProc | SetParam | SetTransaction | AlterSystem }
-
-    WaitApplied = _{ WaitAppliedGlobally | WaitAppliedLocally }
-      WaitAppliedGlobally = @{ ^"wait" ~ W ~ ^"applied" ~ W ~ ^"globally" }
-      WaitAppliedLocally = @{ ^"wait" ~ W ~ ^"applied" ~ W ~ ^"locally" }
-
+         | CreateProc | DropProc | RenameProc | SetParam | SetTransaction | AlterSystem
+         | CreatePartition }
+    CreatePartition = ${
+        ^"create" ~ W ~ ^"table" ~ W ~ (IfNotExists ~ W)? ~ Identifier ~ W ~ ^"partition" ~ W ~ ^"of" ~ W ~
+        Identifier ~ W ~ PartitionOfSpec ~ (W ~ Partition)?
+    }
+        PartitionOfSpec = ${ (^"for" ~ W ~ ^"values" ~ W ~ ForValuesSpec) | ^"default" }
+            ForValuesSpec = _{ ForValuesSpecIn | ForValuesSpecFromTo | ForValuesSpecWith }
+                ForValuesSpecIn = { ^"in" ~ W ~ Row }
+                ForValuesSpecFromTo = ${ ^"from" ~ W ~ ForValuesSpecFromToRow ~ W ~ ^"to" ~ W ~ ForValuesSpecFromToRow }
+                    ForValuesSpecFromToRow = !{ "(" ~ ExprOrMinMax ~ ("," ~ ExprOrMinMax)* ~ ")" }
+                        ExprOrMinMax = { MinValue | MaxValue | Expr }
+                            MinValue = { ^"minvalue" }
+                            MaxValue = { ^"maxvalue" }
+                ForValuesSpecWith = ${ ^"with" ~ WO ~ "(" ~ ^"modulus" ~ W ~ Literal ~ WO ~ "," ~ WO ~ ^"remainder" ~ W ~  Literal ~ WO ~ ")" }
     CreateTable = ${
         ^"create" ~ W ~ ^"table" ~ W ~ (IfNotExists ~ W)? ~ NewTable ~ WO ~
         "(" ~ WO ~ Columns ~ WO ~ ("," ~ WO ~ PrimaryKey)? ~ WO ~ ")" ~
-        (W ~ Engine)? ~ (W ~ Distribution)? ~ (W ~ WaitApplied)? ~ (W ~ TimeoutOption)?
+        (W ~ Engine)? ~ (W ~ Distribution)? ~ (W ~ WaitApplied)? ~ (W ~ Partition)? ~ (W ~ TimeoutOption)?
     }
         NewTable = @{Table}
         Columns = !{ ColumnDef ~ ("," ~ ColumnDef)* }
             ColumnDef = ${ Identifier ~ W ~ ColumnDefType ~ (W ~ ColumnDefIsNull)? ~ (W ~ PrimaryKeyMark)? }
             ColumnDefIsNull = { (NotFlag ~ W)? ~ ^"null" }
             PrimaryKeyMark = { ^"primary" ~ W ~ ^"key" }
-        PrimaryKey = ${ PrimaryKeyMark ~ WO ~ "(" ~ WO ~ PrimaryKeyIdentifiers ~ WO ~ ")" }
-            PrimaryKeyIdentifiers = _{ Identifier ~ (WO ~ "," ~ WO ~ Identifier)* }
+            PrimaryKey = ${ PrimaryKeyMark ~ WO ~ "(" ~ WO ~ PrimaryKeyIdentifiers ~ WO ~ ")" }
+                PrimaryKeyIdentifiers = _{ Identifier ~ (WO ~ "," ~ WO ~ Identifier)* }
         Engine = ${ ^"using" ~ W ~ (Memtx | Vinyl) }
             Memtx = { ^"memtx" }
             Vinyl = { ^"vinyl" }
         Distribution = ${ ^"distributed" ~ W ~ (Global | Sharding) }
-        Global = { ^"globally" }
-        Sharding = ${ ^"by" ~ WO ~ "(" ~ WO ~ ShardingIdentifiers ~ WO ~ ")" ~ (W ~ Tier)? }
-            ShardingIdentifiers = _{ Identifier ~ (WO ~ "," ~ WO ~ Identifier)* }
-        Tier = ${ ^"in" ~ W ~ ^"tier" ~ W ~ Identifier }
+            Global = { ^"globally" }
+            Sharding = ${ ^"by" ~ WO ~ "(" ~ WO ~ ShardingIdentifiers ~ WO ~ ")" ~ (W ~ Tier)? }
+                ShardingIdentifiers = _{ Identifier ~ (WO ~ "," ~ WO ~ Identifier)* }
+                Tier = ${ ^"in" ~ W ~ ^"tier" ~ W ~ Identifier }
+        WaitApplied = _{ WaitAppliedGlobally | WaitAppliedLocally }
+            WaitAppliedGlobally = @{ ^"wait" ~ W ~ ^"applied" ~ W ~ ^"globally" }
+            WaitAppliedLocally = @{ ^"wait" ~ W ~ ^"applied" ~ W ~ ^"locally" }
+        Partition = ${ ^"partition" ~ W ~ ^"by" ~ W ~ PartitionType ~ WO ~ PartitionBySpec }
+            PartitionType = { PartitionRange | PartitionList | PartitionHash }
+                PartitionRange = { ^"range" }
+                PartitionList = { ^"list" }
+                PartitionHash = { ^"hash" }
+            PartitionBySpec = !{ "(" ~ Identifier ~ ("," ~ Identifier)* ~ ")" }
     DropTable = ${ ^"drop" ~ W ~ ^"table" ~ W ~ (IfExists ~ W)? ~ Table ~ (W ~ WaitApplied)? ~ (W ~ TimeoutOption)? }
     CreateProc = ${
         ^"create" ~ W ~ ^"procedure" ~ W ~ (IfNotExists ~ W)? ~ Identifier ~ WO
-- 
GitLab