diff options
author | Michael Widenius <monty@mariadb.org> | 2016-06-29 09:14:22 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-06-30 11:43:02 +0200 |
commit | db7edfed17efe6bc3684b0fbacc0b0249e4f0fa2 (patch) | |
tree | f1f484057487a73d32f379a5fdaacd53bfa27b5e /sql/sql_insert.cc | |
parent | 23d03a1b1e486da353f20964a1b91068bec209c0 (diff) | |
download | mariadb-git-db7edfed17efe6bc3684b0fbacc0b0249e4f0fa2.tar.gz |
MDEV-7563 Support CHECK constraint as in (or close to) SQL Standard
MDEV-10134 Add full support for DEFAULT
- Added support for using tables with MySQL 5.7 virtual fields,
including MySQL 5.7 syntax
- Better error messages also for old cases
- CREATE ... SELECT now also updates timestamp columns
- Blob can now have default values
- Added new system variable "check_constraint_checks", to turn of
CHECK constraint checking if needed.
- Removed some engine independent tests in suite vcol to only test myisam
- Moved some tests from 'include' to 't'. Should some day be done for all tests.
- FRM version increased to 11 if one uses virtual fields or constraints
- Changed to use a bitmap to check if a field has got a value, instead of
setting HAS_EXPLICIT_VALUE bit in field flags
- Expressions can now be up to 65K in total
- Ensure we are not refering to uninitialized fields when handling virtual fields or defaults
- Changed check_vcol_func_processor() to return a bitmap of used types
- Had to change some functions that calculated cached value in fix_fields to do
this in val() or getdate() instead.
- store_now_in_TIME() now takes a THD argument
- fill_record() now updates default values
- Add a lookahead for NOT NULL, to be able to handle DEFAULT 1+1 NOT NULL
- Automatically generate a name for constraints that doesn't have a name
- Added support for ALTER TABLE DROP CONSTRAINT
- Ensure that partition functions register virtual fields used. This fixes
some bugs when using virtual fields in a partitioning function
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 150 |
1 files changed, 78 insertions, 72 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e3f26ccf377..ee6309aff51 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -282,12 +282,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dup_field->field_name); DBUG_RETURN(-1); } - if (table->default_field) - table->mark_default_fields_for_write(); } - /* Mark virtual columns used in the insert statement */ - if (table->vfield) - table->mark_virtual_columns_for_write(TRUE); // For the values we need select_priv #ifndef NO_EMBEDDED_ACCESS_CHECKS table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); @@ -359,7 +354,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, return -1; if (table->default_field) - table->mark_default_fields_for_write(); + table->mark_default_fields_for_write(FALSE); if (table->found_next_number_field) { @@ -801,6 +796,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, info.update_fields= &update_fields; info.update_values= &update_values; info.view= (table_list->view ? table_list : 0); + info.table_list= table_list; /* Count warnings for all inserts. @@ -901,6 +897,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, INSERT INTO t1 VALUES () */ restore_record(table,s->default_values); // Get empty record + table->reset_default_fields(); if (fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0, TRG_EVENT_INSERT)) { @@ -961,11 +958,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } - if (table->default_field && table->update_default_fields()) - { - error= 1; - break; - } if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? @@ -1504,18 +1496,8 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, if (!table) table= table_list->table; - - if (!fields.elements && table->vfield) - { - for (Field **vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++) - { - if ((*vfield_ptr)->vcol_info->stored_in_db) - { - thd->lex->unit.insert_table_with_stored_vcol= table; - break; - } - } - } + if (table->s->virtual_stored_fields) + thd->lex->unit.insert_table_with_stored_vcol= table; if (!select_insert) { @@ -1702,16 +1684,17 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) DBUG_ASSERT(table->insert_values != NULL); store_record(table,insert_values); restore_record(table,record[1]); + table->reset_default_fields(); /* in INSERT ... ON DUPLICATE KEY UPDATE the set of modified fields can change per row. Thus, we have to do reset_default_fields() per row. Twice (before insert and before update). */ - table->reset_default_fields(); DBUG_ASSERT(info->update_fields->elements == info->update_values->elements); - if (fill_record_n_invoke_before_triggers(thd, table, *info->update_fields, + if (fill_record_n_invoke_before_triggers(thd, table, + *info->update_fields, *info->update_values, info->ignore, TRG_EVENT_UPDATE)) @@ -1728,20 +1711,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) */ if (different_records && table->default_field) { - bool res; - enum_sql_command cmd= thd->lex->sql_command; - thd->lex->sql_command= SQLCOM_UPDATE; - res= table->update_default_fields(); - thd->lex->sql_command= cmd; - if (res) + if (table->update_default_fields(1, info->ignore)) goto err; } - table->reset_default_fields(); /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ - if (info->view && - (res= info->view->view_check_option(current_thd, info->ignore)) == - VIEW_CHECK_SKIP) + res= info->table_list->view_check_option(table->in_use, info->ignore); + if (res == VIEW_CHECK_SKIP) goto ok_or_after_trg_err; if (res == VIEW_CHECK_ERROR) goto before_trg_err; @@ -2361,11 +2337,12 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) { my_ptrdiff_t adjust_ptrs; Field **field,**org_field, *found_next_number_field; - Field **UNINIT_VAR(vfield), **UNINIT_VAR(dfield_ptr); + Field **vfield= 0, **dfield_ptr= 0; TABLE *copy; TABLE_SHARE *share; uchar *bitmap; char *copy_tmp; + uint bitmaps_used; DBUG_ENTER("Delayed_insert::get_local_table"); /* First request insert thread to get a lock */ @@ -2419,13 +2396,14 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) copy_tmp= (char*) client_thd->alloc(sizeof(*copy)+ (share->fields+1)*sizeof(Field**)+ share->reclength + - share->column_bitmap_size*3); + share->column_bitmap_size*4); if (!copy_tmp) goto error; - if (share->vfields) + if (share->virtual_fields) { - vfield= (Field **) client_thd->alloc((share->vfields+1)*sizeof(Field*)); + vfield= (Field **) client_thd->alloc((share->virtual_fields+1)* + sizeof(Field*)); if (!vfield) goto error; } @@ -2437,12 +2415,14 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) /* Assign the pointers for the field pointers array and the record. */ field= copy->field= (Field**) (copy + 1); bitmap= (uchar*) (field + share->fields + 1); - copy->record[0]= (bitmap + share->column_bitmap_size*3); + copy->record[0]= (bitmap + share->column_bitmap_size*4); memcpy((char*) copy->record[0], (char*) table->record[0], share->reclength); - if (share->default_fields) + if (share->default_fields || share->default_expressions) { - copy->default_field= (Field**) client_thd->alloc((share->default_fields+1)* - sizeof(Field**)); + copy->default_field= (Field**) + client_thd->alloc((share->default_fields + + share->default_expressions + 1)* + sizeof(Field*)); if (!copy->default_field) goto error; dfield_ptr= copy->default_field; @@ -2465,48 +2445,61 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) if (!(*field= (*org_field)->make_new_field(client_thd->mem_root, copy, 1))) goto error; + (*field)->unireg_check= (*org_field)->unireg_check; (*field)->orig_table= copy; // Remove connection (*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0] if (*org_field == found_next_number_field) (*field)->table->found_next_number_field= *field; - if (share->default_fields && - ((*org_field)->has_insert_default_function() || - (*org_field)->has_update_default_function())) - { - /* Put the newly copied field into the set of default fields. */ - *dfield_ptr= *field; - (*dfield_ptr)->unireg_check= (*org_field)->unireg_check; - dfield_ptr++; - } } *field=0; - if (share->vfields) + if (share->virtual_fields || share->default_expressions || + share->default_fields) { + bool error_reported= FALSE; if (!(copy->def_vcol_set= (MY_BITMAP*) alloc_root(client_thd->mem_root, sizeof(MY_BITMAP)))) goto error; copy->vfield= vfield; for (field= copy->field; *field; field++) { + Virtual_column_info *vcol; if ((*field)->vcol_info) { - bool error_reported= FALSE; - if (unpack_vcol_info_from_frm(client_thd, - client_thd->mem_root, - copy, - *field, - &(*field)->vcol_info->expr_str, - &error_reported)) + if (!(vcol= unpack_vcol_info_from_frm(client_thd, + client_thd->mem_root, + copy, + 0, + (*field)->vcol_info, + &error_reported))) goto error; + (*field)->vcol_info= vcol; *vfield++= *field; } + if ((*field)->default_value) + { + if (!(vcol= unpack_vcol_info_from_frm(client_thd, + client_thd->mem_root, + copy, + 0, + (*field)->default_value, + &error_reported))) + goto error; + (*field)->default_value= vcol; + *dfield_ptr++= *field; + } + if ((*field)->has_insert_default_function() || + (*field)->has_update_default_function()) + *dfield_ptr++= *field; } - *vfield= 0; + if (vfield) + *vfield= 0; + if (dfield_ptr) + *dfield_ptr= 0; } - if (share->default_fields) - *dfield_ptr= NULL; + switch_to_nullable_trigger_fields(copy->vfield, copy); + switch_to_nullable_trigger_fields(copy->default_field, copy); /* Adjust in_use for pointing to client thread */ copy->in_use= client_thd; @@ -2518,15 +2511,28 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) copy->def_read_set.bitmap= (my_bitmap_map*) bitmap; copy->def_write_set.bitmap= ((my_bitmap_map*) (bitmap + share->column_bitmap_size)); - if (share->vfields) + bitmaps_used= 2; + if (share->virtual_fields) { my_bitmap_init(copy->def_vcol_set, - (my_bitmap_map*) (bitmap + 2*share->column_bitmap_size), + (my_bitmap_map*) (bitmap + + bitmaps_used*share->column_bitmap_size), share->fields, FALSE); + bitmaps_used++; copy->vcol_set= copy->def_vcol_set; } + if (share->default_fields) + { + if (!(copy->has_value_set= (MY_BITMAP*) alloc_root(client_thd->mem_root, + sizeof(MY_BITMAP)))) + goto error; + my_bitmap_init(copy->has_value_set, + (my_bitmap_map*) (bitmap + + bitmaps_used*share->column_bitmap_size), + share->fields, FALSE); + } copy->tmp_set.bitmap= 0; // To catch errors - bzero((char*) bitmap, share->column_bitmap_size * (share->vfields ? 3 : 2)); + bzero((char*) bitmap, share->column_bitmap_size * bitmaps_used); copy->read_set= ©->def_read_set; copy->write_set= ©->def_write_set; @@ -2793,11 +2799,11 @@ bool Delayed_insert::open_and_lock_table() return TRUE; } - if (table->triggers) + if (table->triggers || table->check_constraints) { /* - Table has triggers. This is not an error, but we do - not support triggers with delayed insert. Terminate the delayed + Table has triggers or check constraints. This is not an error, but we do + not support these with delayed insert. Terminate the delayed thread without an error and thus request lock upgrade. */ return TRUE; @@ -3425,8 +3431,8 @@ select_insert::select_insert(THD *thd_arg, TABLE_LIST *table_list_par, info.ignore= ignore_check_option_errors; info.update_fields= update_fields; info.update_values= update_values; - if (table_list_par) - info.view= (table_list_par->view ? table_list_par : 0); + info.view= (table_list_par->view ? table_list_par : 0); + info.table_list= table_list_par; } @@ -3657,7 +3663,7 @@ int select_insert::send_data(List<Item> &values) thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields store_values(values); - if (table->default_field && table->update_default_fields()) + if (table->default_field && table->update_default_fields(0, info.ignore)) DBUG_RETURN(1); thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; if (thd->is_error()) |