瀏覽代碼

允许逻辑值拆除

myuan 2 年之前
父節點
當前提交
c4896d1d20
共有 5 個文件被更改,包括 760 次插入29 次删除
  1. 36 20
      run_sql_parser_test.py
  2. 52 9
      src/optimizer.cpp
  3. 62 0
      test_configs/sql_checker.py
  4. 63 0
      test_configs/sql_optimizer.py
  5. 547 0
      test_configs/sql_parser.py

+ 36 - 20
run_sql_parser_test.py

@@ -7,17 +7,8 @@ from datetime import datetime
 import orjson
 import os
 import tempfile
-import tests_config
 import importlib
 
-importlib.reload(tests_config)
-
-sql_parser_tests, sql_checker_tests, sql_optimizer_tests = (
-    tests_config.sql_parser_tests,
-    tests_config.sql_checker_tests,
-    tests_config.sql_optimizer_tests
-)
-
 
 async def run_and_output(*args: str, timeout=10) -> tuple[bytes, bytes]:
     p = await subprocess.create_subprocess_exec(
@@ -70,7 +61,10 @@ other: {colored(stderr.decode("utf-8"), "yellow")}
 
 
 async def assert_sqls():
-    for sql, excepted in sql_parser_tests:
+    import test_configs.sql_parser
+    importlib.reload(test_configs.sql_parser)
+
+    for sql, excepted in test_configs.sql_parser.sql_parser_tests:
         await assert_sql(sql, excepted)
 
 
@@ -86,7 +80,10 @@ async def on_parser_modified():
 
 
 async def assert_checks():
-    for sql, res in sql_checker_tests:
+    import test_configs.sql_checker
+    importlib.reload(test_configs.sql_checker)
+
+    for sql, res in test_configs.sql_checker.sql_checker_tests:
         stdout, stderr = await run_and_output("xmake", "run", "sql-checker", "-s", sql)
         print(sql, res)
         if res is True:
@@ -112,9 +109,15 @@ async def on_checker_modified():
     else:
         print(datetime.now(), colored("all checker tests right!", "green"))
 
+
 async def assert_sql_optimizer_check():
-    for sql, res in sql_optimizer_tests:
-        stdout, stderr = await run_and_output("xmake", "run", "sql-optimizer", "-s", sql)
+    import test_configs.sql_optimizer
+    importlib.reload(test_configs.sql_optimizer)
+
+    for sql, res in test_configs.sql_optimizer.sql_optimizer_tests:
+        stdout, stderr = await run_and_output(
+            "xmake", "run", "sql-optimizer", "-s", sql
+        )
         print(sql)
 
         try:
@@ -125,12 +128,11 @@ async def assert_sql_optimizer_check():
                 print(colored(stdout.decode("utf-8"), "yellow"))
                 print(colored(stderr.decode("utf-8"), "yellow"))
                 assert False
-            
+
         except Exception as e:
             print(e)
 
 
-
 async def on_optimizer_modified():
     print(datetime.now(), colored("run optimizer tests...", "yellow"))
     try:
@@ -141,29 +143,42 @@ async def on_optimizer_modified():
         print(datetime.now(), colored("all optimizer tests right!", "green"))
 
 async def restart():
-    async for _ in awatch(__file__, "./tests_config.py"):
+    async for _ in awatch(__file__):
         print("restart")
         os.execl("/bin/python", Path(__file__).as_posix(), Path(__file__).as_posix())
 
 
 async def watch_parser():
-    async for changes in awatch("./src/parser.y", "./src/parser.l"):
+    async for changes in awatch(
+        "./src/parser.y", "./src/parser.l", "test_configs/sql_parser.py"
+    ):
         if await rebuild():
             await asyncio.wait_for(on_parser_modified(), 10)
 
 
 async def watch_checker():
     async for changes in awatch(
-        "./src/checker.cpp", "./src/checker.h", "./src/utils.h", "./src/utils.cpp"
+        "./src/checker.cpp",
+        "./src/checker.h",
+        "./src/utils.h",
+        "./src/utils.cpp",
+        "test_configs/sql_checker.py",
     ):
         if await rebuild():
             await on_checker_modified()
 
+
 async def watch_optimizer():
-    async for changes in awatch("src/optimizer.cpp"):
+    async for changes in awatch(
+        "src/optimizer.cpp",
+        "./src/utils.h",
+        "./src/utils.cpp",
+        "test_configs/sql_optimizer.py",
+    ):
         if await rebuild():
             await on_optimizer_modified()
 
+
 async def rerun_tests():
     await asyncio.gather(
         on_parser_modified(),
@@ -171,12 +186,13 @@ async def rerun_tests():
     )
     await on_optimizer_modified()
 
+
 async def main():
     await asyncio.gather(
         restart(),
         watch_parser(),
         watch_checker(),
-        watch_optimizer(), 
+        watch_optimizer(),
         rerun_tests(),
     )
 

+ 52 - 9
src/optimizer.cpp

@@ -97,8 +97,8 @@ json& check_compare_op(json& j) {
             } else if (new_range.full()) {
                 j = {{"type", "bool"}, {"value", true}};
             } else {
-                if (new_range.max() == new_range.up &&
-                    new_range.min() == new_range.min()) {
+                if (new_range.max() != new_range.up &&
+                    new_range.min() != new_range.down) {
                     j["left"] = {{"type", "小于"},
                                  {"left", j["left"]["left"]},
                                  {"right", new_range.up}};
@@ -113,11 +113,10 @@ json& check_compare_op(json& j) {
                         {"right", {{"type", "int"}, {"value", new_range.down}}},
                         {"op_type", "bin_cmp_op"}};
                 } else if (new_range.min() == new_range.down) {
-                    j = {
-                        {"type", "小于"},
-                        {"left", j["left"]["left"]},
-                        {"right", {{"type", "int"}, {"value", new_range.up}}},
-                        {"op_type", "bin_cmp_op"}};
+                    j = {{"type", "小于"},
+                         {"left", j["left"]["left"]},
+                         {"right", {{"type", "int"}, {"value", new_range.up}}},
+                         {"op_type", "bin_cmp_op"}};
                 }
             }
         }
@@ -126,6 +125,50 @@ json& check_compare_op(json& j) {
     return j;
 }
 
+json& check_logic_op(json& j) {
+    if (j.empty()) {
+        return j;
+    }
+    let op_type = op_type_of(j);
+    if (op_type != OP_LOGIC) {
+        return j;
+    }
+    auto& left = j["left"];
+    auto& right = j["right"];
+
+    // 假 或 -> 单独一侧
+    // 假 且 -> FALSE
+    // 真 或 -> 真
+    // 真 且 -> 另一侧
+    if (left["type"] == "bool" && left["type"] == "bool") {
+        if (j["type"] == "且") {
+            j = {{"type", "bool"}, {"value", left["value"] && right["value"]}};
+        } else if (j["type"] == "或") {
+            j = {{"type", "bool"}, {"value", left["value"] || right["value"]}};
+        }
+    } else if (left["type"] == "bool" || right["type"] == "bool") {
+        if (left["type"] == "bool"){
+            let i = right;
+            right = left;
+            left = i;
+        }
+        bool right_v = right["value"];
+
+        if (j["type"] == "或" && !right_v) {
+            j = left;
+        } else if (j["type"] == "且" && !right_v) {
+            j =  {{"type", "bool"}, {"value", false}};
+        } else if (j["type"] == "或" && right_v) {
+            j =  {{"type", "bool"}, {"value", true}};
+        } else if (j["type"] == "且" && right_v) {
+            j = left;
+        }
+    }
+    // if (left["type"] == "bool") {
+    // }
+    return j;
+}
+
 void process_sql(json& j) {
     let type = j.value("type", "none");
 
@@ -135,6 +178,7 @@ void process_sql(json& j) {
     }
 
     j["where"] = check_compare_op(j["where"]);
+    j["where"] = check_logic_op(j["where"]);
 }
 
 int main(int argc, char** argv) {
@@ -156,8 +200,7 @@ int main(int argc, char** argv) {
         // std::cout << "请输入 sql 或者 sql 文件" << std::endl;
         // return 1;
         stmts = parse_sql(
-                    "select * from person where (age < 18) or (age > 60 and "
-                    "age > 65);")
+                    "select * from person where (age < 18) or (age > 60 and age < 35);")
                     .out;
     }
 

+ 62 - 0
test_configs/sql_checker.py

@@ -0,0 +1,62 @@
+sql_checker_tests = [
+    ("drop table person;", True),
+    ("create table person(name string, age int, classId int);", True),
+    ("select age from person;", True),
+    ("select * from person;", True),
+    ("select gender from person;", "column `gender` not exists in `person`"),
+    ("select 123 from person;", True),
+    ("drop table class;", True),
+    ("create table class (id int, grade int, faculty string);", True),
+    ("select * from class where grade = 2 and faculty = 'Computer Science';", True),
+    (
+        "select * from class where grade = 2 and count=33;",
+        "column `count` not exists in `class`",
+    ),
+    ("select age, class.grade from class, person;", True),
+    (
+        "select age, person.grade from class, person;",
+        "column `person.grade` not exists in `class, person`",
+    ),
+    (
+        """SELECT person.name, grade, faculty
+            FROM person
+            WHERE name = '张三' and classId IN (
+                SELECT *
+                FROM class
+                WHERE class.id = classId
+            );
+        """,
+        "column `grade` not exists in `person`",
+    ),
+    (
+        """select person.name 
+        from person join class 
+        on class.id=person.classId and person.grade=2
+        where age=22;
+        """,
+        "column `person.grade` not exists in `person, class`",
+    ),
+    (
+        """select person.name 
+        from person join class 
+        on class.id=person.classId and class.grade=2
+        where age=22;
+        """,
+        True,
+    ),
+    (
+        """select person.name 
+        from person join class 
+        on class.id=person.classId and class.grade = 'zxc'
+        where age=22;
+        """,
+        "column `class.grade` type is `int`, but `string:'zxc'` type is `string`, cannot `相等`",
+    ),
+    (
+        """select person.name 
+        from person where age>name;
+        """,
+        "column `age` type is `int`, but `name` type is `string`, cannot `大于`",
+    ),
+]
+

+ 63 - 0
test_configs/sql_optimizer.py

@@ -0,0 +1,63 @@
+sql_optimizer_tests = [
+    (
+        "select * from person where (age < 18) or (age > 60 and age < 35);",
+        {
+            "select_cols": [
+                {
+                    "target": {
+                        "type": "select_all_column",
+                        "value": "select_all_column",
+                    },
+                    "type": "select_all_column",
+                }
+            ],
+            "table_names": ["person"],
+            "type": "select_stmt",
+            "where": {
+                "left": {"type": "identifier", "value": "age"},
+                "op_type": "bin_cmp_op",
+                "right": {"type": "int", "value": 18},
+                "type": "小于",
+            },
+        },
+    ),
+    (
+        "select * from person where (age < 18) and age < 5 and age < 35;",
+        {
+            "select_cols": [
+                {
+                    "target": {
+                        "type": "select_all_column",
+                        "value": "select_all_column",
+                    },
+                    "type": "select_all_column",
+                }
+            ],
+            "table_names": ["person"],
+            "type": "select_stmt",
+            "where": {
+                "left": {"type": "identifier", "value": "age"},
+                "op_type": "bin_cmp_op",
+                "right": {"type": "int", "value": 5},
+                "type": "小于",
+            },
+        },
+    ),
+    (
+        "select * from person where age < 18 and (age > 5 and age > 35);",
+        {
+            "select_cols": [
+                {
+                    "target": {
+                        "type": "select_all_column",
+                        "value": "select_all_column",
+                    },
+                    "type": "select_all_column",
+                }
+            ],
+            "table_names": ["person"],
+            "type": "select_stmt",
+            "where": {"type": "bool", "value": False},
+        },
+    ),
+]

+ 547 - 0
test_configs/sql_parser.py

@@ -0,0 +1,547 @@
+sql_parser_tests = [
+    ("create table asd;", [{"type": "create_stmt", "table_name": "asd", "cols": []}]),
+    (
+        "create table tb (col1 INT, col2 string, col3 FLOAT);",
+        [
+            {
+                "type": "create_stmt",
+                "table_name": "tb",
+                "cols": [
+                    {
+                        "type": "create_column",
+                        "column_name": "col1",
+                        "data_type": "INT",
+                        "primary_key": False,
+                    },
+                    {
+                        "type": "create_column",
+                        "column_name": "col2",
+                        "data_type": "string",
+                        "primary_key": False,
+                    },
+                    {
+                        "type": "create_column",
+                        "column_name": "col3",
+                        "data_type": "FLOAT",
+                        "primary_key": False,
+                    },
+                ],
+            }
+        ],
+    ),
+    (
+        """
+    create table tb1 (
+        col1 int primary key, 
+        col2 FLOAT
+    );
+    """,
+        [
+            {
+                "type": "create_stmt",
+                "table_name": "tb1",
+                "cols": [
+                    {
+                        "type": "create_column",
+                        "column_name": "col1",
+                        "data_type": "int",
+                        "primary_key": True,
+                    },
+                    {
+                        "type": "create_column",
+                        "column_name": "col2",
+                        "data_type": "FLOAT",
+                        "primary_key": False,
+                    },
+                ],
+            }
+        ],
+    ),
+    (
+        """
+        create table tb2 (
+            x float,
+            y int,
+            z int
+        );
+        """,
+        [
+            {
+                "type": "create_stmt",
+                "table_name": "tb2",
+                "cols": [
+                    {
+                        "type": "create_column",
+                        "column_name": "x",
+                        "data_type": "float",
+                        "primary_key": False,
+                    },
+                    {
+                        "type": "create_column",
+                        "column_name": "y",
+                        "data_type": "int",
+                        "primary_key": False,
+                    },
+                    {
+                        "type": "create_column",
+                        "column_name": "z",
+                        "data_type": "int",
+                        "primary_key": False,
+                    },
+                ],
+            }
+        ],
+    ),
+    (
+        """insert into tb1 values (1, 'foo');""",
+        [
+            {
+                "type": "insert_stmt",
+                "table_name": "tb1",
+                "values": [
+                    {"type": "int", "value": 1},
+                    {"type": "string", "value": "'foo'"},
+                ],
+            }
+        ],
+    ),
+    (
+        """insert into tb1 values (2, 'foo', 'zxc', 1234.234);""",
+        [
+            {
+                "type": "insert_stmt",
+                "table_name": "tb1",
+                "values": [
+                    {"type": "int", "value": 2},
+                    {"type": "string", "value": "'foo'"},
+                    {"type": "string", "value": "'zxc'"},
+                    {"type": "float", "value": 1234.234},
+                ],
+            }
+        ],
+    ),
+    (
+        "update tb1 set col1=3, col4=4 where col1=2 and col2=4;",
+        [
+            {
+                "type": "update_stmt",
+                "table_name": "tb1",
+                "set": [
+                    {
+                        "type": "assign_const",
+                        "left": {"type": "identifier", "value": "col1"},
+                        "right": {"type": "int", "value": 3},
+                    },
+                    {
+                        "type": "assign_const",
+                        "left": {"type": "identifier", "value": "col4"},
+                        "right": {"type": "int", "value": 4},
+                    },
+                ],
+                "where": {
+                    "type": "且",
+                    "left": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "col1"},
+                        "right": {"type": "int", "value": 2},
+                        "op_type": "bin_cmp_op",
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "col2"},
+                        "right": {"type": "int", "value": 4},
+                        "op_type": "bin_cmp_op",
+                    },
+                    "op_type": "bin_logical_op",
+                },
+            }
+        ],
+    ),
+    (
+        "update tb1 set col1=3, col4=4 where not not not col1=2 and col2=4 or col3=col2;",
+        [
+            {
+                "type": "update_stmt",
+                "table_name": "tb1",
+                "set": [
+                    {
+                        "type": "assign_const",
+                        "left": {"type": "identifier", "value": "col1"},
+                        "right": {"type": "int", "value": 3},
+                    },
+                    {
+                        "type": "assign_const",
+                        "left": {"type": "identifier", "value": "col4"},
+                        "right": {"type": "int", "value": 4},
+                    },
+                ],
+                "where": {
+                    "type": "或",
+                    "left": {
+                        "type": "且",
+                        "left": {
+                            "type": "非",
+                            "left": {
+                                "type": "非",
+                                "left": {
+                                    "type": "非",
+                                    "left": {
+                                        "type": "相等",
+                                        "left": {"type": "identifier", "value": "col1"},
+                                        "right": {"type": "int", "value": 2},
+                                        "op_type": "bin_cmp_op",
+                                    },
+                                },
+                            },
+                        },
+                        "right": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "col2"},
+                            "right": {"type": "int", "value": 4},
+                            "op_type": "bin_cmp_op",
+                        },
+                        "op_type": "bin_logical_op",
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "col3"},
+                        "right": {"type": "identifier", "value": "col2"},
+                        "op_type": "bin_cmp_op",
+                    },
+                    "op_type": "bin_logical_op",
+                },
+            }
+        ],
+    ),
+    (
+        "delete from tb1 where c1 = 1 and c2= 3 or c3=3;",
+        [
+            {
+                "type": "delete_stmt",
+                "table_name": "tb1",
+                "where": {
+                    "type": "或",
+                    "left": {
+                        "type": "且",
+                        "left": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c1"},
+                            "right": {"type": "int", "value": 1},
+                            "op_type": "bin_cmp_op",
+                        },
+                        "right": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c2"},
+                            "right": {"type": "int", "value": 3},
+                            "op_type": "bin_cmp_op",
+                        },
+                        "op_type": "bin_logical_op",
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "c3"},
+                        "right": {"type": "int", "value": 3},
+                        "op_type": "bin_cmp_op",
+                    },
+                    "op_type": "bin_logical_op",
+                },
+            }
+        ],
+    ),
+    (
+        "delete from tb1 where c1 = 1 and (c2= 3 or c3=3) or (c4='asd');",
+        [
+            {
+                "type": "delete_stmt",
+                "table_name": "tb1",
+                "where": {
+                    "type": "或",
+                    "left": {
+                        "type": "且",
+                        "left": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c1"},
+                            "right": {"type": "int", "value": 1},
+                            "op_type": "bin_cmp_op",
+                        },
+                        "right": {
+                            "type": "或",
+                            "left": {
+                                "type": "相等",
+                                "left": {"type": "identifier", "value": "c2"},
+                                "right": {"type": "int", "value": 3},
+                                "op_type": "bin_cmp_op",
+                            },
+                            "right": {
+                                "type": "相等",
+                                "left": {"type": "identifier", "value": "c3"},
+                                "right": {"type": "int", "value": 3},
+                                "op_type": "bin_cmp_op",
+                            },
+                            "op_type": "bin_logical_op",
+                        },
+                        "op_type": "bin_logical_op",
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "c4"},
+                        "right": {"type": "string", "value": "'asd'"},
+                        "op_type": "bin_cmp_op",
+                    },
+                    "op_type": "bin_logical_op",
+                },
+            }
+        ],
+    ),
+    (
+        "select * from t2;",
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_all_column",
+                        "target": {
+                            "type": "select_all_column",
+                            "value": "select_all_column",
+                        },
+                    }
+                ],
+                "table_names": ["t2"],
+                "where": {},
+            }
+        ],
+    ),
+    (
+        "select c2 as t from t2 where col1>2;",
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {"type": "identifier", "value": "c2"},
+                        "alias": "t",
+                    }
+                ],
+                "table_names": ["t2"],
+                "where": {
+                    "type": "大于",
+                    "left": {"type": "identifier", "value": "col1"},
+                    "right": {"type": "int", "value": 2},
+                    "op_type": "bin_cmp_op",
+                },
+            }
+        ],
+    ),
+    (
+        """SELECT Sname FROM Student WHERE Sno IN (1,2) and c in (3, 4, 5);""",
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {"type": "identifier", "value": "Sname"},
+                    }
+                ],
+                "table_names": ["Student"],
+                "where": {
+                    "type": "且",
+                    "left": {
+                        "type": "包含于",
+                        "left": {"type": "identifier", "value": "Sno"},
+                        "right": [
+                            {"type": "int", "value": 1},
+                            {"type": "int", "value": 2},
+                        ],
+                        "op_type": "bin_contains_op",
+                    },
+                    "right": {
+                        "type": "包含于",
+                        "left": {"type": "identifier", "value": "c"},
+                        "right": [
+                            {"type": "int", "value": 3},
+                            {"type": "int", "value": 4},
+                            {"type": "int", "value": 5},
+                        ],
+                        "op_type": "bin_contains_op",
+                    },
+                    "op_type": "bin_logical_op",
+                },
+            }
+        ],
+    ),
+    (
+        """SELECT Student.Sname
+            FROM Student
+            WHERE Sno IN (
+                SELECT Sno
+                FROM SC 
+                WHERE SC.Cno='81003'
+            );
+        """,
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_names": ["Student"],
+                "where": {
+                    "type": "包含于",
+                    "left": {"type": "identifier", "value": "Sno"},
+                    "right": {
+                        "type": "select_stmt",
+                        "select_cols": [
+                            {
+                                "type": "select_column",
+                                "target": {"type": "identifier", "value": "Sno"},
+                            }
+                        ],
+                        "table_names": ["SC"],
+                        "where": {
+                            "type": "相等",
+                            "left": {
+                                "type": "table_field",
+                                "table": "SC",
+                                "field": "Cno",
+                            },
+                            "right": {"type": "string", "value": "'81003'"},
+                            "op_type": "bin_cmp_op",
+                        },
+                    },
+                    "op_type": "bin_contains_op",
+                },
+            }
+        ],
+    ),
+    (
+        """
+        select Student.Sname 
+        from Student join SC 
+        on Student.Sno=SC.Sno 
+        where SC.Cno='81003';
+        """,
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_names": ["Student"],
+                "join_options": {
+                    "type": "join_options",
+                    "join_with": {"type": "identifier", "value": "SC"},
+                    "on": {
+                        "type": "相等",
+                        "left": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sno",
+                        },
+                        "right": {"type": "table_field", "table": "SC", "field": "Sno"},
+                        "op_type": "bin_cmp_op",
+                    },
+                },
+                "where": {
+                    "type": "相等",
+                    "left": {"type": "table_field", "table": "SC", "field": "Cno"},
+                    "right": {"type": "string", "value": "'81003'"},
+                    "op_type": "bin_cmp_op",
+                },
+            }
+        ],
+    ),
+    (
+        """
+        select Student.Sname 
+        from   Student join SC 
+        on     Student.Sno=SC.Sno 
+        and    SC.Cno='81003';
+        """,
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_names": ["Student"],
+                "join_options": {
+                    "type": "join_options",
+                    "join_with": {"type": "identifier", "value": "SC"},
+                    "on": {
+                        "type": "且",
+                        "left": {
+                            "type": "相等",
+                            "left": {
+                                "type": "table_field",
+                                "table": "Student",
+                                "field": "Sno",
+                            },
+                            "right": {
+                                "type": "table_field",
+                                "table": "SC",
+                                "field": "Sno",
+                            },
+                            "op_type": "bin_cmp_op",
+                        },
+                        "right": {
+                            "type": "相等",
+                            "left": {
+                                "type": "table_field",
+                                "table": "SC",
+                                "field": "Cno",
+                            },
+                            "right": {"type": "string", "value": "'81003'"},
+                            "op_type": "bin_cmp_op",
+                        },
+                        "op_type": "bin_logical_op",
+                    },
+                },
+                "where": {},
+            }
+        ],
+    ),
+    ("drop table t1;", [{"type": "drop_stmt", "table_name": "t1"}]),
+    (
+        "select * from tb1, tb2;",
+        [
+            {
+                "type": "select_stmt",
+                "select_cols": [
+                    {
+                        "type": "select_all_column",
+                        "target": {
+                            "type": "select_all_column",
+                            "value": "select_all_column",
+                        },
+                    }
+                ],
+                "table_names": ["tb1", "tb2"],
+                "where": {},
+            }
+        ],
+    ),
+]