summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <evgen@moonbone.local>2007-03-31 02:42:40 +0400
committerunknown <evgen@moonbone.local>2007-03-31 02:42:40 +0400
commitda11d8177e738ca5d35e5f29a58746400eefaf85 (patch)
treee46c1b5c52e7662eb23b9de79e95a79dbaef216f /sql
parent7e1e2280174cad9ad4531682c9b9e85ee41d1004 (diff)
parent86a0ffdd3c068edc63e3bda21d88980699c451dd (diff)
downloadmariadb-git-da11d8177e738ca5d35e5f29a58746400eefaf85.tar.gz
Merge moonbone.local:/mnt/gentoo64/work/bk-trees/mysql-5.0-opt
into moonbone.local:/mnt/gentoo64/work/bk-trees/mysql-5.1-opt mysql-test/r/func_gconcat.result: Auto merged mysql-test/r/insert_update.result: Auto merged mysql-test/r/subselect3.result: Auto merged mysql-test/t/func_gconcat.test: Auto merged mysql-test/t/insert_update.test: Auto merged sql/field_conv.cc: Auto merged sql/item.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_select.cc: Auto merged sql/table.h: Auto merged mysql-test/r/gis.result: Manual merge mysql-test/t/gis.test: Manual merge sql/handler.cc: Manual merge sql/item_sum.cc: Manual merge sql/sql_insert.cc: Manual merge sql/sql_table.cc: Manual merge
Diffstat (limited to 'sql')
-rw-r--r--sql/field_conv.cc2
-rw-r--r--sql/handler.cc5
-rw-r--r--sql/item.cc5
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/sql_base.cc67
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_load.cc3
-rw-r--r--sql/sql_select.cc9
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/table.h5
10 files changed, 84 insertions, 20 deletions
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 88d36615668..a718a402897 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -173,7 +173,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
if (field == field->table->next_number_field)
{
field->table->auto_increment_field_not_null= FALSE;
- return 0; // field is set in handler.cc
+ return 0; // field is set in fill_record()
}
if (field->table->in_use->count_cuted_fields == CHECK_FIELD_WARN)
{
diff --git a/sql/handler.cc b/sql/handler.cc
index 0ecfce9349e..617bf9ee378 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1753,7 +1753,6 @@ int handler::update_auto_increment()
bool append= FALSE;
THD *thd= table->in_use;
struct system_variables *variables= &thd->variables;
- bool auto_increment_field_not_null;
DBUG_ENTER("handler::update_auto_increment");
/*
@@ -1761,11 +1760,9 @@ int handler::update_auto_increment()
than the interval, but not smaller.
*/
DBUG_ASSERT(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
- auto_increment_field_not_null= table->auto_increment_field_not_null;
- table->auto_increment_field_not_null= FALSE; // to reset for next row
if ((nr= table->next_number_field->val_int()) != 0 ||
- auto_increment_field_not_null &&
+ table->auto_increment_field_not_null &&
thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
{
/*
diff --git a/sql/item.cc b/sql/item.cc
index 1482d39b6ba..d4330710bbd 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4363,13 +4363,16 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_GEOMETRY:
if (this->type() == Item::TYPE_HOLDER)
field= new Field_blob(max_length, maybe_null, name, collation.collation,
1);
else
field= new Field_blob(max_length, maybe_null, name, collation.collation);
break; // Blob handled outside of case
+ case MYSQL_TYPE_GEOMETRY:
+ return new Field_geom(max_length, maybe_null, name, table,
+ (Field::geometry_type)
+ ((Item_geometry_func *)this)->get_geometry_type());
}
if (field)
field->init(table);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 7d7662f06f7..7c3762d4785 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -419,7 +419,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
break;
case STRING_RESULT:
if (max_length/collation.collation->mbmaxlen <= 255 ||
- max_length/collation.collation->mbmaxlen >=UINT_MAX16 ||
+ convert_blob_length >=UINT_MAX16 ||
!convert_blob_length)
return make_string_field(table);
field= new Field_varstring(convert_blob_length, maybe_null,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 516ca573cb3..61a89a00655 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2338,6 +2338,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->insert_values= 0;
table->fulltext_searched= 0;
table->file->ft_handler= 0;
+ /* Catch wrong handling of the auto_increment_field_not_null. */
+ DBUG_ASSERT(!table->auto_increment_field_not_null);
+ table->auto_increment_field_not_null= FALSE;
if (table->timestamp_field)
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
table->pos_in_table_list= table_list;
@@ -6238,6 +6241,11 @@ err_no_arena:
values values to fill with
ignore_errors TRUE if we should ignore errors
+ NOTE
+ fill_record() may set table->auto_increment_field_not_null and a
+ caller should make sure that it is reset after their last call to this
+ function.
+
RETURN
FALSE OK
TRUE error occured
@@ -6250,27 +6258,52 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values,
List_iterator_fast<Item> f(fields),v(values);
Item *value, *fld;
Item_field *field;
+ TABLE *table= 0;
DBUG_ENTER("fill_record");
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ if (fields.elements)
+ {
+ /*
+ On INSERT or UPDATE fields are checked to be from the same table,
+ thus we safely can take table from the first field.
+ */
+ fld= (Item_field*)f++;
+ if (!(field= fld->filed_for_view_update()))
+ {
+ my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
+ goto err;
+ }
+ table= field->field->table;
+ table->auto_increment_field_not_null= FALSE;
+ f.rewind();
+ }
while ((fld= f++))
{
if (!(field= fld->filed_for_view_update()))
{
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name);
- DBUG_RETURN(TRUE);
+ goto err;
}
value=v++;
Field *rfield= field->field;
- TABLE *table= rfield->table;
+ table= rfield->table;
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
- DBUG_RETURN(TRUE);
+ goto err;
}
}
DBUG_RETURN(thd->net.report_error);
+err:
+ if (table)
+ table->auto_increment_field_not_null= FALSE;
+ DBUG_RETURN(TRUE);
}
@@ -6319,6 +6352,11 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
values list of fields
ignore_errors TRUE if we should ignore errors
+ NOTE
+ fill_record() may set table->auto_increment_field_not_null and a
+ caller should make sure that it is reset after their last call to this
+ function.
+
RETURN
FALSE OK
TRUE error occured
@@ -6329,19 +6367,38 @@ fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
Item *value;
+ TABLE *table= 0;
DBUG_ENTER("fill_record");
Field *field;
+ /*
+ Reset the table->auto_increment_field_not_null as it is valid for
+ only one row.
+ */
+ if (*ptr)
+ {
+ /*
+ On INSERT or UPDATE fields are checked to be from the same table,
+ thus we safely can take table from the first field.
+ */
+ table= (*ptr)->table;
+ table->auto_increment_field_not_null= FALSE;
+ }
while ((field = *ptr++))
{
value=v++;
- TABLE *table= field->table;
+ table= field->table;
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if (value->save_in_field(field, 0) == -1)
- DBUG_RETURN(TRUE);
+ goto err;
}
DBUG_RETURN(thd->net.report_error);
+
+err:
+ if (table)
+ table->auto_increment_field_not_null= FALSE;
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index d24230eb379..c0e0203ed86 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -753,6 +753,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table->next_number_field->val_int() : 0));
table->next_number_field=0;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ table->auto_increment_field_not_null= FALSE;
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (duplic == DUP_REPLACE &&
@@ -2689,6 +2690,7 @@ select_insert::~select_insert()
if (table)
{
table->next_number_field=0;
+ table->auto_increment_field_not_null= FALSE;
table->file->ha_reset();
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index cf356a4b336..7d2c2281bba 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -512,6 +512,7 @@ err:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
+ table->auto_increment_field_not_null= FALSE;
thd->abort_on_warning= 0;
DBUG_RETURN(error);
}
@@ -609,8 +610,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
{
uint length;
byte save_chr;
- if (field == table->next_number_field)
- table->auto_increment_field_not_null= TRUE;
if ((length=(uint) (read_info.row_end-pos)) >
field->field_length)
length=field->field_length;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f2555e7f3f9..7fd290fe452 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8982,20 +8982,19 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
enum enum_field_types type;
/*
- DATE/TIME fields have STRING_RESULT result type. To preserve
- type they needed to be handled separately.
+ DATE/TIME and GEOMETRY fields have STRING_RESULT result type.
+ To preserve type they needed to be handled separately.
*/
if ((type= item->field_type()) == MYSQL_TYPE_DATETIME ||
type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE ||
- type == MYSQL_TYPE_TIMESTAMP)
+ type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_GEOMETRY)
new_field= item->tmp_table_field_from_field_type(table, 1);
/*
Make sure that the blob fits into a Field_varstring which has
2-byte lenght.
*/
else if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
- item->max_length/item->collation.collation->mbmaxlen < UINT_MAX16
- && convert_blob_length)
+ convert_blob_length < UINT_MAX16 && convert_blob_length)
new_field= new Field_varstring(convert_blob_length, maybe_null,
item->name, table->s,
item->collation.collation);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bb3f293941e..3eb47ebae6e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6838,7 +6838,9 @@ copy_data_between_tables(TABLE *from,TABLE *to,
copy_ptr->do_copy(copy_ptr);
}
prev_insert_id= to->file->next_insert_id;
- if ((error=to->file->ha_write_row((byte*) to->record[0])))
+ error=to->file->write_row((byte*) to->record[0]);
+ to->auto_increment_field_not_null= FALSE;
+ if (error)
{
if (!ignore ||
to->file->is_fatal_error(error, HA_CHECK_DUP))
diff --git a/sql/table.h b/sql/table.h
index aa053f207b3..496c7e2efd9 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -439,6 +439,11 @@ struct st_table {
my_bool no_cache;
/* To signal that we should reset query_id for tables and cols */
my_bool clear_query_id;
+ /*
+ To indicate that a non-null value of the auto_increment field
+ was provided by the user or retrieved from the current record.
+ Used only in the MODE_NO_AUTO_VALUE_ON_ZERO mode.
+ */
my_bool auto_increment_field_not_null;
my_bool insert_or_update; /* Can be used by the handler */
my_bool alias_name_used; /* true if table_name is alias */