Add capability for multi join table references (#40)
This commit is contained in:
parent
0909c6a89a
commit
793258f872
File diff suppressed because it is too large
Load Diff
|
@ -188,7 +188,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
||||||
%type <bval> opt_not_exists opt_distinct
|
%type <bval> opt_not_exists opt_distinct
|
||||||
%type <uval> import_file_type opt_join_type column_type
|
%type <uval> import_file_type opt_join_type column_type
|
||||||
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
%type <table> from_clause table_ref table_ref_atomic table_ref_name
|
||||||
%type <table> join_clause join_table table_ref_name_no_alias
|
%type <table> join_clause table_ref_name_no_alias
|
||||||
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr
|
%type <expr> expr operand scalar_expr unary_expr binary_expr logic_expr exists_expr
|
||||||
%type <expr> function_expr between_expr star_expr expr_alias placeholder_expr
|
%type <expr> function_expr between_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
|
||||||
|
@ -225,11 +225,11 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
||||||
%left '^'
|
%left '^'
|
||||||
|
|
||||||
/* Unary Operators */
|
/* Unary Operators */
|
||||||
%right UMINUS
|
%right UMINUS
|
||||||
%left '[' ']'
|
%left '[' ']'
|
||||||
%left '(' ')'
|
%left '(' ')'
|
||||||
%left '.'
|
%left '.'
|
||||||
|
%left JOIN
|
||||||
%%
|
%%
|
||||||
/*********************************
|
/*********************************
|
||||||
** Section 3: Grammar Definition
|
** Section 3: Grammar Definition
|
||||||
|
@ -817,7 +817,7 @@ opt_alias:
|
||||||
******************************/
|
******************************/
|
||||||
|
|
||||||
join_clause:
|
join_clause:
|
||||||
join_table opt_join_type JOIN join_table ON join_condition
|
table_ref_atomic opt_join_type JOIN table_ref_atomic ON join_condition
|
||||||
{
|
{
|
||||||
$$ = new TableRef(kTableJoin);
|
$$ = new TableRef(kTableJoin);
|
||||||
$$->join = new JoinDefinition();
|
$$->join = new JoinDefinition();
|
||||||
|
@ -841,17 +841,6 @@ opt_join_type:
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
join_table:
|
|
||||||
'(' select_statement ')' alias {
|
|
||||||
auto tbl = new TableRef(kTableSelect);
|
|
||||||
tbl->select = $2;
|
|
||||||
tbl->alias = $4;
|
|
||||||
$$ = tbl;
|
|
||||||
}
|
|
||||||
| table_ref_name;
|
|
||||||
|
|
||||||
|
|
||||||
join_condition:
|
join_condition:
|
||||||
expr
|
expr
|
||||||
;
|
;
|
||||||
|
|
|
@ -205,3 +205,45 @@ TEST(SelectCaseWhen) {
|
||||||
ASSERT(caseExpr->expr->isSimpleOp('='));
|
ASSERT(caseExpr->expr->isSimpleOp('='));
|
||||||
ASSERT_EQ(caseExpr->exprList->size(), 2);
|
ASSERT_EQ(caseExpr->exprList->size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SelectJoin) {
|
||||||
|
TEST_PARSE_SINGLE_SQL(
|
||||||
|
"SELECT City.name, Product.category, SUM(price) FROM fact\
|
||||||
|
INNER JOIN City ON fact.city_id = City.id\
|
||||||
|
OUTER JOIN Product ON fact.product_id = Product.id\
|
||||||
|
GROUP BY City.name, Product.category;",
|
||||||
|
kStmtSelect,
|
||||||
|
SelectStatement,
|
||||||
|
result,
|
||||||
|
stmt);
|
||||||
|
|
||||||
|
const TableRef* table = stmt->fromTable;
|
||||||
|
const JoinDefinition* outer_join = table->join;
|
||||||
|
ASSERT_EQ(table->type, kTableJoin);
|
||||||
|
ASSERT_EQ(outer_join->type, kJoinOuter);
|
||||||
|
|
||||||
|
ASSERT_EQ(outer_join->right->type, kTableName);
|
||||||
|
ASSERT_STREQ(outer_join->right->name, "Product");
|
||||||
|
ASSERT(outer_join->condition->isSimpleOp('='));
|
||||||
|
ASSERT_STREQ(outer_join->condition->expr->table, "fact");
|
||||||
|
ASSERT_STREQ(outer_join->condition->expr->name, "product_id");
|
||||||
|
ASSERT_STREQ(outer_join->condition->expr2->table, "Product");
|
||||||
|
ASSERT_STREQ(outer_join->condition->expr2->name, "id");
|
||||||
|
|
||||||
|
// Joins are are left associative.
|
||||||
|
// So the second join should be on the left.
|
||||||
|
ASSERT_EQ(outer_join->left->type, kTableJoin);
|
||||||
|
|
||||||
|
const JoinDefinition* inner_join = outer_join->left->join;
|
||||||
|
ASSERT_EQ(inner_join->type, kJoinInner);
|
||||||
|
ASSERT_EQ(inner_join->left->type, kTableName);
|
||||||
|
ASSERT_STREQ(inner_join->left->name, "fact");
|
||||||
|
ASSERT_EQ(inner_join->right->type, kTableName);
|
||||||
|
ASSERT_STREQ(inner_join->right->name, "City");
|
||||||
|
|
||||||
|
ASSERT(inner_join->condition->isSimpleOp('='));
|
||||||
|
ASSERT_STREQ(inner_join->condition->expr->table, "fact");
|
||||||
|
ASSERT_STREQ(inner_join->condition->expr->name, "city_id");
|
||||||
|
ASSERT_STREQ(inner_join->condition->expr2->table, "City");
|
||||||
|
ASSERT_STREQ(inner_join->condition->expr2->name, "id");
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1;
|
||||||
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
|
SELECT TOP 10 * FROM t1 ORDER BY col1, col2;
|
||||||
SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1;
|
SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1;
|
||||||
SELECT * FROM t WHERE a BETWEEN 1 and c;
|
SELECT * FROM t WHERE a BETWEEN 1 and c;
|
||||||
|
SELECT City.name, Product.category, SUM(price) FROM fact INNER JOIN City ON fact.city_id = City.id INNER JOIN Product ON fact.product_id = Product.id GROUP BY City.name, Product.category;
|
||||||
# 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;
|
||||||
|
|
Loading…
Reference in New Issue