Drizzled Public API Documentation

sql_table.cc
00001 /* Copyright (C) 2000-2004 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /* drop and alter of tables */
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     If the table character set was not given explicitly,
00072     let's fetch the database default character set and
00073     apply it to the table.
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   Execute the drop of a normal or temporary table
00081 
00082   SYNOPSIS
00083     rm_table_part2()
00084     session     Thread Cursor
00085     tables    Tables to drop
00086     if_exists   If set, don't give an error if table doesn't exists.
00087       In this case we give an warning of level 'NOTE'
00088     drop_temporary  Only drop temporary tables
00089 
00090   @todo
00091     When logging to the binary log, we should log
00092     tmp_tables and transactional tables as separate statements if we
00093     are in a transaction;  This is needed to get these tables into the
00094     cached binary log that is only written on COMMIT.
00095 
00096    The current code only writes DROP statements that only uses temporary
00097    tables to the cache binary log.  This should be ok on most cases, but
00098    not all.
00099 
00100  RETURN
00101    0  ok
00102    1  Error
00103    -1 Thread was killed
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     /* Don't give warnings for not found errors, as we already generate notes */
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         // removed temporary table
00135         continue;
00136       case -1:
00137         error= 1;
00138         break;
00139       default:
00140         // temporary table not found
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           If the table was used in lock tables, remember it so that
00150           unlock_table_names can free it
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         // Table was not found on disk and table can't be created from engine
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         /* Generate transaction event ONLY when we successfully drop */ 
00185         if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
00186         {
00187           if (message) // If we have no definition, we don't know if the table should have been replicated
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             /* the table is referenced by a foreign key constraint */
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   Sort keys in the following order:
00249   - PRIMARY KEY
00250   - UNIQUE keys where all column are NOT NULL
00251   - UNIQUE keys that don't contain partial segments
00252   - Other UNIQUE keys
00253   - Normal keys
00254   - Fulltext keys
00255 
00256   This will make checking for duplicated keys faster and ensure that
00257   PRIMARY keys are prioritized.
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       /* Sort NOT NULL keys before other keys */
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     /* Sort keys don't containing partial segments before others */
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;         // Prefer b
00283 
00284   /*
00285     Prefer original key order.  usable_key_parts contains here
00286     the original key position.
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   Check TYPELIB (set or enum) for duplicates
00295 
00296   SYNOPSIS
00297     check_duplicates_in_interval()
00298     set_or_name   "SET" or "ENUM" string for warning message
00299     name    name of the checked column
00300     typelib   list of values for the column
00301     dup_val_count  returns count of duplicate elements
00302 
00303   DESCRIPTION
00304     This function prints an warning for each value in list
00305     which has some duplicates on its right
00306 
00307   RETURN VALUES
00308     0             ok
00309     1             Error
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   Check TYPELIB (set or enum) max and total lengths
00378 
00379   SYNOPSIS
00380     calculate_interval_lengths()
00381     cs            charset+collation pair of the interval
00382     typelib       list of values for the column
00383     max_length    length of the longest item
00384     tot_length    sum of the item lengths
00385 
00386   DESCRIPTION
00387     After this function call:
00388     - ENUM uses max_length
00389     - SET uses tot_length.
00390 
00391   RETURN VALUES
00392     void
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   Prepare a create_table instance for packing
00413 
00414   SYNOPSIS
00415     prepare_create_field()
00416     sql_field     field to prepare for packing
00417     blob_columns  count for BLOBs
00418     timestamps    count for timestamps
00419 
00420   DESCRIPTION
00421     This function prepares a CreateField instance.
00422     Fields such as pack_flag are valid after this call.
00423 
00424   RETURN VALUES
00425    0  ok
00426    1  Error
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     This code came from mysql_prepare_create_table.
00437     Indent preserved to make patching easier
00438   */
00439   assert(sql_field->charset);
00440 
00441   switch (sql_field->sql_type) {
00442   case DRIZZLE_TYPE_BLOB:
00443     sql_field->length= 8; // Unireg field length
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     /* We should replace old TIMESTAMP fields with their newer analogs */
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:  // Rest of string types
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       Initialize length from its original value (number of characters),
00537       which was set in the parser. This is necessary if we're
00538       executing a prepared statement for the second time.
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       table_charset is set in ALTER Table if we want change character set
00547       for all varchar/char columns.
00548       But the table charset must not affect the BLOB fields, so don't
00549       allow to change my_charset_bin to somethig else.
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       Convert the default value from client character
00569       set into the column character set if necessary.
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         Starting from 5.1 we work here with a copy of CreateField
00577         created by the caller, not with the instance that was
00578         originally created during parsing. It's OK to create
00579         a temporary item and initialize with it a member of the
00580         copy -- this item will be thrown away along with the copy
00581         at the end of execution, and thus not introduce a dangling
00582         pointer in the parsed tree of a prepared statement or a
00583         stored procedure statement.
00584       */
00585       sql_field->def= sql_field->def->safe_charset_converter(save_cs);
00586 
00587       if (sql_field->def == NULL)
00588       {
00589         /* Could not convert */
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         Create typelib from interval_list, and if necessary
00602         convert strings from client character set to the
00603         column character set.
00604       */
00605       if (!interval)
00606       {
00607         /*
00608           Create the typelib in runtime memory - we will free the
00609           occupied memory at the same time when we free this
00610           sql_field -- at the end of execution.
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           // Strip trailing spaces.
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(); // Don't need interval_list anymore
00636       }
00637 
00638       /* DRIZZLE_TYPE_ENUM */
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) /* SQL "NULL" maps to 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             /* else, the defaults yield the correct length for NULLs. */
00654           }
00655           else /* not NULL */
00656           {
00657             def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
00658             if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
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     /* Check if we have used the same field name before */
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     If this was a CREATE ... SELECT statement, accept a field
00692     redefinition if we are changing a field in the SELECT part
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     /* Field redefined */
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             We're making one field from two, the result field will have
00715             dup_field->flags as flags. If we've incremented null_fields
00716             because of sql_field->flags, decrement it back.
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();     // Remove first (create) definition
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   /* record_offset will be increased with 'length-of-null-bits' later */
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            &timestamps, &timestamps_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   /* Create keys */
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   /* special marker for keys to be ignored */
00791   static char ignore_key[1];
00792 
00793   /* Calculate number of key segements */
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           foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
00841           'generated', and a generated key is a prefix of the other key.
00842           Then we do not need the generated shorter key.
00843         */
00844         if ((key2->type != Key::FOREIGN_KEY &&
00845              key2->name.data() != ignore_key &&
00846              !foreign_key_prefix(key, key2)))
00847         {
00848           /* @todo issue warning message */
00849           /* mark that the generated key should be ignored */
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       /* ignore redundant keys */
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--;       // Skip this key
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()); // weird
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             /* Implicitly set primary key fields to NOT NULL for ISO conf. */
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--;     // Field is used
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         /* not a critical problem */
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               /* Align key length to multibyte char boundary */
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     /* not a critical problem */
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           /* Align key length to multibyte char boundary */
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       /* Use packed keys for long strings on the first column */
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       /* Check if the key segment is partial, set the key flag accordingly */
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       /* Create the key name based on the first column (if not given) */
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   /* Sort keys in optimized order */
01181   internal::my_qsort((unsigned char*) *key_info_buffer, *key_count, sizeof(KeyInfo),
01182                (qsort_cmp) sort_keys);
01183 
01184   /* Check fields. */
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         An error should be reported if:
01198           - NO_ZERO_DATE SQL mode is active;
01199           - there is no explicit DEFAULT clause (default column value);
01200           - this is a TIMESTAMP column;
01201           - the column is not NULL;
01202           - this is not the DEFAULT CURRENT_TIMESTAMP column.
01203 
01204         In other words, an error should be reported if
01205           - NO_ZERO_DATE SQL mode is active;
01206           - the column definition is equivalent to
01207             'column_name TIMESTAMP DEFAULT 0'.
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   Extend long VARCHAR fields to blob & prepare field if it's a blob
01220 
01221   SYNOPSIS
01222     prepare_blob_field()
01223     sql_field   Field to check
01224 
01225   RETURN
01226     0 ok
01227     1 Error (sql_field can't be converted to blob)
01228         In this case the error is given
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       /* The user has given a length to the blob column */
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       @note if we are building a temp table we need to check to see if a temp table
01272       already exists, otherwise we just need to find out if a normal table exists (aka it is fine
01273       to create a table under a temporary table.
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;    // Mark that table existed
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) // We have a real table
01297     {
01298       /*
01299         We don't assert here, but check the result, because the table could be
01300         in the table definition cache and in the same time the .frm could be
01301         missing from the disk, in case of manual intervention which deletes
01302         the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
01303         Then she could create the table. This case is pretty obscure and
01304         therefore we don't introduce a new error message only for it.
01305       */
01306       /*
01307         @todo improve this error condition.
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;    // Mark that table is created
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     /* Open table and put in temporary table list */
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     We keep this behind the lock to make sure ordering is correct for a table.
01343     This is a very unlikely problem where before we would write out to the
01344     trans log, someone would do a delete/create operation.
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   Ignore the name of this function... it locks :(
01358 
01359   Create a table
01360 
01361   SYNOPSIS
01362     create_table_no_lock()
01363     session     Thread object
01364     db      Database
01365     table_name    Table name
01366     create_info         Create information (like MAX_ROWS)
01367     fields    List of fields to create
01368     keys    List of keys to create
01369     internal_tmp_table  Set to 1 if this is an internal temporary table
01370       (From ALTER Table)
01371     select_field_count
01372 
01373   DESCRIPTION
01374     If one creates a temporary table, this is automatically opened
01375 
01376     Note that this function assumes that caller already have taken
01377     name-lock on table being created or used some other way to ensure
01378     that concurrent operations won't intervene. create_table()
01379     is a wrapper that can be used for this.
01380 
01381   RETURN VALUES
01382     false OK
01383     true  error
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   /* Check for duplicate fields and check type of table to create */
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   /* Build a Table object to pass down to the engine, and the do the actual create. */
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()); /* CREATE TABLE (some confussion on naming, double check) */
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()); /* Lock for removing name_lock during table create */
01480     session->unlink_open_table(name_lock);
01481   }
01482 
01483   return(result);
01484 }
01485 
01486 
01487 /*
01488   Database locking aware wrapper for create_table_no_lock(),
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 ** Give the key name after the first field with an optional '_#' after
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;      // Use fieldname
01545 
01546   buff_end= strncpy(buff, field_name, sizeof(buff)-4);
01547   buff_end+= strlen(buff);
01548 
01549   /*
01550     Only 3 chars + '\0' left, so need to limit to 2 digit
01551     This is ok as we can't have more than 100 keys anyway
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";   // Should never happen
01561 }
01562 
01563 
01564 /****************************************************************************
01565 ** Alter a table definition
01566 ****************************************************************************/
01567 
01568 /*
01569   Rename a table.
01570 
01571   SYNOPSIS
01572     rename_table()
01573       session
01574       base                      The plugin::StorageEngine handle.
01575       old_db                    The old database name.
01576       old_name                  The old table name.
01577       new_db                    The new database name.
01578       new_name                  The new table name.
01579 
01580   RETURN
01581     false   OK
01582     true    Error
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   Force all other threads to stop using the table
01612 
01613   SYNOPSIS
01614     wait_while_table_is_used()
01615     session     Thread Cursor
01616     table   Table to remove from cache
01617     function            HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted
01618                         HA_EXTRA_FORCE_REOPEN if table is not be used
01619                         HA_EXTRA_PREPARE_FOR_RENAME if table is to be renamed
01620   NOTES
01621    When returning, the table will be unusable for other threads until
01622    the table is closed.
01623 
01624   PREREQUISITES
01625     Lock on table::Cache::mutex()
01626     Win32 clients must also have a WRITE LOCK on the table !
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   /* Mark all tables that are in use as 'old' */
01637   session->abortLock(table);  /* end threads waiting on lock */
01638 
01639   /* Wait until all there are no other threads that has this table open */
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   Close a cached table
01646 
01647   SYNOPSIS
01648     close_cached_table()
01649     session     Thread Cursor
01650     table   Table to remove from cache
01651 
01652   NOTES
01653     Function ends by signaling threads waiting for the table to try to
01654     reopen the table.
01655 
01656   PREREQUISITES
01657     Lock on table::Cache::mutex()
01658     Win32 clients must also have a WRITE LOCK on the table !
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   /* Close lock if this is not got with LOCK TABLES */
01666   if (open_tables.lock)
01667   {
01668     unlockTables(open_tables.lock);
01669     open_tables.lock= NULL;     // Start locked threads
01670   }
01671   /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
01672   unlink_open_table(table);
01673 
01674   /* When lock on table::Cache::mutex() is freed other threads can continue */
01675   locking::broadcast_refresh();
01676 }
01677 
01678 /*
01679   RETURN VALUES
01680     false Message sent to net (admin operation went ok)
01681     true  Message should be sent by caller
01682           (admin operation or network communication failed)
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     /* open only one table from local list of command */
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         Time zone tables and SP tables can be add to lex->query_tables list,
01728         so it have to be prepared.
01729         @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
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       CHECK Table command is only command where VIEW allowed here and this
01744       command use only temporary teble method for VIEWs resolving => there
01745       can't be VIEW tree substitition of join view => if opening table
01746       succeed then table->table will have real Table pointer as value (in
01747       case of join view substitution table->table can be 0, but here it is
01748       impossible)
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;       // For query cache
01774       if (session->getClient()->flush())
01775   goto err;
01776       continue;
01777     }
01778 
01779     /* Close all instances of the table to allow repair to rename files */
01780     if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
01781     {
01782       table::Cache::mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
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();  // these errors shouldn't get client
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:        // Probably HA_ADMIN_INTERNAL_ERROR
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();               // Force close of table
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;       // For query cache
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();     // Shouldn't be needed
01905   if (table)
01906     table->table=0;
01907   return true;
01908 }
01909 
01910   /*
01911     Create a new table by copying from source table
01912 
01913     Altough exclusive name-lock on target table protects us from concurrent
01914     DML and DDL operations on it we still want to wrap .FRM creation and call
01915     to plugin::StorageEngine::createTable() in critical section protected by
01916     table::Cache::mutex() in order to provide minimal atomicity against operations which
01917     disregard name-locks, like I_S implementation, for example. This is a
01918     temporary and should not be copied. Instead we should fix our code to
01919     always honor name-locks.
01920 
01921     Also some engines (e.g. NDB cluster) require that table::Cache::mutex() should be held
01922     during the call to plugin::StorageEngine::createTable().
01923     See bug #28614 for more info.
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   // We require an additional table message because during parsing we used
01932   // a "new" message and it will not have all of the information that the
01933   // source table message would have.
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   { // We now do a selective copy of elements on to the new table.
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   /* Fix names of foreign keys being added */
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     As mysql_truncate don't work on a new table at this stage of
01977     creation, instead create the table directly (for both normal and temporary tables).
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   Create a table identical to the specified table
01991 
01992   SYNOPSIS
01993     create_like_table()
01994     session   Thread object
01995     table       Table list element for target table
01996     src_table   Table list element for source table
01997     create_info Create info
01998 
01999   RETURN VALUES
02000     false OK
02001     true  error
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     Check that destination tables does not exist. Note that its name
02016     was already checked when it was added to the table list.
02017 
02018     For temporary tables we don't aim to grab locks.
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) // This is pretty paranoid, but we assume something might not clean up after itself
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         // We created, but we can't open... also, a hack.
02040         (void) session->open_tables.rm_temporary_table(destination_identifier, true);
02041       }
02042       else
02043       {
02044         res= false;
02045       }
02046     }
02047   }
02048   else // Standard table which will require locks.
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 // Otherwise we create the table
02060     {
02061       bool was_created;
02062       {
02063         boost::mutex::scoped_lock lock(table::Cache::mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
02064         was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
02065                                           source_identifier, is_engine_set);
02066       }
02067 
02068       // So we blew the creation of the table, and we scramble to clean up
02069       // anything that might have been created (read... it is a hack)
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()); /* unlink open tables for create table like*/
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 } /* namespace drizzled */