%{ #include #include #include using namespace std; namespace qfe { extern string DefaultSchema; } int qfeerror(const char *s); int qfelex(void); #include "calpontselectexecutionplan.h" #include "simplecolumn.h" #include "calpontsystemcatalog.h" #include "aggregatecolumn.h" execplan::CalpontSelectExecutionPlan* ParserCSEP; execplan::CalpontSystemCatalog* ParserCSC; namespace execplan { class ReturnedColumn; } #include "cseputils.h" %} %union { execplan::ReturnedColumn* rcp; std::string* cp; std::pair* cvp; } //Some of these defines cause conflicts in calpontselectexecutionplan.h, so we prepend QFEP_ %token CHAR_CONST RELOP LOGICOP QFEP_SELECT QFEP_FROM QFEP_WHERE GROUPBY OBJNAME INT_CONST LIMIT ORDERBY ASC %token DESC AS FUNC %type select_column_list table_name filter_predicate_list obj_name_aux opt_alias opt_as %type opt_limit_clause %type OBJNAME CHAR_CONST INT_CONST RELOP LOGICOP FUNC AS %type aliased_column_name select_column_name obj_name func_col groupby_item %type constant %destructor { delete $$; } OBJNAME CHAR_CONST INT_CONST RELOP LOGICOP FUNC AS %destructor { delete $$; } aliased_column_name select_column_name obj_name func_col groupby_item %destructor { delete $$; } constant %% statement: QFEP_SELECT select_column_list QFEP_FROM table_spec opt_where_clause opt_groupby_clause opt_orderby_clause opt_limit_clause ';' ; select_column_list: aliased_column_name { execplan::SRCP rcp($1); ParserCSEP->returnedCols().push_back(rcp); $$ = 0; } | select_column_list ',' aliased_column_name { execplan::SRCP rcp($3); ParserCSEP->returnedCols().push_back(rcp); $$ = 0; } ; select_column_name: obj_name { execplan::SimpleColumn* sc = dynamic_cast($1); if (sc->schemaName() == "infinidb_unknown" && !qfe::DefaultSchema.empty()) sc->schemaName(qfe::DefaultSchema); sc->setOID(); sc->tableAlias(sc->tableName()); sc->alias(execplan::make_tcn(sc->schemaName(), sc->tableName(), sc->columnName()).toString()); $$ = $1; } | func_col ; func_col: FUNC '(' select_column_name ')' { execplan::AggregateColumn* ag = new execplan::AggregateColumn(execplan::AggregateColumn::agname2num(*($1)), $3); delete $1; $$ = ag; } ; aliased_column_name: select_column_name opt_alias ; opt_alias: /* empty */ { $$ = 0; } | opt_as OBJNAME { delete $2; $$ = $1; } | opt_as CHAR_CONST { delete $2; $$ = $1; } ; opt_as: /* empty */ { $$ = 0; } | AS ; table_spec: aliased_table_name ; /* this is too loose for a table name, but it's easier to parse */ table_name: obj_name { execplan::SimpleColumn* sc=0; sc = dynamic_cast($1); execplan::CalpontSystemCatalog::TableAliasName tan; tan.schema = sc->tableName(); if (tan.schema == "infinidb_unknown" && !qfe::DefaultSchema.empty()) tan.schema = qfe::DefaultSchema; if (qfe::DefaultSchema.empty()) qfe::DefaultSchema = tan.schema; tan.table = sc->columnName(); tan.alias = tan.table; execplan::CalpontSelectExecutionPlan::TableList tl; tl.push_back(tan); ParserCSEP->tableList(tl); delete sc; $$ = 0; } ; aliased_table_name: table_name opt_alias ; opt_where_clause: /* empty */ | QFEP_WHERE filter_predicate_list ; filter_predicate_list: obj_name RELOP constant { pair cval = *($3); delete $3; execplan::SimpleColumn* sc=0; sc = dynamic_cast($1); qfe::utils::updateParseTree(ParserCSC, ParserCSEP, sc, *($2), cval); delete sc; delete $2; $$ = 0; } | filter_predicate_list LOGICOP obj_name RELOP constant { //string logicop = *($2); delete $2; pair cval = *($5); delete $5; execplan::SimpleColumn* sc=0; sc = dynamic_cast($3); qfe::utils::updateParseTree(ParserCSC, ParserCSEP, sc, *($4), cval); delete sc; delete $4; $$ = 0; } ; obj_name: obj_name_aux { //This is possibly a table name, but we shove it into a SimpleColumn. We'll // fix this in the table_spec production execplan::SimpleColumn* sc = new execplan::SimpleColumn("infinidb_unknown", "infinidb_unknown", *($1)); sc->tableAlias("infinidb_unknown"); sc->alias(execplan::make_tcn("infinidb_unknown", "infinidb_unknown", *($1)).toString()); //cerr << "inside parser: " << *sc << endl; delete $1; $$ = sc; } | obj_name_aux '.' obj_name_aux { //This is possibly a table name, but we shove it into a SimpleColumn. We'll // fix this in the table_spec production execplan::SimpleColumn* sc = new execplan::SimpleColumn("infinidb_unknown", *($1), *($3)); sc->tableAlias(*($1)); sc->alias(execplan::make_tcn("infinidb_unknown", *($1), *($3)).toString()); //cerr << "inside parser: " << *sc << endl; delete $1; delete $3; $$ = sc; } | obj_name_aux '.' obj_name_aux '.' obj_name_aux { if (qfe::DefaultSchema.empty()) qfe::DefaultSchema = *($1); execplan::SimpleColumn* sc = new execplan::SimpleColumn(*($1), *($3), *($5)); sc->tableAlias(*($3)); sc->alias(execplan::make_tcn(*($1), *($3), *($5)).toString()); //cerr << "inside parser: " << *sc << endl; delete $1; delete $3; delete $5; $$ = sc; } ; obj_name_aux: OBJNAME | '`' OBJNAME '`' { $$ = $2; } ; constant: CHAR_CONST { pair* p = new pair(1, *($1)); delete $1; $$ = p; } | INT_CONST { pair* p = new pair(0, *($1)); delete $1; $$ = p; } ; opt_groupby_clause: /* empty */ | GROUPBY groupby_items_list { YYERROR; } ; groupby_items_list: groupby_item | groupby_items_list ',' groupby_item { delete $3; } ; groupby_item: obj_name | INT_CONST { delete $1; $$ = 0; } ; opt_orderby_clause: /* empty */ | ORDERBY groupby_items_list opt_direction { YYERROR; } ; opt_direction: /* empty */ | ASC | DESC ; opt_limit_clause: /* empty */ { $$ = 0; } | LIMIT INT_CONST { delete $2; YYERROR; $$ = 0; } | LIMIT INT_CONST ',' INT_CONST { delete $2; delete $4; YYERROR; $$ = 0; } ; %% int qfeerror(const string& s) { extern int qfelineno; // defined and maintained in lex.c extern char *qfetext; // defined and maintained in lex.c cerr << "ERROR: " << s << " at symbol \"" << qfetext; cerr << "\" on line " << qfelineno << endl; return -1; } int qfeerror(const char *s) { return qfeerror(string(s)); } string* newstr(const char* cp) { string* strp; strp = new string(cp); return strp; }