Extend table alias with column renames: "AS tbl(c0, c1)"

This commit is contained in:
Falco Duersch 2018-01-10 13:49:30 +01:00
parent 77185183f6
commit 2ff32fbee3
9 changed files with 943 additions and 805 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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,16 +951,28 @@ 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; }
/******************************
* Join Statements
******************************/
@ -1037,4 +1054,3 @@ ident_commalist:
*********************************/
/* empty */

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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 + 1 as b(spam, eggs) from B;

View File

@ -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;

View File

@ -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) {