Bläddra i källkod

拆解测试代码

myuan 2 år sedan
förälder
incheckning
7c8f8b20d5
2 ändrade filer med 540 tillägg och 518 borttagningar
  1. 52 518
      run_sql_parser_test.py
  2. 488 0
      tests_config.py

+ 52 - 518
run_sql_parser_test.py

@@ -6,23 +6,37 @@ from watchdog.events import FileSystemEventHandler
 from watchdog.events import LoggingEventHandler
 import asyncio.subprocess as subprocess
 import asyncio
-from watchfiles import awatch, watch
+from watchfiles import Change, awatch, watch
 from termcolor import colored
 from datetime import datetime
 import orjson
 import os
+import tempfile
+from tests_config import sql_parser_tests
 
 
-async def assert_sql(sql, target):
+async def run_and_output(
+    *args: str, timeout=5
+) -> tuple[bytes, bytes]:
     p = await subprocess.create_subprocess_exec(
-        "xmake",
-        "run",
-        "sql-parser",
-        sql,
+        *args,
         stdout=subprocess.PIPE,
         stderr=subprocess.PIPE,
     )
-    stdout, stderr = await asyncio.wait_for(p.communicate(), timeout=5)
+    stdout, stderr = await asyncio.wait_for(p.communicate(), timeout=timeout)
+    return stdout, stderr
+
+async def rebuild() -> bool:
+    stdout, _ = await run_and_output('xmake')
+    if b"error" in stdout:
+        print(stdout.decode("utf-8"))
+        print(datetime.now(), "-" * 40)
+        return False
+    else:
+        return True
+
+async def assert_sql(sql: str, expected: dict):
+    stdout, stderr = await run_and_output('xmake', 'run', "sql-parser", sql)
 
     if b"error" in stdout:
         print(stdout.decode("utf-8"))
@@ -40,10 +54,10 @@ async def assert_sql(sql, target):
         + (b"\n\n" + stderr).replace(b"\n", b"\n# ")
     )
     assert (
-        output == target
+        output == expected
     ), f"""{colored("sql-parser error", "red")}
 input: {colored(sql, "yellow")}
-expect: {colored(target, "green")}
+expect: {colored(expected, "green")}
 actual: {colored(output, "red")}
 other: {colored(stderr.decode("utf-8"), "yellow")}
 
@@ -51,514 +65,26 @@ other: {colored(stderr.decode("utf-8"), "yellow")}
 
 
 async def assert_sqls():
-    await assert_sql(
-        "create table asd;", [{"type": "create_table", "table_name": "asd", "cols": []}]
-    )
-    await assert_sql(
-        "create table tb (col1 INT, col2 string, col3 FLOAT);",
-        [
-            {
-                "type": "create_table",
-                "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,
-                    },
-                ],
-            }
-        ],
-    )
-    await assert_sql(
-        """
-    create table tb1 (
-        col1 int primary key, 
-        col2 FLOAT
-    );
-    """,
-        [
-            {
-                "type": "create_table",
-                "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,
-                    },
-                ],
-            }
-        ],
-    )
-    await assert_sql(
-        """
-        create table tb2 (
-            x float,
-            y int,
-            z int
-        );
-        """,
-        [
-            {
-                "type": "create_table",
-                "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,
-                    },
-                ],
-            }
-        ],
-    )
-    await assert_sql(
-        """insert into tb1 values (1, 'foo');""",
-        [
-            {
-                "type": "insert",
-                "table_name": "tb1",
-                "values": [
-                    {"type": "int", "value": 1},
-                    {"type": "string", "value": "'foo'"},
-                ],
-            }
-        ],
-    )
-    await assert_sql(
-        """insert into tb1 values (2, 'foo', 'zxc', 1234.234);""",
-        [
-            {
-                "type": "insert",
-                "table_name": "tb1",
-                "values": [
-                    {"type": "int", "value": 2},
-                    {"type": "string", "value": "'foo'"},
-                    {"type": "string", "value": "'zxc'"},
-                    {"type": "float", "value": 1234.234},
-                ],
-            }
-        ],
-    )
+    for sql, excepted in sql_parser_tests:
+        await assert_sql(sql, excepted)
 
-    await assert_sql(
-        "update tb1 set col1=3, col4=4 where col1=2 and col2=4;",
-        [
-            {
-                "type": "update",
-                "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},
-                    },
-                    "right": {
-                        "type": "相等",
-                        "left": {"type": "identifier", "value": "col2"},
-                        "right": {"type": "int", "value": 4},
-                    },
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        "update tb1 set col1=3, col4=4 where not not not col1=2 and col2=4 or col3=col2;",
-        [
-            {
-                "type": "update",
-                "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},
-                                    },
-                                },
-                            },
-                        },
-                        "right": {
-                            "type": "相等",
-                            "left": {"type": "identifier", "value": "col2"},
-                            "right": {"type": "int", "value": 4},
-                        },
-                    },
-                    "right": {
-                        "type": "相等",
-                        "left": {"type": "identifier", "value": "col3"},
-                        "right": {"type": "identifier", "value": "col2"},
-                    },
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        "delete from tb1 where c1 = 1 and c2= 3 or c3=3;",
-        [
-            {
-                "type": "delete",
-                "table_name": "tb1",
-                "where": {
-                    "type": "或",
-                    "left": {
-                        "left": {
-                            "type": "相等",
-                            "left": {"type": "identifier", "value": "c1"},
-                            "right": {"type": "int", "value": 1},
-                        },
-                        "type": "且",
-                        "right": {
-                            "type": "相等",
-                            "left": {"type": "identifier", "value": "c2"},
-                            "right": {"type": "int", "value": 3},
-                        },
-                    },
-                    "right": {
-                        "type": "相等",
-                        "left": {"type": "identifier", "value": "c3"},
-                        "right": {"type": "int", "value": 3},
-                    },
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        "delete from tb1 where c1 = 1 and (c2= 3 or c3=3) or (c4='asd');",
-        [
-            {
-                "type": "delete",
-                "table_name": "tb1",
-                "where": {
-                    "type": "或",
-                    "left": {
-                        "type": "且",
-                        "left": {
-                            "type": "相等",
-                            "left": {"type": "identifier", "value": "c1"},
-                            "right": {"type": "int", "value": 1},
-                        },
-                        "right": {
-                            "type": "或",
-                            "left": {
-                                "type": "相等",
-                                "left": {"type": "identifier", "value": "c2"},
-                                "right": {"type": "int", "value": 3},
-                            },
-                            "right": {
-                                "type": "相等",
-                                "left": {"type": "identifier", "value": "c3"},
-                                "right": {"type": "int", "value": 3},
-                            },
-                        },
-                    },
-                    "right": {
-                        "type": "相等",
-                        "left": {"type": "identifier", "value": "c4"},
-                        "right": {"type": "string", "value": "'asd'"},
-                    },
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        "select * from t2;",
-        [
-            {
-                "type": "select",
-                "select_cols": [{"type": "select_all_column"}],
-                "table_name": "t2",
-                "where": {},
-            }
-        ],
-    )
-    await assert_sql(
-        "select c2 as t from t2 where col1>2;",
-        [
-            {
-                "type": "select",
-                "select_cols": [
-                    {
-                        "type": "select_column",
-                        "target": {"type": "identifier", "value": "c2"},
-                        "alias": "t",
-                    }
-                ],
-                "table_name": "t2",
-                "where": {
-                    "type": "大于",
-                    "left": {"type": "identifier", "value": "col1"},
-                    "right": {"type": "int", "value": 2},
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        """SELECT Sname FROM Student WHERE Sno IN (1,2) and c in (3, 4, 5);""",
-        [
-            {
-                "type": "select",
-                "select_cols": [
-                    {
-                        "type": "select_column",
-                        "target": {"type": "identifier", "value": "Sname"},
-                    }
-                ],
-                "table_name": "Student",
-                "where": {
-                    "type": "且",
-                    "left": {
-                        "type": "包含于",
-                        "left": {"type": "identifier", "value": "Sno"},
-                        "right": [
-                            {"type": "int", "value": 1},
-                            {"type": "int", "value": 2},
-                        ],
-                    },
-                    "right": {
-                        "type": "包含于",
-                        "left": {"type": "identifier", "value": "c"},
-                        "right": [
-                            {"type": "int", "value": 3},
-                            {"type": "int", "value": 4},
-                            {"type": "int", "value": 5},
-                        ],
-                    },
-                },
-            }
-        ],
-    )
 
-    await assert_sql(
-        """SELECT Student.Sname
-            FROM Student
-            WHERE Sno IN (
-                SELECT Sno
-                FROM SC 
-                WHERE SC.Cno='81003'
-            );
-        """,
-        [
-            {
-                "type": "select",
-                "select_cols": [
-                    {
-                        "type": "select_column",
-                        "target": {
-                            "type": "table_field",
-                            "table": "Student",
-                            "field": "Sname",
-                        },
-                    }
-                ],
-                "table_name": "Student",
-                "where": {
-                    "type": "包含于",
-                    "left": {"type": "identifier", "value": "Sno"},
-                    "right": {
-                        "type": "select",
-                        "select_cols": [
-                            {
-                                "type": "select_column",
-                                "target": {"type": "identifier", "value": "Sno"},
-                            }
-                        ],
-                        "table_name": "SC",
-                        "where": {
-                            "type": "相等",
-                            "left": {
-                                "type": "table_field",
-                                "table": "SC",
-                                "field": "Cno",
-                            },
-                            "right": {"type": "string", "value": "'81003'"},
-                        },
-                    },
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        """
-        select Student.Sname 
-        from Student join SC 
-        on Student.Sno=SC.Sno 
-        where SC.Cno='81003';
-        """,
-        [
-            {
-                "type": "select",
-                "select_cols": [
-                    {
-                        "type": "select_column",
-                        "target": {
-                            "type": "table_field",
-                            "table": "Student",
-                            "field": "Sname",
-                        },
-                    }
-                ],
-                "table_name": "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"},
-                    },
-                },
-                "where": {
-                    "type": "相等",
-                    "left": {"type": "table_field", "table": "SC", "field": "Cno"},
-                    "right": {"type": "string", "value": "'81003'"},
-                },
-            }
-        ],
-    )
-    await assert_sql(
-        """
-        select Student.Sname 
-        from   Student join SC 
-        on     Student.Sno=SC.Sno 
-        and    SC.Cno='81003';
-        """,
-        [
-            {
-                "type": "select",
-                "select_cols": [
-                    {
-                        "type": "select_column",
-                        "target": {
-                            "type": "table_field",
-                            "table": "Student",
-                            "field": "Sname",
-                        },
-                    }
-                ],
-                "table_name": "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",
-                            },
-                        },
-                        "right": {
-                            "type": "相等",
-                            "left": {
-                                "type": "table_field",
-                                "table": "SC",
-                                "field": "Cno",
-                            },
-                            "right": {"type": "string", "value": "'81003'"},
-                        },
-                    },
-                },
-                "where": {},
-            }
-        ],
-    )
-
-
-async def on_modified(event):
-    p = await subprocess.create_subprocess_shell(
-        "xmake", stdout=subprocess.PIPE, stderr=subprocess.PIPE
-    )
-    stdout, _ = await p.communicate()
-    if b"error" in stdout:
-        print(stdout.decode("utf-8"))
-        print(datetime.now(), "-" * 40)
-        return
+async def on_parser_modified():
+    print(datetime.now(), colored("run parser tests...", "yellow"))
 
     try:
         await assert_sqls()
     except Exception as e:
         print(e)
     else:
-        print(datetime.now(), colored("all tests right!", "green"))
+        print(datetime.now(), colored("all parser tests right!", "green"))
+
+
+async def on_checker_modified():
+    print(datetime.now(), colored("run checker tests...", "yellow"))
+    stdout, stderr = await run_and_output('xmake', 'run', "sql-checker", "-f", "test.cpp", "-g", "2")
+    print(stdout.decode("utf-8"))
+    print(datetime.now(), colored("all checker tests right!", "green"))
 
 
 async def restart():
@@ -567,18 +93,26 @@ async def restart():
         os.execl("/bin/python", Path(__file__).as_posix(), Path(__file__).as_posix())
 
 
-async def watch_src():
-    async for changes in awatch("src"):
-        print(datetime.now(), "re run...")
-        await asyncio.wait_for(on_modified(changes), 10)
+async def watch_parser():
+    async for changes in awatch("./src/parser.y", "./src/parser.l"):
+        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"):
+        if await rebuild():
+            await on_checker_modified()
 
 
 async def main():
-    try:
-        await assert_sqls()
-    except Exception as e:
-        print(e)
-    await asyncio.gather(restart(), watch_src())
+    await asyncio.gather(
+        restart(),
+        watch_parser(),
+        watch_checker(),
+        on_parser_modified(),
+        on_checker_modified(),
+    )
 
 
 if __name__ == "__main__":

+ 488 - 0
tests_config.py

@@ -0,0 +1,488 @@
+sql_parser_tests = [
+    ("create table asd;", [{"type": "create_table", "table_name": "asd", "cols": []}]),
+    (
+        "create table tb (col1 INT, col2 string, col3 FLOAT);",
+        [
+            {
+                "type": "create_table",
+                "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_table",
+                "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_table",
+                "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",
+                "table_name": "tb1",
+                "values": [
+                    {"type": "int", "value": 1},
+                    {"type": "string", "value": "'foo'"},
+                ],
+            }
+        ],
+    ),
+    (
+        """insert into tb1 values (2, 'foo', 'zxc', 1234.234);""",
+        [
+            {
+                "type": "insert",
+                "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",
+                "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},
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "col2"},
+                        "right": {"type": "int", "value": 4},
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        "update tb1 set col1=3, col4=4 where not not not col1=2 and col2=4 or col3=col2;",
+        [
+            {
+                "type": "update",
+                "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},
+                                    },
+                                },
+                            },
+                        },
+                        "right": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "col2"},
+                            "right": {"type": "int", "value": 4},
+                        },
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "col3"},
+                        "right": {"type": "identifier", "value": "col2"},
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        "delete from tb1 where c1 = 1 and c2= 3 or c3=3;",
+        [
+            {
+                "type": "delete",
+                "table_name": "tb1",
+                "where": {
+                    "type": "或",
+                    "left": {
+                        "left": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c1"},
+                            "right": {"type": "int", "value": 1},
+                        },
+                        "type": "且",
+                        "right": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c2"},
+                            "right": {"type": "int", "value": 3},
+                        },
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "c3"},
+                        "right": {"type": "int", "value": 3},
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        "delete from tb1 where c1 = 1 and (c2= 3 or c3=3) or (c4='asd');",
+        [
+            {
+                "type": "delete",
+                "table_name": "tb1",
+                "where": {
+                    "type": "或",
+                    "left": {
+                        "type": "且",
+                        "left": {
+                            "type": "相等",
+                            "left": {"type": "identifier", "value": "c1"},
+                            "right": {"type": "int", "value": 1},
+                        },
+                        "right": {
+                            "type": "或",
+                            "left": {
+                                "type": "相等",
+                                "left": {"type": "identifier", "value": "c2"},
+                                "right": {"type": "int", "value": 3},
+                            },
+                            "right": {
+                                "type": "相等",
+                                "left": {"type": "identifier", "value": "c3"},
+                                "right": {"type": "int", "value": 3},
+                            },
+                        },
+                    },
+                    "right": {
+                        "type": "相等",
+                        "left": {"type": "identifier", "value": "c4"},
+                        "right": {"type": "string", "value": "'asd'"},
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        "select * from t2;",
+        [
+            {
+                "type": "select",
+                "select_cols": [{"type": "select_all_column"}],
+                "table_name": "t2",
+                "where": {},
+            }
+        ],
+    ),
+    (
+        "select c2 as t from t2 where col1>2;",
+        [
+            {
+                "type": "select",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {"type": "identifier", "value": "c2"},
+                        "alias": "t",
+                    }
+                ],
+                "table_name": "t2",
+                "where": {
+                    "type": "大于",
+                    "left": {"type": "identifier", "value": "col1"},
+                    "right": {"type": "int", "value": 2},
+                },
+            }
+        ],
+    ),
+    (
+        """SELECT Sname FROM Student WHERE Sno IN (1,2) and c in (3, 4, 5);""",
+        [
+            {
+                "type": "select",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {"type": "identifier", "value": "Sname"},
+                    }
+                ],
+                "table_name": "Student",
+                "where": {
+                    "type": "且",
+                    "left": {
+                        "type": "包含于",
+                        "left": {"type": "identifier", "value": "Sno"},
+                        "right": [
+                            {"type": "int", "value": 1},
+                            {"type": "int", "value": 2},
+                        ],
+                    },
+                    "right": {
+                        "type": "包含于",
+                        "left": {"type": "identifier", "value": "c"},
+                        "right": [
+                            {"type": "int", "value": 3},
+                            {"type": "int", "value": 4},
+                            {"type": "int", "value": 5},
+                        ],
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        """SELECT Student.Sname
+            FROM Student
+            WHERE Sno IN (
+                SELECT Sno
+                FROM SC 
+                WHERE SC.Cno='81003'
+            );
+        """,
+        [
+            {
+                "type": "select",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_name": "Student",
+                "where": {
+                    "type": "包含于",
+                    "left": {"type": "identifier", "value": "Sno"},
+                    "right": {
+                        "type": "select",
+                        "select_cols": [
+                            {
+                                "type": "select_column",
+                                "target": {"type": "identifier", "value": "Sno"},
+                            }
+                        ],
+                        "table_name": "SC",
+                        "where": {
+                            "type": "相等",
+                            "left": {
+                                "type": "table_field",
+                                "table": "SC",
+                                "field": "Cno",
+                            },
+                            "right": {"type": "string", "value": "'81003'"},
+                        },
+                    },
+                },
+            }
+        ],
+    ),
+    (
+        """
+        select Student.Sname 
+        from Student join SC 
+        on Student.Sno=SC.Sno 
+        where SC.Cno='81003';
+        """,
+        [
+            {
+                "type": "select",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_name": "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"},
+                    },
+                },
+                "where": {
+                    "type": "相等",
+                    "left": {"type": "table_field", "table": "SC", "field": "Cno"},
+                    "right": {"type": "string", "value": "'81003'"},
+                },
+            }
+        ],
+    ),
+    (
+        """
+        select Student.Sname 
+        from   Student join SC 
+        on     Student.Sno=SC.Sno 
+        and    SC.Cno='81003';
+        """,
+        [
+            {
+                "type": "select",
+                "select_cols": [
+                    {
+                        "type": "select_column",
+                        "target": {
+                            "type": "table_field",
+                            "table": "Student",
+                            "field": "Sname",
+                        },
+                    }
+                ],
+                "table_name": "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",
+                            },
+                        },
+                        "right": {
+                            "type": "相等",
+                            "left": {
+                                "type": "table_field",
+                                "table": "SC",
+                                "field": "Cno",
+                            },
+                            "right": {"type": "string", "value": "'81003'"},
+                        },
+                    },
+                },
+                "where": {},
+            }
+        ],
+    ),
+]