diff --git a/src/lib/Expr.cpp b/src/lib/Expr.cpp index 6407d24..c919ec4 100644 --- a/src/lib/Expr.cpp +++ b/src/lib/Expr.cpp @@ -78,10 +78,11 @@ Expr* Expr::makeColumnRef(char* table, char* name) { return e; } -Expr* Expr::makeFunctionRef(char* func_name, Expr* expr) { +Expr* Expr::makeFunctionRef(char* func_name, Expr* expr, bool distinct) { Expr* e = new Expr(kExprFunctionRef); e->name = func_name; e->expr = expr; + e->distinct = distinct; return e; } diff --git a/src/lib/Expr.h b/src/lib/Expr.h index 709521b..4588c80 100644 --- a/src/lib/Expr.h +++ b/src/lib/Expr.h @@ -22,6 +22,7 @@ typedef enum { kExprOperator } ExprType; + typedef struct Expr Expr; /** @@ -79,6 +80,7 @@ struct Expr { OperatorType op_type; char op_char; + bool distinct; /** @@ -109,7 +111,7 @@ struct Expr { static Expr* makeColumnRef(char* name); static Expr* makeColumnRef(char* table, char* name); - static Expr* makeFunctionRef(char* func_name, Expr* expr); + static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct); }; // Zero initializes an Expr object and assigns it to a space in the heap diff --git a/src/lib/statements/SelectStatement.h b/src/lib/statements/SelectStatement.h index 008618d..a9788a6 100644 --- a/src/lib/statements/SelectStatement.h +++ b/src/lib/statements/SelectStatement.h @@ -93,6 +93,7 @@ struct SelectStatement : SQLStatement { } TableRef* from_table; + bool select_distinct; List* select_list; Expr* where_clause; GroupByDescription* group_by; diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index ffb58f7..874c4d6 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -171,7 +171,7 @@ int yyerror(YYLTYPE* llocp, SQLStatementList** result, yyscan_t scanner, const c %type update_statement %type drop_statement %type table_name opt_alias alias file_path -%type opt_not_exists +%type opt_not_exists opt_distinct %type import_file_type opt_join_type column_type %type from_clause table_ref table_ref_atomic table_ref_name %type
join_clause join_table table_ref_name_no_alias @@ -455,15 +455,20 @@ set_operator: ; select_clause: - SELECT select_list from_clause opt_where opt_group { + SELECT opt_distinct select_list from_clause opt_where opt_group { $$ = new SelectStatement(); - $$->select_list = $2; - $$->from_table = $3; - $$->where_clause = $4; - $$->group_by = $5; + $$->select_distinct = $2; + $$->select_list = $3; + $$->from_table = $4; + $$->where_clause = $5; + $$->group_by = $6; } ; +opt_distinct: + DISTINCT { $$ = true; } + | /* empty */ { $$ = false; } + ; select_list: expr_list @@ -576,7 +581,7 @@ comp_expr: ; function_expr: - IDENTIFIER '(' expr ')' { $$ = Expr::makeFunctionRef($1, $3); } + IDENTIFIER '(' opt_distinct expr ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } ; column_name: diff --git a/src/tests/select.cpp b/src/tests/select.cpp index 74a71bb..e30f5c8 100644 --- a/src/tests/select.cpp +++ b/src/tests/select.cpp @@ -16,6 +16,7 @@ TEST(SelectTest) { TEST(SelectHavingTest) { TEST_PARSE_SINGLE_SQL("SELECT city, AVG(grade) AS avg_grade FROM students GROUP BY city HAVING AVG(grade) < 2.0", kStmtSelect, SelectStatement, stmt); + ASSERT_FALSE(stmt->select_distinct); GroupByDescription* group = stmt->group_by; ASSERT_NOTNULL(group); @@ -28,12 +29,18 @@ TEST(SelectHavingTest) { TEST(SelectDistinctTest) { TEST_PARSE_SINGLE_SQL("SELECT DISTINCT grade, city FROM students;", kStmtSelect, SelectStatement, stmt); + + ASSERT(stmt->select_distinct); ASSERT_NULL(stmt->where_clause); } TEST(SelectGroupDistinctTest) { - TEST_PARSE_SINGLE_SQL("SELECT city, COUNT(DISTINCT name), SUM(DISTINCT grade) FROM students GROUP BY city;", kStmtSelect, SelectStatement, stmt); - ASSERT_NULL(stmt->where_clause); + TEST_PARSE_SINGLE_SQL("SELECT city, COUNT(name), COUNT(DISTINCT grade) FROM students GROUP BY city;", kStmtSelect, SelectStatement, stmt); + + ASSERT_FALSE(stmt->select_distinct); + ASSERT_EQ(stmt->select_list->size(), 3); + ASSERT(!stmt->select_list->at(1)->distinct); + ASSERT(stmt->select_list->at(2)->distinct); }