%{ #include <NdbApi.hpp> #include <common/StmtArea.hpp> #include <common/DataRow.hpp> #include "CodeGen.hpp" #include <FlexLexer.h> #include "SimpleParser.hpp" /* redefine globals after headers */ #define yyparse SimpleParser_yyparse #if YYDEBUG #define yydebug SimpleParser_yydebug #endif #define YYLEX_PARAM simpleParserPtr #define YYPARSE_PARAM simpleParserPtr #define simpleParser (*static_cast<SimpleParser*>(simpleParserPtr)) static int yylex(YYSTYPE* lvalp, void* simpleParserPtr); #define yyerror(s) simpleParser.parseError(s) #if YYDEBUG // does not work in bison 1.75 #undef stderr #define stderr 0 #define YYFPRINTF simpleParser.ctx().print #endif // scanner states #define pushState(sc) simpleParser.pushState(sc) #define popState() simpleParser.popState() #define StateEval SimpleParser_stateEval #define StateType SimpleParser_stateType #define StatePhys SimpleParser_statePhys extern int SimpleParser_stateEval; extern int SimpleParser_stateType; extern int SimpleParser_statePhys; struct LimitPair { int off; int cnt; }; struct PhysAttr { int storage; int logging; }; %} %defines %pure-parser %verbose %union { Plan_root* m_root; Plan_stmt* m_stmt; Plan_select* m_select; Insert_op m_insert_op; Plan_insert* m_insert; Plan_update* m_update; Plan_delete* m_delete; Plan_create_table* m_create_table; Plan_create_index* m_create_index; NdbDictionary::Object::Type m_index_type; Plan_create_row* m_create_row; Plan_ddl_row* m_ddl_row; Plan_ddl_column* m_ddl_column; Plan_ddl_constr* m_ddl_constr; Plan_idx_column* m_idx_column; Plan_data_type* m_data_type; Plan_drop_table* m_drop_table; Plan_drop_index* m_drop_index; Plan_set_row* m_set_row; Plan_expr_row* m_expr_row; bool m_asc_desc; Plan_pred* m_pred; Pred_op::Opcode m_pred_opcode; Comp_op::Opcode m_comp_opcode; Plan_expr* m_expr; Expr_op::Opcode m_expr_opcode; Plan_dml_row* m_dml_row; Plan_dml_column* m_dml_column; Plan_table* m_table; Plan_table_list* m_table_list; const char* m_string; struct LimitPair* m_limit; int m_signed_integer; bool m_distinct; struct PhysAttr* m_phys_attr; NdbDictionary::Object::FragmentType m_storage_attr; bool m_logging_attr; SqlType::Type m_sql_type; } /* keywords */ %token T_AND T_ASC T_AUTO_INCREMENT T_BIGINT T_BINARY T_BLOB T_BY T_CHAR T_CLOB T_CONSTRAINT T_CREATE T_DATETIME T_DEFAULT T_DELETE T_DESC T_DISTINCT T_DOUBLE T_DROP T_FLOAT T_FOREIGN T_FROM T_GROUP T_HASH T_HAVING T_IN T_INDEX T_INSERT T_INT T_INTEGER T_INTO T_IS T_KEY T_LARGE T_LIKE T_LIMIT T_LOGGING T_LONGBLOB T_LONGCLOB T_MEDIUM T_NOLOGGING T_NOT T_NULL T_OFFSET T_ON T_OR T_ORDER T_PRECISION T_PRIMARY T_REAL T_REFERENCES T_ROWNUM T_SELECT T_SET T_SINGLE T_SMALL T_SMALLINT T_STORAGE T_SYSDATE T_TABLE T_UNIQUE T_UNSIGNED T_UPDATE T_VALUES T_VARBINARY T_VARCHAR T_WHERE T_WRITE /* identifiers and constants */ %token <m_string> T_IDENTIFIER <m_string> T_LINTEGER <m_string> T_LDECIMAL <m_string> T_LREAL <m_string> T_STRING /* expressions and predicates */ %token T_PLUS T_MINUS T_TIMES T_DIVIDE T_EQ T_NOTEQ T_LT T_LTEQ T_GT T_GTEQ T_QUES /* common special symbols */ %token T_PERIOD T_COMMA T_PARENLEFT T_PARENRIGHT T_ASTERISK T_ASSIGN %type <m_root> root %type <m_stmt> stmt %type <m_select> stmt_select %type <m_insert> stmt_insert %type <m_insert_op> insert_op %type <m_update> stmt_update %type <m_delete> stmt_delete %type <m_create_table> create_table %type <m_create_index> create_index %type <m_index_type> index_type %type <m_create_row> create_row %type <m_ddl_column> create_column %type <m_ddl_constr> create_constr %type <m_idx_column> idx_column %type <m_data_type> data_type %type <m_ddl_row> ddl_row %type <m_ddl_column> ddl_column %type <m_drop_table> drop_table %type <m_drop_index> drop_index %type <m_asc_desc> asc_desc %type <m_set_row> set_row %type <m_expr_row> expr_row %type <m_expr_row> sort_row %type <m_pred> where_clause %type <m_expr_row> order_clause %type <m_pred> pred %type <m_pred> pred1 %type <m_pred_opcode> pred1_op %type <m_pred> pred2 %type <m_pred_opcode> pred2_op %type <m_pred> pred3 %type <m_pred_opcode> pred3_op %type <m_pred> pred4 %type <m_comp_opcode> comp_op %type <m_expr> expr %type <m_expr> expr1 %type <m_expr_opcode> expr1_op %type <m_expr> expr2 %type <m_expr_opcode> expr2_op %type <m_expr> expr3 %type <m_expr_opcode> expr3_op %type <m_expr> expr4 %type <m_expr> expr_column %type <m_dml_row> dml_row %type <m_dml_column> dml_column %type <m_expr_row> value_row %type <m_expr> value_expr %type <m_table> table %type <m_table_list> table_list %type <m_string> dot_identifier %type <m_limit> limit_clause %type <m_signed_integer> signed_integer %type <m_distinct> distinct_clause %type <m_expr_row> group_clause %type <m_pred> having_clause %type <m_phys_attr> phys_attr %type <m_phys_attr> phys_attr2 %type <m_storage_attr> storage_attr %type <m_logging_attr> logging_attr %type <m_sql_type> blob_type %% root: stmt { Plan_root* root = simpleParser.root(); root->setStmt($1); } ; stmt: stmt_select { $$ = $1; } | stmt_insert { $$ = $1; } | stmt_update { $$ = $1; } | stmt_delete { $$ = $1; } | create_table { $$ = $1; } | create_index { $$ = $1; } | drop_table { $$ = $1; } | drop_index { $$ = $1; } ; stmt_select: T_SELECT distinct_clause expr_row T_FROM table_list where_clause group_clause having_clause order_clause limit_clause { Plan_root* root = simpleParser.root(); Plan_select* stmt = new Plan_select(root); root->saveNode(stmt); stmt->setDistinct($2); stmt->setRow($3); stmt->setList($5); if ($6 != 0) stmt->setPred($6); if ($7 != 0) stmt->setGroup($7); if ($8 != 0) stmt->setHaving($8); if ($9 != 0) stmt->setSort($9); if ($10 != 0) { stmt->setLimit($10->off, $10->cnt); delete $10; } $$ = stmt; } ; stmt_insert: insert_op T_INTO table T_VALUES T_PARENLEFT value_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_insert* stmt = new Plan_insert(root, $1); root->saveNode(stmt); stmt->setTable($3); stmt->setExprRow($6); $$ = stmt; } | insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT T_VALUES T_PARENLEFT value_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_insert* stmt = new Plan_insert(root, $1); root->saveNode(stmt); stmt->setTable($3); stmt->setDmlRow($5); stmt->setExprRow($9); $$ = stmt; } | insert_op T_INTO table stmt_select { Plan_root* root = simpleParser.root(); Plan_insert* stmt = new Plan_insert(root, $1); root->saveNode(stmt); stmt->setTable($3); stmt->setSelect($4); $$ = stmt; } | insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT stmt_select { Plan_root* root = simpleParser.root(); Plan_insert* stmt = new Plan_insert(root, $1); root->saveNode(stmt); stmt->setTable($3); stmt->setDmlRow($5); stmt->setSelect($7); $$ = stmt; } | insert_op T_INTO table T_SET set_row { Plan_root* root = simpleParser.root(); Plan_insert* stmt = new Plan_insert(root, $1); root->saveNode(stmt); stmt->setTable($3); stmt->setMysqlRow($5); $$ = stmt; } ; insert_op: T_INSERT { $$ = Insert_op_insert; } | T_WRITE { $$ = Insert_op_write; } ; stmt_update: T_UPDATE table T_SET set_row where_clause { Plan_root* root = simpleParser.root(); Plan_update* stmt = new Plan_update(root); root->saveNode(stmt); stmt->setTable($2); stmt->setRow($4); if ($5 != 0) stmt->setPred($5); $$ = stmt; } ; stmt_delete: T_DELETE T_FROM table where_clause { Plan_root* root = simpleParser.root(); Plan_delete* stmt = new Plan_delete(root); root->saveNode(stmt); stmt->setTable($3); if ($4 != 0) stmt->setPred($4); $$ = stmt; } ; create_table: T_CREATE T_TABLE dot_identifier T_PARENLEFT create_row T_PARENRIGHT phys_attr { Plan_root* root = simpleParser.root(); Plan_create_table* stmt = new Plan_create_table(root, $3); root->saveNode(stmt); delete[] $3; stmt->setCreateRow($5); if ($7->storage != -1) stmt->setFragmentType((NdbDictionary::Object::FragmentType)$7->storage); if ($7->logging != -1) stmt->setLogging($7->logging); delete $7; $$ = stmt; } ; create_row: create_column { Plan_root* root = simpleParser.root(); Plan_create_row* createRow = new Plan_create_row(root); root->saveNode(createRow); createRow->addColumn($1); $$ = createRow; } | create_constr { Plan_root* root = simpleParser.root(); Plan_create_row* createRow = new Plan_create_row(root); root->saveNode(createRow); createRow->addConstr($1); $$ = createRow; } | create_row T_COMMA create_column { Plan_create_row* createRow = $1; createRow->addColumn($3); $$ = createRow; } | create_row T_COMMA create_constr { Plan_create_row* createRow = $1; createRow->addConstr($3); $$ = createRow; } | create_row T_COMMA create_ignore { $$ = $1; } ; create_column: T_IDENTIFIER { pushState(StateType); } data_type { popState(); } { Plan_root* root = simpleParser.root(); Plan_ddl_column* ddlColumn = new Plan_ddl_column(root, $1); root->saveNode(ddlColumn); delete[] $1; ddlColumn->setType($3); simpleParser.curr(ddlColumn); } create_column_rest { $$ = simpleParser.curr((Plan_ddl_column*)0); } ; data_type: T_CHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary { Plan_root* root = simpleParser.root(); SqlType sqlType(simpleParser.ctx(), SqlType::Char, atoi($3), true); delete[] $3; if (! simpleParser.ctx().ok()) { YYABORT; } Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_BINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT { Plan_root* root = simpleParser.root(); SqlType sqlType(simpleParser.ctx(), SqlType::Binary, atoi($3), true); delete[] $3; if (! simpleParser.ctx().ok()) { YYABORT; } Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_VARCHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary { Plan_root* root = simpleParser.root(); SqlType sqlType(simpleParser.ctx(), SqlType::Varchar, atoi($3), true); delete[] $3; if (! simpleParser.ctx().ok()) { YYABORT; } Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_VARBINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT { Plan_root* root = simpleParser.root(); SqlType sqlType(simpleParser.ctx(), SqlType::Varbinary, atoi($3), true); delete[] $3; if (! simpleParser.ctx().ok()) { YYABORT; } Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_SMALLINT { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Smallint, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_INTEGER { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Integer, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_INT { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Integer, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_BIGINT { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Bigint, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_REAL { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Real, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_FLOAT { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Double, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_DOUBLE T_PRECISION { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Double, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | T_DATETIME { Plan_root* root = simpleParser.root(); SqlType sqlType(SqlType::Datetime, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } | blob_type { Plan_root* root = simpleParser.root(); SqlType sqlType($1, true); Plan_data_type* dataType = new Plan_data_type(root, sqlType); root->saveNode(dataType); $$ = dataType; } ; dummy_binary: /* empty */ | T_BINARY ; blob_type: T_BLOB { $$ = SqlType::Blob; } | T_LONGBLOB { $$ = SqlType::Blob; } | T_CLOB { $$ = SqlType::Clob; } | T_LONGCLOB { $$ = SqlType::Clob; } ; create_column_rest: /* empty */ | data_constr_list ; data_constr_list: data_constr | data_constr_list data_constr ; data_constr: T_NULL | T_NOT T_NULL { Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0); ddlColumn->setNotNull(); } | T_UNSIGNED { Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0); ddlColumn->setUnSigned(); } | T_PRIMARY T_KEY { Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0); ddlColumn->setPrimaryKey(); } | T_AUTO_INCREMENT { Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0); ddlColumn->setAutoIncrement(); } | T_DEFAULT expr { Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0); ddlColumn->setDefaultValue($2); } ; create_constr: T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root); root->saveNode(ddlConstr); ddlConstr->setRow($4); $$ = ddlConstr; } | T_CONSTRAINT dot_identifier T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root); root->saveNode(ddlConstr); ddlConstr->setRow($6); $$ = ddlConstr; } ; create_ignore: T_INDEX dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT | T_FOREIGN T_KEY T_PARENLEFT ddl_row T_PARENRIGHT T_REFERENCES dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT ; ddl_row: ddl_column { Plan_root* root = simpleParser.root(); Plan_ddl_row* ddlRow = new Plan_ddl_row(root); root->saveNode(ddlRow); ddlRow->addColumn($1); $$ = ddlRow; } | ddl_row T_COMMA ddl_column { Plan_ddl_row* ddlRow = $1; ddlRow->addColumn($3); $$ = ddlRow; } ; ddl_column: T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_ddl_column* column = new Plan_ddl_column(root, $1); root->saveNode(column); delete[] $1; $$ = column; } ; create_index: T_CREATE index_type T_INDEX dot_identifier T_ON table { Plan_root* root = simpleParser.root(); Plan_create_index* stmt = new Plan_create_index(root, $4); root->saveNode(stmt); delete[] $4; stmt->setType($2); stmt->setTable($6); simpleParser.curr(stmt); } T_PARENLEFT idx_row T_PARENRIGHT phys_attr { $$ = simpleParser.curr((Plan_create_index*)0); if ($11->storage != -1) $$->setFragmentType((NdbDictionary::Object::FragmentType)$11->storage); if ($11->logging != -1) $$->setLogging($11->logging); delete $11; } ; index_type: T_HASH { $$ = NdbDictionary::Object::HashIndex; } | T_UNIQUE T_HASH { $$ = NdbDictionary::Object::UniqueHashIndex; } | /* empty */ { $$ = NdbDictionary::Object::OrderedIndex; } | T_UNIQUE { $$ = NdbDictionary::Object::UniqueOrderedIndex; } ; idx_row: idx_column { } | idx_row T_COMMA idx_column { } ; idx_column: T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_idx_column* column = new Plan_idx_column(root, $1); root->saveNode(column); delete[] $1; Plan_create_index* stmt = simpleParser.curr((Plan_create_index*)0); stmt->addColumn(column); } ; phys_attr: { pushState(StatePhys); } phys_attr2 { popState(); } { $$ = $2; } ; phys_attr2: /* empty */ { $$ = new PhysAttr(); $$->storage = $$->logging = -1; } | phys_attr2 storage_attr { if ($1->storage != -1 && $1->storage != $2) { simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting STORAGE clauses"); YYABORT; } $$->storage = $2; } | phys_attr2 logging_attr { if ($1->logging != -1 && $1->logging != $2) { simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting LOGGING clauses"); YYABORT; } $$->logging = $2; } ; logging_attr: T_LOGGING { $$ = true; } | T_NOLOGGING { $$ = false; } ; storage_attr: T_STORAGE T_PARENLEFT T_SINGLE T_PARENRIGHT { $$ = NdbDictionary::Object::FragSingle; } | T_STORAGE T_PARENLEFT T_SMALL T_PARENRIGHT { $$ = NdbDictionary::Object::FragAllSmall; } | T_STORAGE T_PARENLEFT T_MEDIUM T_PARENRIGHT { $$ = NdbDictionary::Object::FragAllMedium; } | T_STORAGE T_PARENLEFT T_LARGE T_PARENRIGHT { $$ = NdbDictionary::Object::FragAllLarge; } ; drop_table: T_DROP T_TABLE dot_identifier { Plan_root* root = simpleParser.root(); Plan_drop_table* stmt = new Plan_drop_table(root, $3); root->saveNode(stmt); delete[] $3; $$ = stmt; } ; drop_index: T_DROP T_INDEX dot_identifier { Plan_root* root = simpleParser.root(); Plan_drop_index* stmt = new Plan_drop_index(root, $3); root->saveNode(stmt); delete[] $3; $$ = stmt; } | T_DROP T_INDEX dot_identifier T_ON dot_identifier { Plan_root* root = simpleParser.root(); Plan_drop_index* stmt = new Plan_drop_index(root, $3, $5); root->saveNode(stmt); delete[] $3; delete[] $5; $$ = stmt; } ; distinct_clause: /* empty */ { $$ = false; } | T_DISTINCT { $$ = true; } ; where_clause: /* empty */ { $$ = 0; } | T_WHERE pred { $$ = $2; } ; group_clause: /* empty */ { $$ = 0; } | T_GROUP T_BY value_row { $$ = $3; } ; having_clause: /* empty */ { $$ = 0; } | T_HAVING pred { $$ = $2; } ; order_clause: /* empty */ { $$ = 0; } | T_ORDER T_BY sort_row { $$ = $3; } ; limit_clause: /* empty */ { $$ = 0; } | T_LIMIT signed_integer { LimitPair* p = new LimitPair; p->off = 0; p->cnt = $2; $$ = p; } | T_LIMIT signed_integer T_COMMA signed_integer { LimitPair* p = new LimitPair; p->off = $2, p->cnt = $4; $$ = p; } | T_LIMIT signed_integer T_OFFSET signed_integer { LimitPair* p = new LimitPair; p->off = $4; p->cnt = $2; $$ = p; } ; signed_integer: T_LINTEGER { $$ = atoi($1); delete[] $1; } | T_MINUS T_LINTEGER { $$ = (-1) * atoi($2); delete[] $2; } ; set_row: dml_column T_ASSIGN expr { Plan_root* root = simpleParser.root(); Plan_set_row* row = new Plan_set_row(root); root->saveNode(row); row->addColumn($1); row->addExpr($3); $$ = row; } | set_row T_COMMA dml_column T_ASSIGN expr { Plan_set_row* row = $1; row->addColumn($3); row->addExpr($5); $$ = row; } ; dml_row: dml_column { Plan_root* root = simpleParser.root(); Plan_dml_row* row = new Plan_dml_row(root); root->saveNode(row); row->addColumn($1); $$ = row; } | dml_row T_COMMA dml_column { Plan_dml_row* row = $1; row->addColumn($3); $$ = row; } ; dml_column: T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_dml_column* column = new Plan_dml_column(root, $1); root->saveNode(column); delete[] $1; $$ = column; } ; value_row: value_expr { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->addExpr($1); $$ = row; } | value_row T_COMMA value_expr { Plan_expr_row* row = $1; row->addExpr($3); $$ = row; } ; value_expr: expr { $$ = $1; } ; sort_row: expr asc_desc { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->addExpr($1, $2); $$ = row; } | sort_row T_COMMA expr asc_desc { Plan_expr_row* row = $1; row->addExpr($3, $4); $$ = row; } ; asc_desc: /* empty */ { $$ = true; } | T_ASC { $$ = true; } | T_DESC { $$ = false; } ; expr_row: T_ASTERISK { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->setAsterisk(); $$ = row; } | T_TIMES /* XXX fix scanner state */ { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->setAsterisk(); $$ = row; } | expr { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->addExpr($1); $$ = row; } | expr T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_expr_row* row = new Plan_expr_row(root); root->saveNode(row); row->addExpr($1, BaseString($2)); $$ = row; } | expr_row T_COMMA expr { Plan_expr_row* row = $1; row->addExpr($3); $$ = row; } | expr_row T_COMMA expr T_IDENTIFIER { Plan_expr_row* row = $1; row->addExpr($3, BaseString($4)); $$ = row; } ; pred: { pushState(StateEval); } pred1 { popState(); } { $$ = $2; } ; pred1: pred2 { $$ = $1; } | pred1 pred1_op pred2 { Plan_root* root = simpleParser.root(); Pred_op op($2); Plan_pred_op* pred = new Plan_pred_op(root, op); root->saveNode(pred); pred->setPred(1, $1); pred->setPred(2, $3); $$ = pred; } ; pred1_op: T_OR { $$ = Pred_op::Or; } ; pred2: pred3 { $$ = $1; } | pred2 pred2_op pred3 { Plan_root* root = simpleParser.root(); Pred_op op($2); Plan_pred_op* pred = new Plan_pred_op(root, op); root->saveNode(pred); pred->setPred(1, $1); pred->setPred(2, $3); $$ = pred; } ; pred2_op: T_AND { $$ = Pred_op::And; } ; pred3: pred4 { $$ = $1; } | pred3_op pred3 { Plan_root* root = simpleParser.root(); Pred_op op($1); Plan_pred_op* pred = new Plan_pred_op(root, op); root->saveNode(pred); pred->setPred(1, $2); $$ = pred; } ; pred3_op: T_NOT { $$ = Pred_op::Not; } ; pred4: T_PARENLEFT pred1 T_PARENRIGHT { $$ = $2; } | expr1 comp_op expr1 { Plan_root* root = simpleParser.root(); Comp_op op($2); Plan_comp_op* comp = new Plan_comp_op(root, op); root->saveNode(comp); comp->setExpr(1, $1); comp->setExpr(2, $3); $$ = comp; } | expr1 T_IS T_NULL { Plan_root* root = simpleParser.root(); Comp_op op(Comp_op::Isnull); Plan_comp_op* comp = new Plan_comp_op(root, op); root->saveNode(comp); comp->setExpr(1, $1); $$ = comp; } | expr1 T_IS T_NOT T_NULL { Plan_root* root = simpleParser.root(); Comp_op op(Comp_op::Isnotnull); Plan_comp_op* comp = new Plan_comp_op(root, op); root->saveNode(comp); comp->setExpr(1, $1); $$ = comp; } | expr1 T_IN T_PARENLEFT value_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_pred* predOut = 0; // hack directly into Or of Eq Plan_expr* exprLeft = $1; Plan_expr_row* row = $4; for (unsigned i = row->getSize(); i >= 1; i--) { Plan_expr* exprRight = row->getExpr(i); Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Eq); root->saveNode(comp); comp->setExpr(1, exprLeft); comp->setExpr(2, exprRight); if (predOut == 0) { predOut = comp; } else { Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::Or); root->saveNode(pred); pred->setPred(1, predOut); pred->setPred(2, comp); predOut = pred; } } $$ = predOut; } | expr1 T_NOT T_IN T_PARENLEFT value_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); Plan_pred* predOut = 0; // hack directly into And of Noteq Plan_expr* exprLeft = $1; Plan_expr_row* row = $5; for (unsigned i = row->getSize(); i >= 1; i--) { Plan_expr* exprRight = row->getExpr(i); Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Noteq); root->saveNode(comp); comp->setExpr(1, exprLeft); comp->setExpr(2, exprRight); if (predOut == 0) { predOut = comp; } else { Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::And); root->saveNode(pred); pred->setPred(1, predOut); pred->setPred(2, comp); predOut = pred; } } $$ = predOut; } ; comp_op: T_EQ { $$ = Comp_op::Eq; } | T_NOTEQ { $$ = Comp_op::Noteq; } | T_LT { $$ = Comp_op::Lt; } | T_LTEQ { $$ = Comp_op::Lteq; } | T_GT { $$ = Comp_op::Gt; } | T_GTEQ { $$ = Comp_op::Gteq; } | T_LIKE { $$ = Comp_op::Like; } | T_NOT T_LIKE { $$ = Comp_op::Notlike; } ; expr: { pushState(StateEval); } expr1 { popState(); } { $$ = $2; } ; expr1: expr2 { $$ = $1; } | expr1 expr1_op expr2 { Plan_root* root = simpleParser.root(); Expr_op op($2); Plan_expr_op* expr = new Plan_expr_op(root, op); root->saveNode(expr); expr->setExpr(1, $1); expr->setExpr(2, $3); $$ = expr; } ; expr1_op: T_PLUS { $$ = Expr_op::Add; } | T_MINUS { $$ = Expr_op::Subtract; } ; expr2: expr3 { $$ = $1; } | expr2 expr2_op expr3 { Plan_root* root = simpleParser.root(); Expr_op op($2); Plan_expr_op* expr = new Plan_expr_op(root, op); root->saveNode(expr); expr->setExpr(1, $1); expr->setExpr(2, $3); $$ = expr; } ; expr2_op: T_TIMES { $$ = Expr_op::Multiply; } | T_DIVIDE { $$ = Expr_op::Divide; } ; expr3: expr4 { $$ = $1; } | expr3_op expr3 { Plan_root* root = simpleParser.root(); Expr_op op($1); Plan_expr_op* expr = new Plan_expr_op(root, op); root->saveNode(expr); expr->setExpr(1, $2); $$ = expr; } ; expr3_op: T_PLUS { $$ = Expr_op::Plus; } | T_MINUS { $$ = Expr_op::Minus; } ; expr4: T_PARENLEFT expr1 T_PARENRIGHT { $$ = $2; } | T_IDENTIFIER T_PARENLEFT expr_row T_PARENRIGHT { Plan_root* root = simpleParser.root(); const Expr_func& spec = Expr_func::find($1); if (spec.m_name == 0) { simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "unknown function %s", $1); delete[] $1; YYABORT; } Plan_expr_func* func = new Plan_expr_func(root, spec); root->saveNode(func); delete[] $1; func->setArgs($3); $$ = func; } | T_ROWNUM { Plan_root* root = simpleParser.root(); const Expr_func& spec = Expr_func::find("ROWNUM"); ctx_assert(spec.m_name != 0); Plan_expr_func* func = new Plan_expr_func(root, spec); root->saveNode(func); func->setArgs(0); $$ = func; } | T_SYSDATE { Plan_root* root = simpleParser.root(); const Expr_func& spec = Expr_func::find("SYSDATE"); ctx_assert(spec.m_name != 0); Plan_expr_func* func = new Plan_expr_func(root, spec); root->saveNode(func); func->setArgs(0); $$ = func; } | expr_column { $$ = $1; } | T_STRING { Plan_root* root = simpleParser.root(); LexType lexType(LexType::Char); Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1); root->saveNode(expr); delete[] $1; $$ = expr; } | T_LINTEGER { Plan_root* root = simpleParser.root(); LexType lexType(LexType::Integer); Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1); root->saveNode(expr); delete[] $1; $$ = expr; } | T_LDECIMAL { Plan_root* root = simpleParser.root(); LexType lexType(LexType::Float); Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1); root->saveNode(expr); delete[] $1; $$ = expr; } | T_LREAL { Plan_root* root = simpleParser.root(); LexType lexType(LexType::Float); Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1); root->saveNode(expr); delete[] $1; $$ = expr; } | T_NULL { Plan_root* root = simpleParser.root(); LexType lexType(LexType::Null); Plan_expr_const* expr = new Plan_expr_const(root, lexType, ""); root->saveNode(expr); $$ = expr; } | T_QUES { Plan_root* root = simpleParser.root(); unsigned paramNumber = simpleParser.paramNumber(); ctx_assert(paramNumber != 0); Plan_expr_param* expr = new Plan_expr_param(root, paramNumber); root->saveNode(expr); $$ = expr; } ; expr_column: T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_expr_column* column = new Plan_expr_column(root, $1); root->saveNode(column); delete[] $1; $$ = column; } | T_IDENTIFIER T_PERIOD T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_expr_column* column = new Plan_expr_column(root, $3); root->saveNode(column); delete[] $3; column->setCname($1); $$ = column; } | T_IDENTIFIER T_PERIOD T_IDENTIFIER T_PERIOD T_IDENTIFIER { Plan_root* root = simpleParser.root(); BaseString str; str.append($1); str.append("."); str.append($3); delete[] $1; delete[] $3; Plan_expr_column* column = new Plan_expr_column(root, $5); root->saveNode(column); delete[] $5; column->setCname(str); $$ = column; } ; table_list: table { Plan_root* root = simpleParser.root(); Plan_table_list* tableList = new Plan_table_list(root); root->saveNode(tableList); tableList->addTable($1); $$ = tableList; } | table_list T_COMMA table { Plan_table_list* tableList = $1; tableList->addTable($3); $$ = tableList; } ; table: dot_identifier { Plan_root* root = simpleParser.root(); Plan_table* table = new Plan_table(root, $1); root->saveNode(table); delete[] $1; $$ = table; } | dot_identifier T_IDENTIFIER { Plan_root* root = simpleParser.root(); Plan_table* table = new Plan_table(root, $1); root->saveNode(table); delete[] $1; table->setCname($2); delete[] $2; $$ = table; } ; dot_identifier: T_IDENTIFIER { $$ = $1; } | T_IDENTIFIER T_PERIOD T_IDENTIFIER { char* s = new char[strlen($1) + 1 + strlen($3) + 1]; strcpy(s, $1); strcat(s, "."); strcat(s, $3); delete[] $1; delete[] $3; $$ = s; } ; %% static int yylex(YYSTYPE* lvalp, void* simpleParserPtr) { int ret = simpleParser.yylex(); *lvalp = simpleParser.yylval(); return ret; } /* vim: set filetype=yacc: */