Add capability for multi join table references (#40)

This commit is contained in:
Pedro Flemming 2017-04-21 22:03:12 +02:00 committed by GitHub
parent 0909c6a89a
commit 793258f872
4 changed files with 444 additions and 432 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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
; ;

View File

@ -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");
}

View File

@ -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;