|
@@ -1,64 +1,10 @@
|
|
|
-from pathlib import Path
|
|
|
-import sys
|
|
|
-import time
|
|
|
-from watchdog.observers import Observer
|
|
|
-from watchdog.events import FileSystemEventHandler
|
|
|
-from watchdog.events import LoggingEventHandler
|
|
|
-import asyncio.subprocess as subprocess
|
|
|
-import asyncio
|
|
|
-from watchfiles import awatch, watch
|
|
|
-from termcolor import colored
|
|
|
-from datetime import datetime
|
|
|
-import orjson
|
|
|
-import os
|
|
|
-
|
|
|
-
|
|
|
-async def assert_sql(sql, target):
|
|
|
- p = await subprocess.create_subprocess_exec(
|
|
|
- "xmake",
|
|
|
- "run",
|
|
|
- "sql-parser",
|
|
|
- sql,
|
|
|
- stdout=subprocess.PIPE,
|
|
|
- stderr=subprocess.PIPE,
|
|
|
- )
|
|
|
- stdout, stderr = await asyncio.wait_for(p.communicate(), timeout=5)
|
|
|
-
|
|
|
- if b"error" in stdout:
|
|
|
- print(stdout.decode("utf-8"))
|
|
|
- print(datetime.now(), "-" * 40)
|
|
|
- print(f'other: {colored(stderr.decode("utf-8"), "yellow")}')
|
|
|
- assert False, "sql-parser error"
|
|
|
-
|
|
|
- try:
|
|
|
- output = orjson.loads(stdout)
|
|
|
- except Exception as e:
|
|
|
- output = {"error": e, "output": stdout.decode("utf-8")}
|
|
|
- open("/tmp/temp/test.py", "wb").write(
|
|
|
- f'"{sql}"\n\n'.encode("utf-8")
|
|
|
- + orjson.dumps(output, option=orjson.OPT_INDENT_2)
|
|
|
- + (b"\n\n" + stderr).replace(b"\n", b"\n# ")
|
|
|
- )
|
|
|
- assert (
|
|
|
- output == target
|
|
|
- ), f"""{colored("sql-parser error", "red")}
|
|
|
-input: {colored(sql, "yellow")}
|
|
|
-expect: {colored(target, "green")}
|
|
|
-actual: {colored(output, "red")}
|
|
|
-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(
|
|
|
+sql_parser_tests = [
|
|
|
+ ("create table asd;", [{"type": "create_stmt", "table_name": "asd", "cols": []}]),
|
|
|
+ (
|
|
|
"create table tb (col1 INT, col2 string, col3 FLOAT);",
|
|
|
[
|
|
|
{
|
|
|
- "type": "create_table",
|
|
|
+ "type": "create_stmt",
|
|
|
"table_name": "tb",
|
|
|
"cols": [
|
|
|
{
|
|
@@ -82,8 +28,8 @@ async def assert_sqls():
|
|
|
],
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""
|
|
|
create table tb1 (
|
|
|
col1 int primary key,
|
|
@@ -92,7 +38,7 @@ async def assert_sqls():
|
|
|
""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "create_table",
|
|
|
+ "type": "create_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"cols": [
|
|
|
{
|
|
@@ -110,8 +56,8 @@ async def assert_sqls():
|
|
|
],
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""
|
|
|
create table tb2 (
|
|
|
x float,
|
|
@@ -121,7 +67,7 @@ async def assert_sqls():
|
|
|
""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "create_table",
|
|
|
+ "type": "create_stmt",
|
|
|
"table_name": "tb2",
|
|
|
"cols": [
|
|
|
{
|
|
@@ -145,12 +91,12 @@ async def assert_sqls():
|
|
|
],
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""insert into tb1 values (1, 'foo');""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "insert",
|
|
|
+ "type": "insert_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"values": [
|
|
|
{"type": "int", "value": 1},
|
|
@@ -158,12 +104,12 @@ async def assert_sqls():
|
|
|
],
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""insert into tb1 values (2, 'foo', 'zxc', 1234.234);""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "insert",
|
|
|
+ "type": "insert_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"values": [
|
|
|
{"type": "int", "value": 2},
|
|
@@ -173,13 +119,12 @@ async def assert_sqls():
|
|
|
],
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
-
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"update tb1 set col1=3, col4=4 where col1=2 and col2=4;",
|
|
|
[
|
|
|
{
|
|
|
- "type": "update",
|
|
|
+ "type": "update_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"set": [
|
|
|
{
|
|
@@ -208,12 +153,12 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"update tb1 set col1=3, col4=4 where not not not col1=2 and col2=4 or col3=col2;",
|
|
|
[
|
|
|
{
|
|
|
- "type": "update",
|
|
|
+ "type": "update_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"set": [
|
|
|
{
|
|
@@ -259,12 +204,12 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"delete from tb1 where c1 = 1 and c2= 3 or c3=3;",
|
|
|
[
|
|
|
{
|
|
|
- "type": "delete",
|
|
|
+ "type": "delete_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"where": {
|
|
|
"type": "或",
|
|
@@ -289,12 +234,12 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"delete from tb1 where c1 = 1 and (c2= 3 or c3=3) or (c4='asd');",
|
|
|
[
|
|
|
{
|
|
|
- "type": "delete",
|
|
|
+ "type": "delete_stmt",
|
|
|
"table_name": "tb1",
|
|
|
"where": {
|
|
|
"type": "或",
|
|
@@ -327,23 +272,23 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"select * from t2;",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [{"type": "select_all_column"}],
|
|
|
- "table_name": "t2",
|
|
|
+ "table_names": ["t2"],
|
|
|
"where": {},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"select c2 as t from t2 where col1>2;",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
@@ -351,7 +296,7 @@ async def assert_sqls():
|
|
|
"alias": "t",
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "t2",
|
|
|
+ "table_names": ["t2"],
|
|
|
"where": {
|
|
|
"type": "大于",
|
|
|
"left": {"type": "identifier", "value": "col1"},
|
|
@@ -359,19 +304,19 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""SELECT Sname FROM Student WHERE Sno IN (1,2) and c in (3, 4, 5);""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
|
"target": {"type": "identifier", "value": "Sname"},
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "Student",
|
|
|
+ "table_names": ["Student"],
|
|
|
"where": {
|
|
|
"type": "且",
|
|
|
"left": {
|
|
@@ -394,9 +339,8 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
-
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""SELECT Student.Sname
|
|
|
FROM Student
|
|
|
WHERE Sno IN (
|
|
@@ -407,7 +351,7 @@ async def assert_sqls():
|
|
|
""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
@@ -418,19 +362,19 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "Student",
|
|
|
+ "table_names": ["Student"],
|
|
|
"where": {
|
|
|
"type": "包含于",
|
|
|
"left": {"type": "identifier", "value": "Sno"},
|
|
|
"right": {
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
|
"target": {"type": "identifier", "value": "Sno"},
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "SC",
|
|
|
+ "table_names": ["SC"],
|
|
|
"where": {
|
|
|
"type": "相等",
|
|
|
"left": {
|
|
@@ -444,8 +388,8 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""
|
|
|
select Student.Sname
|
|
|
from Student join SC
|
|
@@ -454,7 +398,7 @@ async def assert_sqls():
|
|
|
""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
@@ -465,7 +409,7 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "Student",
|
|
|
+ "table_names": ["Student"],
|
|
|
"join_options": {
|
|
|
"type": "join_options",
|
|
|
"join_with": {"type": "identifier", "value": "SC"},
|
|
@@ -486,8 +430,8 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- )
|
|
|
- await assert_sql(
|
|
|
+ ),
|
|
|
+ (
|
|
|
"""
|
|
|
select Student.Sname
|
|
|
from Student join SC
|
|
@@ -496,7 +440,7 @@ async def assert_sqls():
|
|
|
""",
|
|
|
[
|
|
|
{
|
|
|
- "type": "select",
|
|
|
+ "type": "select_stmt",
|
|
|
"select_cols": [
|
|
|
{
|
|
|
"type": "select_column",
|
|
@@ -507,7 +451,7 @@ async def assert_sqls():
|
|
|
},
|
|
|
}
|
|
|
],
|
|
|
- "table_name": "Student",
|
|
|
+ "table_names": ["Student"],
|
|
|
"join_options": {
|
|
|
"type": "join_options",
|
|
|
"join_with": {"type": "identifier", "value": "SC"},
|
|
@@ -540,46 +484,21 @@ async def assert_sqls():
|
|
|
"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
|
|
|
-
|
|
|
- try:
|
|
|
- await assert_sqls()
|
|
|
- except Exception as e:
|
|
|
- print(e)
|
|
|
- else:
|
|
|
- print(datetime.now(), colored("all tests right!", "green"))
|
|
|
-
|
|
|
-
|
|
|
-async def restart():
|
|
|
- async for _ in awatch(__file__):
|
|
|
- print("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)
|
|
|
-
|
|
|
+ ),
|
|
|
+ ('drop table t1;', [{"type": "drop_stmt", "table_name": "t1"}]),
|
|
|
+]
|
|
|
|
|
|
-async def main():
|
|
|
- try:
|
|
|
- await assert_sqls()
|
|
|
- except Exception as e:
|
|
|
- print(e)
|
|
|
- await asyncio.gather(restart(), watch_src())
|
|
|
+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`'),
|
|
|
|
|
|
-if __name__ == "__main__":
|
|
|
- asyncio.run(main())
|
|
|
+]
|