This is an automated email from the ASF dual-hosted git repository.

pfzhan pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git


The following commit(s) were added to refs/heads/kylin5 by this push:
     new 7fe50b2d58 [KYLIN-5475] Use javaCC to parse self define DML (#2102)
7fe50b2d58 is described below

commit 7fe50b2d5833ad4b8a09d6a27027563dedce8287
Author: Yang Jiang <[email protected]>
AuthorDate: Wed Apr 2 17:09:17 2025 +0800

    [KYLIN-5475] Use javaCC to parse self define DML (#2102)
    
    * [KYLIN-5475] Use javaCC to parse self define DML
---
 .../kylin/query/util/ManipulationSqlParser.jj      | 152 +++++++++++++++++++++
 .../apache/kylin/query/util/DMLParserResult.java   |  46 +++++++
 .../query/util/ManipulationSqlParserTest.java      | 102 ++++++++++++++
 3 files changed, 300 insertions(+)

diff --git 
a/src/query-common/src/main/codegen/javacc/org/apache/kylin/query/util/ManipulationSqlParser.jj
 
b/src/query-common/src/main/codegen/javacc/org/apache/kylin/query/util/ManipulationSqlParser.jj
new file mode 100644
index 0000000000..7921dfee2b
--- /dev/null
+++ 
b/src/query-common/src/main/codegen/javacc/org/apache/kylin/query/util/ManipulationSqlParser.jj
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+options {
+    IGNORE_CASE = true;
+    STATIC = false;
+    UNICODE_INPUT=true;
+}
+
+PARSER_BEGIN(ManipulationSqlParser)
+package org.apache.kylin.query.util;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.Reader;
+import org.apache.kylin.query.util.DMLParserResult;
+
+
+public class ManipulationSqlParser {
+    public static DMLParserResult evaluate(String src) throws ParseException {
+               Reader reader = new StringReader(src);
+               return new ManipulationSqlParser(reader).parse();
+       }
+}
+
+PARSER_END(ManipulationSqlParser)
+
+// Operator type
+< DEFAULT >
+TOKEN :
+{
+  < SHOW : "SHOW" > |
+  < LOAD : "LOAD"> |
+  < DELETE: "DELETE" > |
+  < CANCEL: "CANCEL" >
+}
+
+// Operator unit
+< DEFAULT >
+TOKEN :
+{
+  < JOB : "JOB" > |
+  < PARTITION : "PARTITION"> |
+  < MODEL: "MODEL" >
+}
+
+< DEFAULT >
+TOKEN: {
+       // identifier
+      < DATE:
+        (["0"-"9"]){4}
+        "-"
+        (["0"-"9"]){2}
+        "-"
+        (["0"-"9"]){2}
+      > |
+        < DEFINENAME: (["a"-"z","A"-"Z","0"-"9"])
+        (["a"-"z","A"-"Z","0"-"9","_"])*
+     > |
+     < JOBID: (["a"-"z","A"-"Z","0"-"9"])
+        (["a"-"z","A"-"Z","0"-"9","-"])*
+        >
+}
+
+<DEFAULT> SKIP :
+{
+    " "
+|   "\t"
+|   "\n"
+|   "\r"
+|   "\f"
+}
+
+DMLParserResult parse():
+{
+       DMLParserResult res = new DMLParserResult();
+       List<String> argList = new ArrayList<String>();
+    Token x, y, sta, end;
+}
+{
+  // SHOW JOB job_id
+   <SHOW> <JOB> x = <JOBID> <EOF>
+       {
+       argList.add(x.image);
+       res.setOperator(DMLParserResult.OPERATOR.SHOW);
+       res.setUnit(DMLParserResult.UNIT.JOB);
+       res.setArg(argList);
+       return res;
+} |
+  // LOAD PARTITION poject_name.model_test (2023-01-01, 2023-02-10)
+   LOOKAHEAD(2) <LOAD>  <PARTITION> x = <DEFINENAME> "." y = <DEFINENAME> "(" 
sta = <DATE> "," end = <DATE> ")" <EOF>
+   {
+         argList.add(x.image);
+         argList.add(y.image);
+         argList.add(sta.image);
+         argList.add(end.image);
+         res.setOperator(DMLParserResult.OPERATOR.LOAD);
+         res.setUnit(DMLParserResult.UNIT.PARTITION);
+         res.setArg(argList);
+         return res;
+   } |
+   // LOAD MODEL poject_name.model_test
+   <LOAD> <MODEL> x = <DEFINENAME> "." y = <DEFINENAME> <EOF>
+      {
+          argList.add(x.image);
+          argList.add(y.image);
+          res.setOperator(DMLParserResult.OPERATOR.LOAD);
+          res.setUnit(DMLParserResult.UNIT.MODEL);
+          res.setArg(argList);
+          return res;
+      } |
+   // DELETE MODEL poject_name.model_name
+   <DELETE> <MODEL> x = <DEFINENAME> "." y = <DEFINENAME> <EOF>
+    {
+         argList.add(x.image);
+         argList.add(y.image);
+         res.setOperator(DMLParserResult.OPERATOR.DELETE);
+         res.setUnit(DMLParserResult.UNIT.MODEL);
+         res.setArg(argList);
+         return res;
+    } |
+   // CANCEL JOB job_id
+   <CANCEL> <JOB> x = <JOBID> <EOF>
+    {
+        argList.add(x.image);
+        res.setOperator(DMLParserResult.OPERATOR.CANCEL);
+        res.setUnit(DMLParserResult.UNIT.JOB);
+        res.setArg(argList);
+        return res;
+    }
+
+   {
+     return res;
+   }
+
+}
\ No newline at end of file
diff --git 
a/src/query-common/src/main/java/org/apache/kylin/query/util/DMLParserResult.java
 
b/src/query-common/src/main/java/org/apache/kylin/query/util/DMLParserResult.java
new file mode 100644
index 0000000000..148b8e6670
--- /dev/null
+++ 
b/src/query-common/src/main/java/org/apache/kylin/query/util/DMLParserResult.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.query.util;
+
+import java.util.List;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class DMLParserResult {
+    // All DML consists with `OPERATOR` +  `UNIT` + multi args
+    public enum OPERATOR {
+        SHOW, LOAD, DELETE, CANCEL;
+    }
+
+    public enum UNIT {
+        JOB, PARTITION, MODEL;
+    }
+
+    OPERATOR operator;
+    UNIT unit;
+    List<String> arg;
+
+    // Notice operator not be Null
+    public boolean isValid() {
+        return operator != null;
+    }
+}
diff --git 
a/src/query/src/test/java/org/apache/kylin/query/util/ManipulationSqlParserTest.java
 
b/src/query/src/test/java/org/apache/kylin/query/util/ManipulationSqlParserTest.java
new file mode 100644
index 0000000000..0b7943c5de
--- /dev/null
+++ 
b/src/query/src/test/java/org/apache/kylin/query/util/ManipulationSqlParserTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.query.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ManipulationSqlParserTest {
+
+    @Test
+    public void showJob() throws ParseException {
+        String sql = "SHOW JOB 
70ba0c50-15b1-a40c-39a9-5f67f0f813c7-713ab396-1038-eecd-824f-3da66d531db6";
+        DMLParserResult evaluate = ManipulationSqlParser.evaluate(sql);
+        Assert.assertEquals(DMLParserResult.OPERATOR.SHOW, evaluate.operator);
+        Assert.assertEquals(DMLParserResult.UNIT.JOB, evaluate.unit);
+        Assert.assertEquals(1, evaluate.arg.size());
+        
Assert.assertEquals("70ba0c50-15b1-a40c-39a9-5f67f0f813c7-713ab396-1038-eecd-824f-3da66d531db6",
+                evaluate.arg.get(0));
+    }
+
+    @Test
+    public void triggerJob() throws ParseException {
+        // 1. trigger partial build job with partition col
+        String sql = "LOAD PARTITION project_name.model_test (2023-01-01, 
2023-02-10)";
+        DMLParserResult evaluate = ManipulationSqlParser.evaluate(sql);
+
+        Assert.assertEquals(DMLParserResult.OPERATOR.LOAD, evaluate.operator);
+        Assert.assertEquals(DMLParserResult.UNIT.PARTITION, evaluate.unit);
+        Assert.assertEquals(4, evaluate.arg.size());
+        Assert.assertEquals("project_name", evaluate.arg.get(0));
+        Assert.assertEquals("model_test", evaluate.arg.get(1));
+        Assert.assertEquals("2023-01-01", evaluate.arg.get(2));
+        Assert.assertEquals("2023-02-10", evaluate.arg.get(3));
+
+        // 2. trigger full build job
+        String sql2 = "LOAD MODEL project_name.model_test2";
+        DMLParserResult evaluate2 = ManipulationSqlParser.evaluate(sql2);
+
+        Assert.assertEquals(evaluate2.operator, DMLParserResult.OPERATOR.LOAD);
+        Assert.assertEquals(evaluate2.unit, DMLParserResult.UNIT.MODEL);
+        Assert.assertEquals(2, evaluate2.arg.size());
+        Assert.assertEquals("project_name", evaluate2.arg.get(0));
+        Assert.assertEquals("model_test2", evaluate2.arg.get(1));
+
+    }
+
+    @Test
+    public void cancelJob() throws ParseException {
+        String sql = "CANCEL JOB 
70ba0c50-15b1-a40c-39a9-5f67f0f813c7-713ab396-1038-eecd-824f-3da66d531db6";
+        DMLParserResult evaluate = ManipulationSqlParser.evaluate(sql);
+
+        Assert.assertEquals(DMLParserResult.OPERATOR.CANCEL, 
evaluate.operator);
+        Assert.assertEquals(DMLParserResult.UNIT.JOB, evaluate.unit);
+        Assert.assertEquals(1, evaluate.arg.size());
+        
Assert.assertEquals("70ba0c50-15b1-a40c-39a9-5f67f0f813c7-713ab396-1038-eecd-824f-3da66d531db6",
+                evaluate.arg.get(0));
+    }
+
+    @Test
+    public void deleteModel() throws ParseException {
+        String sql = "DELETE MODEL project_name.model_test";
+        DMLParserResult evaluate = ManipulationSqlParser.evaluate(sql);
+
+        Assert.assertEquals(DMLParserResult.OPERATOR.DELETE, 
evaluate.operator);
+        Assert.assertEquals(DMLParserResult.UNIT.MODEL, evaluate.unit);
+        Assert.assertEquals(2, evaluate.arg.size());
+        Assert.assertEquals("project_name", evaluate.arg.get(0));
+        Assert.assertEquals("model_test", evaluate.arg.get(1));
+    }
+
+    @Test
+    public void testError() {
+        String sql = "DELETE MODELs model_test";
+        Assert.assertThrows(ParseException.class, () -> 
ManipulationSqlParser.evaluate(sql));
+    }
+
+    @Test
+    public void validDMLParserResult() {
+        DMLParserResult test = new DMLParserResult();
+        test.unit = DMLParserResult.UNIT.JOB;
+        Assert.assertFalse(test.isValid());
+
+        test.operator = DMLParserResult.OPERATOR.SHOW;
+        Assert.assertTrue(test.isValid());
+    }
+}

Reply via email to