Skip to content

Commit

Permalink
Merge pull request #33 from aceforeverd/feat/with-config-clause
Browse files Browse the repository at this point in the history
feat: config clause
  • Loading branch information
aceforeverd authored Dec 17, 2021
2 parents e83addd + 8088a0e commit 4b69a81
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 7 deletions.
1 change: 1 addition & 0 deletions zetasql/parser/ast_node_kind.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ enum ASTNodeKind {
AST_SELECT_INTO_STATEMENT,
AST_ESCAPED_EXPRESSION,
AST_STOP_STATEMENT,
AST_CONFIG_CLAUSE,
AST_WITH_WEIGHT,
kLastASTNodeKind = AST_WITH_WEIGHT
};
Expand Down
23 changes: 17 additions & 6 deletions zetasql/parser/bison_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ using zetasql::ASTDropStatement;
%token KW_CASE "CASE"
%token KW_CAST "CAST"
%token KW_COLLATE "COLLATE"
%token KW_CONFIG "CONFIG"
%token KW_CREATE "CREATE"
%token KW_CROSS "CROSS"
%token KW_CURRENT "CURRENT"
Expand Down Expand Up @@ -1182,6 +1183,7 @@ using zetasql::ASTDropStatement;
%type <node> opt_like_string_literal
%type <node> opt_like_path_expression
%type <node> opt_limit_offset_clause
%type <node> opt_config_clause
%type <node> opt_maxsize
%type <node> opt_on_or_using_clause_list
%type <node> on_or_using_clause_list
Expand Down Expand Up @@ -1605,9 +1607,9 @@ sql_statement_body:
;

query_statement:
query
query opt_config_clause
{
$$ = MAKE_NODE(ASTQueryStatement, @$, {$1});
$$ = MAKE_NODE(ASTQueryStatement, @$, {$1, $2});
}
;

Expand Down Expand Up @@ -3413,16 +3415,16 @@ into_statement:
;

select_into_statement:
query "INTO" "OUTFILE" string_literal opt_options_list
query "INTO" "OUTFILE" string_literal opt_options_list opt_config_clause
{
$$ = MAKE_NODE(ASTSelectIntoStatement, @$, {$1, $4, $5})
$$ = MAKE_NODE(ASTSelectIntoStatement, @$, {$1, $4, $5, $6})
}
;

load_data_statement:
"LOAD" "DATA" "INFILE" string_literal "INTO" "TABLE" path_expression opt_options_list
"LOAD" "DATA" "INFILE" string_literal "INTO" "TABLE" path_expression opt_options_list opt_config_clause
{
$$ = MAKE_NODE(ASTLoadDataStatement, @$, {$4, $7, $8});
$$ = MAKE_NODE(ASTLoadDataStatement, @$, {$4, $7, $8, $9});
}
;

Expand Down Expand Up @@ -5074,6 +5076,14 @@ opt_limit_offset_clause:
| /* Nothing */ { $$ = nullptr; }
;

opt_config_clause:
"CONFIG" options_list
{
$$ = MAKE_NODE(ASTConfigClause, @$, {$2});
}
| /* Nothing */ { $$ = nullptr; }
;

opt_having_modifier:
"HAVING" "MAX" expression
{
Expand Down Expand Up @@ -7241,6 +7251,7 @@ reserved_keyword_rule:
| "CASE"
| "CAST"
| "COLLATE"
| "CONFIG"
| "CREATE"
| "CROSS"
| "CURRENT"
Expand Down
1 change: 1 addition & 0 deletions zetasql/parser/flex_tokenizer.l
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ collate { return BisonParserImpl::token::KW_COLLATE; }
column { return BisonParserImpl::token::KW_COLUMN; }
columns { return BisonParserImpl::token::KW_COLUMNS; }
commit { return BisonParserImpl::token::KW_COMMIT; }
config { return BisonParserImpl::token::KW_CONFIG; }
connection { return BisonParserImpl::token::KW_CONNECTION; }
const { return BisonParserImpl::token::KW_CONST; }
constant { return BisonParserImpl::token::KW_CONSTANT; }
Expand Down
3 changes: 3 additions & 0 deletions zetasql/parser/gen_parse_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,9 @@ def main(argv):
'query',
'ASTQuery',
field_loader=FieldLoaderMethod.REQUIRED),
Field(
'config_clause',
'ASTConfigClause'),
])

gen.AddNode(
Expand Down
1 change: 1 addition & 0 deletions zetasql/parser/keywords.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ constexpr KeywordInfoPOD kAllKeywords[] = {
{"column", KW_COLUMN},
{"columns", KW_COLUMNS},
{"commit", KW_COMMIT},
{"config", KW_CONFIG, KeywordInfo::kReserved},
{"connection", KW_CONNECTION},
{"const", KW_CONST},
{"constant", KW_CONSTANT},
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(104 /* CAUTION */, num_reserved);
EXPECT_EQ(105 /* CAUTION */, num_reserved);
}

} // namespace
Expand Down
1 change: 1 addition & 0 deletions zetasql/parser/parse_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ static absl::flat_hash_map<ASTNodeKind, std::string> CreateNodeNamesMap() {
map[AST_SELECT_INTO_STATEMENT] = "SelectIntoStatement";
map[AST_ESCAPED_EXPRESSION] = "EscapedExpression";
map[AST_STOP_STATEMENT] = "StopStatement";
map[AST_CONFIG_CLAUSE] = "ConfigClause";
map[AST_WITH_WEIGHT] = "WithWeight";
map[AST_WITH_PARTITION_COLUMNS_CLAUSE] = "WithPartitionColumnsClause";
for (int kind = kFirstASTNodeKind; kind <= kLastASTNodeKind;
Expand Down
26 changes: 26 additions & 0 deletions zetasql/parser/parse_tree_manual.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ class ASTSelectIntoStatement final : public ASTStatement {
const ASTQuery* query() const { return query_; }
const ASTStringLiteral* out_file() const { return out_file_; }
const ASTOptionsList* options_list() const { return options_list_; }
const ASTConfigClause* opt_config() const { return opt_config_; }

std::string UnparseQuery() const;

Expand All @@ -781,11 +782,13 @@ class ASTSelectIntoStatement final : public ASTStatement {
fl.AddRequired(&query_);
fl.AddRequired(&out_file_);
fl.AddOptional(&options_list_, AST_OPTIONS_LIST);
fl.AddOptional(&opt_config_, AST_CONFIG_CLAUSE);
}

const ASTQuery* query_ = nullptr;
const ASTStringLiteral* out_file_ = nullptr;
const ASTOptionsList* options_list_ = nullptr;
const ASTConfigClause* opt_config_ = nullptr;
};
// super class of all load statements
class ASTLoadStatement : public ASTStatement {
Expand All @@ -805,18 +808,21 @@ class ASTLoadDataStatement final : public ASTLoadStatement {
const ASTStringLiteral* in_file() const { return in_file_; }
const ASTPathExpression* table_name() const { return table_name_; }
const ASTOptionsList* options_list() const { return options_list_; }
const ASTConfigClause* opt_config() const { return opt_config_; }

private:
void InitFields() final {
FieldLoader fl(this);
fl.AddRequired(&in_file_);
fl.AddRequired(&table_name_);
fl.AddOptional(&options_list_, AST_OPTIONS_LIST);
fl.AddOptional(&opt_config_, AST_CONFIG_CLAUSE);
}

const ASTStringLiteral* in_file_ = nullptr;
const ASTPathExpression* table_name_ = nullptr;
const ASTOptionsList* options_list_ = nullptr;
const ASTConfigClause* opt_config_ = nullptr;
};

class ASTUseStatement final : public ASTStatement {
Expand Down Expand Up @@ -1886,6 +1892,26 @@ class ASTLimitOffset final : public ASTNode {
const ASTExpression* offset_ = nullptr;
};

class ASTConfigClause final : public ASTNode {
public:
static constexpr ASTNodeKind kConcreteNodeKind = AST_CONFIG_CLAUSE;

ASTConfigClause() : ASTNode(kConcreteNodeKind) {}
void Accept(ParseTreeVisitor* visitor, void* data) const override;
zetasql_base::StatusOr<VisitResult> Accept(
NonRecursiveParseTreeVisitor* visitor) const override;

const ASTOptionsList* options_list() const { return options_list_; }

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

const ASTOptionsList* options_list_ = nullptr;
};

class ASTHavingModifier final : public ASTNode {
public:
static constexpr ASTNodeKind kConcreteNodeKind = AST_HAVING_MODIFIER;
Expand Down
59 changes: 59 additions & 0 deletions zetasql/parser/testdata/from.test
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,65 @@ SELECT
'foo' AS b
==

# query statement with config clause
select T1.a as a, T2.b as b from Table1 as T1 last join Table2 T2 using (c, d) config ( a = 'k' );
--
QueryStatement [0-97]
Query [0-78]
Select [0-78]
SelectList [7-27]
SelectColumn [7-16]
PathExpression [7-11]
Identifier(T1) [7-9]
Identifier(a) [10-11]
Alias [12-16]
Identifier(a) [15-16]
SelectColumn [18-27]
PathExpression [18-22]
Identifier(T2) [18-20]
Identifier(b) [21-22]
Alias [23-27]
Identifier(b) [26-27]
FromClause [28-78]
Join(LAST) [46-78]
TablePathExpression [33-45]
PathExpression [33-39]
Identifier(Table1) [33-39]
Alias [40-45]
Identifier(T1) [43-45]
TablePathExpression [56-65]
PathExpression [56-62]
Identifier(Table2) [56-62]
Alias [63-65]
Identifier(T2) [63-65]
UsingClause [66-78]
Identifier(c) [73-74]
Identifier(d) [76-77]
ConfigClause [79-97]
OptionsList [86-97]
OptionsEntry [88-95]
Identifier(a) [88-89]
StringLiteral('k') [92-95]
--
SELECT
T1.a AS a,
T2.b AS b
FROM
Table1 AS T1
LAST JOIN
Table2 AS T2
USING(c, d)
CONFIG(a = 'k')
==

# config clause can't appear inside subquery
select T1.a as a, T2.b as b from Table1 as T1 config (k='k') last join Table2 T2 using (c, d);
--
ERROR: Syntax error: Expected end of input but got keyword LAST [at 1:62]
...a as a, T2.b as b from Table1 as T1 config (k='k') last join Table2 T2 usi...
^
==

# Empty SELECT list
select {{|@{a=b}|ALL|DISTINCT|AS foo|@{a=b} DISTINCT AS foo}} from t
--
Expand Down
38 changes: 38 additions & 0 deletions zetasql/parser/testdata/load.test
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,41 @@ ERROR: Syntax error: Unexpected ";" [at 1:40]
load data infile 'data.file' into table;
^
==

# load data with config
load data infile 'data.csv' into table foo config (charset = 'utf-8');
--
LoadDataStatement [0-69]
StringLiteral('data.csv') [17-27]
PathExpression [39-42]
Identifier(foo) [39-42]
ConfigClause [43-69]
OptionsList [50-69]
OptionsEntry [51-68]
Identifier(charset) [51-58]
StringLiteral('utf-8') [61-68]
--
LOAD DATA INFILE 'data.csv' INTO TABLE foo
CONFIG(charset = 'utf-8')
==

# load data with config
load data infile 'data.csv' into table foo options (charset = 'utf-8') config (charset = 'utf-8');
--
LoadDataStatement [0-97]
StringLiteral('data.csv') [17-27]
PathExpression [39-42]
Identifier(foo) [39-42]
OptionsList [51-70]
OptionsEntry [52-69]
Identifier(charset) [52-59]
StringLiteral('utf-8') [62-69]
ConfigClause [71-97]
OptionsList [78-97]
OptionsEntry [79-96]
Identifier(charset) [79-86]
StringLiteral('utf-8') [89-96]
--
LOAD DATA INFILE 'data.csv' INTO TABLE foo OPTIONS(charset = 'utf-8')
CONFIG(charset = 'utf-8')
==
46 changes: 46 additions & 0 deletions zetasql/parser/testdata/select_into.test
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,52 @@ FROM
INTO OUTFILE 'data.csv' OPTIONS(charset = 'utf-8')
==

# select into with config clause
select col1, col2 from db1.t1 into outfile 'data.csv' options (charset = 'utf-8') config (val=12);
--
SelectIntoStatement [0-97]
Query [0-29]
Select [0-29]
SelectList [7-17]
SelectColumn [7-11]
PathExpression [7-11]
Identifier(col1) [7-11]
SelectColumn [13-17]
PathExpression [13-17]
Identifier(col2) [13-17]
FromClause [18-29]
TablePathExpression [23-29]
PathExpression [23-29]
Identifier(db1) [23-26]
Identifier(t1) [27-29]
StringLiteral('data.csv') [43-53]
OptionsList [62-81]
OptionsEntry [63-80]
Identifier(charset) [63-70]
StringLiteral('utf-8') [73-80]
ConfigClause [82-97]
OptionsList [89-97]
OptionsEntry [90-96]
Identifier(val) [90-93]
IntLiteral(12) [94-96]
--
SELECT
col1,
col2
FROM
db1.t1
INTO OUTFILE 'data.csv' OPTIONS(charset = 'utf-8')
CONFIG(val = 12)
==

# config clause can't appear inside subquery
select T1.a as a, T2.b as b from Table1 as T1 config (k='k') last join Table2 T2 using (c, d) into outfile 'data.csv';
--
ERROR: Syntax error: Expected end of input but got keyword LAST [at 1:62]
...a as a, T2.b as b from Table1 as T1 config (k='k') last join Table2 T2 usi...
^
==

select col1, col2 from db1.t1 into outfile;
--
ERROR: Syntax error: Expected string literal but got ";" [at 1:43]
Expand Down
17 changes: 17 additions & 0 deletions zetasql/parser/unparser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ void Unparser::visitASTExplainStatement(const ASTExplainStatement* node,
void Unparser::visitASTQueryStatement(const ASTQueryStatement* node,
void* data) {
visitASTQuery(node->query(), data);
if (node->config_clause() != nullptr) {
println();
node->config_clause()->Accept(this, data);
}
}

void Unparser::visitASTFunctionParameter(
Expand Down Expand Up @@ -1090,6 +1094,10 @@ void Unparser::visitASTLoadDataStatement(const ASTLoadDataStatement* node, void*
print("OPTIONS");
node->options_list()->Accept(this, data);
}
if (node->opt_config() != nullptr) {
println();
node->opt_config()->Accept(this, data);
}
}

void Unparser::visitASTSelectIntoStatement(const ASTSelectIntoStatement* node, void* data) {
Expand All @@ -1100,6 +1108,10 @@ void Unparser::visitASTSelectIntoStatement(const ASTSelectIntoStatement* node, v
print("OPTIONS");
node->options_list()->Accept(this, data);
}
if (node->opt_config() != nullptr) {
println();
node->opt_config()->Accept(this, data);
}
}
void Unparser::visitASTModuleStatement(const ASTModuleStatement* node,
void* data) {
Expand Down Expand Up @@ -1465,6 +1477,11 @@ void Unparser::visitASTLimitOffset(const ASTLimitOffset* node, void* data) {
UnparseChildrenWithSeparator(node, data, "OFFSET");
}

void Unparser::visitASTConfigClause(const ASTConfigClause* node, void* data) {
print("CONFIG");
node->options_list()->Accept(this, data);
}

void Unparser::visitASTHavingModifier(const ASTHavingModifier* node,
void* data) {
println();
Expand Down
Loading

0 comments on commit 4b69a81

Please sign in to comment.