diff options
author | unknown <bell@sanja.is.com.ua> | 2004-11-25 02:27:02 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-11-25 02:27:02 +0200 |
commit | a352372170815bebd65755bc5fff00fdf964cf9b (patch) | |
tree | 64b87aad2e52257f0c6cb4d27336e0d1fb516494 /sql | |
parent | f88d01932f4a81682267e21022686d3dea4edb78 (diff) | |
parent | 00899088a5f576721ecbf3ca235cdfcd691c8a0e (diff) | |
download | mariadb-git-a352372170815bebd65755bc5fff00fdf964cf9b.tar.gz |
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-join-5.0
sql/item.cc:
Auto merged
sql/item.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/table.h:
Auto merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 4 | ||||
-rw-r--r-- | sql/ha_myisammrg.cc | 11 | ||||
-rw-r--r-- | sql/ha_myisammrg.h | 1 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 56 | ||||
-rw-r--r-- | sql/ha_ndbcluster.h | 5 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/item.cc | 42 | ||||
-rw-r--r-- | sql/item.h | 15 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 20 | ||||
-rw-r--r-- | sql/mysql_priv.h | 9 | ||||
-rw-r--r-- | sql/mysqld.cc | 23 | ||||
-rw-r--r-- | sql/opt_range.cc | 6 | ||||
-rw-r--r-- | sql/set_var.cc | 17 | ||||
-rw-r--r-- | sql/sp.cc | 3 | ||||
-rw-r--r-- | sql/sp_head.cc | 8 | ||||
-rw-r--r-- | sql/sp_head.h | 8 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_do.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 28 | ||||
-rw-r--r-- | sql/sql_lex.h | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 45 | ||||
-rw-r--r-- | sql/sql_select.cc | 13 | ||||
-rw-r--r-- | sql/sql_select.h | 3 | ||||
-rw-r--r-- | sql/sql_show.cc | 26 | ||||
-rw-r--r-- | sql/sql_table.cc | 15 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 107 | ||||
-rw-r--r-- | sql/sql_trigger.h | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 66 | ||||
-rw-r--r-- | sql/table.h | 5 |
29 files changed, 375 insertions, 185 deletions
diff --git a/sql/field.cc b/sql/field.cc index e372a37d2f6..e8669dad406 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1863,9 +1863,9 @@ int Field_long::store(double nr) res=0; error= 1; } - else if (nr > (double) (ulong) ~0L) + else if (nr > (double) UINT_MAX32) { - res=(int32) (uint32) ~0L; + res= UINT_MAX32; error= 1; } else diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 2574892b1fe..744128faf69 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -35,6 +35,17 @@ const char **ha_myisammrg::bas_ext() const { static const char *ext[]= { ".MRG", NullS }; return ext; } +const char *ha_myisammrg::index_type(uint key_number) +{ + return ((table->key_info[key_number].flags & HA_FULLTEXT) ? + "FULLTEXT" : + (table->key_info[key_number].flags & HA_SPATIAL) ? + "SPATIAL" : + (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ? + "RTREE" : + "BTREE"); +} + int ha_myisammrg::open(const char *name, int mode, uint test_if_locked) { diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index 264c580220c..6058c32c805 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -32,6 +32,7 @@ class ha_myisammrg: public handler ~ha_myisammrg() {} const char *table_type() const { return "MRG_MyISAM"; } const char **bas_ext() const; + const char *index_type(uint key_number); ulong table_flags() const { return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME | diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index a9537db39c7..a77d9cf05af 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -796,7 +796,8 @@ int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase) error= create_unique_index(unique_index_name, key_info); break; case UNIQUE_INDEX: - error= create_unique_index(unique_index_name, key_info); + if (!(error= check_index_fields_not_null(i))) + error= create_unique_index(unique_index_name, key_info); break; case ORDERED_INDEX: error= create_ordered_index(index_name, key_info); @@ -848,6 +849,26 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const ORDERED_INDEX); } +int ha_ndbcluster::check_index_fields_not_null(uint inx) +{ + KEY* key_info= table->key_info + inx; + KEY_PART_INFO* key_part= key_info->key_part; + KEY_PART_INFO* end= key_part+key_info->key_parts; + DBUG_ENTER("check_index_fields_not_null"); + + for (; key_part != end; key_part++) + { + Field* field= key_part->field; + if (field->maybe_null()) + { + my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX), + MYF(0),field->field_name); + DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX); + } + } + + DBUG_RETURN(0); +} void ha_ndbcluster::release_metadata() { @@ -1247,7 +1268,7 @@ inline int ha_ndbcluster::next_result(byte *buf) m_ops_pending= 0; m_blobs_pending= FALSE; } - check= cursor->nextResult(contact_ndb); + check= cursor->nextResult(contact_ndb, m_force_send); if (check == 0) { // One more record found @@ -1540,7 +1561,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key, DBUG_ASSERT(op->getSorted() == sorted); DBUG_ASSERT(op->getLockMode() == (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type)); - if(op->reset_bounds()) + if(op->reset_bounds(m_force_send)) DBUG_RETURN(ndb_err(m_active_trans)); } @@ -2373,7 +2394,7 @@ int ha_ndbcluster::index_last(byte *buf) int res; if((res= ordered_index_scan(0, 0, TRUE, buf)) == 0){ NdbResultSet *cursor= m_active_cursor; - while((res= cursor->nextResult(TRUE)) == 0); + while((res= cursor->nextResult(TRUE, m_force_send)) == 0); if(res == 1){ unpack_record(buf); table->status= 0; @@ -2459,7 +2480,7 @@ int ha_ndbcluster::rnd_init(bool scan) { if (!scan) DBUG_RETURN(1); - int res= cursor->restart(); + int res= cursor->restart(m_force_send); DBUG_ASSERT(res == 0); } index_init(table->primary_key); @@ -2490,7 +2511,7 @@ int ha_ndbcluster::close_scan() m_ops_pending= 0; } - cursor->close(); + cursor->close(m_force_send); m_active_cursor= NULL; DBUG_RETURN(0); } @@ -3014,6 +3035,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) m_transaction_on= FALSE; else m_transaction_on= thd->variables.ndb_use_transactions; + // m_use_local_query_cache= thd->variables.ndb_use_local_query_cache; m_active_trans= thd->transaction.all.ndb_tid ? (NdbConnection*)thd->transaction.all.ndb_tid: @@ -3740,7 +3762,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): m_ha_not_exact_count(FALSE), m_force_send(TRUE), m_autoincrement_prefetch(32), - m_transaction_on(TRUE) + m_transaction_on(TRUE), + m_use_local_query_cache(FALSE) { int i; @@ -4428,7 +4451,7 @@ bool ha_ndbcluster::low_byte_first() const } bool ha_ndbcluster::has_transactions() { - return TRUE; + return m_transaction_on; } const char* ha_ndbcluster::index_type(uint key_number) { @@ -4445,7 +4468,10 @@ const char* ha_ndbcluster::index_type(uint key_number) } uint8 ha_ndbcluster::table_cache_type() { - return HA_CACHE_TBL_NOCACHE; + if (m_use_local_query_cache) + return HA_CACHE_TBL_TRANSACT; + else + return HA_CACHE_TBL_NOCACHE; } /* @@ -4613,13 +4639,12 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, { DBUG_ENTER("ndb_get_table_statistics"); DBUG_PRINT("enter", ("table: %s", table)); - + NdbConnection* pTrans= ndb->startTransaction(); do { - NdbConnection* pTrans= ndb->startTransaction(); if (pTrans == NULL) break; - + NdbScanOperation* pOp= pTrans->getNdbScanOperation(table); if (pOp == NULL) break; @@ -4636,13 +4661,13 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows); pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits); - check= pTrans->execute(NoCommit); + check= pTrans->execute(NoCommit, AbortOnError, TRUE); if (check == -1) break; Uint64 sum_rows= 0; Uint64 sum_commits= 0; - while((check= rs->nextResult(TRUE)) == 0) + while((check= rs->nextResult(TRUE, TRUE)) == 0) { sum_rows+= rows; sum_commits+= commits; @@ -4651,6 +4676,8 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, if (check == -1) break; + rs->close(TRUE); + ndb->closeTransaction(pTrans); if(row_count) * row_count= sum_rows; @@ -4660,6 +4687,7 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, DBUG_RETURN(0); } while(0); + ndb->closeTransaction(pTrans); DBUG_PRINT("exit", ("failed")); DBUG_RETURN(-1); } diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 02d7b96db20..2f18a52b8e9 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -160,7 +160,8 @@ class ha_ndbcluster: public handler void release_metadata(); NDB_INDEX_TYPE get_index_type(uint idx_no) const; NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const; - + int check_index_fields_not_null(uint index_no); + int pk_read(const byte *key, uint key_len, byte *buf); int complemented_pk_read(const byte *old_data, byte *new_data); int peek_row(); @@ -238,10 +239,12 @@ class ha_ndbcluster: public handler char *m_blobs_buffer; uint32 m_blobs_buffer_size; uint m_dupkey; + // set from thread variables at external lock bool m_ha_not_exact_count; bool m_force_send; ha_rows m_autoincrement_prefetch; bool m_transaction_on; + bool m_use_local_query_cache; void set_rec_per_key(); void records_update(); diff --git a/sql/handler.cc b/sql/handler.cc index 3c5244927d4..b474e6290f2 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -970,8 +970,10 @@ int handler::read_first_row(byte * buf, uint primary_key) /* If there is very few deleted rows in the table, find the first row by scanning the table. + TODO remove the test for HA_READ_ORDER */ - if (deleted < 10 || primary_key >= MAX_KEY) + if (deleted < 10 || primary_key >= MAX_KEY || + !(index_flags(primary_key, 0, 0) & HA_READ_ORDER)) { (void) ha_rnd_init(1); while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ; diff --git a/sql/item.cc b/sql/item.cc index 542d13c9476..f8dc0c6eec8 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -160,7 +160,7 @@ void Item::rename(char *new_name) Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par) :orig_db_name(db_name_par), orig_table_name(table_name_par), - orig_field_name(field_name_par), + orig_field_name(field_name_par), alias_name_used(FALSE), db_name(db_name_par), table_name(table_name_par), field_name(field_name_par), cached_field_index(NO_CACHED_FIELD_INDEX), cached_table(0), depended_from(0) @@ -174,6 +174,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item) orig_db_name(item->orig_db_name), orig_table_name(item->orig_table_name), orig_field_name(item->orig_field_name), + alias_name_used(item->alias_name_used), db_name(item->db_name), table_name(item->table_name), field_name(item->field_name), @@ -631,6 +632,7 @@ void Item_field::set_field(Field *field_par) table_name=field_par->table_name; field_name=field_par->field_name; db_name=field_par->table->table_cache_key; + alias_name_used= field_par->table->alias_name_used; unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); collation.set(field_par->charset(), DERIVATION_IMPLICIT); fixed= 1; @@ -680,7 +682,8 @@ void Item_ident::print(String *str) THD *thd= current_thd; char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME]; const char *d_name= db_name, *t_name= table_name; - if (lower_case_table_names) + if (lower_case_table_names== 1 || + (lower_case_table_names == 2 && !alias_name_used)) { if (table_name && table_name[0]) { @@ -702,7 +705,7 @@ void Item_ident::print(String *str) append_identifier(thd, str, nm, strlen(nm)); return; } - if (db_name && db_name[0]) + if (db_name && db_name[0] && !alias_name_used) { append_identifier(thd, str, d_name, strlen(d_name)); str->append('.'); @@ -2959,6 +2962,10 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) decimals= (*ref)->decimals; collation.set((*ref)->collation); with_sum_func= (*ref)->with_sum_func; + if ((*ref)->type() == FIELD_ITEM) + alias_name_used= ((Item_ident *) (*ref))->alias_name_used; + else + alias_name_used= TRUE; // it is not field, so it is was resolved by alias fixed= 1; if (ref && (*ref)->check_cols(1)) @@ -3174,16 +3181,12 @@ void Item_insert_value::print(String *str) NOTE This function does almost the same as fix_fields() for Item_field but is invoked during trigger definition parsing and takes TABLE - object as its argument. - - RETURN VALUES - 0 ok - 1 field was not found. + object as its argument. If proper field was not found in table + error will be reported at fix_fields() time. */ -bool Item_trigger_field::setup_field(THD *thd, TABLE *table, +void Item_trigger_field::setup_field(THD *thd, TABLE *table, enum trg_event_type event) { - bool result= 1; uint field_idx= (uint)-1; bool save_set_query_id= thd->set_query_id; @@ -3197,12 +3200,9 @@ bool Item_trigger_field::setup_field(THD *thd, TABLE *table, field= (row_version == OLD_ROW && event == TRG_EVENT_UPDATE) ? table->triggers->old_field[field_idx] : table->field[field_idx]; - result= 0; } thd->set_query_id= save_set_query_id; - - return result; } @@ -3226,10 +3226,18 @@ bool Item_trigger_field::fix_fields(THD *thd, FIXME may be we still should bother about permissions here. */ DBUG_ASSERT(fixed == 0); - // QQ: May be this should be moved to setup_field? - set_field(field); - fixed= 1; - return 0; + + if (field) + { + // QQ: May be this should be moved to setup_field? + set_field(field); + fixed= 1; + return 0; + } + + my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name, + (row_version == NEW_ROW) ? "NEW" : "OLD"); + return 1; } diff --git a/sql/item.h b/sql/item.h index 75c5bd8fc80..8f6d6581884 100644 --- a/sql/item.h +++ b/sql/item.h @@ -269,6 +269,14 @@ public: virtual bool get_time(TIME *ltime); virtual bool get_date_result(TIME *ltime,uint fuzzydate) { return get_date(ltime,fuzzydate); } + /* + This function is used only in Item_func_isnull/Item_func_isnotnull + (implementations of IS NULL/IS NOT NULL clauses). Item_func_is{not}null + calls this method instead of one of val/result*() methods, which + normally will set null_value. This allows to determine nullness of + a complex expression without fully evaluating it. + Any new item which can be NULL must implement this call. + */ virtual bool is_null() { return 0; } /* it is "top level" item of WHERE clause and we do not need correct NULL @@ -462,6 +470,7 @@ public: const char *db_name; const char *table_name; const char *field_name; + bool alias_name_used; /* true if item was resolved against alias */ /* Cached value of index for this field in table->field array, used by prep. stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX @@ -713,6 +722,8 @@ public: void print(String *str); /* parameter never equal to other parameter of other item */ bool eq(const Item *item, bool binary_cmp) const { return 0; } + bool is_null() + { DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; } }; class Item_int :public Item_num @@ -1312,13 +1323,15 @@ public: /* Is this item represents row from NEW or OLD row ? */ enum row_version_type {OLD_ROW, NEW_ROW}; row_version_type row_version; + /* Next in list of all Item_trigger_field's in trigger */ + Item_trigger_field *next_trg_field; Item_trigger_field(row_version_type row_ver_par, const char *field_name_par): Item_field((const char *)NULL, (const char *)NULL, field_name_par), row_version(row_ver_par) {} - bool setup_field(THD *thd, TABLE *table, enum trg_event_type event); + void setup_field(THD *thd, TABLE *table, enum trg_event_type event); enum Type type() const { return TRIGGER_FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; bool fix_fields(THD *, struct st_table_list *, Item **); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4a4485ba2da..23bd1b503f7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2429,11 +2429,12 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return FALSE; } int error; - if ((error=regcomp(&preg,res->c_ptr(), - (cmp_collation.collation->state & MY_CS_BINSORT) ? - REG_EXTENDED | REG_NOSUB : - REG_EXTENDED | REG_NOSUB | REG_ICASE, - cmp_collation.collation))) + if ((error= regcomp(&preg,res->c_ptr(), + ((cmp_collation.collation->state & MY_CS_BINSORT) || + (cmp_collation.collation->state & MY_CS_CSSORT)) ? + REG_EXTENDED | REG_NOSUB : + REG_EXTENDED | REG_NOSUB | REG_ICASE, + cmp_collation.collation))) { (void) regerror(error,&preg,buff,sizeof(buff)); my_error(ER_REGEXP_ERROR, MYF(0), buff); @@ -2481,10 +2482,11 @@ longlong Item_func_regex::val_int() regex_compiled=0; } if (regcomp(&preg,res2->c_ptr(), - (cmp_collation.collation->state & MY_CS_BINSORT) ? - REG_EXTENDED | REG_NOSUB : - REG_EXTENDED | REG_NOSUB | REG_ICASE, - cmp_collation.collation)) + ((cmp_collation.collation->state & MY_CS_BINSORT) || + (cmp_collation.collation->state & MY_CS_CSSORT)) ? + REG_EXTENDED | REG_NOSUB : + REG_EXTENDED | REG_NOSUB | REG_ICASE, + cmp_collation.collation)) { null_value=1; return 0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 581d82f2c2b..eb53394b96b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -378,6 +378,15 @@ typedef struct st_sql_list { first= save->first; elements+= save->elements; } + inline void push_back(struct st_sql_list *save) + { + if (save->first) + { + *next= save->first; + next= save->next; + elements+= save->elements; + } + } } SQL_LIST; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cd158e48b11..3001cda8b2b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -469,6 +469,7 @@ Query_cache query_cache; #ifdef HAVE_SMEM char *shared_memory_base_name= default_shared_memory_base_name; bool opt_enable_shared_memory; +HANDLE smem_event_connect_request= 0; #endif #include "sslopt-vars.h" @@ -746,6 +747,15 @@ void kill_mysql(void) CloseHandle(hEvent); */ } +#ifdef HAVE_SMEM + /* + Send event to smem_event_connect_request for aborting + */ + if (!SetEvent(smem_event_connect_request)) + { + DBUG_PRINT("error",("Got error: %ld from SetEvent of smem_event_connect_request",GetLastError())); + } +#endif #endif #elif defined(OS2) pthread_cond_signal(&eventShutdown); // post semaphore @@ -3799,7 +3809,6 @@ pthread_handler_decl(handle_connections_shared_memory,arg) /* file-mapping object, use for create shared memory */ HANDLE handle_connect_file_map= 0; char *handle_connect_map= 0; // pointer on shared memory - HANDLE event_connect_request= 0; // for start connection actions HANDLE event_connect_answer= 0; ulong smem_buffer_length= shared_memory_buffer_length + 4; ulong connect_number= 1; @@ -3820,7 +3829,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg) */ suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS); strmov(suffix_pos, "CONNECT_REQUEST"); - if ((event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0) + if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0) { errmsg= "Could not create request event"; goto error; @@ -3851,7 +3860,13 @@ pthread_handler_decl(handle_connections_shared_memory,arg) while (!abort_loop) { /* Wait a request from client */ - WaitForSingleObject(event_connect_request,INFINITE); + WaitForSingleObject(smem_event_connect_request,INFINITE); + + /* + it can be after shutdown command + */ + if (abort_loop) + goto error; HANDLE handle_client_file_map= 0; char *handle_client_map= 0; @@ -3976,7 +3991,7 @@ error: if (handle_connect_map) UnmapViewOfFile(handle_connect_map); if (handle_connect_file_map) CloseHandle(handle_connect_file_map); if (event_connect_answer) CloseHandle(event_connect_answer); - if (event_connect_request) CloseHandle(event_connect_request); + if (smem_event_connect_request) CloseHandle(smem_event_connect_request); decrement_handler_count(); DBUG_RETURN(0); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3368482f28d..6392a2fee32 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2869,10 +2869,10 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, trp->records= best_rows? best_rows : 1; trp->index_scan_costs= best_index_scan_costs; trp->cpk_scan= cpk_scan; + DBUG_PRINT("info", + ("Returning non-covering ROR-intersect plan: cost %g, records %lu", + trp->read_cost, (ulong) trp->records)); } - DBUG_PRINT("info", - ("Returning non-covering ROR-intersect plan: cost %g, records %lu", - trp->read_cost, (ulong) trp->records)); DBUG_RETURN(trp); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 79d886fb84f..46865de9314 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2781,13 +2781,18 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list) while ((var=it++)) { if ((error=var->check(thd))) - DBUG_RETURN(error); + goto err; } - if (thd->net.report_error) - DBUG_RETURN(1); - it.rewind(); - while ((var=it++)) - error|= var->update(thd); // Returns 0, -1 or 1 + if (!thd->net.report_error) + { + it.rewind(); + while ((var= it++)) + error|= var->update(thd); // Returns 0, -1 or 1 + } + else + error= 1; +err: + free_underlaid_joins(thd, &thd->lex->select_lex); DBUG_RETURN(error); } diff --git a/sql/sp.cc b/sql/sp.cc index 41ce3552292..9eff1655711 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1154,7 +1154,6 @@ sp_change_db(THD *thd, char *name, bool no_access_check) int length, db_length; char *dbname=my_strdup((char*) name,MYF(MY_WME)); char path[FN_REFLEN]; - ulong db_access; HA_CREATE_INFO create; DBUG_ENTER("sp_change_db"); DBUG_PRINT("enter", ("db: %s, no_access_check: %d", name, no_access_check)); @@ -1175,6 +1174,8 @@ sp_change_db(THD *thd, char *name, bool no_access_check) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (! no_access_check) { + ulong db_access; + if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 7db79128bb8..114ff0d451a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -275,6 +275,11 @@ sp_head::init(LEX *lex) DBUG_ENTER("sp_head::init"); lex->spcont= m_pcont= new sp_pcontext(NULL); + /* + Altough trg_table_fields list is used only in triggers we init for all + types of stored procedures to simplify reset_lex()/restore_lex() code. + */ + lex->trg_table_fields.empty(); my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8); m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0; m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str= @@ -771,7 +776,7 @@ sp_head::reset_lex(THD *thd) sublex->spcont= oldlex->spcont; /* And trigger related stuff too */ sublex->trg_chistics= oldlex->trg_chistics; - sublex->trg_table= oldlex->trg_table; + sublex->trg_table_fields.empty(); sublex->sp_lex_in_use= FALSE; DBUG_VOID_RETURN; } @@ -790,6 +795,7 @@ sp_head::restore_lex(THD *thd) // Update some state in the old one first oldlex->ptr= sublex->ptr; oldlex->next_state= sublex->next_state; + oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); // Collect some data from the sub statement lex. sp_merge_funs(oldlex, sublex); diff --git a/sql/sp_head.h b/sql/sp_head.h index 4bfe1076f65..c4d2068661c 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -439,13 +439,9 @@ public: virtual void print(String *str); - bool setup_field(THD *thd, TABLE *table, enum trg_event_type event) - { - return trigger_field.setup_field(thd, table, event); - } -private: - Item_trigger_field trigger_field; + +private: Item *value; }; // class sp_instr_trigger_field : public sp_instr diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e2a9ac5680d..8fba30e2df8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1050,8 +1050,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->reginfo.lock_type=TL_READ; /* Assume read */ reset: + if (thd->lex->need_correct_ident()) + table->alias_name_used= my_strcasecmp(table_alias_charset, + table->real_name, alias); /* Fix alias if table name changes */ - if (strcmp(table->table_name,alias)) + if (strcmp(table->table_name, alias)) { uint length=(uint) strlen(alias)+1; table->table_name= (char*) my_realloc(table->table_name,length, diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 3ca3bea743a..3f34835c2c9 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,6 +29,7 @@ bool mysql_do(THD *thd, List<Item> &values) DBUG_RETURN(TRUE); while ((value = li++)) value->val_int(); + free_underlaid_joins(thd, &thd->lex->select_lex); thd->clear_error(); // DO always is OK send_ok(thd); DBUG_RETURN(FALSE); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7d933f9f833..63741bcb176 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -175,7 +175,6 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->duplicates= DUP_ERROR; lex->sphead= NULL; lex->spcont= NULL; - lex->trg_table= NULL; lex->proc_list.first= 0; if (lex->spfuns.records) @@ -1724,6 +1723,7 @@ bool st_lex::can_not_use_merged() TRUE yes, we need only structure FALSE no, we need data */ + bool st_lex::only_view_structure() { switch(sql_command) @@ -1743,6 +1743,32 @@ bool st_lex::only_view_structure() /* + Should Items_ident be printed correctly + + SYNOPSIS + need_correct_ident() + + RETURN + TRUE yes, we need only structure + FALSE no, we need data +*/ + + +bool st_lex::need_correct_ident() +{ + switch(sql_command) + { + case SQLCOM_SHOW_CREATE: + case SQLCOM_SHOW_TABLES: + case SQLCOM_CREATE_VIEW: + return TRUE; + default: + return FALSE; + } +} + + +/* initialize limit counters SYNOPSIS diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8c02aa48f62..169ee4e66eb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -754,11 +754,13 @@ typedef struct st_lex /* Characterstics of trigger being created */ st_trg_chistics trg_chistics; /* - Points to table being opened when we are parsing trigger definition - while opening table. 0 if we are parsing user provided CREATE TRIGGER - or any other statement. Used for NEW/OLD row field lookup in trigger. + List of all items (Item_trigger_field objects) representing fields in + old/new version of row in trigger. We use this list for checking whenever + all such fields are valid at trigger creation time and for binding these + fields to TABLE object at table open (altough for latter pointer to table + being opened is probably enough). */ - TABLE *trg_table; + SQL_LIST trg_table_fields; st_lex() :result(0) { @@ -804,6 +806,7 @@ typedef struct st_lex bool can_use_merged(); bool can_not_use_merged(); bool only_view_structure(); + bool need_correct_ident(); } LEX; extern TABLE_LIST fake_time_zone_tables_list; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7089a79124d..af3392349ab 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3352,16 +3352,15 @@ create_error: } case SQLCOM_CREATE_FUNCTION: // UDF function { - sp_head *sph; if (check_access(thd,INSERT_ACL,"mysql",0,1,0)) break; #ifdef HAVE_DLOPEN - if ((sph= sp_find_function(thd, lex->spname))) + if (sp_find_function(thd, lex->spname)) { my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str); goto error; } - if (!(res = mysql_create_function(thd,&lex->udf))) + if (!(res = mysql_create_function(thd, &lex->udf))) send_ok(thd); #else res= TRUE; @@ -3813,35 +3812,35 @@ create_error: else sp= sp_find_function(thd, lex->spname); mysql_reset_errors(thd); - if (! sp) - result= SP_KEY_NOT_FOUND; - else + if (sp) { if (check_sp_definer_access(thd, sp)) goto error; if (lex->sql_command == SQLCOM_DROP_PROCEDURE) result= sp_drop_procedure(thd, lex->spname); else - { result= sp_drop_function(thd, lex->spname); + } + else + { #ifdef HAVE_DLOPEN - if (result == SP_KEY_NOT_FOUND) - { - udf_func *udf = find_udf(lex->spname->m_name.str, - lex->spname->m_name.length); - if (udf) + if (lex->sql_command == SQLCOM_DROP_FUNCTION) + { + udf_func *udf = find_udf(lex->spname->m_name.str, + lex->spname->m_name.length); + if (udf) + { + if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) + goto error; + if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0)) - goto error; - if (!(res = mysql_drop_function(thd,&lex->spname->m_name))) - { - send_ok(thd); - break; - } + send_ok(thd); + break; } } -#endif } +#endif + result= SP_KEY_NOT_FOUND; } res= result; switch (result) @@ -3926,11 +3925,11 @@ create_error: } case SQLCOM_CREATE_TRIGGER: { - /* We don't care much about trigger body at that point */ + res= mysql_create_or_drop_trigger(thd, all_tables, 1); + + /* We don't care about trigger body after this point */ delete lex->sphead; lex->sphead= 0; - - res= mysql_create_or_drop_trigger(thd, all_tables, 1); break; } case SQLCOM_DROP_TRIGGER: diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ae60eb759d0..93ed04be4b2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -238,7 +238,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result) /* If we have real error reported erly then this will be ignored */ - result->send_error(ER_UNKNOWN_ERROR, NullS); + result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR)); result->abort(); } DBUG_RETURN(res); @@ -2632,11 +2632,7 @@ add_key_field(KEY_FIELD **key_fields, uint and_level, COND *cond, bool is_const=1; for (uint i=0; i<num_values; i++) - /* - TODO: This looks like a bug. It should be - is_const&= (value[i])->const_item(); - */ - is_const&= (*value)->const_item(); + is_const&= value[i]->const_item(); if (is_const) stat[0].const_keys.merge(possible_keys); /* @@ -12905,8 +12901,9 @@ void st_table_list::print(THD *thd, String *str) str->append('.'); if (schema_table) { - append_identifier(thd, str, alias, strlen(alias)); - cmp_name= alias; + append_identifier(thd, str, schema_table_name, + strlen(schema_table_name)); + cmp_name= schema_table_name; } else { diff --git a/sql/sql_select.h b/sql/sql_select.h index 7fd9bf48b0b..5e42fc0ee30 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -277,8 +277,6 @@ class JOIN :public Sql_alloc hidden_group_fields= 0; /*safety*/ buffer_result= test(select_options & OPTION_BUFFER_RESULT) && !test(select_options & OPTION_FOUND_ROWS); - all_fields= fields_arg; - fields_list= fields_arg; error= 0; select= 0; return_tab= 0; @@ -288,6 +286,7 @@ class JOIN :public Sql_alloc optimized= 0; cond_equal= 0; + all_fields= fields_arg; fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); tmp_table_param.copy_field=0; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1642a2eaa17..55c38ff37c9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -597,7 +597,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) else { if (table_list->schema_table) - protocol->store(table_list->alias, system_charset_info); + protocol->store(table_list->schema_table_name, system_charset_info); else protocol->store(table->table_name, system_charset_info); if (store_create_info(thd, table_list, &buffer)) @@ -938,7 +938,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) else packet->append("CREATE TABLE ", 13); if (table_list->schema_table) - alias= table_list->alias; + alias= table_list->schema_table_name; else alias= (lower_case_table_names == 2 ? table->table_name : table->real_name); @@ -2193,7 +2193,7 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, tmp_buff= (show_table->table_charset ? show_table-> table_charset->name : "default"); table->field[17]->store(tmp_buff, strlen(tmp_buff), cs); - if (file->table_flags() & HA_HAS_CHECKSUM) + if (file->table_flags() & (ulong) HA_HAS_CHECKSUM) { table->field[18]->store((longlong) file->checksum()); table->field[18]->set_notnull(); @@ -2282,7 +2282,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, !wild_case_compare(system_charset_info, field->field_name,wild)) { uint tmp_length; - char *tmp_buff; + const char *tmp_buff; byte *pos; uint flags=field->flags; char tmp[MAX_FIELD_WIDTH]; @@ -2298,7 +2298,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, table->field[4]->store((longlong) count); field->sql_type(type); table->field[14]->store(type.ptr(), type.length(), cs); - tmp_buff= strchr(type.ptr(),'('); + tmp_buff= strchr(type.ptr(), '('); table->field[7]->store(type.ptr(), (tmp_buff ? tmp_buff - type.ptr() : type.length()), cs); @@ -2909,12 +2909,13 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) 0 Can't create table */ -TABLE *create_schema_table(THD *thd, ST_SCHEMA_TABLE *schema_table) +TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) { int field_count= 0; Item *item; TABLE *table; List<Item> field_list; + ST_SCHEMA_TABLE *schema_table= table_list->schema_table; ST_FIELD_INFO *fields_info= schema_table->fields_info; CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("create_schema_table"); @@ -2959,8 +2960,7 @@ TABLE *create_schema_table(THD *thd, ST_SCHEMA_TABLE *schema_table) field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->options | TMP_TABLE_ALL_COLUMNS), - HA_POS_ERROR, - (char *) schema_table->table_name))) + HA_POS_ERROR, table_list->real_name))) DBUG_RETURN(0); DBUG_RETURN(table); } @@ -3130,13 +3130,13 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) { TABLE *table; DBUG_ENTER("mysql_schema_table"); - if (!(table= table_list->schema_table-> - create_table(thd, table_list->schema_table))) + if (!(table= table_list->schema_table->create_table(thd, table_list))) { DBUG_RETURN(1); } table->tmp_table= TMP_TABLE; table->grant.privilege= SELECT_ACL; + table_list->schema_table_name= table_list->real_name; table_list->real_name= table->real_name; table_list->table= table; table->next= thd->derived_tables; @@ -3291,14 +3291,14 @@ ST_FIELD_INFO columns_fields_info[]= {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"}, {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"}, - {"DATA_TYPE", 40, MYSQL_TYPE_STRING, 0, 0, 0}, + {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0}, {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0}, {"CHARACTER_SET_NAME", 40, MYSQL_TYPE_STRING, 0, 1, 0}, {"COLLATION_NAME", 40, MYSQL_TYPE_STRING, 0, 1, "Collation"}, - {"COLUMN_TYPE", 40, MYSQL_TYPE_STRING, 0, 0, "Type"}, + {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"}, {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"}, {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"}, @@ -3356,7 +3356,7 @@ ST_FIELD_INFO proc_fields_info[]= {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"}, {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"}, {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"}, - {"SQL_MODE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0}, + {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"}, {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5020b4820a0..a7c08f356a2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -835,7 +835,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, #endif } - List_iterator<key_part_spec> cols(key->columns); + List_iterator<key_part_spec> cols(key->columns), cols2(key->columns); CHARSET_INFO *ft_key_charset=0; // for FULLTEXT for (uint column_nr=0 ; (column=cols++) ; column_nr++) { @@ -851,6 +851,19 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name); DBUG_RETURN(-1); } + for (uint dup_nr= 0; dup_nr < column_nr; dup_nr++) + { + key_part_spec *dup_column= cols2++; + if (!my_strcasecmp(system_charset_info, + column->field_name, dup_column->field_name)) + { + my_printf_error(ER_DUP_FIELDNAME, + ER(ER_DUP_FIELDNAME),MYF(0), + column->field_name); + DBUG_RETURN(-1); + } + } + cols2.rewind(); /* for fulltext keys keyseg length is 1 for blobs (it's ignored in ft code anyway, and 0 (set to column width later) for char's. it has to be correct col width for char's, as char data are not diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 7637679430f..a88dc0b20bf 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -136,6 +136,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; LEX_STRING dir, file; LEX_STRING *trg_def, *name; + Item_trigger_field *trg_field; List_iterator_fast<LEX_STRING> it(names_list); /* We don't allow creation of several triggers of the same type yet */ @@ -157,6 +158,31 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) } /* + Let us check if all references to fields in old/new versions of row in + this trigger are ok. + + NOTE: We do it here more from ease of use standpoint. We still have to + do some checks on each execution. E.g. we can catch privilege changes + only during execution. Also in near future, when we will allow access + to other tables from trigger we won't be able to catch changes in other + tables... + + To simplify code a bit we have to create Fields for accessing to old row + values if we have ON UPDATE trigger. + */ + if (!old_field && lex->trg_chistics.event == TRG_EVENT_UPDATE && + prepare_old_row_accessors(table)) + return 1; + + for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first); + trg_field; trg_field= trg_field->next_trg_field) + { + trg_field->setup_field(thd, table, lex->trg_chistics.event); + if (trg_field->fix_fields(thd, (TABLE_LIST *)0, (Item **)0)) + return 1; + } + + /* Here we are creating file with triggers and save all triggers in it. sql_create_definition_file() files handles renaming and backup of older versions @@ -275,6 +301,44 @@ Table_triggers_list::~Table_triggers_list() /* + Prepare array of Field objects which will represent OLD.* row values in + ON UPDATE trigger (by referencing to record[1] instead of record[0]). + + SYNOPSIS + prepare_old_row_accessors() + table - pointer to TABLE object for which we are creating fields. + + RETURN VALUE + False - success + True - error +*/ +bool Table_triggers_list::prepare_old_row_accessors(TABLE *table) +{ + Field **fld, **old_fld; + + if (!(old_field= (Field **)alloc_root(&table->mem_root, + (table->fields + 1) * + sizeof(Field*)))) + return 1; + + for (fld= table->field, old_fld= old_field; *fld; fld++, old_fld++) + { + /* + QQ: it is supposed that it is ok to use this function for field + cloning... + */ + if (!(*old_fld= (*fld)->new_field(&table->mem_root, table))) + return 1; + (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] - + table->record[0])); + } + *old_fld= 0; + + return 0; +} + + +/* Check whenever .TRG file for table exist and load all triggers it contains. SYNOPSIS @@ -317,7 +381,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, if (!strncmp(triggers_file_type.str, parser->type()->str, parser->type()->length)) { - Field **fld, **old_fld; Table_triggers_list *triggers= new (&table->mem_root) Table_triggers_list(); @@ -330,31 +393,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, table->triggers= triggers; - /* - We have to prepare array of Field objects which will represent OLD.* - row values by referencing to record[1] instead of record[0] - - TODO: This could be avoided if there is no ON UPDATE trigger. - */ - if (!(triggers->old_field= - (Field **)alloc_root(&table->mem_root, (table->fields + 1) * - sizeof(Field*)))) + /* TODO: This could be avoided if there is no ON UPDATE trigger. */ + if (triggers->prepare_old_row_accessors(table)) DBUG_RETURN(1); - for (fld= table->field, old_fld= triggers->old_field; *fld; - fld++, old_fld++) - { - /* - QQ: it is supposed that it is ok to use this function for field - cloning... - */ - if (!(*old_fld= (*fld)->new_field(&table->mem_root, table))) - DBUG_RETURN(1); - (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] - - table->record[0])); - } - *old_fld= 0; - List_iterator_fast<LEX_STRING> it(triggers->definitions_list); LEX_STRING *trg_create_str, *trg_name_str; char *trg_name_buff; @@ -365,7 +407,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, while ((trg_create_str= it++)) { lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length); - lex.trg_table= table; + if (yyparse((void *)thd) || thd->is_fatal_error) { /* @@ -400,6 +442,21 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, if (triggers->names_list.push_back(trg_name_str, &table->mem_root)) goto err_with_lex_cleanup; + /* + Let us bind Item_trigger_field objects representing access to fields + in old/new versions of row in trigger to Field objects in table being + opened. + + We ignore errors here, because if even something is wrong we still will + be willing to open table to perform some operations (e.g. SELECT)... + Anyway some things can be checked only during trigger execution. + */ + for (Item_trigger_field *trg_field= + (Item_trigger_field *)(lex.trg_table_fields.first); + trg_field; + trg_field= trg_field->next_trg_field) + trg_field->setup_field(thd, table, lex.trg_chistics.event); + lex_end(&lex); } thd->lex= old_lex; diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index d0376f056d9..82e7c1ce023 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -65,4 +65,7 @@ public: } friend class Item_trigger_field; + +private: + bool prepare_old_row_accessors(TABLE *table); }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d2f02acb75b..dd9cd4af0f3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1238,8 +1238,9 @@ create: my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); YYABORT; } - - sp= new sp_head(); + + if (!(sp= new sp_head())) + YYABORT; sp->reset_thd_mem_root(YYTHD); sp->init(lex); @@ -6622,6 +6623,7 @@ simple_ident_q: (!my_strcasecmp(system_charset_info, $1.str, "NEW") || !my_strcasecmp(system_charset_info, $1.str, "OLD"))) { + Item_trigger_field *trg_fld; bool new_row= ($1.str[0]=='N' || $1.str[0]=='n'); if (lex->trg_chistics.event == TRG_EVENT_INSERT && @@ -6638,23 +6640,18 @@ simple_ident_q: YYABORT; } - Item_trigger_field *trg_fld= - new Item_trigger_field(new_row ? Item_trigger_field::NEW_ROW : - Item_trigger_field::OLD_ROW, - $3.str); - - if (lex->trg_table && - trg_fld->setup_field(thd, lex->trg_table, - lex->trg_chistics.event)) - { - /* - FIXME. Far from perfect solution. See comment for - "SET NEW.field_name:=..." for more info. - */ - my_error(ER_BAD_FIELD_ERROR, MYF(0), - $3.str, new_row ? "NEW": "OLD"); + if (!(trg_fld= new Item_trigger_field(new_row ? + Item_trigger_field::NEW_ROW: + Item_trigger_field::OLD_ROW, + $3.str))) YYABORT; - } + + /* + Let us add this item to list of all Item_trigger_field objects + in trigger. + */ + lex->trg_table_fields.link_in_list((byte *)trg_fld, + (byte**)&trg_fld->next_trg_field); $$= (Item *)trg_fld; } @@ -7156,28 +7153,19 @@ option_value: /* QQ: Shouldn't this be field's default value ? */ it= new Item_null(); } - i= new sp_instr_set_trigger_field(lex->sphead->instructions(), - lex->spcont, $1.base_name, it); - if (lex->trg_table && i->setup_field(YYTHD, lex->trg_table, - lex->trg_chistics.event)) - { - /* - FIXME. Now we are catching this kind of errors only - during opening tables. But this doesn't save us from most - common user error - misspelling field name, because we - will bark too late in this case... Moreover it is easy to - make table unusable with such kind of error... - - So in future we either have to parse trigger definition - second time during create trigger or gather all trigger - fields in one list and perform setup_field() for them as - separate stage. - - Error message also should be improved. - */ - my_error(ER_BAD_FIELD_ERROR, MYF(0), $1.base_name, "NEW"); + + if (!(i= new sp_instr_set_trigger_field( + lex->sphead->instructions(), lex->spcont, + $1.base_name, it))) YYABORT; - } + + /* + Let us add this item to list of all Item_trigger_field + objects in trigger. + */ + lex->trg_table_fields.link_in_list((byte *)&i->trigger_field, + (byte **)&i->trigger_field.next_trg_field); + lex->sphead->add_instr(i); } else if ($1.var) diff --git a/sql/table.h b/sql/table.h index c942b038eae..ed9c1445cdf 100644 --- a/sql/table.h +++ b/sql/table.h @@ -160,6 +160,7 @@ struct st_table { my_bool no_keyread, no_cache; my_bool clear_query_id; /* To reset query_id for tables and cols */ my_bool auto_increment_field_not_null; + my_bool alias_name_used; /* true if table_name is alias */ Field *next_number_field, /* Set if next_number is activated */ *found_next_number_field, /* Set on open */ *rowid_field; @@ -243,7 +244,7 @@ typedef struct st_schema_table const char* table_name; ST_FIELD_INFO *fields_info; /* Create information_schema table */ - TABLE *(*create_table) (THD *thd, struct st_schema_table *schema_table); + TABLE *(*create_table) (THD *thd, struct st_table_list *table_list); /* Fill table with data */ int (*fill_table) (THD *thd, struct st_table_list *tables, COND *cond); /* Handle fileds for old SHOW */ @@ -286,7 +287,7 @@ typedef struct st_table_list struct st_table_list *next_local; /* link in a global list of all queries tables */ struct st_table_list *next_global, **prev_global; - char *db, *alias, *real_name; + char *db, *alias, *real_name, *schema_table_name; char *option; /* Used by cache index */ Item *on_expr; /* Used with outer join */ COND_EQUAL *cond_equal; /* Used with outer join */ |