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::UpdateClause*>* update_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 ($$);
} <str_vec> <table_vec> <column_vec> <update_vec> <expr_vec>
} <str_vec> <table_vec> <column_vec> <update_vec> <expr_vec> <order_vec>
%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> column_name literal int_literal num_literal string_literal
%type <expr> comp_expr opt_where join_condition opt_having
%type <order> opt_order
%type <limit> opt_limit
%type <limit> opt_limit opt_top
%type <order> order_desc
%type <order_type> opt_order_type
%type <column_t> column_def
%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 <expr_vec> expr_list select_list literal_list
%type <table_vec> table_ref_commalist
%type <order_vec> opt_order order_list
%type <update_vec> update_clause_commalist
%type <column_vec> column_def_commalist
@ -502,13 +504,14 @@ set_operator:
;
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();
$$->selectDistinct = $2;
$$->selectList = $3;
$$->fromTable = $4;
$$->whereClause = $5;
$$->groupBy = $6;
$$->limit = $2;
$$->selectDistinct = $3;
$$->selectList = $4;
$$->fromTable = $5;
$$->whereClause = $6;
$$->groupBy = $7;
}
;
@ -521,7 +524,6 @@ select_list:
expr_list
;
from_clause:
FROM table_ref { $$ = $2; }
;
@ -546,16 +548,31 @@ opt_having:
| /* empty */ { $$ = NULL; }
opt_order:
ORDER BY expr opt_order_type { $$ = new OrderDescription($4, $3); }
ORDER BY order_list { $$ = $3; }
| /* 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:
ASC { $$ = kOrderAsc; }
| DESC { $$ = kOrderDesc; }
| /* 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:
LIMIT int_literal { $$ = new LimitDescription($2->ival, kNoOffset); delete $2; }

View File

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

View File

@ -139,8 +139,8 @@ namespace hsql {
if (stmt->order != NULL) {
inprint("OrderBy:", numIndent + 1);
printExpression(stmt->order->expr, numIndent + 2);
if (stmt->order->type == kOrderAsc) inprint("ascending", numIndent + 2);
printExpression(stmt->order->at(0)->expr, numIndent + 2);
if (stmt->order->at(0)->type == kOrderAsc) inprint("ascending", 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 (SELECT * FROM t1);
SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
# 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 * FROM t1 JOIN t2 ON c1 = c2;