Allow order by to define a list of expressions to order by

This commit is contained in:
Pedro 2017-03-07 02:30:44 +01:00
parent 36adab70c5
commit f82504b319
5 changed files with 52 additions and 14 deletions

View File

@ -131,6 +131,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
std::vector<hsql::ColumnDefinition*>* column_vec; std::vector<hsql::ColumnDefinition*>* column_vec;
std::vector<hsql::UpdateClause*>* update_vec; std::vector<hsql::UpdateClause*>* update_vec;
std::vector<hsql::Expr*>* expr_vec; std::vector<hsql::Expr*>* expr_vec;
std::vector<hsql::OrderDescription*>* order_vec;
} }
@ -146,7 +147,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
} }
} }
delete ($$); delete ($$);
} <str_vec> <table_vec> <column_vec> <update_vec> <expr_vec> } <str_vec> <table_vec> <column_vec> <update_vec> <expr_vec> <order_vec>
%destructor { delete ($$); } <*> %destructor { delete ($$); } <*>
@ -197,8 +198,8 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
%type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias placeholder_expr %type <expr> expr scalar_expr unary_expr binary_expr function_expr star_expr expr_alias placeholder_expr
%type <expr> column_name literal int_literal num_literal string_literal %type <expr> column_name literal int_literal num_literal string_literal
%type <expr> comp_expr opt_where join_condition opt_having %type <expr> comp_expr opt_where join_condition opt_having
%type <order> opt_order %type <limit> opt_limit opt_top
%type <limit> opt_limit %type <order> order_desc
%type <order_type> opt_order_type %type <order_type> opt_order_type
%type <column_t> column_def %type <column_t> column_def
%type <update_t> update_clause %type <update_t> update_clause
@ -207,6 +208,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult** result, yyscan_t scanner, const ch
%type <str_vec> ident_commalist opt_column_list %type <str_vec> ident_commalist opt_column_list
%type <expr_vec> expr_list select_list literal_list %type <expr_vec> expr_list select_list literal_list
%type <table_vec> table_ref_commalist %type <table_vec> table_ref_commalist
%type <order_vec> opt_order order_list
%type <update_vec> update_clause_commalist %type <update_vec> update_clause_commalist
%type <column_vec> column_def_commalist %type <column_vec> column_def_commalist
@ -502,13 +504,14 @@ set_operator:
; ;
select_clause: select_clause:
SELECT opt_distinct select_list from_clause opt_where opt_group { SELECT opt_top opt_distinct select_list from_clause opt_where opt_group {
$$ = new SelectStatement(); $$ = new SelectStatement();
$$->selectDistinct = $2; $$->limit = $2;
$$->selectList = $3; $$->selectDistinct = $3;
$$->fromTable = $4; $$->selectList = $4;
$$->whereClause = $5; $$->fromTable = $5;
$$->groupBy = $6; $$->whereClause = $6;
$$->groupBy = $7;
} }
; ;
@ -521,7 +524,6 @@ select_list:
expr_list expr_list
; ;
from_clause: from_clause:
FROM table_ref { $$ = $2; } FROM table_ref { $$ = $2; }
; ;
@ -546,16 +548,31 @@ opt_having:
| /* empty */ { $$ = NULL; } | /* empty */ { $$ = NULL; }
opt_order: opt_order:
ORDER BY expr opt_order_type { $$ = new OrderDescription($4, $3); } ORDER BY order_list { $$ = $3; }
| /* empty */ { $$ = NULL; } | /* empty */ { $$ = NULL; }
; ;
order_list:
order_desc { $$ = new std::vector<OrderDescription*>(); $$->push_back($1); }
| order_list ',' order_desc { $1->push_back($3); $$ = $1; }
;
order_desc:
expr opt_order_type { $$ = new OrderDescription($2, $1); }
;
opt_order_type: opt_order_type:
ASC { $$ = kOrderAsc; } ASC { $$ = kOrderAsc; }
| DESC { $$ = kOrderDesc; } | DESC { $$ = kOrderDesc; }
| /* empty */ { $$ = kOrderAsc; } | /* empty */ { $$ = kOrderAsc; }
; ;
// TODO: TOP and LIMIT can take more than just int literals.
opt_top:
TOP int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }
| /* empty */ { $$ = NULL; }
;
opt_limit: opt_limit:
LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; } LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }

View File

@ -63,7 +63,7 @@ namespace hsql {
GroupByDescription* groupBy; GroupByDescription* groupBy;
SelectStatement* unionSelect; SelectStatement* unionSelect;
OrderDescription* order; std::vector<OrderDescription*>* order;
LimitDescription* limit; LimitDescription* limit;
}; };

View File

@ -139,8 +139,8 @@ namespace hsql {
if (stmt->order != NULL) { if (stmt->order != NULL) {
inprint("OrderBy:", numIndent + 1); inprint("OrderBy:", numIndent + 1);
printExpression(stmt->order->expr, numIndent + 2); printExpression(stmt->order->at(0)->expr, numIndent + 2);
if (stmt->order->type == kOrderAsc) inprint("ascending", numIndent + 2); if (stmt->order->at(0)->type == kOrderAsc) inprint("ascending", numIndent + 2);
else inprint("descending", numIndent + 2); else inprint("descending", numIndent + 2);
} }

View File

@ -73,3 +73,23 @@ TEST(SelectGroupDistinctTest) {
} }
TEST(OrderByTest) {
TEST_PARSE_SINGLE_SQL(
"SELECT grade, city FROM students ORDER BY grade, city DESC;",
kStmtSelect,
SelectStatement,
result,
stmt);
ASSERT_NULL(stmt->whereClause);
ASSERT_NOTNULL(stmt->order);
ASSERT_EQ(stmt->order->size(), 2);
ASSERT_EQ(stmt->order->at(0)->type, kOrderAsc);
ASSERT_STREQ(stmt->order->at(0)->expr->name, "grade");
ASSERT_EQ(stmt->order->at(1)->type, kOrderDesc);
ASSERT_STREQ(stmt->order->at(1)->expr->name, "city");
delete result;
}

View File

@ -8,6 +8,7 @@ SELECT * FROM "table" LIMIT 10 OFFSET 10; SELECT * FROM second;
SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1; SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1;
SELECT * FROM (SELECT * FROM t1); SELECT * FROM (SELECT * FROM t1);
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
# JOIN # JOIN
SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5 SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5
SELECT * FROM t1 JOIN t2 ON c1 = c2; SELECT * FROM t1 JOIN t2 ON c1 = c2;