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;
|
extern int hsql_debug;
|
||||||
#endif
|
#endif
|
||||||
/* "%code requires" blocks. */
|
/* "%code requires" blocks. */
|
||||||
#line 35 "bison_parser.y" /* yacc.c:1915 */
|
#line 35 "bison_parser.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
// %code requires block
|
// %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. */
|
/* Token type. */
|
||||||
#ifndef HSQL_TOKENTYPE
|
#ifndef HSQL_TOKENTYPE
|
||||||
|
@ -218,7 +218,7 @@ extern int hsql_debug;
|
||||||
|
|
||||||
union HSQL_STYPE
|
union HSQL_STYPE
|
||||||
{
|
{
|
||||||
#line 95 "bison_parser.y" /* yacc.c:1915 */
|
#line 95 "bison_parser.y" /* yacc.c:1909 */
|
||||||
|
|
||||||
double fval;
|
double fval;
|
||||||
int64_t ival;
|
int64_t ival;
|
||||||
|
@ -247,6 +247,7 @@ union HSQL_STYPE
|
||||||
hsql::ColumnDefinition* column_t;
|
hsql::ColumnDefinition* column_t;
|
||||||
hsql::GroupByDescription* group_t;
|
hsql::GroupByDescription* group_t;
|
||||||
hsql::UpdateClause* update_t;
|
hsql::UpdateClause* update_t;
|
||||||
|
hsql::Alias* alias_t;
|
||||||
|
|
||||||
std::vector<hsql::SQLStatement*>* stmt_vec;
|
std::vector<hsql::SQLStatement*>* stmt_vec;
|
||||||
|
|
||||||
|
@ -257,7 +258,7 @@ union HSQL_STYPE
|
||||||
std::vector<hsql::Expr*>* expr_vec;
|
std::vector<hsql::Expr*>* expr_vec;
|
||||||
std::vector<hsql::OrderDescription*>* order_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;
|
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::ColumnDefinition* column_t;
|
||||||
hsql::GroupByDescription* group_t;
|
hsql::GroupByDescription* group_t;
|
||||||
hsql::UpdateClause* update_t;
|
hsql::UpdateClause* update_t;
|
||||||
|
hsql::Alias* alias_t;
|
||||||
|
|
||||||
std::vector<hsql::SQLStatement*>* stmt_vec;
|
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 { } <fval> <ival> <uval> <bval> <order_type>
|
||||||
%destructor { free( ($$.name) ); free( ($$.schema) ); } <table_name>
|
%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 <drop_stmt> drop_statement
|
||||||
%type <show_stmt> show_statement
|
%type <show_stmt> show_statement
|
||||||
%type <table_name> table_name
|
%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 <bval> opt_not_exists opt_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 nonjoin_table_ref_atomic
|
%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 <column_t> column_def
|
||||||
%type <update_t> update_clause
|
%type <update_t> update_clause
|
||||||
%type <group_t> opt_group
|
%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 <str_vec> ident_commalist opt_column_list
|
||||||
%type <expr_vec> expr_list select_list literal_list hint_list opt_hints
|
%type <expr_vec> expr_list select_list literal_list hint_list opt_hints
|
||||||
|
@ -735,7 +737,10 @@ literal_list:
|
||||||
expr_alias:
|
expr_alias:
|
||||||
expr opt_alias {
|
expr opt_alias {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$->alias = $2;
|
if ($2) {
|
||||||
|
$$->alias = strdup($2->name);
|
||||||
|
delete $2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -906,7 +911,7 @@ table_ref_atomic:
|
||||||
|
|
||||||
nonjoin_table_ref_atomic:
|
nonjoin_table_ref_atomic:
|
||||||
table_ref_name
|
table_ref_name
|
||||||
| '(' select_statement ')' opt_alias {
|
| '(' select_statement ')' opt_table_alias {
|
||||||
auto tbl = new TableRef(kTableSelect);
|
auto tbl = new TableRef(kTableSelect);
|
||||||
tbl->select = $2;
|
tbl->select = $2;
|
||||||
tbl->alias = $4;
|
tbl->alias = $4;
|
||||||
|
@ -921,7 +926,7 @@ table_ref_commalist:
|
||||||
|
|
||||||
|
|
||||||
table_ref_name:
|
table_ref_name:
|
||||||
table_name opt_alias {
|
table_name opt_table_alias {
|
||||||
auto tbl = new TableRef(kTableName);
|
auto tbl = new TableRef(kTableName);
|
||||||
tbl->schema = $1.schema;
|
tbl->schema = $1.schema;
|
||||||
tbl->name = $1.name;
|
tbl->name = $1.name;
|
||||||
|
@ -946,11 +951,23 @@ table_name:
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
alias:
|
table_alias:
|
||||||
AS IDENTIFIER { $$ = $2; }
|
alias
|
||||||
| IDENTIFIER
|
| 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:
|
opt_alias:
|
||||||
alias
|
alias
|
||||||
| /* empty */ { $$ = nullptr; }
|
| /* empty */ { $$ = nullptr; }
|
||||||
|
@ -1037,4 +1054,3 @@ ident_commalist:
|
||||||
*********************************/
|
*********************************/
|
||||||
|
|
||||||
/* empty */
|
/* empty */
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,14 @@ namespace hsql {
|
||||||
char* name;
|
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.
|
// Holds reference to tables. Can be either table names or a select statement.
|
||||||
struct TableRef {
|
struct TableRef {
|
||||||
TableRef(TableRefType type);
|
TableRef(TableRefType type);
|
||||||
|
@ -33,7 +41,7 @@ namespace hsql {
|
||||||
|
|
||||||
char* schema;
|
char* schema;
|
||||||
char* name;
|
char* name;
|
||||||
char* alias;
|
Alias* alias;
|
||||||
|
|
||||||
SelectStatement* select;
|
SelectStatement* select;
|
||||||
std::vector<TableRef*>* list;
|
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::TableRef(TableRefType type) :
|
TableRef::TableRef(TableRefType type) :
|
||||||
type(type),
|
type(type),
|
||||||
|
@ -244,10 +259,10 @@ namespace hsql {
|
||||||
TableRef::~TableRef() {
|
TableRef::~TableRef() {
|
||||||
free(schema);
|
free(schema);
|
||||||
free(name);
|
free(name);
|
||||||
free(alias);
|
|
||||||
|
|
||||||
delete select;
|
delete select;
|
||||||
delete join;
|
delete join;
|
||||||
|
delete alias;
|
||||||
|
|
||||||
if (list != nullptr) {
|
if (list != nullptr) {
|
||||||
for (TableRef* table : *list) {
|
for (TableRef* table : *list) {
|
||||||
|
@ -262,7 +277,7 @@ namespace hsql {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* TableRef::getName() const {
|
const char* TableRef::getName() const {
|
||||||
if (alias != nullptr) return alias;
|
if (alias) return alias->name;
|
||||||
else return name;
|
else return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
namespace hsql {
|
namespace hsql {
|
||||||
|
|
||||||
void printOperatorExpression(Expr* expr, uintmax_t numIndent);
|
void printOperatorExpression(Expr* expr, uintmax_t numIndent);
|
||||||
|
void printAlias(Alias* alias, uintmax_t numIndent);
|
||||||
|
|
||||||
std::string indent(uintmax_t numIndent) {
|
std::string indent(uintmax_t numIndent) {
|
||||||
return std::string(numIndent, '\t');
|
return std::string(numIndent, '\t');
|
||||||
|
@ -54,9 +55,20 @@ namespace hsql {
|
||||||
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, numIndent);
|
for (TableRef* tbl : *table->list) printTableRefInfo(tbl, numIndent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (table->alias != nullptr) {
|
|
||||||
|
if (table->alias) {
|
||||||
|
printAlias(table->alias, numIndent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printAlias(Alias* alias, uintmax_t numIndent) {
|
||||||
inprint("Alias", numIndent + 1);
|
inprint("Alias", numIndent + 1);
|
||||||
inprint(table->alias, numIndent + 2);
|
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');
|
!INSERT INTO test_table VALUESd (1, 2, 'test');
|
||||||
!SELECT * FROM t WHERE a = ? AND b = ?;SELECT 1;
|
!SELECT * FROM t WHERE a = ? AND b = ?;SELECT 1;
|
||||||
!SHOW COLUMNS;
|
!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 (SELECT C_CUSTKEY, COUNT(O_ORDERKEY)
|
||||||
FROM CUSTOMER left outer join ORDERS on C_CUSTKEY = O_CUSTKEY
|
FROM CUSTOMER left outer join ORDERS on C_CUSTKEY = O_CUSTKEY
|
||||||
AND O_COMMENT not like '%%special%%requests%%'
|
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
|
GROUP BY C_COUNT
|
||||||
ORDER BY CUSTDIST DESC, C_COUNT DESC;
|
ORDER BY CUSTDIST DESC, C_COUNT DESC;
|
|
@ -343,9 +343,55 @@ TEST(SelectColumnOrder) {
|
||||||
|
|
||||||
// Make sure the order of the table list is corrects
|
// 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(0)->name, "a");
|
||||||
ASSERT_STREQ(stmt->fromTable->list->at(1)->alias, "b");
|
ASSERT_STREQ(stmt->fromTable->list->at(1)->alias->name, "b");
|
||||||
ASSERT_STREQ(stmt->fromTable->list->at(2)->alias, "c");
|
ASSERT_STREQ(stmt->fromTable->list->at(2)->alias->name, "c");
|
||||||
ASSERT_STREQ(stmt->fromTable->list->at(3)->alias, "d");
|
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) {
|
TEST(Operators) {
|
||||||
|
|
Loading…
Reference in New Issue