Skip to content

Commit

Permalink
Merge pull request #9 from jingchen2222/feat/support_last_join
Browse files Browse the repository at this point in the history
feat: support last join
  • Loading branch information
jingchen2222 authored May 25, 2021
2 parents c8f1d46 + e94b6db commit 739652f
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 23 deletions.
41 changes: 36 additions & 5 deletions zetasql/parser/bison_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ using zetasql::ASTDropStatement;
%token KW_INTO "INTO"
%token KW_IS "IS"
%token KW_JOIN "JOIN"
%token KW_LAST "LAST"
%token KW_LEFT "LEFT"
%token KW_LIKE "LIKE"
%token KW_LIMIT "LIMIT"
Expand Down Expand Up @@ -842,7 +843,6 @@ using zetasql::ASTDropStatement;
%token KW_JSON "JSON"
%token KW_KEY "KEY"
%token KW_LANGUAGE "LANGUAGE"
%token KW_LAST "LAST"
%token KW_LEAVE "LEAVE"
%token KW_LEVEL "LEVEL"
%token KW_LOOP "LOOP"
Expand Down Expand Up @@ -4657,7 +4657,20 @@ join:
zetasql::parser::ErrorInfo error_info;
auto node = zetasql::parser::JoinRuleAction(
FirstNonEmptyLocation({@2, @3, @4, @5}), @$,
$1, $2, $3, $4, $6, $7, $8, parser, &error_info);
$1, $2, $3, $4, $6, $7, nullptr, $8, parser, &error_info);
if (node == nullptr) {
YYERROR_AND_ABORT_AT(error_info.location, error_info.message);
}

$$ = node;
}
| join_input opt_natural "LAST" join_hint "JOIN" opt_hint table_primary
opt_order_by_clause opt_on_or_using_clause_list
{
zetasql::parser::ErrorInfo error_info;
auto node = zetasql::parser::JoinRuleAction(
FirstNonEmptyLocation({@2, @3, @4, @5}), @$,
$1, $2, zetasql::ASTJoin::LAST, $4, $6, $7, $8, $9, parser, &error_info);
if (node == nullptr) {
YYERROR_AND_ABORT_AT(error_info.location, error_info.message);
}
Expand Down Expand Up @@ -4715,15 +4728,33 @@ from_clause_contents:
zetasql::parser::ErrorInfo error_info;
auto node = zetasql::parser::JoinRuleAction(
FirstNonEmptyLocation({@2, @3, @4, @5}), @$,
$1, $2, $3, $4, $6, $7, $8,
$1, $2, $3, $4, $6, $7, nullptr, $8,
parser, &error_info);
if (node == nullptr) {
YYERROR_AND_ABORT_AT(error_info.location, error_info.message);
}

$$ = node;
}
| "@"
| from_clause_contents opt_natural "LAST" join_hint "JOIN" opt_hint
table_primary opt_order_by_clause on_or_using_clause_list
{
// Give an error if we have a RIGHT or FULL JOIN following a comma
// join since our left-to-right binding would violate the standard.
// See (broken link).
zetasql::parser::ErrorInfo error_info;
auto node = zetasql::parser::JoinRuleAction(
FirstNonEmptyLocation({@2, @3, @4, @5}), @$,
$1, $2, zetasql::ASTJoin::LAST, $4, $6, $7, $8, $9,
parser, &error_info);
if (node == nullptr) {
YYERROR_AND_ABORT_AT(error_info.location, error_info.message);
}

$$ = node;
}
|
"@"
{
YYERROR_AND_ABORT_AT(
@1, "Query parameters cannot be used in place of table names");
Expand Down Expand Up @@ -7036,6 +7067,7 @@ reserved_keyword_rule:
| "INTO"
| "IS"
| "JOIN"
| "LAST"
| "LEFT"
| "LIKE"
| "LIMIT"
Expand Down Expand Up @@ -7171,7 +7203,6 @@ keyword_as_identifier:
| "JSON"
| "KEY"
| "LANGUAGE"
| "LAST"
| "LEAVE"
| "LEVEL"
| "LOOP"
Expand Down
7 changes: 4 additions & 3 deletions zetasql/parser/join_proccessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ ASTNode* JoinRuleAction(
const zetasql_bison_parser::location& start_location,
const zetasql_bison_parser::location& end_location, ASTNode* lhs,
bool natural, ASTJoin::JoinType join_type, ASTJoin::JoinHint join_hint,
ASTNode* hint, ASTNode* table_primary, ASTNode* on_or_using_clause_list,
ASTNode* hint, ASTNode* table_primary, ASTNode* order_by,
ASTNode* on_or_using_clause_list,
BisonParser* parser,
ErrorInfo* error_info) {
auto clause_list =
Expand Down Expand Up @@ -440,11 +441,11 @@ ASTNode* JoinRuleAction(
}
join = parser->CreateASTNode<ASTJoin>(
start_location, end_location,
{lhs, hint, table_primary, on_or_using_clause});
{lhs, hint, table_primary, order_by, on_or_using_clause});
join->set_transformation_needed(IsTransformationNeeded(lhs));
} else {
join = parser->CreateASTNode<ASTJoin>(
start_location, end_location, {lhs, hint, table_primary, clause_list});
start_location, end_location, {lhs, hint, table_primary, order_by, clause_list});
join->set_transformation_needed(true);
}

Expand Down
1 change: 1 addition & 0 deletions zetasql/parser/join_proccessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ ASTNode* JoinRuleAction(
const zetasql_bison_parser::location& end_location, ASTNode* lhs,
bool opt_natural, ASTJoin::JoinType join_type, ASTJoin::JoinHint join_hint,
ASTNode* opt_hint, ASTNode* table_primary,
ASTNode* opt_order_by,
ASTNode* opt_on_or_using_clause_list,
BisonParser* parser, ErrorInfo* error_info);

Expand Down
2 changes: 1 addition & 1 deletion zetasql/parser/keywords.cc
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ constexpr KeywordInfoPOD kAllKeywords[] = {
{"json", KW_JSON},
{"key", KW_KEY},
{"language", KW_LANGUAGE},
{"last", KW_LAST},
{"last", KW_LAST, KeywordInfo::kReserved},
{"lateral", KW_LATERAL, KeywordInfo::kReserved},
{"leave", KW_LEAVE},
{"left", KW_LEFT, KeywordInfo::kReserved},
Expand Down
2 changes: 1 addition & 1 deletion zetasql/parser/keywords_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ TEST(ParserTest, DontAddNewReservedKeywords) {
// allows new queries to work that will not work on older code.
// Before changing this, co-ordinate with all engines to make sure the change
// is done safely.
EXPECT_EQ(97 /* CAUTION */, num_reserved);
EXPECT_EQ(98 /* CAUTION */, num_reserved);
}

} // namespace
Expand Down
2 changes: 2 additions & 0 deletions zetasql/parser/parse_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ std::string ASTJoin::GetSQLForJoinType() const {
return "LEFT";
case RIGHT:
return "RIGHT";
case LAST:
return "LAST";
}
}

Expand Down
14 changes: 11 additions & 3 deletions zetasql/parser/parse_tree_manual.h
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ class ASTJoin final : public ASTTableExpression {
std::string GetSQLForJoinType() const;
std::string GetSQLForJoinHint() const;

enum JoinType { DEFAULT_JOIN_TYPE, COMMA, CROSS, FULL, INNER, LEFT, RIGHT };
enum JoinType { DEFAULT_JOIN_TYPE, COMMA, CROSS, FULL, INNER, LEFT, RIGHT, LAST};

JoinType join_type() const { return join_type_; }
void set_join_type(JoinType join_type) { join_type_ = join_type; }
Expand All @@ -1302,6 +1302,8 @@ class ASTJoin final : public ASTTableExpression {
const ASTHint* hint() const { return hint_; }
const ASTTableExpression* lhs() const { return lhs_; }
const ASTTableExpression* rhs() const { return rhs_; }
// If present, order rhs before apply using clause
const ASTOrderBy* order_by() const { return order_by_; }
const ASTOnClause* on_clause() const { return on_clause_; }
const ASTUsingClause* using_clause() const { return using_clause_; }

Expand Down Expand Up @@ -1331,6 +1333,7 @@ class ASTJoin final : public ASTTableExpression {
fl.AddRequired(&lhs_);
fl.AddOptional(&hint_, AST_HINT);
fl.AddRequired(&rhs_);
fl.AddOptional(&order_by_, AST_ORDER_BY);
fl.AddOptional(&on_clause_, AST_ON_CLAUSE);
fl.AddOptional(&using_clause_, AST_USING_CLAUSE);

Expand All @@ -1345,6 +1348,7 @@ class ASTJoin final : public ASTTableExpression {
const ASTHint* hint_ = nullptr;
const ASTTableExpression* lhs_ = nullptr;
const ASTTableExpression* rhs_ = nullptr;
const ASTOrderBy* order_by_ = nullptr;
const ASTOnClause* on_clause_ = nullptr;
const ASTUsingClause* using_clause_ = nullptr;
const ASTOnOrUsingClauseList* clause_list_ = nullptr;
Expand Down Expand Up @@ -1405,10 +1409,10 @@ class ASTOnClause final : public ASTNode {
FieldLoader fl(this);
fl.AddRequired(&expression_);
}

const ASTExpression* expression_ = nullptr;
};


class ASTUsingClause final : public ASTNode {
public:
static constexpr ASTNodeKind kConcreteNodeKind = AST_USING_CLAUSE;
Expand All @@ -1418,16 +1422,20 @@ class ASTUsingClause final : public ASTNode {
zetasql_base::StatusOr<VisitResult> Accept(
NonRecursiveParseTreeVisitor* visitor) const override;

// If present, order dataset before apply using clause
const ASTOrderBy* order_by() const { return order_by_; }

const absl::Span<const ASTIdentifier* const>& keys() const {
return keys_;
}

private:
void InitFields() final {
FieldLoader fl(this);
fl.AddRequired(&order_by_);
fl.AddRestAsRepeated(&keys_);
}

const ASTOrderBy* order_by_ = nullptr;
absl::Span<const ASTIdentifier* const> keys_;
};

Expand Down
Loading

0 comments on commit 739652f

Please sign in to comment.