~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Lee Bieber
  • Date: 2010-11-20 01:33:21 UTC
  • mfrom: (1878.10.4 drizzle_bug665252)
  • Revision ID: kalebral@gmail.com-20101120013321-7nk9lq4nnr20zk6b
Merge Billy - removed my_getsysdate, my_micro_time and my_micro_time_and_time and replaced with boost::date_time for compatibility.

Show diffs side-by-side

added added

removed removed

Lines of Context:
107
107
  assert(select_lex->db);
108
108
 
109
109
  /* Chicken/Egg... we need to search for the table, to know if the table exists, so we can build a full identifier from it */
110
 
  message::table::shared_ptr original_table_message;
 
110
  message::TablePtr original_table_message;
111
111
  {
112
112
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
113
113
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
114
114
    {
115
 
      std::string path;
116
 
      identifier.getSQLPath(path);
117
 
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
 
115
      my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
118
116
      return true;
119
117
    }
120
118
 
125
123
 
126
124
      if (not create_info.db_type)
127
125
      {
128
 
        std::string path;
129
 
        identifier.getSQLPath(path);
130
 
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
 
126
        my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
131
127
        return true;
132
128
      }
133
129
    }
134
130
  }
135
131
 
136
132
  if (not validateCreateTableOption())
 
133
  {
137
134
    return true;
 
135
  }
138
136
 
139
137
  /* ALTER TABLE ends previous transaction */
140
138
  if (not session->endActiveTransaction())
 
139
  {
141
140
    return true;
 
141
  }
142
142
 
143
143
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
 
144
  {
144
145
    return true;
 
146
  }
145
147
 
146
148
  bool res;
147
149
  if (original_table_message->type() == message::Table::STANDARD )
347
349
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
348
350
        {
349
351
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
350
 
          return true;
 
352
                goto err;
351
353
        }
352
354
        if ((def->def= alter->def))
353
355
        {
355
357
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
356
358
        }
357
359
        else
358
 
        {
359
360
          def->flags|= NO_DEFAULT_VALUE_FLAG;
360
 
        }
361
361
        alter_it.remove();
362
362
      }
363
363
    }
368
368
    if (def->change && ! def->field)
369
369
    {
370
370
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
371
 
      return true;
 
371
      goto err;
372
372
    }
373
373
    /*
374
 
      If we have been given a field which has no default value, and is not null then we need to bail.
 
374
      Check that the DATE/DATETIME not null field we are going to add is
 
375
      either has a default value or the '0000-00-00' is allowed by the
 
376
      set sql mode.
 
377
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
378
      flag to allow ALTER Table only if the table to be altered is empty.
375
379
    */
376
 
    if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
 
380
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
381
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
382
        ! alter_info->datetime_field &&
 
383
        ! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)))
377
384
    {
 
385
      alter_info->datetime_field= def;
378
386
      alter_info->error_if_not_empty= true;
379
387
    }
380
388
    if (! def->after)
381
 
    {
382
389
      new_create_list.push_back(def);
383
 
    }
384
390
    else if (def->after == first_keyword)
385
 
    {
386
391
      new_create_list.push_front(def);
387
 
    }
388
392
    else
389
393
    {
390
394
      CreateField *find;
397
401
      if (! find)
398
402
      {
399
403
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
400
 
        return true;
 
404
        goto err;
401
405
      }
402
406
      find_it.after(def); /* Put element after this */
403
407
      /*
413
417
      if (alter_info->build_method == HA_BUILD_ONLINE)
414
418
      {
415
419
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
416
 
        return true;
 
420
        goto err;
417
421
      }
418
422
      alter_info->build_method= HA_BUILD_OFFLINE;
419
423
    }
424
428
             MYF(0),
425
429
             alter_info->alter_list.head()->name,
426
430
             table->getMutableShare()->getTableName());
427
 
    return true;
 
431
    goto err;
428
432
  }
429
433
  if (! new_create_list.elements)
430
434
  {
431
435
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
432
436
               ER(ER_CANT_REMOVE_ALL_FIELDS),
433
437
               MYF(0));
434
 
    return true;
 
438
    goto err;
435
439
  }
436
440
 
437
441
  /*
568
572
      if (key->type == Key::FOREIGN_KEY)
569
573
      {
570
574
        if (((Foreign_key *)key)->validate(new_create_list))
571
 
        {
572
 
          return true;
573
 
        }
 
575
          goto err;
574
576
 
575
577
        Foreign_key *fkey= (Foreign_key*)key;
576
578
        add_foreign_key_to_table_message(&table_message,
591
593
        my_error(ER_WRONG_NAME_FOR_INDEX,
592
594
                 MYF(0),
593
595
                 key->name.str);
594
 
        return true;
 
596
        goto err;
595
597
      }
596
598
    }
597
599
  }
618
620
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
619
621
             MYF(0),
620
622
             alter_info->drop_list.head()->name);
621
 
    return true;
 
623
    goto err;
622
624
  }
623
625
  if (alter_info->alter_list.elements)
624
626
  {
625
627
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
626
628
             MYF(0),
627
629
             alter_info->alter_list.head()->name);
628
 
    return true;
 
630
    goto err;
629
631
  }
630
632
 
631
633
  if (not table_message.options().has_comment()
644
646
  rc= false;
645
647
  alter_info->create_list.swap(new_create_list);
646
648
  alter_info->key_list.swap(new_key_list);
 
649
err:
647
650
 
648
651
  size_t num_engine_options= table_message.engine().options_size();
649
652
  size_t original_num_engine_options= original_proto.engine().options_size();
670
673
 
671
674
  drizzled::message::update(table_message);
672
675
 
673
 
  return false;
 
676
  return rc;
674
677
}
675
678
 
676
679
/* table_list should contain just one table */
791
794
 
792
795
      if (session.find_temporary_table(new_table_identifier))
793
796
      {
794
 
        std::string path;
795
 
        new_table_identifier.getSQLPath(path);
796
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
797
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
797
798
        return false;
798
799
      }
799
800
    }
806
807
 
807
808
      if (not name_lock)
808
809
      {
809
 
        std::string path;
810
 
        new_table_identifier.getSQLPath(path);
811
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
810
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
812
811
        return false;
813
812
      }
814
813
 
815
814
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
816
815
      {
817
 
        std::string path;
818
 
        new_table_identifier.getSQLPath(path);
819
 
 
820
816
        /* Table will be closed by Session::executeCommand() */
821
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
817
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
822
818
 
823
 
        table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
819
        LOCK_open.lock(); /* ALTER TABLe */
824
820
        session.unlink_open_table(name_lock);
825
 
        table::Cache::singleton().mutex().unlock();
 
821
        LOCK_open.unlock();
826
822
 
827
823
        return false;
828
824
      }
893
889
  ha_rows copied= 0;
894
890
  ha_rows deleted= 0;
895
891
 
896
 
  if (not original_table_identifier.isValid())
897
 
    return true;
898
 
 
899
 
  if (not new_table_identifier.isValid())
900
 
    return true;
901
 
 
902
892
  session->set_proc_info("init");
903
893
 
904
894
  table->use_all_columns();
934
924
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
935
925
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
936
926
  {
937
 
    std::string path;
938
 
    new_table_identifier.getSQLPath(path);
939
 
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
 
927
    my_error(ER_ILLEGAL_HA, MYF(0), new_table_identifier.getSQLPath().c_str());
940
928
 
941
929
    return true;
942
930
  }
970
958
          while the fact that the table is still open gives us protection
971
959
          from concurrent DDL statements.
972
960
        */
973
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
961
        LOCK_open.lock(); /* DDL wait for/blocker */
974
962
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
975
 
        table::Cache::singleton().mutex().unlock();
 
963
        LOCK_open.unlock();
976
964
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
977
965
        /* COND_refresh will be signaled in close_thread_tables() */
978
966
        break;
979
967
      case DISABLE:
980
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
968
        LOCK_open.lock(); /* DDL wait for/blocker */
981
969
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
982
 
        table::Cache::singleton().mutex().unlock();
 
970
        LOCK_open.unlock();
983
971
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
984
972
        /* COND_refresh will be signaled in close_thread_tables() */
985
973
        break;
997
985
                            table->getAlias());
998
986
      }
999
987
 
1000
 
      table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
 
988
      LOCK_open.lock(); /* Lock to remove all instances of table from table cache before ALTER */
1001
989
      /*
1002
990
        Unlike to the above case close_cached_table() below will remove ALL
1003
991
        instances of Table from table cache (it will also remove table lock
1004
992
        held by this thread). So to make actual table renaming and writing
1005
993
        to binlog atomic we have to put them into the same critical section
1006
 
        protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
 
994
        protected by LOCK_open mutex. This also removes gap for races between
1007
995
        access() and mysql_rename_table() calls.
1008
996
      */
1009
997
 
1025
1013
        */
1026
1014
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1027
1015
        {
1028
 
          std::string path;
1029
 
          new_table_identifier.getSQLPath(path);
1030
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
1016
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
1031
1017
          error= -1;
1032
1018
        }
1033
1019
        else
1060
1046
        error= -1;
1061
1047
      }
1062
1048
 
1063
 
      table::Cache::singleton().mutex().unlock();
 
1049
      LOCK_open.unlock();
1064
1050
      table_list->table= NULL;
1065
1051
 
1066
1052
      return error;
1105
1091
 
1106
1092
  if (not new_table)
1107
1093
  {
1108
 
    plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1094
    quick_rm_table(*session, new_table_as_temporary);
1109
1095
    return true;
1110
1096
  }
1111
1097
 
1149
1135
    */
1150
1136
    if (alter_info->error_if_not_empty && session->row_count)
1151
1137
    {
1152
 
      my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
 
1138
      const char *f_val= 0;
 
1139
      enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1140
 
 
1141
      switch (alter_info->datetime_field->sql_type)
 
1142
      {
 
1143
      case DRIZZLE_TYPE_DATE:
 
1144
        f_val= "0000-00-00";
 
1145
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1146
        break;
 
1147
      case DRIZZLE_TYPE_DATETIME:
 
1148
        f_val= "0000-00-00 00:00:00";
 
1149
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1150
        break;
 
1151
      default:
 
1152
        /* Shouldn't get here. */
 
1153
        assert(0);
 
1154
      }
 
1155
      bool save_abort_on_warning= session->abort_on_warning;
 
1156
      session->abort_on_warning= true;
 
1157
      make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1158
                                   f_val, internal::strlength(f_val), t_type,
 
1159
                                   alter_info->datetime_field->field_name);
 
1160
      session->abort_on_warning= save_abort_on_warning;
1153
1161
    }
1154
1162
 
1155
1163
    if (original_table_identifier.isTmp())
1161
1169
      }
1162
1170
      else
1163
1171
      {
1164
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1172
        quick_rm_table(*session, new_table_as_temporary);
1165
1173
      }
1166
1174
 
1167
1175
      return true;
1183
1191
        delete new_table;
1184
1192
      }
1185
1193
 
1186
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1194
      LOCK_open.lock(); /* ALTER TABLE */
1187
1195
 
1188
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1189
 
      table::Cache::singleton().mutex().unlock();
 
1196
      quick_rm_table(*session, new_table_as_temporary);
 
1197
      LOCK_open.unlock();
1190
1198
 
1191
1199
      return true;
1192
1200
    }
1233
1241
      delete new_table;
1234
1242
    }
1235
1243
 
1236
 
    table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1244
    LOCK_open.lock(); /* ALTER TABLE */
1237
1245
 
1238
1246
    /*
1239
1247
      Data is copied. Now we:
1278
1286
    if (mysql_rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1279
1287
    {
1280
1288
      error= 1;
1281
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1289
      quick_rm_table(*session, new_table_as_temporary);
1282
1290
    }
1283
1291
    else
1284
1292
    {
1287
1295
        /* Try to get everything back. */
1288
1296
        error= 1;
1289
1297
 
1290
 
        plugin::StorageEngine::dropTable(*session, new_table_identifier);
 
1298
        quick_rm_table(*session, new_table_identifier);
1291
1299
 
1292
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1300
        quick_rm_table(*session, new_table_as_temporary);
1293
1301
 
1294
1302
        mysql_rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1295
1303
      }
1296
1304
      else
1297
1305
      {
1298
 
        plugin::StorageEngine::dropTable(*session, original_table_to_drop);
 
1306
        quick_rm_table(*session, original_table_to_drop);
1299
1307
      }
1300
1308
    }
1301
1309
 
1307
1315
        from list of open tables list and table cache.
1308
1316
      */
1309
1317
      session->unlink_open_table(table);
1310
 
      table::Cache::singleton().mutex().unlock();
 
1318
      LOCK_open.unlock();
1311
1319
 
1312
1320
      return true;
1313
1321
    }
1314
1322
 
1315
 
    table::Cache::singleton().mutex().unlock();
 
1323
    LOCK_open.unlock();
1316
1324
 
1317
1325
    session->set_proc_info("end");
1318
1326
 
1395
1403
 
1396
1404
    if (name_lock)
1397
1405
    {
1398
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
1406
      LOCK_open.lock(); /* ALTER TABLe */
1399
1407
      session->unlink_open_table(name_lock);
1400
 
      table::Cache::singleton().mutex().unlock();
 
1408
      LOCK_open.unlock();
1401
1409
    }
1402
1410
  }
1403
1411
 
1546
1554
        to->next_number_field->reset();
1547
1555
    }
1548
1556
 
1549
 
    for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
 
1557
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1550
1558
    {
1551
 
      if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1552
 
      {
1553
 
        copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1554
 
                                    ER_WARN_DATA_TRUNCATED, 1);
1555
 
        copy->to_field->reset();
1556
 
        error= 1;
1557
 
        break;
1558
 
      }
1559
 
 
1560
1559
      copy_ptr->do_copy(copy_ptr);
1561
1560
    }
1562
 
 
1563
 
    if (error)
1564
 
    {
1565
 
      break;
1566
 
    }
1567
 
 
1568
1561
    prev_insert_id= to->cursor->next_insert_id;
1569
1562
    error= to->cursor->insertRecord(to->record[0]);
1570
1563
    to->auto_increment_field_not_null= false;
1571
1564
 
1572
1565
    if (error)
1573
1566
    { 
1574
 
      if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
1567
      if (!ignore ||
 
1568
          to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1575
1569
      { 
1576
1570
        to->print_error(error, MYF(0));
1577
1571
        break;