Below is the list of changes that have just been committed into a local
5.0 repository of mydev. When mydev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2213 06/07/06 19:36:07 ingo@stripped +6 -0
Merge chilla.local:/home/mydev/mysql-5.0
into chilla.local:/home/mydev/mysql-5.0-bug16218
sql/table.cc
1.226 06/07/06 19:35:59 ingo@stripped +0 -0
Auto merged
sql/sql_trigger.cc
1.51 06/07/06 19:35:59 ingo@stripped +0 -0
Auto merged
sql/sql_select.cc
1.429 06/07/06 19:35:58 ingo@stripped +0 -0
Auto merged
sql/sql_insert.cc
1.195 06/07/06 19:35:58 ingo@stripped +0 -0
Auto merged
sql/field.h
1.183 06/07/06 19:35:58 ingo@stripped +0 -0
Auto merged
sql/field.cc
1.313 06/07/06 19:35:58 ingo@stripped +0 -0
Auto merged
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: ingo
# Host: chilla.local
# Root: /home/mydev/mysql-5.0-bug16218/RESYNC
--- 1.312/sql/field.cc 2006-06-21 22:49:13 +02:00
+++ 1.313/sql/field.cc 2006-07-06 19:35:58 +02:00
@@ -1515,7 +1515,8 @@ bool Field::optimize_range(uint idx, uin
}
-Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type __attribute__((unused)))
{
Field *tmp;
if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
@@ -1540,7 +1541,7 @@ Field *Field::new_key_field(MEM_ROOT *ro
uint new_null_bit)
{
Field *tmp;
- if ((tmp= new_field(root, new_table)))
+ if ((tmp= new_field(root, new_table, table == new_table)))
{
tmp->ptr= new_ptr;
tmp->null_ptr= new_null_ptr;
@@ -6227,29 +6228,21 @@ uint Field_string::max_packed_col_length
}
-Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type)
{
Field *new_field;
- if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
- return Field::new_field(root, new_table);
+ if (type() != MYSQL_TYPE_VAR_STRING || keep_type)
+ return Field::new_field(root, new_table, keep_type);
/*
Old VARCHAR field which should be modified to a VARCHAR on copy
This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now VARCHAR fields.
*/
- if ((new_field= new Field_varstring(field_length, maybe_null(),
- field_name, new_table, charset())))
- {
- /*
- delayed_insert::get_local_table() needs a ptr copied from old table.
- This is what other new_field() methods do too. The above method of
- Field_varstring sets ptr to NULL.
- */
- new_field->ptr= ptr;
- }
- return new_field;
+ return new Field_varstring(field_length, maybe_null(),
+ field_name, new_table, charset());
}
/****************************************************************************
@@ -6741,9 +6734,11 @@ int Field_varstring::cmp_binary(const ch
}
-Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table)
+Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type)
{
- Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table);
+ Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
+ keep_type);
if (res)
res->length_bytes= length_bytes;
return res;
--- 1.182/sql/field.h 2006-06-20 23:05:31 +02:00
+++ 1.183/sql/field.h 2006-07-06 19:35:58 +02:00
@@ -211,7 +211,8 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
+ bool keep_type);
virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
@@ -1033,7 +1034,7 @@ public:
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
};
@@ -1105,7 +1106,7 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table);
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
--- 1.194/sql/sql_insert.cc 2006-06-27 01:34:07 +02:00
+++ 1.195/sql/sql_insert.cc 2006-07-06 19:35:58 +02:00
@@ -17,6 +17,44 @@
/* Insert of records */
+/*
+ INSERT DELAYED
+
+ Insert delayed is distinguished from a normal insert by lock_type ==
+ TL_WRITE_DELAYED instead of TL_WRITE. It first tries to open a
+ "delayed" table (delayed_get_table()), but falls back to
+ open_and_lock_tables() on error and proceeds as normal insert then.
+
+ Opening a "delayed" table means to find a delayed insert thread that
+ has the table open already. If this fails, a new thread is created and
+ waited for to open and lock the table.
+
+ If accessing the thread succeeded, in
+ delayed_insert::get_local_table() the table of the thread is copied
+ for local use. A copy is required because the normal insert logic
+ works on a target table, but the other threads table object must not
+ be used. The insert logic uses the record buffer to create a record.
+ And the delayed insert thread uses the record buffer to pass the
+ record to the table handler. So there must be different objects. Also
+ the copied table is not included in the lock, so that the statement
+ can proceed even if the real table cannot be accessed at this moment.
+
+ Copying a table object is not a trivial operation. Besides the TABLE
+ object there are the field pointer array, the field objects and the
+ record buffer. After copying the field objects, their pointers into
+ the record must be "moved" to point to the new record buffer.
+
+ After this setup the normal insert logic is used. Only that for
+ delayed inserts write_delayed() is called instead of write_record().
+ It inserts the rows into a queue and signals the delayed insert thread
+ instead of writing directly to the table.
+
+ The delayed insert thread awakes from the signal. It locks the table,
+ inserts the rows from the queue, unlocks the table, and waits for the
+ next signal. It does normally live until a FLUSH TABLES or SHUTDOWN.
+
+*/
+
#include "mysql_priv.h"
#include "sp_head.h"
#include "sql_trigger.h"
@@ -1441,6 +1479,7 @@ TABLE *delayed_insert::get_local_table(T
my_ptrdiff_t adjust_ptrs;
Field **field,**org_field, *found_next_number_field;
TABLE *copy;
+ DBUG_ENTER("delayed_insert::get_local_table");
/* First request insert thread to get a lock */
status=1;
@@ -1464,31 +1503,47 @@ TABLE *delayed_insert::get_local_table(T
}
}
+ /*
+ Allocate memory for the TABLE object, the field pointers array, and
+ one record buffer of reclength size. Normally a table has three
+ record buffers of rec_buff_length size, which includes alignment
+ bytes. Since the table copy is used for creating one record only,
+ the other record buffers and alignment are unnecessary.
+ */
client_thd->proc_info="allocating local table";
copy= (TABLE*) client_thd->alloc(sizeof(*copy)+
(table->s->fields+1)*sizeof(Field**)+
table->s->reclength);
if (!copy)
goto error;
+
+ /* Copy the TABLE object. */
*copy= *table;
copy->s= ©->share_not_to_be_used;
// No name hashing
bzero((char*) ©->s->name_hash,sizeof(copy->s->name_hash));
/* We don't need to change the file handler here */
- field=copy->field=(Field**) (copy+1);
- copy->record[0]=(byte*) (field+table->s->fields+1);
- memcpy((char*) copy->record[0],(char*) table->record[0],table->s->reclength);
-
- /* Make a copy of all fields */
+ /* Assign the pointers for the field pointers array and the record. */
+ field= copy->field= (Field**) (copy + 1);
+ copy->record[0]= (byte*) (field + table->s->fields + 1);
+ memcpy((char*) copy->record[0], (char*) table->record[0],
+ table->s->reclength);
- adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]);
+ /*
+ Make a copy of all fields.
+ The copied fields need to point into the copied record. This is done
+ by copying the field objects with their old pointer values and then
+ "move" the pointers by the distance between the original and copied
+ records. That way we preserve the relative positions in the records.
+ */
+ adjust_ptrs= PTR_BYTE_DIFF(copy->record[0], table->record[0]);
- found_next_number_field=table->found_next_number_field;
- for (org_field=table->field ; *org_field ; org_field++,field++)
+ found_next_number_field= table->found_next_number_field;
+ for (org_field= table->field; *org_field; org_field++, field++)
{
- if (!(*field= (*org_field)->new_field(client_thd->mem_root,copy)))
- return 0;
+ if (!(*field= (*org_field)->new_field(client_thd->mem_root, copy, 1)))
+ DBUG_RETURN(0);
(*field)->orig_table= copy; // Remove connection
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
@@ -1515,14 +1570,14 @@ TABLE *delayed_insert::get_local_table(T
/* Adjust lock_count. This table object is not part of a lock. */
copy->lock_count= 0;
- return copy;
+ DBUG_RETURN(copy);
/* Got fatal error */
error:
tables_in_use--;
status=1;
pthread_cond_signal(&cond); // Inform thread about abort
- return 0;
+ DBUG_RETURN(0);
}
--- 1.428/sql/sql_select.cc 2006-06-30 00:01:11 +02:00
+++ 1.429/sql/sql_select.cc 2006-07-06 19:35:58 +02:00
@@ -8017,7 +8017,8 @@ Field* create_tmp_field_from_field(THD *
org_field->field_name, table,
org_field->charset());
else
- new_field= org_field->new_field(thd->mem_root, table);
+ new_field= org_field->new_field(thd->mem_root, table,
+ table == org_field->table);
if (new_field)
{
if (item)
@@ -13062,7 +13063,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PA
saved value
*/
Field *field= item->field;
- item->result_field=field->new_field(thd->mem_root,field->table);
+ item->result_field=field->new_field(thd->mem_root,field->table, 1);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
--- 1.225/sql/table.cc 2006-07-03 10:19:08 +02:00
+++ 1.226/sql/table.cc 2006-07-06 19:35:59 +02:00
@@ -804,7 +804,8 @@ int openfrm(THD *thd, const char *name,
if (!(field->flags & BLOB_FLAG))
{ // Create a new field
field=key_part->field=field->new_field(&outparam->mem_root,
- outparam);
+ outparam,
+ outparam == field->table);
field->field_length=key_part->length;
}
}
--- 1.50/sql/sql_trigger.cc 2006-06-26 20:57:13 +02:00
+++ 1.51/sql/sql_trigger.cc 2006-07-06 19:35:59 +02:00
@@ -183,6 +183,15 @@ bool mysql_create_or_drop_trigger(THD *t
!(tables= add_table_for_trigger(thd, thd->lex->spname)))
DBUG_RETURN(TRUE);
+ /*
+ We don't allow creating triggers on tables in the 'mysql' schema
+ */
+ if (create && !my_strcasecmp(system_charset_info, "mysql", tables->db))
+ {
+ my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
@@ -366,7 +375,9 @@ bool Table_triggers_list::create_trigger
/* We don't allow creation of several triggers of the same type yet */
if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time])
{
- my_message(ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS), MYF(0));
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "multiple triggers with the same action time"
+ " and event for one table");
return 1;
}
@@ -933,8 +944,7 @@ bool Table_triggers_list::check_n_load(T
save_db.str= thd->db;
save_db.length= thd->db_length;
- thd->db_length= strlen(db);
- thd->db= (char *) db;
+ thd->reset_db((char*) db, strlen(db));
while ((trg_create_str= it++))
{
trg_sql_mode= itm++;
@@ -1036,8 +1046,7 @@ bool Table_triggers_list::check_n_load(T
lex_end(&lex);
}
- thd->db= save_db.str;
- thd->db_length= save_db.length;
+ thd->reset_db(save_db.str, save_db.length);
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
@@ -1050,8 +1059,7 @@ err_with_lex_cleanup:
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
- thd->db= save_db.str;
- thd->db_length= save_db.length;
+ thd->reset_db(save_db.str, save_db.length);
DBUG_RETURN(1);
}
| Thread |
|---|
| • bk commit into 5.0 tree (ingo:1.2213) | ingo | 6 Jul |