Selaa lähdekoodia

恢复到不带not的where

myuan 2 vuotta sitten
vanhempi
commit
3634b05163
3 muutettua tiedostoa jossa 223 lisäystä ja 45 poistoa
  1. 77 8
      run_test.py
  2. 4 0
      src/calc.l
  3. 142 37
      src/calc.y

+ 77 - 8
run_test.py

@@ -24,7 +24,7 @@ async def assert_sql(sql, target):
     )
     stdout, stderr = await p.communicate()
     if stderr:
-        print(colored(stderr, "yellow"))
+        print(colored(stderr.decode("utf-8"), "yellow"))
     if b"error" in stdout:
         print(stdout.decode("utf-8"))
         print(datetime.now(), "-" * 40)
@@ -167,8 +167,9 @@ async def assert_sqls():
             }
         ],
     )
+
     await assert_sql(
-        "update tb1 set col1=3, col4=4 where not col1=2 and col2=3;",
+        "update tb1 set col1=3, col4=4 where col1=2 and col2=4;",
         [
             {
                 "type": "update",
@@ -188,18 +189,38 @@ async def assert_sqls():
                 "where": {
                     "type": "且",
                     "left": {
-                        "type": "非",
-                        "right": {
-                            "type": "相等",
-                            "left": {"type": "identifier", "value": "col1"},
-                            "right": {"type": "int", "value": 2},
-                        },
+                        "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 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": {
                 },
             }
         ],
@@ -304,6 +325,54 @@ async def assert_sqls():
             }
         ],
     )
+    await assert_sql(
+        """SELECT Sname
+            FROM Student
+            WHERE Sno IN (1,2,3) and 2 not in (3, 4, 5) or not 3 in (1, 2);""",
+        [
+            {
+                "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},
+                            {"type": "int", "value": 3},
+                        ],
+                    },
+                    "right": {
+                        "type": "不包含于",
+                        "left": {"type": "int", "value": 2},
+                        "right": [
+                            {"type": "int", "value": 3},
+                            {"type": "int", "value": 4},
+                            {"type": "int", "value": 5},
+                        ],
+                    },
+                },
+            }
+        ],
+    )
+    await assert_sql(
+        """SELECT Sname
+FROM Student
+WHERE Sno IN (
+    SELECT Sno
+    FROM SC 
+    WHERE Cno='81003'
+);""",
+        [],
+    )
 
 
 async def on_modified(event):

+ 4 - 0
src/calc.l

@@ -43,11 +43,15 @@ extern YYSTYPE yylval;
 "OR"        return OR;
 "NOT"       return NOT;
 "AS"        return AS;
+"IN"        return IN;
+"ON"        return ON;
 
 ;		    {return NEWLINE;}
 
 [*]			return *yytext;
 [,]			return *yytext;
+[.]         return *yytext;
+
 [=]			{cp_yylval_and_return('=');}
 [<]			{cp_yylval_and_return('<');}
 [>]			{cp_yylval_and_return('>');}

+ 142 - 37
src/calc.y

@@ -4,6 +4,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <cjson/cJSON.h>
+#include <signal.h>
 
 
 extern int yylex();
@@ -17,6 +18,29 @@ void yyerror(const char* s);
 
 char* catstr(char* s1, char* s2);
 cJSON* jroot;
+
+
+
+#define SIMPLE_OP_NODE(res, type, left, right) \
+	fprintf(stderr, "SIMPLE_OP_NODE type: %s %s %s\n", (type), cJSON_Print(left), cJSON_Print(right)); \
+	cJSON* node = cJSON_CreateObject(); \
+	cJSON_AddStringToObject(node, "type", type); \
+	cJSON_AddItemToObject(node, "left", left); \
+	cJSON_AddItemToObject(node, "right", right); \
+	res = node;
+
+#define SIMPLE_OP_NODE_ONLY_LEFT(res, type, left) \
+	fprintf(stderr, "SIMPLE_OP_NODE_ONLY_LEFT type: %s %s %s\n", (type), cJSON_Print(left)); \
+	cJSON* node = cJSON_CreateObject(); \
+	cJSON_AddStringToObject(node, "type", type); \
+	cJSON_AddItemToObject(node, "left", left); \
+	res = node;
+
+#define SIMPLE_TYPE_VALUE_OBJECT(res, type_name, json_type_name, value) \
+	cJSON* node = cJSON_CreateObject(); \
+	cJSON_AddStringToObject(node, "type", #type_name); \
+	cJSON_Add##json_type_name##ToObject(node, "value", value); \
+	res = node;
 %}
 
 %union {
@@ -30,8 +54,8 @@ cJSON* jroot;
 %token IDENTIFIER 
 
 %token SELECT FROM WHERE INSERT INTO VALUES DELETE UPDATE SET JOIN CREATE TABLE 
-%token AS
-%token AND OR NOT
+%token AS ON
+%token AND OR NOT IN
 %token INT_V FLOAT_V STRING_V // 作为 value 出现的
 %token INT_T FLOAT_T STRING_T // 作为 字面量 type 出现的情况
 
@@ -42,13 +66,23 @@ cJSON* jroot;
 
 %type <iv> INT_V
 %type <fv> FLOAT_V
-%type <sv> STRING_V
-%type <sv> IDENTIFIER data_type PRIMARY_KEY col_options bin_compare_op bin_logical_op unary_compare_op
+%type <sv> STRING_V NOT
+%type <sv> IDENTIFIER data_type PRIMARY_KEY col_options bin_cmp_op bin_logical_op unary_compare_op bin_contains_op
 %type <jv> create_definition create_col_list create_table_stmt data_value
 %type <jv> insert_stmt insert_list 
 %type <jv> update_stmt update_list single_assign_item
-%type <jv> where_condition_item where_conditions identifier identifier_or_const_value the_whole_where_smt
+%type <jv> where_condition_item where_conditions identifier identifier_or_const_value the_whole_where_smt 
 %type <jv> delete_stmt select_stmt select_item select_items 
+%type <jv> data_value_list identifier_or_const_value_or_const_value_list
+%type <jv> search_expr compare_expr single_expr expr where_expr logical_expr negative_expr
+
+
+// %left OR
+// %left AND
+// %right NOT
+// %nonassoc '=' '>' '<'
+// %left '+' '-'
+// %left '*' '/'
 
 %start statement
 
@@ -102,7 +136,7 @@ create_col_list: create_definition {
     ;
 
 create_definition: IDENTIFIER data_type col_options {
-		sprintf(stderr, "得列 %s %s with options %s: %d\n", $1, $2, $3, strlen($3));
+		// fprintf(stderr, "得列 %s %s with options %s: %d\n", $1, $2, $3, strlen($3));
 
 		cJSON* node = cJSON_CreateObject();
 		cJSON_AddStringToObject(node, "type", "create_column");
@@ -151,27 +185,12 @@ insert_list: data_value {
 		// printf("迭代\n %s", cJSON_Print($$));
 	}
 ;
-data_value: INT_V {
-		cJSON* node = cJSON_CreateObject();
-		cJSON_AddStringToObject(node, "type", "int");
-		cJSON_AddNumberToObject(node, "value", $1);
-		$$=node;
-	}
-	| FLOAT_V {
-		cJSON* node = cJSON_CreateObject();
-		cJSON_AddStringToObject(node, "type", "float");
-		cJSON_AddNumberToObject(node, "value", $1);
-		$$=node;
-	}
-	| STRING_V {
-		cJSON* node = cJSON_CreateObject();
-		cJSON_AddStringToObject(node, "type", "string");
-		cJSON_AddStringToObject(node, "value", $1);
-		$$=node;
-	}
+data_value: INT_V {SIMPLE_TYPE_VALUE_OBJECT($$, int, Number, $1);}
+	| FLOAT_V {SIMPLE_TYPE_VALUE_OBJECT($$, float, Number, $1);}
+	| STRING_V {SIMPLE_TYPE_VALUE_OBJECT($$, string, String, $1);}
 ;
 
-update_stmt: UPDATE IDENTIFIER SET update_list WHERE where_conditions NEWLINE {
+update_stmt: UPDATE IDENTIFIER SET update_list WHERE where_expr NEWLINE {
 		cJSON* node = cJSON_CreateObject();
 		cJSON_AddStringToObject(node, "type", "update");
 		cJSON_AddStringToObject(node, "table_name", $2);
@@ -201,7 +220,68 @@ single_assign_item: identifier '=' identifier_or_const_value {
 ;
 
 the_whole_where_smt: {$$=cJSON_CreateObject();}
-	| WHERE where_conditions {$$=$2;};
+	| WHERE where_expr {$$=$2;}
+;
+
+// where 后的条件跟 select 中的有本质区别
+// select 中的只是常量或者字段名, 而 where 中的是表达式
+
+single_expr: identifier {$$=$1;}
+	| IDENTIFIER '.' IDENTIFIER {
+		cJSON* node = cJSON_CreateObject();
+		cJSON_AddStringToObject(node, "type", "table_field");
+		cJSON_AddStringToObject(node, "table", $1);
+		cJSON_AddStringToObject(node, "field", $3);
+		$$=node;
+	}
+	| data_value {$$=$1;}
+	| '(' single_expr ')' {$$=$2;}
+;
+where_expr: logical_expr {$$=$1;};
+;
+
+compare_expr: compare_expr bin_cmp_op compare_expr {SIMPLE_OP_NODE($$, $2, $1, $3);}
+	| single_expr {$$=$1;}
+
+;
+negative_expr: NOT negative_expr {SIMPLE_OP_NODE_ONLY_LEFT($$, "非", $2);}
+	| compare_expr {$$=$1;}
+;
+logical_expr: negative_expr bin_logical_op negative_expr {SIMPLE_OP_NODE($$, $2, $1, $3);}
+	| single_expr {$$=$1;}
+;
+
+// expr: compare_expr 
+// 	| negative_expr
+// 	| logical_expr
+// ;
+
+// compare_expr: expr bin_cmp_op single_expr
+
+// expr: expr bin_cmp_op expr {SIMPLE_OP_NODE($$, $2, $1, $3)}
+// 	| expr bin_cmp_op '(' expr ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
+// 	// | '(' expr ')' {$$=$2;}
+// 	// | NOT expr {SIMPLE_OP_NODE_ONLY_LEFT($$, "非", $2); 
+// 	// 	fprintf(stderr, "非asd %s\n", cJSON_Print($2));
+// 	// }
+// ;
+// // expr: expr bin_logical_op expr {SIMPLE_OP_NODE($$, $2, $1, $3)}
+
+
+// expr_list: expr{
+// 		cJSON* node = cJSON_CreateArray();
+// 		cJSON_AddItemToArray(node, $1);
+// 		$$=node;
+// 	}
+// 	| expr_list ',' expr {
+// 		fprintf(stderr, "迭代 expr_list\n %s", cJSON_Print($1));
+// 		cJSON_AddItemToArray($1, $3);
+// 		$$=$1;
+// 	}
+
+// expr: expr bin_contains_op '(' expr_list ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
+// 	| expr bin_contains_op '(' select_stmt ')' {SIMPLE_OP_NODE($$, $2, $1, $4)}
+
 
 where_conditions: where_condition_item {
 		$$=$1;
@@ -218,6 +298,12 @@ where_conditions: where_condition_item {
 		cJSON_AddItemToObject(node, "right", $3);
 		$$=node;
 	}
+	| unary_compare_op where_condition_item {
+		cJSON* node = cJSON_CreateObject();
+		cJSON_AddStringToObject(node, "type", $1);
+		cJSON_AddItemToObject(node, "right", $2);
+		$$=node;
+	}
 	|  where_conditions bin_logical_op '(' where_conditions ')' {
 		cJSON* node = cJSON_CreateObject();
 		cJSON_AddStringToObject(node, "type", $2);
@@ -226,13 +312,7 @@ where_conditions: where_condition_item {
 		cJSON_AddItemToObject(node, "right", $4);
 		$$=node;
 	}
-	| unary_compare_op where_condition_item {
-		cJSON* node = cJSON_CreateObject();
-		cJSON_AddStringToObject(node, "type", $1);
-		cJSON_AddItemToObject(node, "right", $2);
-		$$=node;
-	}
-	
+
 ;
 
 identifier: IDENTIFIER {
@@ -243,22 +323,44 @@ identifier: IDENTIFIER {
 	}
 identifier_or_const_value: identifier {$$=$1;}
 	| data_value {$$=$1;}
+;
+data_value_list: data_value {
+		cJSON* node = cJSON_CreateArray();
+		cJSON_AddItemToArray(node, $1);
+		$$=node;
+	}
+	| data_value_list ',' data_value {
+		cJSON_AddItemToArray($1, $3);
+		$$=$1;
+	}
+;
+identifier_or_const_value_or_const_value_list: identifier_or_const_value{$$=$1;}
+	| data_value_list {$$=$1;}
 
-where_condition_item: identifier_or_const_value bin_compare_op identifier_or_const_value {
+where_condition_item: identifier_or_const_value bin_cmp_op identifier_or_const_value {
 		cJSON* node = cJSON_CreateObject();
 		cJSON_AddStringToObject(node, "type", $2);
 		cJSON_AddItemToObject(node, "left", $1);
 		cJSON_AddItemToObject(node, "right", $3);
 		$$=node;
-	};
+	}
+	| identifier_or_const_value bin_contains_op '(' data_value_list ')' {
+		cJSON* node = cJSON_CreateObject();
+		cJSON_AddStringToObject(node, "type", $2);
+		cJSON_AddItemToObject(node, "left", $1);
+		cJSON_AddItemToObject(node, "right", $4);
+		$$=node;
+	}
+;
 
 
-bin_compare_op: '=' {$$ = "相等";}
+bin_cmp_op: '=' {$$ = "相等";}
 	| '>' {$$ = "大于";}
 	| '<' {$$ = "小于";}
 	| ">=" {$$ = "大等";}
 	| "<=" {$$ = "小等";}
 	| "!=" {$$ = "不等";}
+	| IN {$$ = "包含于";}
 ;
 
 unary_compare_op: NOT {$$ = "非";};
@@ -266,6 +368,9 @@ unary_compare_op: NOT {$$ = "非";};
 bin_logical_op: AND {$$ = "且";}
 	| OR {$$ = "或";}
 
+bin_contains_op: IN {$$ = "包含于";}
+	| NOT IN {$$ = "不包含于";}
+
 delete_stmt: DELETE FROM IDENTIFIER the_whole_where_smt NEWLINE {
 		cJSON* node = cJSON_CreateObject();
 		cJSON_AddStringToObject(node, "type", "delete");
@@ -331,7 +436,7 @@ int main(int ac, char** av) {
 }
 
 void yyerror(const char *s) {
-	printf("error: %s at %s\n", s, yytext);
+	fprintf(stderr, "error: %s at %s\n", s, yytext);
 	exit(1);
 }