Merge pull request #79 from f4lco/table-alias-with-columns
Extend table alias with column renames: "AS tbl(c0, c1)"
This commit is contained in:
commit
c7e8309363
File diff suppressed because it is too large
Load Diff
|
@ -48,7 +48,7 @@
|
|||
extern int hsql_debug;
|
||||
#endif
|
||||
/* "%code requires" blocks. */
|
||||
#line 35 "bison_parser.y" /* yacc.c:1915 */
|
||||
#line 35 "bison_parser.y" /* yacc.c:1909 */
|
||||
|
||||
// %code requires block
|
||||
|
||||
|
@ -72,7 +72,7 @@ extern int hsql_debug;
|
|||
} \
|
||||
}
|
||||
|
||||
#line 76 "bison_parser.h" /* yacc.c:1915 */
|
||||
#line 76 "bison_parser.h" /* yacc.c:1909 */
|
||||
|
||||
/* Token type. */
|
||||
#ifndef HSQL_TOKENTYPE
|
||||
|
@ -218,7 +218,7 @@ extern int hsql_debug;
|
|||
|
||||
union HSQL_STYPE
|
||||
{
|
||||
#line 95 "bison_parser.y" /* yacc.c:1915 */
|
||||
#line 95 "bison_parser.y" /* yacc.c:1909 */
|
||||
|
||||
double fval;
|
||||
int64_t ival;
|
||||
|
@ -247,6 +247,7 @@ union HSQL_STYPE
|
|||
hsql::ColumnDefinition* column_t;
|
||||
hsql::GroupByDescription* group_t;
|
||||
hsql::UpdateClause* update_t;
|
||||
hsql::Alias* alias_t;
|
||||
|
||||
std::vector<hsql::SQLStatement*>* stmt_vec;
|
||||
|
||||
|
@ -257,7 +258,7 @@ union HSQL_STYPE
|
|||
std::vector<hsql::Expr*>* expr_vec;
|
||||
std::vector<hsql::OrderDescription*>* order_vec;
|
||||
|
||||
#line 261 "bison_parser.h" /* yacc.c:1915 */
|
||||
#line 262 "bison_parser.h" /* yacc.c:1909 */
|
||||
};
|
||||
|
||||
typedef union HSQL_STYPE HSQL_STYPE;
|
||||
|
|
|
@ -120,6 +120,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
|||
hsql::ColumnDefinition* column_t;
|
||||
hsql::GroupByDescription* group_t;
|
||||
hsql::UpdateClause* update_t;
|
||||
hsql::Alias* alias_t;
|
||||
|
||||
std::vector<hsql::SQLStatement*>* stmt_vec;
|
||||
|
||||
|
@ -133,7 +134,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
|||
|
||||
|
||||
/*********************************
|
||||
** Descrutor symbols
|
||||
** Destructor symbols
|
||||
*********************************/
|
||||
%destructor { } <fval> <ival> <uval> <bval> <order_type>
|
||||
%destructor { free( ($$.name) ); free( ($$.schema) ); } <table_name>
|
||||
|
@ -189,7 +190,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
|||
%type <drop_stmt> drop_statement
|
||||
%type <show_stmt> show_statement
|
||||
%type <table_name> table_name
|
||||
%type <sval> opt_alias alias file_path prepare_target_query
|
||||
%type <sval> file_path prepare_target_query
|
||||
%type <bval> opt_not_exists opt_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 nonjoin_table_ref_atomic
|
||||
|
@ -205,6 +206,7 @@ int yyerror(YYLTYPE* llocp, SQLParserResult* result, yyscan_t scanner, const cha
|
|||
%type <column_t> column_def
|
||||
%type <update_t> update_clause
|
||||
%type <group_t> opt_group
|
||||
%type <alias_t> opt_table_alias table_alias opt_alias alias
|
||||
|
||||
%type <str_vec> ident_commalist opt_column_list
|
||||
%type <expr_vec> expr_list select_list literal_list hint_list opt_hints
|
||||
|
@ -735,7 +737,10 @@ literal_list:
|
|||
expr_alias:
|
||||
expr opt_alias {
|
||||
$$ = $1;
|
||||
$$->alias = $2;
|
||||
if ($2) {
|
||||
$$->alias = strdup($2->name);
|
||||
delete $2;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -906,7 +911,7 @@ table_ref_atomic:
|
|||
|
||||
nonjoin_table_ref_atomic:
|
||||
table_ref_name
|
||||
| '(' select_statement ')' opt_alias {
|
||||
| '(' select_statement ')' opt_table_alias {
|
||||
auto tbl = new TableRef(kTableSelect);
|
||||
tbl->select = $2;
|
||||
tbl->alias = $4;
|
||||
|
@ -921,7 +926,7 @@ table_ref_commalist:
|
|||
|
||||
|
||||
table_ref_name:
|
||||
table_name opt_alias {
|
||||
table_name opt_table_alias {
|
||||
auto tbl = new TableRef(kTableName);
|
||||
tbl->schema = $1.schema;
|
||||
tbl->name = $1.name;
|
||||
|
@ -946,11 +951,23 @@ table_name:
|
|||
;
|
||||
|
||||
|
||||
alias:
|
||||
AS IDENTIFIER { $$ = $2; }
|
||||
| IDENTIFIER
|
||||
table_alias:
|
||||
alias
|
||||
| AS IDENTIFIER '(' ident_commalist ')' { $$ = new Alias($2, $4); }
|
||||
;
|
||||
|
||||
|
||||
opt_table_alias:
|
||||
table_alias
|
||||
| /* empty */ { $$ = nullptr; }
|
||||
|
||||
|
||||
alias:
|
||||
AS IDENTIFIER { $$ = new Alias($2); }
|
||||
| IDENTIFIER { $$ = new Alias($1); }
|
||||
;
|
||||
|
||||
|
||||
opt_alias:
|
||||
alias
|
||||
| /* empty */ { $$ = nullptr; }
|
||||
|
@ -1037,4 +1054,3 @@ ident_commalist:
|
|||
*********************************/
|
||||
|
||||
/* empty */
|
||||
|
||||
|
|
|
@ -24,6 +24,14 @@ namespace hsql {
|
|||
char* name;
|
||||
};
|
||||
|
||||
struct Alias {
|
||||
Alias(char* name, std::vector<char*>* columns = nullptr);
|
||||
~Alias();
|
||||
|
||||
char* name;
|
||||
std::vector<char*>* columns;
|
||||
};
|
||||
|
||||
// Holds reference to tables. Can be either table names or a select statement.
|
||||
struct TableRef {
|
||||
TableRef(TableRefType type);
|
||||
|
@ -33,7 +41,7 @@ namespace hsql {
|
|||
|
||||
char* schema;
|
||||
char* name;
|
||||
char* alias;
|
||||
Alias* alias;
|
||||
|
||||
SelectStatement* select;
|
||||
std::vector<TableRef*>* list;
|
||||
|
|
|
@ -231,6 +231,21 @@ namespace hsql {
|
|||
}
|
||||
}
|
||||
|
||||
// Alias
|
||||
Alias::Alias(char* name, std::vector<char*>* columns) :
|
||||
name(name),
|
||||
columns(columns) {}
|
||||
|
||||
Alias::~Alias() {
|
||||
free(name);
|
||||
if (columns) {
|
||||
for (char* column : *columns) {
|
||||
free(column);
|
||||
}
|
||||
delete columns;
|
||||
}
|
||||
}
|
||||
|
||||
// TableRef
|
||||
TableRef::TableRef(TableRefType type) :
|
||||
type(type),
|
||||
|
@ -244,10 +259,10 @@ namespace hsql {
|
|||
TableRef::~TableRef() {
|
||||
free(schema);
|
||||
free(name);
|
||||
free(alias);
|
||||
|
||||
delete select;
|
||||
delete join;
|
||||
delete alias;
|
||||
|
||||
if (list != nullptr) {
|
||||
for (TableRef* table : *list) {
|
||||
|
@ -262,7 +277,7 @@ namespace hsql {
|
|||
}
|
||||
|
||||
const char* TableRef::getName() const {
|
||||
if (alias != nullptr) return alias;
|
||||
if (alias) return alias->name;
|
||||
else return name;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
namespace hsql {
|
||||
|
||||
void printOperatorExpression(Expr* expr, uintmax_t numIndent);
|
||||
void printAlias(Alias* alias, uintmax_t numIndent);
|
||||
|
||||
std::string indent(uintmax_t numIndent) {
|
||||
return std::string(numIndent, '\t');
|
||||
|
@ -54,9 +55,20 @@ namespace hsql {
|
|||
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, numIndent);
|
||||
break;
|
||||
}
|
||||
if (table->alias != nullptr) {
|
||||
inprint("Alias", numIndent + 1);
|
||||
inprint(table->alias, numIndent + 2);
|
||||
|
||||
if (table->alias) {
|
||||
printAlias(table->alias, numIndent);
|
||||
}
|
||||
}
|
||||
|
||||
void printAlias(Alias* alias, uintmax_t numIndent) {
|
||||
inprint("Alias", numIndent + 1);
|
||||
inprint(alias->name, numIndent + 2);
|
||||
|
||||
if (alias->columns) {
|
||||
for (char* column : *(alias->columns)) {
|
||||
inprint(column, numIndent + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
!INSERT INTO test_table VALUESd (1, 2, 'test');
|
||||
!SELECT * FROM t WHERE a = ? AND b = ?;SELECT 1;
|
||||
!SHOW COLUMNS;
|
||||
!select a + 2 as b(spam, eggs) from B;
|
||||
|
|
|
@ -3,6 +3,6 @@ SELECT C_COUNT, COUNT(*) AS CUSTDIST
|
|||
FROM (SELECT C_CUSTKEY, COUNT(O_ORDERKEY)
|
||||
FROM CUSTOMER left outer join ORDERS on C_CUSTKEY = O_CUSTKEY
|
||||
AND O_COMMENT not like '%%special%%requests%%'
|
||||
GROUP BY C_CUSTKEY) AS C_ORDERS
|
||||
GROUP BY C_CUSTKEY) AS C_ORDERS (C_CUSTKEY, C_COUNT)
|
||||
GROUP BY C_COUNT
|
||||
ORDER BY CUSTDIST DESC, C_COUNT DESC;
|
|
@ -343,9 +343,55 @@ TEST(SelectColumnOrder) {
|
|||
|
||||
// Make sure the order of the table list is corrects
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(0)->name, "a");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(1)->alias, "b");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(2)->alias, "c");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(3)->alias, "d");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(1)->alias->name, "b");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(2)->alias->name, "c");
|
||||
ASSERT_STREQ(stmt->fromTable->list->at(3)->alias->name, "d");
|
||||
}
|
||||
|
||||
|
||||
TEST(SelectAliasAbsent) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT * FROM students;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
ASSERT_NULL(stmt->fromTable->alias);
|
||||
}
|
||||
|
||||
TEST(SelectAliasSimple) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT * FROM students AS s1;",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
Alias* alias = stmt->fromTable->alias;
|
||||
ASSERT_NOTNULL(alias);
|
||||
ASSERT_STREQ(alias->name, "s1");
|
||||
ASSERT_NULL(alias->columns);
|
||||
}
|
||||
|
||||
TEST(SelectAliasWithColumns) {
|
||||
TEST_PARSE_SINGLE_SQL(
|
||||
"SELECT * FROM students AS s1(id, city);",
|
||||
kStmtSelect,
|
||||
SelectStatement,
|
||||
result,
|
||||
stmt);
|
||||
|
||||
Alias* alias = stmt->fromTable->alias;
|
||||
ASSERT_NOTNULL(alias);
|
||||
|
||||
ASSERT_NOTNULL(alias->name);
|
||||
ASSERT_STREQ(alias->name, "s1");
|
||||
|
||||
ASSERT_NOTNULL(alias->columns);
|
||||
ASSERT_EQ(alias->columns->size(), 2);
|
||||
ASSERT_STREQ(alias->columns->at(0), "id");
|
||||
ASSERT_STREQ(alias->columns->at(1), "city");
|
||||
}
|
||||
|
||||
TEST(Operators) {
|
||||
|
|
Loading…
Reference in New Issue