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:
mrks 2018-02-12 11:42:02 +01:00 committed by GitHub
commit c7e8309363
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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; 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;

View File

@ -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 */

View File

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

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

View File

@ -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) {
inprint("Alias", numIndent + 1); if (table->alias) {
inprint(table->alias, numIndent + 2); 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'); !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;

View File

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

View File

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