00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <config.h>
00019 #include <plugin/myisam/myisam.h>
00020 #include <drizzled/show.h>
00021 #include <drizzled/error.h>
00022 #include <drizzled/gettext.h>
00023 #include <drizzled/data_home.h>
00024 #include <drizzled/sql_parse.h>
00025 #include <drizzled/sql_lex.h>
00026 #include <drizzled/session.h>
00027 #include <drizzled/sql_base.h>
00028 #include <drizzled/lock.h>
00029 #include <drizzled/item/int.h>
00030 #include <drizzled/item/empty_string.h>
00031 #include <drizzled/transaction_services.h>
00032 #include <drizzled/transaction_services.h>
00033 #include <drizzled/table_proto.h>
00034 #include <drizzled/plugin/client.h>
00035 #include <drizzled/identifier.h>
00036 #include <drizzled/internal/m_string.h>
00037 #include <drizzled/charset.h>
00038 #include <drizzled/definition/cache.h>
00039 #include <drizzled/system_variables.h>
00040 #include <drizzled/statement/alter_table.h>
00041 #include <drizzled/sql_table.h>
00042 #include <drizzled/pthread_globals.h>
00043 #include <drizzled/typelib.h>
00044 #include <drizzled/plugin/storage_engine.h>
00045 #include <drizzled/diagnostics_area.h>
00046 #include <drizzled/open_tables_state.h>
00047 #include <drizzled/table/cache.h>
00048 #include <drizzled/create_field.h>
00049
00050 #include <algorithm>
00051 #include <sstream>
00052
00053 #include <boost/unordered_set.hpp>
00054
00055 using namespace std;
00056
00057 namespace drizzled {
00058
00059 bool is_primary_key(const char* name)
00060 {
00061 return strcmp(name, "PRIMARY") == 0;
00062 }
00063
00064 static bool check_if_keyname_exists(const char *name,KeyInfo *start, KeyInfo *end);
00065 static const char *make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end);
00066 static bool prepare_blob_field(Session *session, CreateField *sql_field);
00067
00068 void set_table_default_charset(HA_CREATE_INFO *create_info, const char *db)
00069 {
00070
00071
00072
00073
00074
00075 if (not create_info->default_table_charset)
00076 create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier::Schema(str_ref(db)));
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 int rm_table_part2(Session *session, TableList *tables, bool if_exists,
00107 bool drop_temporary)
00108 {
00109 TableList *table;
00110 util::string::vector wrong_tables;
00111 int error= 0;
00112 bool foreign_key_error= false;
00113
00114 do
00115 {
00116 boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
00117
00118 if (not drop_temporary && session->lock_table_names_exclusively(tables))
00119 {
00120 return 1;
00121 }
00122
00123
00124 session->no_warnings_for_error= 1;
00125
00126 for (table= tables; table; table= table->next_local)
00127 {
00128 identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
00129
00130 error= session->open_tables.drop_temporary_table(tmp_identifier);
00131
00132 switch (error) {
00133 case 0:
00134
00135 continue;
00136 case -1:
00137 error= 1;
00138 break;
00139 default:
00140
00141 error= 0;
00142 }
00143
00144 if (drop_temporary == false)
00145 {
00146 abort_locked_tables(session, tmp_identifier);
00147 table::Cache::removeTable(*session, tmp_identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
00148
00149
00150
00151
00152 Table *locked_table= drop_locked_tables(session, tmp_identifier);
00153 if (locked_table)
00154 table->table= locked_table;
00155
00156 if (session->getKilled())
00157 {
00158 error= -1;
00159 break;
00160 }
00161 }
00162 identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
00163
00164 message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
00165
00166 if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
00167 {
00168
00169 if (if_exists)
00170 {
00171 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
00172 ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
00173 table->getTableName());
00174 }
00175 else
00176 {
00177 error= 1;
00178 }
00179 }
00180 else
00181 {
00182 drizzled::error_t local_error;
00183
00184
00185 if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
00186 {
00187 if (message)
00188 {
00189 TransactionServices::dropTable(*session, identifier, *message, if_exists);
00190 }
00191 }
00192 else
00193 {
00194 if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
00195 {
00196 error= 0;
00197 session->clear_error();
00198 }
00199
00200 if (local_error == HA_ERR_ROW_IS_REFERENCED)
00201 {
00202
00203 foreign_key_error= true;
00204 }
00205 error= local_error;
00206 }
00207 }
00208
00209 if (error)
00210 {
00211 wrong_tables.push_back(table->getTableName());
00212 }
00213 }
00214
00215 tables->unlock_table_names();
00216
00217 } while (0);
00218
00219 if (wrong_tables.size())
00220 {
00221 if (not foreign_key_error)
00222 {
00223 std::string table_error;
00224
00225 BOOST_FOREACH(util::string::vector::reference iter, wrong_tables)
00226 {
00227 table_error+= iter;
00228 table_error+= ',';
00229 }
00230 table_error.resize(table_error.size() -1);
00231
00232 my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
00233 table_error.c_str());
00234 }
00235 else
00236 {
00237 my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
00238 }
00239 error= 1;
00240 }
00241
00242 session->no_warnings_for_error= 0;
00243
00244 return error;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 static int sort_keys(KeyInfo *a, KeyInfo *b)
00261 {
00262 ulong a_flags= a->flags, b_flags= b->flags;
00263
00264 if (a_flags & HA_NOSAME)
00265 {
00266 if (!(b_flags & HA_NOSAME))
00267 return -1;
00268 if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY))
00269 {
00270
00271 return (a_flags & (HA_NULL_PART_KEY)) ? 1 : -1;
00272 }
00273 if (is_primary_key(a->name))
00274 return -1;
00275 if (is_primary_key(b->name))
00276 return 1;
00277
00278 if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
00279 return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
00280 }
00281 else if (b_flags & HA_NOSAME)
00282 return 1;
00283
00284
00285
00286
00287
00288 return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
00289 (a->usable_key_parts > b->usable_key_parts) ? 1 :
00290 0);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 class typelib_set_member
00313 {
00314 public:
00315 string s;
00316 const charset_info_st * const cs;
00317
00318 typelib_set_member(const char* value, unsigned int length,
00319 const charset_info_st * const charset)
00320 : s(value, length),
00321 cs(charset)
00322 {}
00323 };
00324
00325 static bool operator==(typelib_set_member const& a, typelib_set_member const& b)
00326 {
00327 return (my_strnncoll(a.cs,
00328 (const unsigned char*)a.s.c_str(), a.s.length(),
00329 (const unsigned char*)b.s.c_str(), b.s.length())==0);
00330 }
00331
00332
00333 namespace
00334 {
00335 class typelib_set_member_hasher
00336 {
00337 boost::hash<string> hasher;
00338 public:
00339 std::size_t operator()(const typelib_set_member& t) const
00340 {
00341 return hasher(t.s);
00342 }
00343 };
00344 }
00345
00346 static bool check_duplicates_in_interval(const char *set_or_name,
00347 const char *name, TYPELIB *typelib,
00348 const charset_info_st * const cs,
00349 unsigned int *dup_val_count)
00350 {
00351 TYPELIB tmp= *typelib;
00352 const char **cur_value= typelib->type_names;
00353 unsigned int *cur_length= typelib->type_lengths;
00354 *dup_val_count= 0;
00355
00356 boost::unordered_set<typelib_set_member, typelib_set_member_hasher> interval_set;
00357
00358 for ( ; tmp.count > 0; cur_value++, cur_length++)
00359 {
00360 tmp.type_names++;
00361 tmp.type_lengths++;
00362 tmp.count--;
00363 if (interval_set.count(typelib_set_member(*cur_value, *cur_length, cs)))
00364 {
00365 my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
00366 name,*cur_value,set_or_name);
00367 return 1;
00368 }
00369 else
00370 interval_set.insert(typelib_set_member(*cur_value, *cur_length, cs));
00371 }
00372 return 0;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 static void calculate_interval_lengths(const charset_info_st * const cs,
00395 TYPELIB *interval,
00396 uint32_t *max_length,
00397 uint32_t *tot_length)
00398 {
00399 const char **pos;
00400 uint32_t *len;
00401 *max_length= *tot_length= 0;
00402 for (pos= interval->type_names, len= interval->type_lengths;
00403 *pos ; pos++, len++)
00404 {
00405 uint32_t length= cs->cset->numchars(cs, *pos, *pos + *len);
00406 *tot_length+= length;
00407 set_if_bigger(*max_length, (uint32_t)length);
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 int prepare_create_field(CreateField *sql_field,
00429 uint32_t *blob_columns,
00430 int *timestamps,
00431 int *timestamps_with_niladic)
00432 {
00433 unsigned int dup_val_count;
00434
00435
00436
00437
00438
00439 assert(sql_field->charset);
00440
00441 switch (sql_field->sql_type) {
00442 case DRIZZLE_TYPE_BLOB:
00443 sql_field->length= 8;
00444 (*blob_columns)++;
00445 break;
00446
00447 case DRIZZLE_TYPE_ENUM:
00448 {
00449 if (check_duplicates_in_interval("ENUM",
00450 sql_field->field_name,
00451 sql_field->interval,
00452 sql_field->charset,
00453 &dup_val_count))
00454 {
00455 return 1;
00456 }
00457 }
00458 break;
00459
00460 case DRIZZLE_TYPE_MICROTIME:
00461 case DRIZZLE_TYPE_TIMESTAMP:
00462
00463 if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
00464 {
00465 if (!*timestamps)
00466 {
00467 sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
00468 (*timestamps_with_niladic)++;
00469 }
00470 else
00471 {
00472 sql_field->unireg_check= Field::NONE;
00473 }
00474 }
00475 else if (sql_field->unireg_check != Field::NONE)
00476 {
00477 (*timestamps_with_niladic)++;
00478 }
00479
00480 (*timestamps)++;
00481
00482 break;
00483
00484 case DRIZZLE_TYPE_BOOLEAN:
00485 case DRIZZLE_TYPE_DATE:
00486 case DRIZZLE_TYPE_DATETIME:
00487 case DRIZZLE_TYPE_DECIMAL:
00488 case DRIZZLE_TYPE_DOUBLE:
00489 case DRIZZLE_TYPE_LONG:
00490 case DRIZZLE_TYPE_LONGLONG:
00491 case DRIZZLE_TYPE_NULL:
00492 case DRIZZLE_TYPE_TIME:
00493 case DRIZZLE_TYPE_UUID:
00494 case DRIZZLE_TYPE_IPV6:
00495 case DRIZZLE_TYPE_VARCHAR:
00496 break;
00497 }
00498
00499 return 0;
00500 }
00501
00502 static int prepare_create_table(Session *session,
00503 HA_CREATE_INFO *create_info,
00504 message::Table &create_proto,
00505 AlterInfo *alter_info,
00506 bool tmp_table,
00507 uint32_t *db_options,
00508 KeyInfo **key_info_buffer,
00509 uint32_t *key_count,
00510 int select_field_count)
00511 {
00512 const char *key_name;
00513 CreateField *sql_field,*dup_field;
00514 uint field,null_fields,blob_columns,max_key_length;
00515 ulong record_offset= 0;
00516 KeyInfo *key_info;
00517 KeyPartInfo *key_part_info;
00518 int timestamps= 0, timestamps_with_niladic= 0;
00519 int dup_no;
00520 int select_field_pos,auto_increment=0;
00521 List<CreateField>::iterator it(alter_info->create_list.begin());
00522 List<CreateField>::iterator it2(alter_info->create_list.begin());
00523 uint32_t total_uneven_bit_length= 0;
00524
00525 plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
00526
00527 select_field_pos= alter_info->create_list.size() - select_field_count;
00528 null_fields=blob_columns=0;
00529 max_key_length= engine->max_key_length();
00530
00531 for (int32_t field_no=0; (sql_field=it++) ; field_no++)
00532 {
00533 const charset_info_st *save_cs;
00534
00535
00536
00537
00538
00539
00540 sql_field->length= sql_field->char_length;
00541
00542 if (!sql_field->charset)
00543 sql_field->charset= create_info->default_table_charset;
00544
00545
00546
00547
00548
00549
00550
00551 if (create_info->table_charset && sql_field->charset != &my_charset_bin)
00552 sql_field->charset= create_info->table_charset;
00553
00554 save_cs= sql_field->charset;
00555 if ((sql_field->flags & BINCMP_FLAG) &&
00556 !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname, MY_CS_BINSORT)))
00557 {
00558 char tmp[64];
00559 char *tmp_pos= tmp;
00560 strncpy(tmp_pos, save_cs->csname, sizeof(tmp)-4);
00561 tmp_pos+= strlen(tmp);
00562 strncpy(tmp_pos, STRING_WITH_LEN("_bin"));
00563 my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
00564 return true;
00565 }
00566
00567
00568
00569
00570
00571 if (sql_field->def &&
00572 save_cs != sql_field->def->collation.collation &&
00573 (sql_field->sql_type == DRIZZLE_TYPE_ENUM))
00574 {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 sql_field->def= sql_field->def->safe_charset_converter(save_cs);
00586
00587 if (sql_field->def == NULL)
00588 {
00589
00590 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
00591 return true;
00592 }
00593 }
00594
00595 if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
00596 {
00597 const charset_info_st * const cs= sql_field->charset;
00598 TYPELIB *interval= sql_field->interval;
00599
00600
00601
00602
00603
00604
00605 if (!interval)
00606 {
00607
00608
00609
00610
00611
00612 interval= sql_field->interval= typelib(*session->mem_root, sql_field->interval_list);
00613
00614 List<String>::iterator int_it(sql_field->interval_list.begin());
00615 String conv, *tmp;
00616 char comma_buf[4];
00617 int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf, (unsigned char*) comma_buf + sizeof(comma_buf));
00618 assert(comma_length > 0);
00619
00620 for (uint32_t i= 0; (tmp= int_it++); i++)
00621 {
00622 uint32_t lengthsp;
00623 if (String::needs_conversion(tmp->length(), tmp->charset(), cs))
00624 {
00625 conv.copy(tmp->ptr(), tmp->length(), cs);
00626 interval->type_names[i]= session->mem.strdup(conv);
00627 interval->type_lengths[i]= conv.length();
00628 }
00629
00630
00631 lengthsp= cs->cset->lengthsp(cs, interval->type_names[i], interval->type_lengths[i]);
00632 interval->type_lengths[i]= lengthsp;
00633 ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
00634 }
00635 sql_field->interval_list.clear();
00636 }
00637
00638
00639 {
00640 uint32_t field_length;
00641 assert(sql_field->sql_type == DRIZZLE_TYPE_ENUM);
00642 if (sql_field->def != NULL)
00643 {
00644 String str, *def= sql_field->def->val_str(&str);
00645 if (def == NULL)
00646 {
00647 if (sql_field->flags & NOT_NULL_FLAG)
00648 {
00649 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
00650 return true;
00651 }
00652
00653
00654 }
00655 else
00656 {
00657 def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
00658 if (interval->find_type2(def->ptr(), def->length(), cs) == 0)
00659 {
00660 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
00661 return true;
00662 }
00663 }
00664 }
00665 uint32_t new_dummy;
00666 calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
00667 sql_field->length= field_length;
00668 }
00669 set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
00670 }
00671
00672 sql_field->create_length_to_internal_length();
00673 if (prepare_blob_field(session, sql_field))
00674 return true;
00675
00676 if (!(sql_field->flags & NOT_NULL_FLAG))
00677 null_fields++;
00678
00679 if (check_column_name(sql_field->field_name))
00680 {
00681 my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
00682 return true;
00683 }
00684
00685
00686 for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
00687 {
00688 if (system_charset_info->strcasecmp(sql_field->field_name, dup_field->field_name) == 0)
00689 {
00690
00691
00692
00693
00694 if (field_no < select_field_pos || dup_no >= select_field_pos)
00695 {
00696 my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
00697 return true;
00698 }
00699 else
00700 {
00701
00702 sql_field->def= dup_field->def;
00703 sql_field->sql_type= dup_field->sql_type;
00704 sql_field->charset= (dup_field->charset ?
00705 dup_field->charset :
00706 create_info->default_table_charset);
00707 sql_field->length= dup_field->char_length;
00708 sql_field->pack_length= dup_field->pack_length;
00709 sql_field->key_length= dup_field->key_length;
00710 sql_field->decimals= dup_field->decimals;
00711 sql_field->create_length_to_internal_length();
00712 sql_field->unireg_check= dup_field->unireg_check;
00713
00714
00715
00716
00717
00718 if (!(sql_field->flags & NOT_NULL_FLAG))
00719 null_fields--;
00720 sql_field->flags= dup_field->flags;
00721 sql_field->interval= dup_field->interval;
00722 it2.remove();
00723 select_field_pos--;
00724 break;
00725 }
00726 }
00727 }
00728
00730 if (not create_proto.engine().name().compare("MyISAM") &&
00731 ((sql_field->flags & BLOB_FLAG) ||
00732 (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
00733 {
00734 (*db_options)|= HA_OPTION_PACK_RECORD;
00735 }
00736
00737 it2= alter_info->create_list.begin();
00738 }
00739
00740
00741 record_offset= 0;
00742 null_fields+= total_uneven_bit_length;
00743
00744 it= alter_info->create_list.begin();
00745 while ((sql_field=it++))
00746 {
00747 assert(sql_field->charset != 0);
00748
00749 if (prepare_create_field(sql_field, &blob_columns,
00750 ×tamps, ×tamps_with_niladic))
00751 return true;
00752 sql_field->offset= record_offset;
00753 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
00754 auto_increment++;
00755 }
00756 if (timestamps_with_niladic > 1)
00757 {
00758 my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
00759 ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
00760 return true;
00761 }
00762 if (auto_increment > 1)
00763 {
00764 my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
00765 return true;
00766 }
00767 if (auto_increment &&
00768 (engine->check_flag(HTON_BIT_NO_AUTO_INCREMENT)))
00769 {
00770 my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
00771 ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
00772 return true;
00773 }
00774
00775 if (blob_columns && (engine->check_flag(HTON_BIT_NO_BLOBS)))
00776 {
00777 my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
00778 MYF(0));
00779 return true;
00780 }
00781
00782
00783
00784 List<Key>::iterator key_iterator(alter_info->key_list.begin());
00785 List<Key>::iterator key_iterator2(alter_info->key_list.begin());
00786 uint32_t key_parts=0, fk_key_count=0;
00787 bool primary_key=0,unique_key=0;
00788 Key *key, *key2;
00789 uint32_t tmp, key_number;
00790
00791 static char ignore_key[1];
00792
00793
00794 *key_count= 0;
00795
00796 while ((key=key_iterator++))
00797 {
00798 if (key->type == Key::FOREIGN_KEY)
00799 {
00800 fk_key_count++;
00801 if (((Foreign_key *)key)->validate(alter_info->create_list))
00802 return true;
00803
00804 Foreign_key *fk_key= (Foreign_key*) key;
00805
00806 add_foreign_key_to_table_message(&create_proto,
00807 fk_key->name.data(),
00808 fk_key->columns,
00809 fk_key->ref_table,
00810 fk_key->ref_columns,
00811 fk_key->delete_opt,
00812 fk_key->update_opt,
00813 fk_key->match_opt);
00814
00815 if (fk_key->ref_columns.size() &&
00816 fk_key->ref_columns.size() != fk_key->columns.size())
00817 {
00818 my_error(ER_WRONG_FK_DEF, MYF(0),
00819 (fk_key->name.data() ? fk_key->name.data() : "foreign key without name"),
00820 ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
00821 return true;
00822 }
00823 continue;
00824 }
00825 (*key_count)++;
00826 tmp= engine->max_key_parts();
00827 if (key->columns.size() > tmp)
00828 {
00829 my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
00830 return true;
00831 }
00832 if (check_identifier_name(key->name, ER_TOO_LONG_IDENT))
00833 return true;
00834 key_iterator2= alter_info->key_list.begin();
00835 if (key->type != Key::FOREIGN_KEY)
00836 {
00837 while ((key2 = key_iterator2++) != key)
00838 {
00839
00840
00841
00842
00843
00844 if ((key2->type != Key::FOREIGN_KEY &&
00845 key2->name.data() != ignore_key &&
00846 !foreign_key_prefix(key, key2)))
00847 {
00848
00849
00850 if (!key2->generated ||
00851 (key->generated && key->columns.size() <
00852 key2->columns.size()))
00853 key->name.assign(ignore_key, 1);
00854 else
00855 {
00856 key2->name.assign(ignore_key, 1);
00857 key_parts-= key2->columns.size();
00858 (*key_count)--;
00859 }
00860 break;
00861 }
00862 }
00863 }
00864 if (key->name.data() != ignore_key)
00865 key_parts+=key->columns.size();
00866 else
00867 (*key_count)--;
00868 if (key->name.data() && !tmp_table && (key->type != Key::PRIMARY) && is_primary_key(key->name.data()))
00869 {
00870 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.data());
00871 return true;
00872 }
00873 }
00874 tmp= engine->max_keys();
00875 if (*key_count > tmp)
00876 {
00877 my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
00878 return true;
00879 }
00880
00881 (*key_info_buffer)= key_info= (KeyInfo*) memory::sql_calloc(sizeof(KeyInfo) * (*key_count));
00882 key_part_info=(KeyPartInfo*) memory::sql_calloc(sizeof(KeyPartInfo)*key_parts);
00883
00884 key_iterator= alter_info->key_list.begin();
00885 key_number=0;
00886 for (; (key=key_iterator++) ; key_number++)
00887 {
00888 uint32_t key_length=0;
00889 Key_part_spec *column;
00890
00891 if (key->name.data() == ignore_key)
00892 {
00893
00894 do
00895 key=key_iterator++;
00896 while (key && key->name.data() == ignore_key);
00897 if (!key)
00898 break;
00899 }
00900
00901 switch (key->type) {
00902 case Key::MULTIPLE:
00903 key_info->flags= 0;
00904 break;
00905 case Key::FOREIGN_KEY:
00906 key_number--;
00907 continue;
00908 default:
00909 key_info->flags = HA_NOSAME;
00910 break;
00911 }
00912 if (key->generated)
00913 key_info->flags|= HA_GENERATED_KEY;
00914
00915 key_info->key_parts=(uint8_t) key->columns.size();
00916 key_info->key_part=key_part_info;
00917 key_info->usable_key_parts= key_number;
00918 key_info->algorithm= key->key_create_info.algorithm;
00919
00920 uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
00921 key->key_create_info.comment.begin(),
00922 key->key_create_info.comment.end(),
00923 INDEX_COMMENT_MAXLEN);
00924
00925 if (tmp_len < key->key_create_info.comment.size())
00926 {
00927 my_error(ER_WRONG_STRING_LENGTH, MYF(0), key->key_create_info.comment.data(), "INDEX COMMENT", (uint32_t) INDEX_COMMENT_MAXLEN);
00928 return -1;
00929 }
00930
00931 key_info->comment.assign(key_info->comment.data(), key->key_create_info.comment.size());
00932 if (key_info->comment.size() > 0)
00933 {
00934 key_info->flags|= HA_USES_COMMENT;
00935 key_info->comment.assign(key->key_create_info.comment.data(), key_info->comment.size());
00936 }
00937
00938 message::Table::Field *protofield= NULL;
00939
00940 List<Key_part_spec>::iterator cols(key->columns.begin());
00941 List<Key_part_spec>::iterator cols2(key->columns.begin());
00942 for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
00943 {
00944 uint32_t length;
00945 Key_part_spec *dup_column;
00946 int proto_field_nr= 0;
00947
00948 it= alter_info->create_list.begin();
00949 field=0;
00950 while ((sql_field=it++) && ++proto_field_nr &&
00951 system_charset_info->strcasecmp(column->field_name.data(), sql_field->field_name))
00952 {
00953 field++;
00954 }
00955
00956 if (!sql_field)
00957 {
00958 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.data());
00959 return true;
00960 }
00961
00962 while ((dup_column= cols2++) != column)
00963 {
00964 if (!system_charset_info->strcasecmp(column->field_name.data(), dup_column->field_name.data()))
00965 {
00966 my_printf_error(ER_DUP_FIELDNAME,
00967 ER(ER_DUP_FIELDNAME),MYF(0),
00968 column->field_name.data());
00969 return true;
00970 }
00971 }
00972 cols2= key->columns.begin();
00973
00974 if (create_proto.field_size() > 0)
00975 protofield= create_proto.mutable_field(proto_field_nr - 1);
00976
00977 {
00978 column->length*= sql_field->charset->mbmaxlen;
00979
00980 if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
00981 {
00982 if (! (engine->check_flag(HTON_BIT_CAN_INDEX_BLOBS)))
00983 {
00984 my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.data());
00985 return true;
00986 }
00987 if (! column->length)
00988 {
00989 my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.data());
00990 return true;
00991 }
00992 }
00993
00994 if (! (sql_field->flags & NOT_NULL_FLAG))
00995 {
00996 if (key->type == Key::PRIMARY)
00997 {
00998
00999 sql_field->flags|= NOT_NULL_FLAG;
01000 null_fields--;
01001
01002 if (protofield)
01003 {
01004 message::Table::Field::FieldConstraints *constraints;
01005 constraints= protofield->mutable_constraints();
01006 constraints->set_is_notnull(true);
01007 }
01008
01009 }
01010 else
01011 {
01012 key_info->flags|= HA_NULL_PART_KEY;
01013 if (! (engine->check_flag(HTON_BIT_NULL_IN_KEY)))
01014 {
01015 my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.data());
01016 return true;
01017 }
01018 }
01019 }
01020
01021 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
01022 {
01023 if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
01024 auto_increment--;
01025 }
01026 }
01027
01028 key_part_info->fieldnr= field;
01029 key_part_info->offset= (uint16_t) sql_field->offset;
01030 key_part_info->key_type= 0;
01031 length= sql_field->key_length;
01032
01033 if (column->length)
01034 {
01035 if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
01036 {
01037 if ((length=column->length) > max_key_length ||
01038 length > engine->max_key_part_length())
01039 {
01040 length= min(max_key_length, engine->max_key_part_length());
01041 if (key->type == Key::MULTIPLE)
01042 {
01043
01044 char warn_buff[DRIZZLE_ERRMSG_SIZE];
01045 snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
01046 length);
01047 push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
01048 ER_TOO_LONG_KEY, warn_buff);
01049
01050 length-= length % sql_field->charset->mbmaxlen;
01051 }
01052 else
01053 {
01054 my_error(ER_TOO_LONG_KEY,MYF(0),length);
01055 return true;
01056 }
01057 }
01058 }
01059 else if ((column->length > length ||
01060 ! Field::type_can_have_key_part(sql_field->sql_type)))
01061 {
01062 my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
01063 return true;
01064 }
01065 else if (! (engine->check_flag(HTON_BIT_NO_PREFIX_CHAR_KEYS)))
01066 {
01067 length=column->length;
01068 }
01069 }
01070 else if (length == 0)
01071 {
01072 my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.data());
01073 return true;
01074 }
01075 if (length > engine->max_key_part_length())
01076 {
01077 length= engine->max_key_part_length();
01078 if (key->type == Key::MULTIPLE)
01079 {
01080
01081 char warn_buff[DRIZZLE_ERRMSG_SIZE];
01082 snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
01083 length);
01084 push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
01085 ER_TOO_LONG_KEY, warn_buff);
01086
01087 length-= length % sql_field->charset->mbmaxlen;
01088 }
01089 else
01090 {
01091 my_error(ER_TOO_LONG_KEY,MYF(0),length);
01092 return true;
01093 }
01094 }
01095 key_part_info->length=(uint16_t) length;
01096
01097 if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
01098 (length >= KEY_DEFAULT_PACK_LENGTH &&
01099 (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR ||
01100 sql_field->sql_type == DRIZZLE_TYPE_BLOB)))
01101 {
01102 if ((column_nr == 0 && sql_field->sql_type == DRIZZLE_TYPE_BLOB) ||
01103 sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)
01104 {
01105 key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
01106 }
01107 else
01108 {
01109 key_info->flags|= HA_PACK_KEY;
01110 }
01111 }
01112
01113 if (length != sql_field->key_length)
01114 key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
01115
01116 key_length+=length;
01117 key_part_info++;
01118
01119
01120 if (column_nr == 0)
01121 {
01122 if (key->type == Key::PRIMARY)
01123 {
01124 if (primary_key)
01125 {
01126 my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
01127 MYF(0));
01128 return true;
01129 }
01130 static const char pkey_name[]= "PRIMARY";
01131 key_name=pkey_name;
01132 primary_key=1;
01133 }
01134 else if (!(key_name= key->name.data()))
01135 key_name=make_unique_key_name(sql_field->field_name,
01136 *key_info_buffer, key_info);
01137 if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
01138 {
01139 my_error(ER_DUP_KEYNAME, MYF(0), key_name);
01140 return true;
01141 }
01142 key_info->name=(char*) key_name;
01143 }
01144 }
01145
01146 if (!key_info->name || check_column_name(key_info->name))
01147 {
01148 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
01149 return true;
01150 }
01151
01152 if (!(key_info->flags & HA_NULL_PART_KEY))
01153 {
01154 unique_key=1;
01155 }
01156
01157 key_info->key_length=(uint16_t) key_length;
01158
01159 if (key_length > max_key_length)
01160 {
01161 my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
01162 return true;
01163 }
01164
01165 key_info++;
01166 }
01167
01168 if (!unique_key && !primary_key &&
01169 (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
01170 {
01171 my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
01172 return true;
01173 }
01174
01175 if (auto_increment > 0)
01176 {
01177 my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
01178 return true;
01179 }
01180
01181 internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
01182 (qsort_cmp) sort_keys);
01183
01184
01185 it= alter_info->create_list.begin();
01186 while ((sql_field=it++))
01187 {
01188 Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
01189
01190 if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
01191 !sql_field->def &&
01192 (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
01193 (sql_field->flags & NOT_NULL_FLAG) &&
01194 (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
01195 {
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
01211 return true;
01212 }
01213 }
01214
01215 return false;
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 static bool prepare_blob_field(Session *,
01232 CreateField *sql_field)
01233 {
01234
01235 if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
01236 !(sql_field->flags & BLOB_FLAG))
01237 {
01238 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
01239 MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
01240 return 1;
01241 }
01242
01243 if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
01244 {
01245 if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
01246 {
01247
01248 sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
01249 }
01250 sql_field->length= 0;
01251 }
01252 return 0;
01253 }
01254
01255 static bool locked_create_event(Session *session,
01256 const identifier::Table &identifier,
01257 HA_CREATE_INFO *create_info,
01258 message::Table &table_proto,
01259 AlterInfo *alter_info,
01260 bool is_if_not_exists,
01261 bool internal_tmp_table,
01262 uint db_options,
01263 uint key_count,
01264 KeyInfo *key_info_buffer)
01265 {
01266 bool error= true;
01267
01268 {
01269
01270
01271
01272
01273
01274
01275 bool exists=
01276 plugin::StorageEngine::doesTableExist(*session, identifier,
01277 identifier.getType() != message::Table::STANDARD );
01278
01279 if (exists)
01280 {
01281 if (is_if_not_exists)
01282 {
01283 error= false;
01284 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
01285 ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
01286 identifier.getTableName().c_str());
01287 create_info->table_existed= 1;
01288 return error;
01289 }
01290
01291 my_error(ER_TABLE_EXISTS_ERROR, identifier);
01292
01293 return error;
01294 }
01295
01296 if (identifier.getType() == message::Table::STANDARD)
01297 {
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 if (definition::Cache::find(identifier.getKey()))
01310 {
01311 my_error(ER_TABLE_EXISTS_ERROR, identifier);
01312
01313 return error;
01314 }
01315 }
01316 }
01317
01318 session->set_proc_info("creating table");
01319 create_info->table_existed= 0;
01320
01321 create_info->table_options= db_options;
01322
01323 if (not rea_create_table(session, identifier,
01324 table_proto,
01325 create_info, alter_info->create_list,
01326 key_count, key_info_buffer))
01327 {
01328 return error;
01329 }
01330
01331 if (identifier.getType() == message::Table::TEMPORARY)
01332 {
01333
01334 if (not (session->open_temporary_table(identifier)))
01335 {
01336 (void) session->open_tables.rm_temporary_table(identifier);
01337 return error;
01338 }
01339 }
01340
01341
01342
01343
01344
01345
01346
01347 if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
01348 {
01349 TransactionServices::createTable(*session, table_proto);
01350 }
01351
01352 return false;
01353 }
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 bool create_table_no_lock(Session *session,
01387 const identifier::Table &identifier,
01388 HA_CREATE_INFO *create_info,
01389 message::Table &table_proto,
01390 AlterInfo *alter_info,
01391 bool internal_tmp_table,
01392 uint32_t select_field_count,
01393 bool is_if_not_exists)
01394 {
01395 uint db_options, key_count;
01396 KeyInfo *key_info_buffer;
01397 bool error= true;
01398
01399
01400 if (not alter_info->create_list.size())
01401 {
01402 my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
01403 MYF(0));
01404 return true;
01405 }
01406 assert(identifier.getTableName() == table_proto.name());
01407 db_options= create_info->table_options;
01408
01409 set_table_default_charset(create_info, identifier.getSchemaName().c_str());
01410
01411
01412 if (not prepare_create_table(session, create_info, table_proto, alter_info,
01413 internal_tmp_table,
01414 &db_options,
01415 &key_info_buffer, &key_count,
01416 select_field_count))
01417 {
01418 boost::mutex::scoped_lock lock(table::Cache::mutex());
01419 error= locked_create_event(session,
01420 identifier,
01421 create_info,
01422 table_proto,
01423 alter_info,
01424 is_if_not_exists,
01425 internal_tmp_table,
01426 db_options, key_count,
01427 key_info_buffer);
01428 }
01429
01430 session->set_proc_info("After create");
01431
01432 return(error);
01433 }
01434
01438 static bool drizzle_create_table(Session *session,
01439 const identifier::Table &identifier,
01440 HA_CREATE_INFO *create_info,
01441 message::Table &table_proto,
01442 AlterInfo *alter_info,
01443 bool internal_tmp_table,
01444 uint32_t select_field_count,
01445 bool is_if_not_exists)
01446 {
01447 Table *name_lock= session->lock_table_name_if_not_cached(identifier);
01448 bool result;
01449 if (name_lock == NULL)
01450 {
01451 if (is_if_not_exists)
01452 {
01453 push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
01454 ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
01455 identifier.getTableName().c_str());
01456 create_info->table_existed= 1;
01457 result= false;
01458 }
01459 else
01460 {
01461 my_error(ER_TABLE_EXISTS_ERROR, identifier);
01462 result= true;
01463 }
01464 }
01465 else
01466 {
01467 result= create_table_no_lock(session,
01468 identifier,
01469 create_info,
01470 table_proto,
01471 alter_info,
01472 internal_tmp_table,
01473 select_field_count,
01474 is_if_not_exists);
01475 }
01476
01477 if (name_lock)
01478 {
01479 boost::mutex::scoped_lock lock(table::Cache::mutex());
01480 session->unlink_open_table(name_lock);
01481 }
01482
01483 return(result);
01484 }
01485
01486
01487
01488
01489
01490 bool create_table(Session *session,
01491 const identifier::Table &identifier,
01492 HA_CREATE_INFO *create_info,
01493 message::Table &table_proto,
01494 AlterInfo *alter_info,
01495 bool internal_tmp_table,
01496 uint32_t select_field_count,
01497 bool is_if_not_exists)
01498 {
01499 if (identifier.isTmp())
01500 {
01501 return create_table_no_lock(session,
01502 identifier,
01503 create_info,
01504 table_proto,
01505 alter_info,
01506 internal_tmp_table,
01507 select_field_count,
01508 is_if_not_exists);
01509 }
01510
01511 return drizzle_create_table(session,
01512 identifier,
01513 create_info,
01514 table_proto,
01515 alter_info,
01516 internal_tmp_table,
01517 select_field_count,
01518 is_if_not_exists);
01519 }
01520
01521
01522
01523
01524
01525
01526 static bool
01527 check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
01528 {
01529 for (KeyInfo *key= start; key != end; key++)
01530 {
01531 if (!system_charset_info->strcasecmp(name, key->name))
01532 return 1;
01533 }
01534 return 0;
01535 }
01536
01537
01538 static const char*
01539 make_unique_key_name(const char *field_name,KeyInfo *start,KeyInfo *end)
01540 {
01541 char buff[MAX_FIELD_NAME],*buff_end;
01542
01543 if (not check_if_keyname_exists(field_name,start,end) && not is_primary_key(field_name))
01544 return field_name;
01545
01546 buff_end= strncpy(buff, field_name, sizeof(buff)-4);
01547 buff_end+= strlen(buff);
01548
01549
01550
01551
01552
01553 for (uint32_t i=2 ; i< 100; i++)
01554 {
01555 *buff_end= '_';
01556 internal::int10_to_str(i, buff_end+1, 10);
01557 if (!check_if_keyname_exists(buff,start,end))
01558 return memory::sql_strdup(buff);
01559 }
01560 return (char*) "not_specified";
01561 }
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585 bool
01586 rename_table(Session &session,
01587 plugin::StorageEngine *base,
01588 const identifier::Table &from,
01589 const identifier::Table &to)
01590 {
01591 if (not plugin::StorageEngine::doesSchemaExist(to))
01592 {
01593 my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
01594 return true;
01595 }
01596
01597 int error= base->renameTable(session, from, to);
01598 if (error == HA_ERR_WRONG_COMMAND)
01599 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
01600 else if (error)
01601 {
01602 my_error(ER_ERROR_ON_RENAME, MYF(0),
01603 from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str(),
01604 to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str(), error);
01605 }
01606 return error;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 void wait_while_table_is_used(Session *session, Table *table,
01630 enum ha_extra_function function)
01631 {
01632
01633 safe_mutex_assert_owner(table::Cache::mutex().native_handle());
01634
01635 table->cursor->extra(function);
01636
01637 session->abortLock(table);
01638
01639
01640 identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
01641 table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 void Session::close_cached_table(Table *table)
01662 {
01663
01664 wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
01665
01666 if (open_tables.lock)
01667 {
01668 unlockTables(open_tables.lock);
01669 open_tables.lock= NULL;
01670 }
01671
01672 unlink_open_table(table);
01673
01674
01675 locking::broadcast_refresh();
01676 }
01677
01678
01679
01680
01681
01682
01683
01684 static bool admin_table(Session* session, TableList* tables,
01685 const char *operator_name,
01686 thr_lock_type lock_type,
01687 bool open_for_modify,
01688 int (Cursor::*operator_func)(Session*))
01689 {
01690 TableList *table;
01691 Select_Lex *select= &session->lex().select_lex;
01692 List<Item> field_list;
01693 Item *item;
01694 int result_code= 0;
01695 const charset_info_st * const cs= system_charset_info;
01696
01697 if (! session->endActiveTransaction())
01698 return 1;
01699
01700 field_list.push_back(item = new Item_empty_string("Table", NAME_CHAR_LEN * 2, cs));
01701 item->maybe_null = 1;
01702 field_list.push_back(item = new Item_empty_string("Op", 10, cs));
01703 item->maybe_null = 1;
01704 field_list.push_back(item = new Item_empty_string("Msg_type", 10, cs));
01705 item->maybe_null = 1;
01706 field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
01707 item->maybe_null = 1;
01708 session->getClient()->sendFields(field_list);
01709
01710 for (table= tables; table; table= table->next_local)
01711 {
01712 identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
01713 bool fatal_error=0;
01714
01715 std::string table_name = table_identifier.getSQLPath();
01716
01717 table->lock_type= lock_type;
01718
01719 {
01720 TableList *save_next_global, *save_next_local;
01721 save_next_global= table->next_global;
01722 table->next_global= 0;
01723 save_next_local= table->next_local;
01724 table->next_local= 0;
01725 select->table_list.first= (unsigned char*)table;
01726
01727
01728
01729
01730
01731 session->lex().query_tables= table;
01732 session->lex().query_tables_last= &table->next_global;
01733 session->lex().query_tables_own_last= 0;
01734 session->no_warnings_for_error= 0;
01735
01736 session->openTablesLock(table);
01737 session->no_warnings_for_error= 0;
01738 table->next_global= save_next_global;
01739 table->next_local= save_next_local;
01740 }
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750 if (!table->table)
01751 {
01752 if (!session->main_da().m_warn_list.size())
01753 push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
01754 ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
01755 result_code= HA_ADMIN_CORRUPT;
01756 goto send_result;
01757 }
01758
01759 if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
01760 {
01761 char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
01762 uint32_t length;
01763 session->getClient()->store(table_name.c_str());
01764 session->getClient()->store(operator_name);
01765 session->getClient()->store(STRING_WITH_LEN("error"));
01766 length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
01767 table_name.c_str());
01768 session->getClient()->store(buff, length);
01769 TransactionServices::autocommitOrRollback(*session, false);
01770 session->endTransaction(COMMIT);
01771 session->close_thread_tables();
01772 session->lex().reset_query_tables_list(false);
01773 table->table=0;
01774 if (session->getClient()->flush())
01775 goto err;
01776 continue;
01777 }
01778
01779
01780 if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
01781 {
01782 table::Cache::mutex().lock();
01783 const char *old_message=session->enter_cond(COND_refresh, table::Cache::mutex(),
01784 "Waiting to get writelock");
01785 session->abortLock(table->table);
01786 identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
01787 table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
01788 session->exit_cond(old_message);
01789 if (session->getKilled())
01790 goto err;
01791 open_for_modify= 0;
01792 }
01793
01794 result_code = (table->table->cursor->*operator_func)(session);
01795
01796 send_result:
01797
01798 session->lex().cleanup_after_one_table_open();
01799 session->clear_error();
01800 {
01801 BOOST_FOREACH(DRIZZLE_ERROR* err, session->main_da().m_warn_list)
01802 {
01803 session->getClient()->store(table_name.c_str());
01804 session->getClient()->store(operator_name);
01805 session->getClient()->store(warning_level_names[err->level].data(), warning_level_names[err->level].size());
01806 session->getClient()->store(err->msg);
01807 if (session->getClient()->flush())
01808 goto err;
01809 }
01810 drizzle_reset_errors(*session, true);
01811 }
01812 session->getClient()->store(table_name.c_str());
01813 session->getClient()->store(operator_name);
01814
01815 switch (result_code) {
01816 case HA_ADMIN_NOT_IMPLEMENTED:
01817 {
01818 char buf[ERRMSGSIZE+20];
01819 uint32_t length=snprintf(buf, ERRMSGSIZE,
01820 ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
01821 session->getClient()->store(STRING_WITH_LEN("note"));
01822 session->getClient()->store(buf, length);
01823 }
01824 break;
01825
01826 case HA_ADMIN_OK:
01827 session->getClient()->store(STRING_WITH_LEN("status"));
01828 session->getClient()->store(STRING_WITH_LEN("OK"));
01829 break;
01830
01831 case HA_ADMIN_FAILED:
01832 session->getClient()->store(STRING_WITH_LEN("status"));
01833 session->getClient()->store(STRING_WITH_LEN("Operation failed"));
01834 break;
01835
01836 case HA_ADMIN_REJECT:
01837 session->getClient()->store(STRING_WITH_LEN("status"));
01838 session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
01839 open_for_modify= false;
01840 break;
01841
01842 case HA_ADMIN_ALREADY_DONE:
01843 session->getClient()->store(STRING_WITH_LEN("status"));
01844 session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
01845 break;
01846
01847 case HA_ADMIN_CORRUPT:
01848 session->getClient()->store(STRING_WITH_LEN("error"));
01849 session->getClient()->store(STRING_WITH_LEN("Corrupt"));
01850 fatal_error=1;
01851 break;
01852
01853 case HA_ADMIN_INVALID:
01854 session->getClient()->store(STRING_WITH_LEN("error"));
01855 session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
01856 break;
01857
01858 default:
01859 {
01860 char buf[ERRMSGSIZE+20];
01861 uint32_t length=snprintf(buf, ERRMSGSIZE,
01862 _("Unknown - internal error %d during operation"),
01863 result_code);
01864 session->getClient()->store(STRING_WITH_LEN("error"));
01865 session->getClient()->store(buf, length);
01866 fatal_error=1;
01867 break;
01868 }
01869 }
01870 if (table->table)
01871 {
01872 if (fatal_error)
01873 {
01874 table->table->getMutableShare()->resetVersion();
01875 }
01876 else if (open_for_modify)
01877 {
01878 if (table->table->getShare()->getType())
01879 {
01880 table->table->cursor->info(HA_STATUS_CONST);
01881 }
01882 else
01883 {
01884 boost::unique_lock<boost::mutex> lock(table::Cache::mutex());
01885 identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
01886 table::Cache::removeTable(*session, identifier, RTFC_NO_FLAG);
01887 }
01888 }
01889 }
01890 TransactionServices::autocommitOrRollback(*session, false);
01891 session->endTransaction(COMMIT);
01892 session->close_thread_tables();
01893 table->table=0;
01894 if (session->getClient()->flush())
01895 goto err;
01896 }
01897
01898 session->my_eof();
01899 return false;
01900
01901 err:
01902 TransactionServices::autocommitOrRollback(*session, true);
01903 session->endTransaction(ROLLBACK);
01904 session->close_thread_tables();
01905 if (table)
01906 table->table=0;
01907 return true;
01908 }
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925 static bool create_table_wrapper(Session &session,
01926 const message::Table& create_table_proto,
01927 const identifier::Table& destination_identifier,
01928 const identifier::Table& source_identifier,
01929 bool is_engine_set)
01930 {
01931
01932
01933
01934 message::Table new_table_message;
01935
01936 message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
01937
01938 if (not source_table_message)
01939 {
01940 my_error(ER_TABLE_UNKNOWN, source_identifier);
01941 return false;
01942 }
01943
01944 new_table_message.CopyFrom(*source_table_message);
01945 new_table_message.set_type(destination_identifier.isTmp() ? message::Table::TEMPORARY : message::Table::STANDARD);
01946
01947 if (is_engine_set)
01948 {
01949 new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
01950 }
01951
01952 {
01953 new_table_message.set_name(create_table_proto.name());
01954 new_table_message.set_schema(create_table_proto.schema());
01955 new_table_message.set_catalog(create_table_proto.catalog());
01956 }
01957
01958
01959 for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
01960 {
01961 if (new_table_message.fk_constraint(j).has_name())
01962 {
01963 std::string name(new_table_message.name());
01964 char number[20];
01965
01966 name.append("_ibfk_");
01967 snprintf(number, sizeof(number), "%d", j+1);
01968 name.append(number);
01969
01970 message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
01971 pfkey->set_name(name);
01972 }
01973 }
01974
01975
01976
01977
01978
01979 bool success= plugin::StorageEngine::createTable(session, destination_identifier, new_table_message);
01980
01981 if (success && not destination_identifier.isTmp())
01982 {
01983 TransactionServices::createTable(session, new_table_message);
01984 }
01985
01986 return success;
01987 }
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004 bool create_like_table(Session* session,
02005 const identifier::Table& destination_identifier,
02006 const identifier::Table& source_identifier,
02007 message::Table &create_table_proto,
02008 bool is_if_not_exists,
02009 bool is_engine_set)
02010 {
02011 bool res= true;
02012 bool table_exists= false;
02013
02014
02015
02016
02017
02018
02019
02020 if (destination_identifier.isTmp())
02021 {
02022 if (session->open_tables.find_temporary_table(destination_identifier))
02023 {
02024 table_exists= true;
02025 }
02026 else
02027 {
02028 bool was_created= create_table_wrapper(*session,
02029 create_table_proto,
02030 destination_identifier,
02031 source_identifier,
02032 is_engine_set);
02033 if (not was_created)
02034 {
02035 (void) session->open_tables.rm_temporary_table(destination_identifier, true);
02036 }
02037 else if (not session->open_temporary_table(destination_identifier))
02038 {
02039
02040 (void) session->open_tables.rm_temporary_table(destination_identifier, true);
02041 }
02042 else
02043 {
02044 res= false;
02045 }
02046 }
02047 }
02048 else
02049 {
02050 Table *name_lock= session->lock_table_name_if_not_cached(destination_identifier);
02051 if (not name_lock)
02052 {
02053 table_exists= true;
02054 }
02055 else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
02056 {
02057 table_exists= true;
02058 }
02059 else
02060 {
02061 bool was_created;
02062 {
02063 boost::mutex::scoped_lock lock(table::Cache::mutex());
02064 was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
02065 source_identifier, is_engine_set);
02066 }
02067
02068
02069
02070 if (not was_created)
02071 {
02072 plugin::StorageEngine::dropTable(*session, destination_identifier);
02073 }
02074 else
02075 {
02076 res= false;
02077 }
02078 }
02079
02080 if (name_lock)
02081 {
02082 boost::mutex::scoped_lock lock(table::Cache::mutex());
02083 session->unlink_open_table(name_lock);
02084 }
02085 }
02086
02087 if (table_exists)
02088 {
02089 if (is_if_not_exists)
02090 {
02091 char warn_buff[DRIZZLE_ERRMSG_SIZE];
02092 snprintf(warn_buff, sizeof(warn_buff),
02093 ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
02094 push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
02095 ER_TABLE_EXISTS_ERROR, warn_buff);
02096 return false;
02097 }
02098
02099 my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
02100
02101 return true;
02102 }
02103
02104 return res;
02105 }
02106
02107
02108 bool analyze_table(Session* session, TableList* tables)
02109 {
02110 return admin_table(session, tables, "analyze", TL_READ_NO_INSERT, true, &Cursor::ha_analyze);
02111 }
02112
02113
02114 bool check_table(Session* session, TableList* tables)
02115 {
02116 return admin_table(session, tables, "check", TL_READ_NO_INSERT, false, &Cursor::ha_check);
02117 }
02118
02119 }