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 <uval> import_file_type opt_join_type column_type
%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> function_expr between_expr star_expr expr_alias placeholder_expr
%type <expr> column_name literal int_literal num_literal string_literal
@ -229,7 +229,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
%left '[' ']'
%left '(' ')'
%left '.'
%left JOIN
%%
/*********************************
** Section 3: Grammar Definition
@ -817,7 +817,7 @@ opt_alias:
******************************/
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);
$$->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:
expr
;

View File

@ -205,3 +205,45 @@ TEST(SelectCaseWhen) {
ASSERT(caseExpr->expr->isSimpleOp('='));
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 a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1;
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
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;