summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-11-25 02:27:02 +0200
committerunknown <bell@sanja.is.com.ua>2004-11-25 02:27:02 +0200
commita352372170815bebd65755bc5fff00fdf964cf9b (patch)
tree64b87aad2e52257f0c6cb4d27336e0d1fb516494 /sql
parentf88d01932f4a81682267e21022686d3dea4edb78 (diff)
parent00899088a5f576721ecbf3ca235cdfcd691c8a0e (diff)
downloadmariadb-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.cc4
-rw-r--r--sql/ha_myisammrg.cc11
-rw-r--r--sql/ha_myisammrg.h1
-rw-r--r--sql/ha_ndbcluster.cc56
-rw-r--r--sql/ha_ndbcluster.h5
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/item.cc42
-rw-r--r--sql/item.h15
-rw-r--r--sql/item_cmpfunc.cc20
-rw-r--r--sql/mysql_priv.h9
-rw-r--r--sql/mysqld.cc23
-rw-r--r--sql/opt_range.cc6
-rw-r--r--sql/set_var.cc17
-rw-r--r--sql/sp.cc3
-rw-r--r--sql/sp_head.cc8
-rw-r--r--sql/sp_head.h8
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_do.cc1
-rw-r--r--sql/sql_lex.cc28
-rw-r--r--sql/sql_lex.h11
-rw-r--r--sql/sql_parse.cc45
-rw-r--r--sql/sql_select.cc13
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_show.cc26
-rw-r--r--sql/sql_table.cc15
-rw-r--r--sql/sql_trigger.cc107
-rw-r--r--sql/sql_trigger.h3
-rw-r--r--sql/sql_yacc.yy66
-rw-r--r--sql/table.h5
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 */