#ifndef LASUITE_H #define LASUITE_H enum TOKTYPE { TOK_EOF, TOK_INVAL, TOK_UNKNOWN, // Corruption in input TOK_OPNBRACE, TOK_CLSBRACE, TOK_OPNSQUARE, TOK_CLSSQUARE, TOK_OPNPAR, TOK_CLSPAR, TOK_STAR, // * TOK_PLUS,TOK_MINUS,TOK_DIVIDE,TOK_MULTIPLY,TOK_MODULO, // TOK_STAR vs TOK_MULITPLY TOK_NAME, TOK_STRING, TOK_NUM, TOK_COMMA, TOK_COLON, TOK_DIFFER, // != or <> TOK_NOT, // ! TOK_EQUAL, // = TOK_LEFTJOIN, // *= TOK_RIGHTJOIN, // =* TOK_SMALLER,TOK_SMALLEREQ, // < <= TOK_GREATER,TOK_GREATEREQ, // > >= // All keywords TOK_IN, TOK_FROM, TOK_INTO, TOK_SELECT, TOK_UPDATE, TOK_TABLE, TOK_WHERE, TOK_TOP, TOK_TO, TOK_HAVING, TOK_DELETE, TOK_TRUNCATE, TOK_LIKE, TOK_AS, TOK_ORDER, TOK_BY, TOK_ASC, TOK_DESC, TOK_GROUP, TOK_DISTINCT, TOK_CREATE, TOK_COUNT, TOK_OR, TOK_AND, TOK_FUNCTION, TOK_SET, TOK_JOIN, TOK_INNER, TOK_LEFT, TOK_RIGHT, TOK_OUTER, TOK_ON, TOK_OFF, TOK_CASE, TOK_CASEval, TOK_WHEN, TOK_THEN, TOK_ELSE, TOK_END, TOK_INDEX, TOK_IS, TOK_DROP, TOK_ADD, TOK_MODIFY, TOK_IF, TOK_WHILE, TOK_BEGIN, TOK_INSERT, TOK_VALUES, TOK_EXISTS, TOK_UNIQUE, TOK_CLUSTERED, TOK_NONCLUSTERED, TOK_UNION, TOK_NULL, TOK_BETWEEN, TOK_USE, TOK_IDENTITY, TOK_DEFAULT, TOK_CHECK, TOK_CONSTRAINT, TOK_LOCK, TOK_GRANT, TOK_FIELDTYPE, TOK_SETUSER, TOK_WITH, TOK_WITHOPTION, TOK_PARTITION, TOK_ROUNDROBIN, TOK_PRINT, TOK_REFERENCES, TOK_TRIGGER, TOK_FOR, TOK_PRIMARY, TOK_KEY, TOK_EXEC, TOK_ALTER, TOK_FOREIGN, TOK_SP_HELPSEGMENT, TOK_SP_CONFIGURE, TOK_SP_DBOPTION, TOK_CHECKPOINT, TOK_READTEXT, TOK_WRITETEXT, TOK_WAITFOR, TOK_DELAY, TOK_TRANSACTION, TOK_COMMIT, TOK_ROLLBACK, TOK_DBCC, TOK_TRACEON, TOK_STATISTICS, TOK_DECLARE, TOK_BULK, TOK_NODESCRIBE, TOK_OUTPUT, TOK_ALL }; #include #include #include #include #define ERROR_PARSER 10000 #define ERROR_REFORMAT 10001 struct SQL_OPTS{ std::string limit; bool nocount; unsigned textsize; bool logthis; // Request tds to log the original query bool no_order_by; std::string format_error; // Error message produce during the reformat operation int temp_alloc_id; std::map temp2id; // ID allocated for temporary table int sqlerror; // Last SQL or parser error bool is_assign; // Used during the reformat process to find out if this was @var assignment bool last_was_select; // Last statement was a select. Use to select either found_rows() or row_count() // function to replace @@rowcount bool mysql_mode; // "set mysql on" bypass the parser until we get "set mysql off" SQL_OPTS(){ nocount = false; textsize = 32768; logthis = false; no_order_by = false; temp_alloc_id=1000; sqlerror = 0; // This is either a MySQL error number, or ERROR_xxx above is_assign = false; last_was_select = false; mysql_mode = false; } void addtemptable(const std::string &table); void deltemptable(const std::string &table); int gettempid(const std::string &table); }; class TOKEN{ public: TOKTYPE type; std::string val; TOKEN(){ type = TOK_EOF; } }; class PARSE{ std::string buf; const char *pt; const char *last; std::stack saved; bool inval; public: PARSE (const char *line); void showlast (); void unget(const TOKEN &tok); TOKEN get(); void setinval(TOKEN &t); unsigned getlastpos(); }; struct ITEMS{ virtual ITEMS *dup() const = 0; virtual ~ITEMS(){}; virtual void dump() const = 0; virtual bool cmp(const ITEMS *) const = 0; }; class EXPR; class PAREXPR; class UNION; class USE; class GRANT; class EXEC; class ALTER; class SELECT; class UPDATE; class INSERT; class DROP; class SET; class IF; class CREATE_INDEX; class CREATE_TABLE; class CREATE_TRIGGER; class DELETE; class TRUNCATE; class DECLARE; struct ITEM{ enum ITEMTYPE{ IS_UNKNOWN, IS_TOKEN, IS_EXPR, IS_PAREXPR, IS_UNION, IS_SELECT, IS_UPDATE, IS_INSERT, IS_DROP, IS_SET, IS_IF, IS_CREATE_TABLE, IS_CREATE_INDEX, IS_CREATE_TRIGGER, IS_DELETE, IS_TRUNCATE, IS_ITEMS, IS_USE, IS_GRANT, IS_EXEC,IS_ALTER,IS_DECLARE } type; union { void *ptr; EXPR *expr; PAREXPR *parexpr; UNION *uunion; SELECT *select; UPDATE *update; INSERT *insert; DROP *drop; SET *sset; IF *iif; CREATE_TABLE *ctable; CREATE_INDEX *cindex; CREATE_TRIGGER *ctrig; DELETE *del; TRUNCATE *truncate; ITEMS *items; USE *use; GRANT *grant; EXEC *exec; ALTER *alter; DECLARE *declare; }u; TOKEN t; void init(){ type = IS_UNKNOWN; u.ptr = NULL; } ITEM(TOKEN &_t); ITEM(ITEMS &_i); ITEM(EXPR &_i); ITEM(PAREXPR &_i); ITEM(UNION &_i); ITEM(USE &_u); ITEM(GRANT &_g); ITEM(EXEC &_e); ITEM(ALTER &_a); ITEM(SELECT &_s); ITEM(INSERT &_i); ITEM(UPDATE &_u); ITEM(DROP &_d); ITEM(SET &_s); ITEM(IF &_i); ITEM(CREATE_TABLE &_c); ITEM(CREATE_INDEX &_c); ITEM(CREATE_TRIGGER &_c); ITEM(DELETE &_t); ITEM(TRUNCATE &_t); ITEM(DECLARE &_t); ITEM(const ITEM &it); ~ITEM(); void dump() const; bool cmp(const ITEM &it) const; bool cmpstruct(const ITEM &it) const; // Compare the structure of the query, not the values std::string getckey() const; // Get the classification key of the ITEM to speed up search void reformat (std::string &s, SQL_OPTS &opts) const; bool istokentype (TOKTYPE toktype) const{ return type == IS_TOKEN && t.type == toktype; } }; struct EXPR: public ITEMS{ std::vector items; EXPR(); EXPR(const EXPR &e); EXPR *dup() const; void add (TOKEN &t); unsigned size() const; void add (ITEMS &i); void add (USE &i); void add (GRANT &g); void add (EXEC &e); void add (ALTER &a); void add (EXPR &e); void add (PAREXPR &e); void add (UNION &e); void add (SELECT &s); void add (UPDATE &s); void add (INSERT &s); void add (DROP &s); void add (SET &s); void add (IF &s); void add (CREATE_TABLE &s); void add (CREATE_INDEX &s); void add (CREATE_TRIGGER &s); void add (DELETE &s); void add (TRUNCATE &s); void add (DECLARE &s); void dump(bool top) const; void dump() const; void dumptop() const; bool cmp(const ITEMS *it) const; bool cmpstruct(const ITEMS *it) const; std::string getckey() const; void reformat (std::string &s, SQL_OPTS &opts) const; bool not_empty() const; }; struct ONESQL{ std::string sql; bool is_assign; // There is a variable assignment in this query (select @var:=1) ONESQL(){ is_assign = false; } ONESQL(const char *_sql){ sql = _sql; is_assign = false; } }; void parser_inittokens(); void parser_initfunctions(); class EXPR; int f_main (PARSE &p, EXPR &expr); int parser_expr_reformat (const EXPR &expr, std::vector &tbs, SQL_OPTS &opts, unsigned id); void parser_set_renamedb (const char *oldname, const char *newname); void parser_set_createindex (bool nocreateindex); void parser_setusertype (const char *sybase_type, const char *mysql_type); void parser_set_createtb (const std::vector &tb); std::string parser_cnvsybtype(const char *sybtype); void parser_set_engine(const char *engine); // Stats about how stuff is used struct PATCH_USAGE{ unsigned function_convert; unsigned function_datediff; unsigned function_object_name; unsigned function_object_id; unsigned function_textptr; unsigned function_db_id; unsigned setuser; unsigned error; unsigned no_default_on_create; unsigned grant; unsigned exec; unsigned alter; unsigned old_outer_join; unsigned skip_order_by; PATCH_USAGE(){ function_convert = 0; function_datediff = 0; function_object_name = 0; function_object_id = 0; function_textptr = 0; function_db_id = 0; setuser = 0; error = 0; no_default_on_create = 0; grant = 0; exec = 0; alter = 0; old_outer_join = 0; skip_order_by = 0; } }; extern PATCH_USAGE pusage; #endif