00001 /* -*- C++ -*- */ 00002 /* Copyright (C) 2002 MySQL AB 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00017 00018 #ifndef _SP_HEAD_H_ 00019 #define _SP_HEAD_H_ 00020 00021 #ifdef USE_PRAGMA_INTERFACE 00022 #pragma interface /* gcc class implementation */ 00023 #endif 00024 00025 #include <stddef.h> 00026 00027 // Values for the type enum. This reflects the order of the enum declaration 00028 // in the CREATE TABLE command. 00029 #define TYPE_ENUM_FUNCTION 1 00030 #define TYPE_ENUM_PROCEDURE 2 00031 #define TYPE_ENUM_TRIGGER 3 00032 00033 Item_result 00034 sp_map_result_type(enum enum_field_types type); 00035 00036 Item::Type 00037 sp_map_item_type(enum enum_field_types type); 00038 00039 uint 00040 sp_get_flags_for_command(LEX *lex); 00041 00042 struct sp_label; 00043 class sp_instr; 00044 class sp_instr_opt_meta; 00045 class sp_instr_jump_if_not; 00046 struct sp_cond_type; 00047 struct sp_variable; 00048 00049 class sp_name : public Sql_alloc 00050 { 00051 public: 00052 00053 LEX_STRING m_db; 00054 LEX_STRING m_name; 00055 LEX_STRING m_qname; 00056 /* 00057 Key representing routine in the set of stored routines used by statement. 00058 Consists of 1-byte routine type and m_qname (which usually refences to 00059 same buffer). Note that one must complete initialization of the key by 00060 calling set_routine_type(). 00061 */ 00062 LEX_STRING m_sroutines_key; 00063 00064 sp_name(LEX_STRING db, LEX_STRING name) 00065 : m_db(db), m_name(name) 00066 { 00067 m_qname.str= m_sroutines_key.str= 0; 00068 m_qname.length= m_sroutines_key.length= 0; 00069 } 00070 00071 /* 00072 Creates temporary sp_name object from key, used mainly 00073 for SP-cache lookups. 00074 */ 00075 sp_name(char *key, uint key_len) 00076 { 00077 m_sroutines_key.str= key; 00078 m_sroutines_key.length= key_len; 00079 m_name.str= m_qname.str= key + 1; 00080 m_name.length= m_qname.length= key_len - 1; 00081 m_db.str= 0; 00082 m_db.length= 0; 00083 } 00084 00085 // Init. the qualified name from the db and name. 00086 void init_qname(THD *thd); // thd for memroot allocation 00087 00088 void set_routine_type(char type) 00089 { 00090 m_sroutines_key.str[0]= type; 00091 } 00092 00093 ~sp_name() 00094 {} 00095 }; 00096 00097 00098 bool 00099 check_routine_name(LEX_STRING name); 00100 00101 class sp_head :private Query_arena 00102 { 00103 sp_head(const sp_head &); /* Prevent use of these */ 00104 void operator=(sp_head &); 00105 00106 MEM_ROOT main_mem_root; 00107 public: 00108 /* Possible values of m_flags */ 00109 enum { 00110 HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN 00111 IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE 00112 IN_HANDLER= 4, // Is set if the parser is in a handler body 00113 MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) 00114 CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE 00115 IS_INVOKED= 32, // Is set if this sp_head is being used 00116 HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit' 00117 /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ 00118 HAS_COMMIT_OR_ROLLBACK= 128, 00119 LOG_SLOW_STATEMENTS= 256, // Used by events 00120 LOG_GENERAL_LOG= 512, // Used by events 00121 BINLOG_ROW_BASED_IF_MIXED= 1024 00122 }; 00123 00124 /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ 00125 int m_type; 00126 uint m_flags; // Boolean attributes of a stored routine 00127 00128 create_field m_return_field_def; /* This is used for FUNCTIONs only. */ 00129 00130 const uchar *m_tmp_query; // Temporary pointer to sub query string 00131 st_sp_chistics *m_chistics; 00132 ulong m_sql_mode; // For SHOW CREATE and execution 00133 LEX_STRING m_qname; // db.name 00134 LEX_STRING m_db; 00135 LEX_STRING m_name; 00136 LEX_STRING m_params; 00137 LEX_STRING m_body; 00138 LEX_STRING m_defstr; 00139 LEX_STRING m_definer_user; 00140 LEX_STRING m_definer_host; 00141 longlong m_created; 00142 longlong m_modified; 00143 /* Recursion level of the current SP instance. The levels are numbered from 0 */ 00144 ulong m_recursion_level; 00145 /* 00146 A list of diferent recursion level instances for the same procedure. 00147 For every recursion level we have a sp_head instance. This instances 00148 connected in the list. The list ordered by increasing recursion level 00149 (m_recursion_level). 00150 */ 00151 sp_head *m_next_cached_sp; 00152 /* 00153 Pointer to the first element of the above list 00154 */ 00155 sp_head *m_first_instance; 00156 /* 00157 Pointer to the first free (non-INVOKED) routine in the list of 00158 cached instances for this SP. This pointer is set only for the first 00159 SP in the list of instences (see above m_first_cached_sp pointer). 00160 The pointer equal to 0 if we have no free instances. 00161 For non-first instance value of this pointer meanless (point to itself); 00162 */ 00163 sp_head *m_first_free_instance; 00164 /* 00165 Pointer to the last element in the list of instances of the SP. 00166 For non-first instance value of this pointer meanless (point to itself); 00167 */ 00168 sp_head *m_last_cached_sp; 00169 /* 00170 Set containing names of stored routines used by this routine. 00171 Note that unlike elements of similar set for statement elements of this 00172 set are not linked in one list. Because of this we are able save memory 00173 by using for this set same objects that are used in 'sroutines' sets 00174 for statements of which this stored routine consists. 00175 */ 00176 HASH m_sroutines; 00177 // Pointers set during parsing 00178 const uchar *m_param_begin, *m_param_end, *m_body_begin; 00179 00180 /* 00181 Security context for stored routine which should be run under 00182 definer privileges. 00183 */ 00184 Security_context m_security_ctx; 00185 00186 static void * 00187 operator new(size_t size); 00188 00189 static void 00190 operator delete(void *ptr, size_t size); 00191 00192 sp_head(); 00193 00194 // Initialize after we have reset mem_root 00195 void 00196 init(LEX *lex); 00197 00198 /* Copy sp name from parser. */ 00199 void 00200 init_sp_name(THD *thd, sp_name *spname); 00201 00202 // Initialize strings after parsing header 00203 void 00204 init_strings(THD *thd, LEX *lex); 00205 00206 int 00207 create(THD *thd); 00208 00209 virtual ~sp_head(); 00210 00211 // Free memory 00212 void 00213 destroy(); 00214 00215 bool 00216 execute_trigger(THD *thd, const char *db, const char *table, 00217 GRANT_INFO *grant_onfo); 00218 00219 bool 00220 execute_function(THD *thd, Item **args, uint argcount, Field *return_fld); 00221 00222 bool 00223 execute_procedure(THD *thd, List<Item> *args); 00224 00225 int 00226 show_create_procedure(THD *thd); 00227 00228 int 00229 show_create_function(THD *thd); 00230 00231 void 00232 add_instr(sp_instr *instr); 00233 00234 inline uint 00235 instructions() 00236 { 00237 return m_instr.elements; 00238 } 00239 00240 inline sp_instr * 00241 last_instruction() 00242 { 00243 sp_instr *i; 00244 00245 get_dynamic(&m_instr, (gptr)&i, m_instr.elements-1); 00246 return i; 00247 } 00248 00249 // Resets lex in 'thd' and keeps a copy of the old one. 00250 void 00251 reset_lex(THD *thd); 00252 00253 // Restores lex in 'thd' from our copy, but keeps some status from the 00254 // one in 'thd', like ptr, tables, fields, etc. 00255 void 00256 restore_lex(THD *thd); 00257 00258 // Put the instruction on the backpatch list, associated with the label. 00259 void 00260 push_backpatch(sp_instr *, struct sp_label *); 00261 00262 // Update all instruction with this label in the backpatch list to 00263 // the current position. 00264 void 00265 backpatch(struct sp_label *); 00266 00267 // Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. 00268 void 00269 new_cont_backpatch(sp_instr_opt_meta *i); 00270 00271 // Add an instruction to the current level 00272 void 00273 add_cont_backpatch(sp_instr_opt_meta *i); 00274 00275 // Backpatch (and pop) the current level to the current position. 00276 void 00277 do_cont_backpatch(); 00278 00279 char *name(uint *lenp = 0) const 00280 { 00281 if (lenp) 00282 *lenp= m_name.length; 00283 return m_name.str; 00284 } 00285 00286 char *create_string(THD *thd, ulong *lenp); 00287 00288 Field *create_result_field(uint field_max_length, const char *field_name, 00289 TABLE *table); 00290 00291 bool fill_field_definition(THD *thd, LEX *lex, 00292 enum enum_field_types field_type, 00293 create_field *field_def); 00294 00295 void set_info(longlong created, longlong modified, 00296 st_sp_chistics *chistics, ulong sql_mode); 00297 00298 void set_definer(const char *definer, uint definerlen); 00299 void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name); 00300 00301 void reset_thd_mem_root(THD *thd); 00302 00303 void restore_thd_mem_root(THD *thd); 00304 00305 void optimize(); 00306 void opt_mark(uint ip); 00307 00308 void recursion_level_error(THD *thd); 00309 00310 inline sp_instr * 00311 get_instr(uint i) 00312 { 00313 sp_instr *ip; 00314 00315 if (i < m_instr.elements) 00316 get_dynamic(&m_instr, (gptr)&ip, i); 00317 else 00318 ip= NULL; 00319 return ip; 00320 } 00321 00322 /* Add tables used by routine to the table list. */ 00323 bool add_used_tables_to_table_list(THD *thd, 00324 TABLE_LIST ***query_tables_last_ptr, 00325 TABLE_LIST *belong_to_view); 00326 00327 /* 00328 Check if this stored routine contains statements disallowed 00329 in a stored function or trigger, and set an appropriate error message 00330 if this is the case. 00331 */ 00332 bool is_not_allowed_in_function(const char *where) 00333 { 00334 if (m_flags & CONTAINS_DYNAMIC_SQL) 00335 my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL"); 00336 else if (m_flags & MULTI_RESULTS) 00337 my_error(ER_SP_NO_RETSET, MYF(0), where); 00338 else if (m_flags & HAS_SET_AUTOCOMMIT_STMT) 00339 my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0)); 00340 else if (m_type != TYPE_ENUM_PROCEDURE && 00341 (m_flags & sp_head::HAS_COMMIT_OR_ROLLBACK)) 00342 { 00343 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 00344 return TRUE; 00345 } 00346 return test(m_flags & 00347 (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT)); 00348 } 00349 00350 #ifndef DBUG_OFF 00351 int show_routine_code(THD *thd); 00352 #endif 00353 00354 /* 00355 This method is intended for attributes of a routine which need 00356 to propagate upwards to the LEX of the caller (when a property of a 00357 sp_head needs to "taint" the caller). 00358 */ 00359 void propagate_attributes(LEX *lex) 00360 { 00361 #ifdef HAVE_ROW_BASED_REPLICATION 00362 /* 00363 If this routine needs row-based binary logging, the entire top statement 00364 too (we cannot switch from statement-based to row-based only for this 00365 routine, as in statement-based the top-statement may be binlogged and 00366 the substatements not). 00367 */ 00368 if (m_flags & BINLOG_ROW_BASED_IF_MIXED) 00369 lex->binlog_row_based_if_mixed= TRUE; 00370 #endif 00371 } 00372 00373 00374 private: 00375 00376 MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root 00377 THD *m_thd; // Set if we have reset mem_root 00378 00379 sp_pcontext *m_pcont; // Parse context 00380 List<LEX> m_lex; // Temp. store for the other lex 00381 DYNAMIC_ARRAY m_instr; // The "instructions" 00382 typedef struct 00383 { 00384 struct sp_label *lab; 00385 sp_instr *instr; 00386 } bp_t; 00387 List<bp_t> m_backpatch; // Instructions needing backpatching 00388 /* 00389 We need a special list for backpatching of instructions with a continue 00390 destination (in the case of a continue handler catching an error in 00391 the test), since it would otherwise interfere with the normal backpatch 00392 mechanism - e.g. jump_if_not instructions have two different destinations 00393 which are to be patched differently. 00394 Since these occur in a more restricted way (always the same "level" in 00395 the code), we don't need the label. 00396 */ 00397 List<sp_instr_opt_meta> m_cont_backpatch; 00398 uint m_cont_level; // The current cont. backpatch level 00399 00400 /* 00401 Multi-set representing optimized list of tables to be locked by this 00402 routine. Does not include tables which are used by invoked routines. 00403 00404 Note: for prelocking-free SPs this multiset is constructed too. 00405 We do so because the same instance of sp_head may be called both 00406 in prelocked mode and in non-prelocked mode. 00407 */ 00408 HASH m_sptabs; 00409 00410 bool 00411 execute(THD *thd); 00412 00413 /* 00414 Merge the list of tables used by query into the multi-set of tables used 00415 by routine. 00416 */ 00417 bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check); 00418 }; // class sp_head : public Sql_alloc 00419 00420 00421 // 00422 // "Instructions"... 00423 // 00424 00425 class sp_instr :public Query_arena, public Sql_alloc 00426 { 00427 sp_instr(const sp_instr &); /* Prevent use of these */ 00428 void operator=(sp_instr &); 00429 00430 public: 00431 00432 uint marked; 00433 uint m_ip; // My index 00434 sp_pcontext *m_ctx; // My parse context 00435 00436 // Should give each a name or type code for debugging purposes? 00437 sp_instr(uint ip, sp_pcontext *ctx) 00438 :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) 00439 {} 00440 00441 virtual ~sp_instr() 00442 { free_items(); } 00443 00444 00445 /* 00446 Execute this instruction 00447 00448 SYNOPSIS 00449 execute() 00450 thd Thread handle 00451 nextp OUT index of the next instruction to execute. (For most 00452 instructions this will be the instruction following this 00453 one). 00454 00455 RETURN 00456 0 on success, 00457 other if some error occured 00458 */ 00459 00460 virtual int execute(THD *thd, uint *nextp) = 0; 00461 00462 /* 00463 Execute core function of instruction after all preparations (e.g. 00464 setting of proper LEX, saving part of the thread context have been 00465 done). 00466 00467 Should be implemented for instructions using expressions or whole 00468 statements (thus having to have own LEX). Used in concert with 00469 sp_lex_keeper class and its descendants (there are none currently). 00470 */ 00471 virtual int exec_core(THD *thd, uint *nextp); 00472 00473 virtual void print(String *str) = 0; 00474 00475 virtual void backpatch(uint dest, sp_pcontext *dst_ctx) 00476 {} 00477 00478 /* 00479 Mark this instruction as reachable during optimization and return the 00480 index to the next instruction. Jump instruction will mark their 00481 destination too recursively. 00482 */ 00483 virtual uint opt_mark(sp_head *sp) 00484 { 00485 marked= 1; 00486 return m_ip+1; 00487 } 00488 00489 /* 00490 Short-cut jumps to jumps during optimization. This is used by the 00491 jump instructions' opt_mark() methods. 'start' is the starting point, 00492 used to prevent the mark sweep from looping for ever. Return the 00493 end destination. 00494 */ 00495 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 00496 { 00497 return m_ip; 00498 } 00499 00500 /* 00501 Inform the instruction that it has been moved during optimization. 00502 Most instructions will simply update its index, but jump instructions 00503 must also take care of their destination pointers. Forward jumps get 00504 pushed to the backpatch list 'ibp'. 00505 */ 00506 virtual void opt_move(uint dst, List<sp_instr> *ibp) 00507 { 00508 m_ip= dst; 00509 } 00510 00511 }; // class sp_instr : public Sql_alloc 00512 00513 00514 /* 00515 Auxilary class to which instructions delegate responsibility 00516 for handling LEX and preparations before executing statement 00517 or calculating complex expression. 00518 00519 Exist mainly to avoid having double hierarchy between instruction 00520 classes. 00521 00522 TODO: Add ability to not store LEX and do any preparations if 00523 expression used is simple. 00524 */ 00525 00526 class sp_lex_keeper 00527 { 00528 /* Prevent use of these */ 00529 sp_lex_keeper(const sp_lex_keeper &); 00530 void operator=(sp_lex_keeper &); 00531 public: 00532 00533 sp_lex_keeper(LEX *lex, bool lex_resp) 00534 : m_lex(lex), m_lex_resp(lex_resp), 00535 lex_query_tables_own_last(NULL) 00536 { 00537 lex->sp_lex_in_use= TRUE; 00538 } 00539 virtual ~sp_lex_keeper() 00540 { 00541 if (m_lex_resp) 00542 { 00543 lex_end(m_lex); 00544 delete m_lex; 00545 } 00546 } 00547 00548 /* 00549 Prepare execution of instruction using LEX, if requested check whenever 00550 we have read access to tables used and open/lock them, call instruction's 00551 exec_core() method, perform cleanup afterwards. 00552 */ 00553 int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, 00554 sp_instr* instr); 00555 00556 inline uint sql_command() const 00557 { 00558 return (uint)m_lex->sql_command; 00559 } 00560 00561 void disable_query_cache() 00562 { 00563 m_lex->safe_to_cache_query= 0; 00564 } 00565 private: 00566 00567 LEX *m_lex; 00568 /* 00569 Indicates whenever this sp_lex_keeper instance responsible 00570 for LEX deletion. 00571 */ 00572 bool m_lex_resp; 00573 00574 /* 00575 Support for being able to execute this statement in two modes: 00576 a) inside prelocked mode set by the calling procedure or its ancestor. 00577 b) outside of prelocked mode, when this statement enters/leaves 00578 prelocked mode itself. 00579 */ 00580 00581 /* 00582 List of additional tables this statement needs to lock when it 00583 enters/leaves prelocked mode on its own. 00584 */ 00585 TABLE_LIST *prelocking_tables; 00586 00587 /* 00588 The value m_lex->query_tables_own_last should be set to this when the 00589 statement enters/leaves prelocked mode on its own. 00590 */ 00591 TABLE_LIST **lex_query_tables_own_last; 00592 }; 00593 00594 00595 // 00596 // Call out to some prepared SQL statement. 00597 // 00598 class sp_instr_stmt : public sp_instr 00599 { 00600 sp_instr_stmt(const sp_instr_stmt &); /* Prevent use of these */ 00601 void operator=(sp_instr_stmt &); 00602 00603 public: 00604 00605 LEX_STRING m_query; // For thd->query 00606 00607 sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex) 00608 : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE) 00609 { 00610 m_query.str= 0; 00611 m_query.length= 0; 00612 } 00613 00614 virtual ~sp_instr_stmt() 00615 {}; 00616 00617 virtual int execute(THD *thd, uint *nextp); 00618 00619 virtual int exec_core(THD *thd, uint *nextp); 00620 00621 virtual void print(String *str); 00622 00623 private: 00624 00625 sp_lex_keeper m_lex_keeper; 00626 00627 }; // class sp_instr_stmt : public sp_instr 00628 00629 00630 class sp_instr_set : public sp_instr 00631 { 00632 sp_instr_set(const sp_instr_set &); /* Prevent use of these */ 00633 void operator=(sp_instr_set &); 00634 00635 public: 00636 00637 sp_instr_set(uint ip, sp_pcontext *ctx, 00638 uint offset, Item *val, enum enum_field_types type, 00639 LEX *lex, bool lex_resp) 00640 : sp_instr(ip, ctx), m_offset(offset), m_value(val), m_type(type), 00641 m_lex_keeper(lex, lex_resp) 00642 {} 00643 00644 virtual ~sp_instr_set() 00645 {} 00646 00647 virtual int execute(THD *thd, uint *nextp); 00648 00649 virtual int exec_core(THD *thd, uint *nextp); 00650 00651 virtual void print(String *str); 00652 00653 private: 00654 00655 uint m_offset; // Frame offset 00656 Item *m_value; 00657 enum enum_field_types m_type; // The declared type 00658 sp_lex_keeper m_lex_keeper; 00659 00660 }; // class sp_instr_set : public sp_instr 00661 00662 00663 /* 00664 Set NEW/OLD row field value instruction. Used in triggers. 00665 */ 00666 class sp_instr_set_trigger_field : public sp_instr 00667 { 00668 sp_instr_set_trigger_field(const sp_instr_set_trigger_field &); 00669 void operator=(sp_instr_set_trigger_field &); 00670 00671 public: 00672 00673 sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, 00674 Item_trigger_field *trg_fld, 00675 Item *val, LEX *lex) 00676 : sp_instr(ip, ctx), 00677 trigger_field(trg_fld), 00678 value(val), m_lex_keeper(lex, TRUE) 00679 {} 00680 00681 virtual ~sp_instr_set_trigger_field() 00682 {} 00683 00684 virtual int execute(THD *thd, uint *nextp); 00685 00686 virtual int exec_core(THD *thd, uint *nextp); 00687 00688 virtual void print(String *str); 00689 00690 private: 00691 Item_trigger_field *trigger_field; 00692 Item *value; 00693 sp_lex_keeper m_lex_keeper; 00694 }; // class sp_instr_trigger_field : public sp_instr 00695 00696 00697 /* 00698 An abstract class for all instructions with destinations that 00699 needs to be updated by the optimizer. 00700 Even if not all subclasses will use both the normal destination and 00701 the continuation destination, we put them both here for simplicity. 00702 */ 00703 class sp_instr_opt_meta : public sp_instr 00704 { 00705 public: 00706 00707 uint m_dest; // Where we will go 00708 uint m_cont_dest; // Where continue handlers will go 00709 00710 sp_instr_opt_meta(uint ip, sp_pcontext *ctx) 00711 : sp_instr(ip, ctx), 00712 m_dest(0), m_cont_dest(0), m_optdest(0), m_cont_optdest(0) 00713 {} 00714 00715 sp_instr_opt_meta(uint ip, sp_pcontext *ctx, uint dest) 00716 : sp_instr(ip, ctx), 00717 m_dest(dest), m_cont_dest(0), m_optdest(0), m_cont_optdest(0) 00718 {} 00719 00720 virtual ~sp_instr_opt_meta() 00721 {} 00722 00723 virtual void set_destination(uint old_dest, uint new_dest) 00724 = 0; 00725 00726 protected: 00727 00728 sp_instr *m_optdest; // Used during optimization 00729 sp_instr *m_cont_optdest; // Used during optimization 00730 00731 }; // class sp_instr_opt_meta : public sp_instr 00732 00733 class sp_instr_jump : public sp_instr_opt_meta 00734 { 00735 sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */ 00736 void operator=(sp_instr_jump &); 00737 00738 public: 00739 00740 sp_instr_jump(uint ip, sp_pcontext *ctx) 00741 : sp_instr_opt_meta(ip, ctx) 00742 {} 00743 00744 sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest) 00745 : sp_instr_opt_meta(ip, ctx, dest) 00746 {} 00747 00748 virtual ~sp_instr_jump() 00749 {} 00750 00751 virtual int execute(THD *thd, uint *nextp); 00752 00753 virtual void print(String *str); 00754 00755 virtual uint opt_mark(sp_head *sp); 00756 00757 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start); 00758 00759 virtual void opt_move(uint dst, List<sp_instr> *ibp); 00760 00761 virtual void backpatch(uint dest, sp_pcontext *dst_ctx) 00762 { 00763 if (m_dest == 0) // Don't reset 00764 m_dest= dest; 00765 } 00766 00767 /* 00768 Update the destination; used by the optimizer. 00769 */ 00770 virtual void set_destination(uint old_dest, uint new_dest) 00771 { 00772 if (m_dest == old_dest) 00773 m_dest= new_dest; 00774 } 00775 00776 }; // class sp_instr_jump : public sp_instr_opt_meta 00777 00778 00779 class sp_instr_jump_if_not : public sp_instr_jump 00780 { 00781 sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */ 00782 void operator=(sp_instr_jump_if_not &); 00783 00784 public: 00785 00786 sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) 00787 : sp_instr_jump(ip, ctx), m_expr(i), 00788 m_lex_keeper(lex, TRUE) 00789 {} 00790 00791 sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) 00792 : sp_instr_jump(ip, ctx, dest), m_expr(i), 00793 m_lex_keeper(lex, TRUE) 00794 {} 00795 00796 virtual ~sp_instr_jump_if_not() 00797 {} 00798 00799 virtual int execute(THD *thd, uint *nextp); 00800 00801 virtual int exec_core(THD *thd, uint *nextp); 00802 00803 virtual void print(String *str); 00804 00805 virtual uint opt_mark(sp_head *sp); 00806 00807 /* Override sp_instr_jump's shortcut; we stop here */ 00808 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 00809 { 00810 return m_ip; 00811 } 00812 00813 virtual void opt_move(uint dst, List<sp_instr> *ibp); 00814 00815 virtual void set_destination(uint old_dest, uint new_dest) 00816 { 00817 sp_instr_jump::set_destination(old_dest, new_dest); 00818 if (m_cont_dest == old_dest) 00819 m_cont_dest= new_dest; 00820 } 00821 00822 private: 00823 00824 Item *m_expr; // The condition 00825 sp_lex_keeper m_lex_keeper; 00826 00827 }; // class sp_instr_jump_if_not : public sp_instr_jump 00828 00829 00830 class sp_instr_freturn : public sp_instr 00831 { 00832 sp_instr_freturn(const sp_instr_freturn &); /* Prevent use of these */ 00833 void operator=(sp_instr_freturn &); 00834 00835 public: 00836 00837 sp_instr_freturn(uint ip, sp_pcontext *ctx, 00838 Item *val, enum enum_field_types type, LEX *lex) 00839 : sp_instr(ip, ctx), m_value(val), m_type(type), m_lex_keeper(lex, TRUE) 00840 {} 00841 00842 virtual ~sp_instr_freturn() 00843 {} 00844 00845 virtual int execute(THD *thd, uint *nextp); 00846 00847 virtual int exec_core(THD *thd, uint *nextp); 00848 00849 virtual void print(String *str); 00850 00851 virtual uint opt_mark(sp_head *sp) 00852 { 00853 marked= 1; 00854 return UINT_MAX; 00855 } 00856 00857 protected: 00858 00859 Item *m_value; 00860 enum enum_field_types m_type; 00861 sp_lex_keeper m_lex_keeper; 00862 00863 }; // class sp_instr_freturn : public sp_instr 00864 00865 00866 class sp_instr_hpush_jump : public sp_instr_jump 00867 { 00868 sp_instr_hpush_jump(const sp_instr_hpush_jump &); /* Prevent use of these */ 00869 void operator=(sp_instr_hpush_jump &); 00870 00871 public: 00872 00873 sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp) 00874 : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp) 00875 { 00876 m_cond.empty(); 00877 } 00878 00879 virtual ~sp_instr_hpush_jump() 00880 { 00881 m_cond.empty(); 00882 } 00883 00884 virtual int execute(THD *thd, uint *nextp); 00885 00886 virtual void print(String *str); 00887 00888 virtual uint opt_mark(sp_head *sp); 00889 00890 /* Override sp_instr_jump's shortcut; we stop here. */ 00891 virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) 00892 { 00893 return m_ip; 00894 } 00895 00896 inline void add_condition(struct sp_cond_type *<
