diff options
author | unknown <konstantin@mysql.com> | 2006-02-02 12:03:35 +0300 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2006-02-02 12:03:35 +0300 |
commit | f0263ac452817f83d28047a20399fdef1e232e9a (patch) | |
tree | 72eba57e7d347ae15c6a57558fd619c2afc05b31 /sql | |
parent | 7088b39da895cf22a2b71d21a8313cbf0dda3760 (diff) | |
parent | 13f908c23e8a663f265bdcb16f6ec5c4a45bb470 (diff) | |
download | mariadb-git-f0263ac452817f83d28047a20399fdef1e232e9a.tar.gz |
Merge mysql.com:/home/kostja/mysql/mysql-5.0-for_merge
into mysql.com:/home/kostja/mysql/mysql-5.1-merge
client/mysqltest.c:
Auto merged
mysql-test/r/alter_table.result:
Auto merged
mysql-test/r/create.result:
Auto merged
mysql-test/r/ctype_ucs.result:
Auto merged
mysql-test/r/mysqltest.result:
Auto merged
mysql-test/r/ps.result:
Auto merged
mysql-test/r/sp-error.result:
Auto merged
mysql-test/r/sp.result:
Auto merged
mysql-test/r/type_decimal.result:
Auto merged
mysql-test/r/variables.result:
Auto merged
mysql-test/r/view_grant.result:
Auto merged
mysql-test/t/alter_table.test:
Auto merged
mysql-test/t/create.test:
Auto merged
mysql-test/t/ctype_ucs.test:
Auto merged
mysql-test/t/mysqltest.test:
Auto merged
mysql-test/t/ps.test:
Auto merged
mysql-test/t/sp.test:
Auto merged
sql/ha_berkeley.cc:
Auto merged
sql/sp_head.cc:
Auto merged
sql/sp_head.h:
Auto merged
sql/sql_handler.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/share/errmsg.txt:
Auto merged
mysql-test/mysql-test-run.pl:
SCCS merged
sql/sql_yacc.yy:
Manual merge: resolve the conflict with moved sp_if rule
Diffstat (limited to 'sql')
-rw-r--r-- | sql/share/errmsg.txt | 4 | ||||
-rw-r--r-- | sql/sp_head.cc | 143 | ||||
-rw-r--r-- | sql/sp_head.h | 88 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 9 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 2 | ||||
-rw-r--r-- | sql/sql_handler.cc | 7 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 19 |
7 files changed, 154 insertions, 118 deletions
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 80910a8fd81..084ab31c459 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5172,8 +5172,8 @@ ER_SP_WRONG_NO_OF_FETCH_ARGS eng "Incorrect number of FETCH variables" ger "Falsche Anzahl von FETCH-Variablen" ER_SP_FETCH_NO_DATA 02000 - eng "No data to FETCH" - ger "Keine Daten mit FETCH abzuholen" + eng "No data - zero rows fetched, selected, or processed" + ger "Keine Daten - null Zeilen geholt (fetch), ausgewählt oder verarbeitet" ER_SP_DUP_PARAM 42000 eng "Duplicate parameter: %s" ger "Doppelter Parameter: %s" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 33eb652208f..e1af0b7d939 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -433,7 +433,8 @@ sp_head::operator delete(void *ptr, size_t size) sp_head::sp_head() :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), m_flags(0), m_recursion_level(0), m_next_cached_sp(0), - m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this) + m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this), + m_cont_level(0) { m_return_field_def.charset = NULL; @@ -442,6 +443,7 @@ sp_head::sp_head() DBUG_ENTER("sp_head::sp_head"); m_backpatch.empty(); + m_cont_backpatch.empty(); m_lex.empty(); hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); @@ -1751,6 +1753,39 @@ sp_head::fill_field_definition(THD *thd, LEX *lex, void +sp_head::new_cont_backpatch(sp_instr_jump_if_not *i) +{ + m_cont_level+= 1; + if (i) + { + /* Use the cont. destination slot to store the level */ + i->m_cont_dest= m_cont_level; + (void)m_cont_backpatch.push_front(i); + } +} + +void +sp_head::add_cont_backpatch(sp_instr_jump_if_not *i) +{ + i->m_cont_dest= m_cont_level; + (void)m_cont_backpatch.push_front(i); +} + +void +sp_head::do_cont_backpatch() +{ + uint dest= instructions(); + uint lev= m_cont_level--; + sp_instr_jump_if_not *i; + + while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev) + { + i->m_cont_dest= dest; + (void)m_cont_backpatch.pop(); + } +} + +void sp_head::set_info(longlong created, longlong modified, st_sp_chistics *chistics, ulong sql_mode) { @@ -1964,7 +1999,10 @@ sp_head::show_create_function(THD *thd) /* - TODO: what does this do?? + Do some minimal optimization of the code: + 1) Mark used instructions + 1.1) While doing this, shortcut jumps to jump instructions + 2) Compact the code, removing unused instructions */ void sp_head::optimize() @@ -1987,7 +2025,7 @@ void sp_head::optimize() else { if (src != dst) - { + { // Move the instruction and update prev. jumps sp_instr *ibp; List_iterator_fast<sp_instr> li(bp); @@ -1995,8 +2033,7 @@ void sp_head::optimize() while ((ibp= li++)) { sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp); - if (ji->m_dest == src) - ji->m_dest= dst; + ji->set_destination(src, dst); } } i->opt_move(dst, &bp); @@ -2430,67 +2467,6 @@ sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp) /* - sp_instr_jump_if class functions -*/ - -int -sp_instr_jump_if::execute(THD *thd, uint *nextp) -{ - DBUG_ENTER("sp_instr_jump_if::execute"); - DBUG_PRINT("info", ("destination: %u", m_dest)); - DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this)); -} - -int -sp_instr_jump_if::exec_core(THD *thd, uint *nextp) -{ - Item *it; - int res; - - it= sp_prepare_func_item(thd, &m_expr); - if (!it) - res= -1; - else - { - res= 0; - if (it->val_bool()) - *nextp = m_dest; - else - *nextp = m_ip+1; - } - - return res; -} - -void -sp_instr_jump_if::print(String *str) -{ - /* jump_if dest ... */ - if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too - return; - str->qs_append(STRING_WITH_LEN("jump_if ")); - str->qs_append(m_dest); - str->qs_append(' '); - m_expr->print(str); -} - -uint -sp_instr_jump_if::opt_mark(sp_head *sp) -{ - sp_instr *i; - - marked= 1; - if ((i= sp->get_instr(m_dest))) - { - m_dest= i->opt_shortcut_jump(sp, this); - m_optdest= sp->get_instr(m_dest); - } - sp->opt_mark(m_dest); - return m_ip+1; -} - - -/* sp_instr_jump_if_not class functions */ @@ -2511,7 +2487,10 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) it= sp_prepare_func_item(thd, &m_expr); if (! it) + { res= -1; + *nextp = m_cont_dest; + } else { res= 0; @@ -2529,11 +2508,13 @@ void sp_instr_jump_if_not::print(String *str) { /* jump_if_not dest ... */ - if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too + if (str->reserve(2*SP_INSTR_UINT_MAXLEN+14+32)) // Add some for the expr. too return; str->qs_append(STRING_WITH_LEN("jump_if_not ")); str->qs_append(m_dest); - str->qs_append(' '); + str->append('('); + str->qs_append(m_cont_dest); + str->append(") "); m_expr->print(str); } @@ -2550,9 +2531,35 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp) m_optdest= sp->get_instr(m_dest); } sp->opt_mark(m_dest); + if ((i= sp->get_instr(m_cont_dest))) + { + m_cont_dest= i->opt_shortcut_jump(sp, this); + m_cont_optdest= sp->get_instr(m_cont_dest); + } + sp->opt_mark(m_cont_dest); return m_ip+1; } +void +sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr> *bp) +{ + /* + cont. destinations may point backwards after shortcutting jumps + during the mark phase. If it's still pointing forwards, only + push this for backpatching if sp_instr_jump::opt_move() will not + do it (i.e. if the m_dest points backwards). + */ + if (m_cont_dest > m_ip) + { // Forward + if (m_dest < m_ip) + bp->push_back(this); + } + else if (m_cont_optdest) + m_cont_dest= m_cont_optdest->m_ip; // Backward + /* This will take care of m_dest and m_ip */ + sp_instr_jump::opt_move(dst, bp); +} + /* sp_instr_freturn class functions diff --git a/sql/sp_head.h b/sql/sp_head.h index e4ef7526683..37ab486c6f3 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex); struct sp_label; class sp_instr; +class sp_instr_jump_if_not; struct sp_cond_type; struct sp_pvar; @@ -265,6 +266,18 @@ public: int check_backpatch(THD *thd); + // Start a new cont. backpatch level. If 'i' is NULL, the level is just incr. + void + new_cont_backpatch(sp_instr_jump_if_not *i); + + // Add an instruction to the current level + void + add_cont_backpatch(sp_instr_jump_if_not *i); + + // Backpatch (and pop) the current level to the current position. + void + do_cont_backpatch(); + char *name(uint *lenp = 0) const { if (lenp) @@ -356,6 +369,18 @@ private: } bp_t; List<bp_t> m_backpatch; // Instructions needing backpatching /* + We need a special list for backpatching of conditional jump's continue + destination (in the case of a continue handler catching an error in + the test), since it would otherwise interfere with the normal backpatch + mechanism - jump_if_not instructions have two different destination + which are to be patched differently. + Since these occur in a more restricted way (always the same "level" in + the code), we don't need the label. + */ + List<sp_instr_jump_if_not> m_cont_backpatch; + uint m_cont_level; // The current cont. backpatch level + + /* Multi-set representing optimized list of tables to be locked by this routine. Does not include tables which are used by invoked routines. @@ -668,50 +693,17 @@ public: m_dest= dest; } -protected: - - sp_instr *m_optdest; // Used during optimization - -}; // class sp_instr_jump : public sp_instr - - -class sp_instr_jump_if : public sp_instr_jump -{ - sp_instr_jump_if(const sp_instr_jump_if &); /* Prevent use of these */ - void operator=(sp_instr_jump_if &); - -public: - - sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) - : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE) - {} - - sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) - : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE) - {} - - virtual ~sp_instr_jump_if() - {} - - virtual int execute(THD *thd, uint *nextp); - - virtual int exec_core(THD *thd, uint *nextp); - - virtual void print(String *str); - - virtual uint opt_mark(sp_head *sp); - - virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start) + virtual void set_destination(uint old_dest, uint new_dest) { - return m_ip; + if (m_dest == old_dest) + m_dest= new_dest; } -private: +protected: - Item *m_expr; // The condition - sp_lex_keeper m_lex_keeper; + sp_instr *m_optdest; // Used during optimization -}; // class sp_instr_jump_if : public sp_instr_jump +}; // class sp_instr_jump : public sp_instr class sp_instr_jump_if_not : public sp_instr_jump @@ -721,12 +713,16 @@ class sp_instr_jump_if_not : public sp_instr_jump public: + uint m_cont_dest; // Where continue handlers will go + sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex) - : sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE) + : sp_instr_jump(ip, ctx), m_cont_dest(0), m_expr(i), + m_lex_keeper(lex, TRUE), m_cont_optdest(0) {} sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex) - : sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE) + : sp_instr_jump(ip, ctx, dest), m_cont_dest(0), m_expr(i), + m_lex_keeper(lex, TRUE), m_cont_optdest(0) {} virtual ~sp_instr_jump_if_not() @@ -745,10 +741,20 @@ public: return m_ip; } + virtual void opt_move(uint dst, List<sp_instr> *ibp); + + virtual void set_destination(uint old_dest, uint new_dest) + { + sp_instr_jump::set_destination(old_dest, new_dest); + if (m_cont_dest == old_dest) + m_cont_dest= new_dest; + } + private: Item *m_expr; // The condition sp_lex_keeper m_lex_keeper; + sp_instr *m_cont_optdest; // Used during optimization }; // class sp_instr_jump_if_not : public sp_instr_jump diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 6d803362d86..d1cd7b964c2 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -52,6 +52,15 @@ typedef struct sp_pvar #define SP_LAB_BEGIN 2 // Label at BEGIN #define SP_LAB_ITER 3 // Label at iteration control +/* + An SQL/PSM label. Can refer to the identifier used with the + "label_name:" construct which may precede some SQL/PSM statements, or + to an implicit implementation-dependent identifier which the parser + inserts before a high-level flow control statement such as + IF/WHILE/REPEAT/LOOP, when such statement is rewritten into + a combination of low-level jump/jump_if instructions and labels. +*/ + typedef struct sp_label { char *name; diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index c36c904f45d..215de01e657 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno, Only "exception conditions" are propagated to handlers in calling contexts. If no handler is found locally for a "completion condition" (warning or "not found") we will simply resume execution. - */ + */ if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) && level == MYSQL_ERROR::WARN_LEVEL_ERROR) return m_prev_runtime_ctx->find_handler(sql_errno, level); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 78eacd02e56..9dfa20da522 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -422,12 +422,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, if (!lock) goto err0; // mysql_lock_tables() printed error message already - if (cond && ((!cond->fixed && - cond->fix_fields(thd, &cond)) || cond->check_cols(1))) + if (cond) { if (table->query_id != thd->query_id) cond->cleanup(); // File was reopened - goto err0; + if ((!cond->fixed && + cond->fix_fields(thd, &cond)) || cond->check_cols(1)) + goto err0; } if (keyname) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 513dc0b7416..a116dc27891 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2288,7 +2288,9 @@ sp_proc_stmt: ; sp_proc_stmt_if: - IF sp_if END IF {} + IF { Lex->sphead->new_cont_backpatch(NULL); } + sp_if END IF + { Lex->sphead->do_cont_backpatch(); } ; sp_proc_stmt_statement: @@ -2366,13 +2368,17 @@ sp_proc_stmt_case_simple: CASE_SYM WHEN_SYM { Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE; + Lex->sphead->new_cont_backpatch(NULL); } - sp_case END CASE_SYM {} + sp_case END CASE_SYM { Lex->sphead->do_cont_backpatch(); } ; sp_proc_stmt_case: CASE_SYM - { Lex->sphead->reset_lex(YYTHD); } + { + Lex->sphead->reset_lex(YYTHD); + Lex->sphead->new_cont_backpatch(NULL); + } expr WHEN_SYM { LEX *lex= Lex; @@ -2396,6 +2402,7 @@ sp_proc_stmt_case: sp_case END CASE_SYM { Lex->spcont->pop_case_expr_id(); + Lex->sphead->do_cont_backpatch(); } ; @@ -2686,6 +2693,7 @@ sp_if: $2, lex); sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + sp->add_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2744,6 +2752,7 @@ sp_case: i= new sp_instr_jump_if_not(ip, ctx, expr, lex); } sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + sp->add_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2873,6 +2882,7 @@ sp_unlabeled_control: /* Jumping forward */ sp->push_backpatch(i, lex->spcont->last_label()); + sp->new_cont_backpatch(i); sp->add_instr(i); sp->restore_lex(YYTHD); } @@ -2884,6 +2894,7 @@ sp_unlabeled_control: sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); lex->sphead->add_instr(i); + lex->sphead->do_cont_backpatch(); } | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM { Lex->sphead->reset_lex(YYTHD); } @@ -2897,6 +2908,8 @@ sp_unlabeled_control: lex); lex->sphead->add_instr(i); lex->sphead->restore_lex(YYTHD); + /* We can shortcut the cont_backpatch here */ + i->m_cont_dest= ip+1; } ; |