~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/statement_transform.cc

  • Committer: Olaf van der Spek
  • Date: 2011-06-23 11:44:30 UTC
  • mto: This revision was merged to the branch mainline in revision 2348.
  • Revision ID: olafvdspek@gmail.com-20110623114430-no355yypk4y3icqb
Refactor

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems
5
 
 *  Copyright (c) 2010 Jay Pipes
 
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
 
5
 *  Copyright (C) 2010 Jay Pipes
6
6
 *
7
7
 *  Authors:
8
8
 *
29
29
 * Statement messages to other formats, including SQL strings.
30
30
 */
31
31
 
32
 
#include "config.h"
 
32
#include <config.h>
33
33
 
34
34
#include <boost/lexical_cast.hpp>
35
 
#include "drizzled/message/statement_transform.h"
36
 
#include "drizzled/message/transaction.pb.h"
37
 
#include "drizzled/message/table.pb.h"
38
 
#include "drizzled/charset.h"
39
 
#include "drizzled/charset_info.h"
40
 
#include "drizzled/global_charset_info.h"
 
35
 
 
36
#include <drizzled/charset.h>
 
37
#include <drizzled/message.h>
 
38
#include <drizzled/message/statement_transform.h>
 
39
#include <drizzled/message/transaction.pb.h>
 
40
#include <drizzled/message/access.h>
41
41
 
42
42
#include <string>
43
43
#include <vector>
152
152
      const InsertHeader &insert_header= source.insert_header();
153
153
      const InsertData &insert_data= source.insert_data();
154
154
      size_t num_keys= insert_data.record_size();
155
 
      size_t x;
156
155
 
157
156
      if (num_keys > 1 && ! already_in_transaction)
158
157
        sql_strings.push_back("START TRANSACTION");
159
158
 
160
 
      for (x= 0; x < num_keys; ++x)
 
159
      for (size_t x= 0; x < num_keys; ++x)
161
160
      {
162
161
        string destination;
163
162
 
318
317
      sql_strings.push_back(destination);
319
318
    }
320
319
    break;
 
320
  case Statement::ALTER_SCHEMA:
 
321
    {
 
322
      assert(source.has_alter_schema_statement());
 
323
      string destination;
 
324
      error= transformAlterSchemaStatementToSql(source.alter_schema_statement(),
 
325
                                                destination,
 
326
                                                sql_variant);
 
327
      sql_strings.push_back(destination);
 
328
    }
 
329
    break;
321
330
  case Statement::SET_VARIABLE:
322
331
    {
323
332
      assert(source.has_set_variable_statement());
329
338
    }
330
339
    break;
331
340
  case Statement::RAW_SQL:
 
341
    {
 
342
      if (source.has_raw_sql_schema())
 
343
      {
 
344
        string destination("USE ");
 
345
        destination.append(source.raw_sql_schema());
 
346
        sql_strings.push_back(destination);
 
347
      }
 
348
      sql_strings.push_back(source.sql());
 
349
    }
 
350
    break;
332
351
  default:
333
352
    sql_strings.push_back(source.sql());
334
353
    break;
383
402
                                                           destination,
384
403
                                                           sql_variant);
385
404
 
386
 
  char quoted_identifier= '`';
387
 
  if (sql_variant == ANSI)
388
 
    quoted_identifier= '"';
389
 
 
390
405
  destination.append(") VALUES (");
391
406
 
392
407
  /* Add insert values */
456
471
                                                           destination,
457
472
                                                           sql_variant);
458
473
 
459
 
  char quoted_identifier= '`';
460
 
  if (sql_variant == ANSI)
461
 
    quoted_identifier= '"';
462
 
 
463
474
  destination.append(") VALUES (", 10);
464
475
 
465
476
  /* Add insert values */
806
817
}
807
818
 
808
819
enum TransformSqlError
 
820
transformAlterSchemaStatementToSql(const AlterSchemaStatement &statement,
 
821
                                   string &destination,
 
822
                                   enum TransformSqlVariant sql_variant)
 
823
{
 
824
  const Schema &before= statement.before();
 
825
  const Schema &after= statement.after();
 
826
 
 
827
  /* Make sure we are given the before and after for the same object */
 
828
  if (before.uuid() != after.uuid())
 
829
    return UUID_MISMATCH;
 
830
 
 
831
  char quoted_identifier= '`';
 
832
  if (sql_variant == ANSI)
 
833
    quoted_identifier= '"';
 
834
 
 
835
  destination.append("ALTER SCHEMA ");
 
836
  destination.push_back(quoted_identifier);
 
837
  destination.append(before.name());
 
838
  destination.push_back(quoted_identifier);
 
839
 
 
840
  /*
 
841
   * Diff our schemas. Currently, only collation can change so a
 
842
   * diff of the two structures is not really necessary.
 
843
   */
 
844
  destination.append(" COLLATE = ");
 
845
  destination.append(after.collation());
 
846
 
 
847
  return NONE;
 
848
}
 
849
 
 
850
enum TransformSqlError
809
851
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
810
852
                                  string &destination,
811
853
                                  enum TransformSqlVariant sql_variant)
833
875
 
834
876
  const Schema &schema= statement.schema();
835
877
 
836
 
  destination.append("CREATE SCHEMA ", 14);
 
878
  destination.append("CREATE SCHEMA ");
837
879
  destination.push_back(quoted_identifier);
838
880
  destination.append(schema.name());
839
881
  destination.push_back(quoted_identifier);
840
882
 
841
883
  if (schema.has_collation())
842
884
  {
843
 
    destination.append(" COLLATE ", 9);
 
885
    destination.append(" COLLATE ");
844
886
    destination.append(schema.collation());
845
887
  }
846
888
 
 
889
  if (not message::is_replicated(schema))
 
890
  {
 
891
    destination.append(" REPLICATE = FALSE");
 
892
  }
 
893
 
 
894
  if (message::has_definer(schema))
 
895
  {
 
896
    destination.append(" DEFINER ");
 
897
    destination.push_back('\'');
 
898
    destination.append(message::definer(schema));
 
899
    destination.push_back('\'');
 
900
  }
 
901
 
847
902
  return NONE;
848
903
}
849
904
 
858
913
 
859
914
  const TableMetadata &table_metadata= statement.table_metadata();
860
915
 
861
 
  destination.append("DROP TABLE ", 11);
 
916
  destination.append("DROP TABLE ");
862
917
 
863
918
  /* Add the IF EXISTS clause if necessary */
864
919
  if (statement.has_if_exists_clause() &&
865
920
      statement.if_exists_clause() == true)
866
921
  {
867
 
    destination.append("IF EXISTS ", 10);
 
922
    destination.append("IF EXISTS ");
868
923
  }
869
924
 
870
925
  destination.push_back(quoted_identifier);
889
944
 
890
945
  const TableMetadata &table_metadata= statement.table_metadata();
891
946
 
892
 
  destination.append("TRUNCATE TABLE ", 15);
 
947
  destination.append("TRUNCATE TABLE ");
893
948
  destination.push_back(quoted_identifier);
894
949
  destination.append(table_metadata.schema_name());
895
950
  destination.push_back(quoted_identifier);
910
965
  const FieldMetadata &variable_metadata= statement.variable_metadata();
911
966
  bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
912
967
 
913
 
  destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
 
968
  destination.append("SET GLOBAL "); /* Only global variables are replicated */
914
969
  destination.append(variable_metadata.name());
915
970
  destination.push_back('=');
916
971
 
942
997
  if (sql_variant == ANSI)
943
998
    quoted_identifier= '"';
944
999
 
945
 
  destination.append("CREATE ", 7);
 
1000
  destination.append("CREATE ");
946
1001
 
947
1002
  if (table.type() == Table::TEMPORARY)
948
 
    destination.append("TEMPORARY ", 10);
 
1003
    destination.append("TEMPORARY ");
949
1004
  
950
 
  destination.append("TABLE ", 6);
 
1005
  destination.append("TABLE ");
951
1006
  if (with_schema)
952
1007
  {
953
1008
    append_escaped_string(&destination, table.schema(), quoted_identifier);
954
1009
    destination.push_back('.');
955
1010
  }
956
1011
  append_escaped_string(&destination, table.name(), quoted_identifier);
957
 
  destination.append(" (\n", 3);
 
1012
  destination.append(" (\n");
958
1013
 
959
1014
  enum TransformSqlError result= NONE;
960
1015
  size_t num_fields= table.field_size();
963
1018
    const Table::Field &field= table.field(x);
964
1019
 
965
1020
    if (x != 0)
966
 
      destination.append(",\n", 2);
 
1021
      destination.append(",\n");
967
1022
 
968
1023
    destination.append("  ");
969
1024
 
976
1031
  size_t num_indexes= table.indexes_size();
977
1032
  
978
1033
  if (num_indexes > 0)
979
 
    destination.append(",\n", 2);
 
1034
    destination.append(",\n");
980
1035
 
981
1036
  for (size_t x= 0; x < num_indexes; ++x)
982
1037
  {
983
1038
    const message::Table::Index &index= table.indexes(x);
984
1039
 
985
1040
    if (x != 0)
986
 
      destination.append(",\n", 2);
 
1041
      destination.append(",\n");
987
1042
 
988
1043
    result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
989
1044
    
994
1049
  size_t num_foreign_keys= table.fk_constraint_size();
995
1050
 
996
1051
  if (num_foreign_keys > 0)
997
 
    destination.append(",\n", 2);
 
1052
    destination.append(",\n");
998
1053
 
999
1054
  for (size_t x= 0; x < num_foreign_keys; ++x)
1000
1055
  {
1001
1056
    const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1002
1057
 
1003
1058
    if (x != 0)
1004
 
      destination.append(",\n", 2);
 
1059
      destination.append(",\n");
1005
1060
 
1006
1061
    result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1007
1062
 
1009
1064
      return result;
1010
1065
  }
1011
1066
 
1012
 
  destination.append("\n)", 2);
 
1067
  destination.append("\n)");
1013
1068
 
1014
1069
  /* Add ENGINE = " clause */
1015
1070
  if (table.has_engine())
1016
1071
  {
1017
 
    destination.append(" ENGINE=", 8);
 
1072
    destination.append(" ENGINE=");
1018
1073
    destination.append(table.engine().name());
1019
1074
 
1020
1075
    size_t num_engine_options= table.engine().options_size();
1024
1079
    {
1025
1080
      const Engine::Option &option= table.engine().options(x);
1026
1081
      destination.append(option.name());
1027
 
      destination.append("='", 2);
 
1082
      destination.append("='");
1028
1083
      destination.append(option.state());
1029
 
      destination.append("'", 1);
1030
 
      if(x != num_engine_options-1)
1031
 
        destination.append(", ", 2);
 
1084
      destination.append("'");
 
1085
      if (x != num_engine_options-1)
 
1086
      {
 
1087
        destination.append(", ");
 
1088
      }
1032
1089
    }
1033
1090
  }
1034
1091
 
1035
1092
  if (table.has_options())
1036
1093
    (void) transformTableOptionsToSql(table.options(), destination, sql_variant);
1037
1094
 
 
1095
  if (not message::is_replicated(table))
 
1096
  {
 
1097
    destination.append(" REPLICATE = FALSE");
 
1098
  }
 
1099
 
 
1100
  if (message::has_definer(table))
 
1101
  {
 
1102
    destination.append(" DEFINER ");
 
1103
    destination.push_back('\'');
 
1104
    destination.append(message::definer(table));
 
1105
    destination.push_back('\'');
 
1106
  }
 
1107
 
1038
1108
  return NONE;
1039
1109
}
1040
1110
 
1048
1118
 
1049
1119
  if (options.has_comment())
1050
1120
  {
1051
 
    destination.append(" COMMENT=", 9);
 
1121
    destination.append(" COMMENT=");
1052
1122
    append_escaped_string(&destination, options.comment());
1053
1123
  }
1054
1124
 
1055
1125
  if (options.has_collation())
1056
1126
  {
1057
 
    destination.append(" COLLATE = ", 11);
 
1127
    destination.append(" COLLATE = ");
1058
1128
    destination.append(options.collation());
1059
1129
  }
1060
1130
 
1061
1131
  if (options.has_data_file_name())
1062
1132
  {
1063
 
    destination.append("\nDATA_FILE_NAME = '", 19);
 
1133
    destination.append("\nDATA_FILE_NAME = '");
1064
1134
    destination.append(options.data_file_name());
1065
1135
    destination.push_back('\'');
1066
1136
  }
1067
1137
 
1068
1138
  if (options.has_index_file_name())
1069
1139
  {
1070
 
    destination.append("\nINDEX_FILE_NAME = '", 20);
 
1140
    destination.append("\nINDEX_FILE_NAME = '");
1071
1141
    destination.append(options.index_file_name());
1072
1142
    destination.push_back('\'');
1073
1143
  }
1074
1144
 
1075
1145
  if (options.has_max_rows())
1076
1146
  {
1077
 
    destination.append("\nMAX_ROWS = ", 12);
 
1147
    destination.append("\nMAX_ROWS = ");
1078
1148
    destination.append(boost::lexical_cast<string>(options.max_rows()));
1079
1149
  }
1080
1150
 
1081
1151
  if (options.has_min_rows())
1082
1152
  {
1083
 
    destination.append("\nMIN_ROWS = ", 12);
 
1153
    destination.append("\nMIN_ROWS = ");
1084
1154
    destination.append(boost::lexical_cast<string>(options.min_rows()));
1085
1155
  }
1086
1156
 
1087
1157
  if (options.has_user_set_auto_increment_value()
1088
1158
      && options.has_auto_increment_value())
1089
1159
  {
1090
 
    destination.append(" AUTO_INCREMENT=", 16);
 
1160
    destination.append(" AUTO_INCREMENT=");
1091
1161
    destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
1092
1162
  }
1093
1163
 
1094
1164
  if (options.has_avg_row_length())
1095
1165
  {
1096
 
    destination.append("\nAVG_ROW_LENGTH = ", 18);
 
1166
    destination.append("\nAVG_ROW_LENGTH = ");
1097
1167
    destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1098
1168
  }
1099
1169
 
1100
 
  if (options.has_checksum() &&
1101
 
      options.checksum())
1102
 
    destination.append("\nCHECKSUM = TRUE", 16);
1103
 
  if (options.has_page_checksum() &&
1104
 
      options.page_checksum())
1105
 
    destination.append("\nPAGE_CHECKSUM = TRUE", 21);
 
1170
  if (options.has_checksum() && options.checksum())
 
1171
    destination.append("\nCHECKSUM = TRUE");
 
1172
 
 
1173
  if (options.has_page_checksum() && options.page_checksum())
 
1174
    destination.append("\nPAGE_CHECKSUM = TRUE");
1106
1175
 
1107
1176
  return NONE;
1108
1177
}
1120
1189
  destination.append("  ", 2);
1121
1190
 
1122
1191
  if (index.is_primary())
1123
 
    destination.append("PRIMARY ", 8);
 
1192
    destination.append("PRIMARY ");
1124
1193
  else if (index.is_unique())
1125
 
    destination.append("UNIQUE ", 7);
 
1194
    destination.append("UNIQUE ");
1126
1195
 
1127
1196
  destination.append("KEY ", 4);
1128
1197
  if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1174
1243
  case Table::Index::UNKNOWN_INDEX:
1175
1244
    break;
1176
1245
  case Table::Index::BTREE:
1177
 
    destination.append(" USING BTREE", 12);
 
1246
    destination.append(" USING BTREE");
1178
1247
    break;
1179
1248
  case Table::Index::RTREE:
1180
 
    destination.append(" USING RTREE", 12);
 
1249
    destination.append(" USING RTREE");
1181
1250
    break;
1182
1251
  case Table::Index::HASH:
1183
 
    destination.append(" USING HASH", 11);
 
1252
    destination.append(" USING HASH");
1184
1253
    break;
1185
1254
  case Table::Index::FULLTEXT:
1186
 
    destination.append(" USING FULLTEXT", 15);
 
1255
    destination.append(" USING FULLTEXT");
1187
1256
    break;
1188
1257
  }
1189
1258
 
1190
1259
  if (index.has_comment())
1191
1260
  {
1192
 
    destination.append(" COMMENT ", 9);
 
1261
    destination.append(" COMMENT ");
1193
1262
    append_escaped_string(&destination, index.comment());
1194
1263
  }
1195
1264
 
1229
1298
  if (sql_variant == ANSI)
1230
1299
    quoted_identifier= '"';
1231
1300
 
1232
 
  destination.append("  ", 2);
 
1301
  destination.append("  ");
1233
1302
 
1234
1303
  if (fkey.has_name())
1235
1304
  {
1236
 
    destination.append("CONSTRAINT ", 11);
 
1305
    destination.append("CONSTRAINT ");
1237
1306
    append_escaped_string(&destination, fkey.name(), quoted_identifier);
1238
1307
    destination.append(" ", 1);
1239
1308
  }
1240
1309
 
1241
 
  destination.append("FOREIGN KEY (", 13);
 
1310
  destination.append("FOREIGN KEY (");
1242
1311
 
1243
1312
  for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1244
1313
  {
1249
1318
                          quoted_identifier);
1250
1319
  }
1251
1320
 
1252
 
  destination.append(") REFERENCES ", 13);
 
1321
  destination.append(") REFERENCES ");
1253
1322
 
1254
1323
  append_escaped_string(&destination, fkey.references_table_name(),
1255
1324
                        quoted_identifier);
1256
 
  destination.append(" (", 2);
 
1325
  destination.append(" (");
1257
1326
 
1258
1327
  for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1259
1328
  {
1268
1337
 
1269
1338
  if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1270
1339
  {
1271
 
    destination.append(" ON UPDATE ", 11);
 
1340
    destination.append(" ON UPDATE ");
1272
1341
    transformForeignKeyOptionToSql(fkey.update_option(), destination);
1273
1342
  }
1274
1343
 
1275
1344
  if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1276
1345
  {
1277
 
    destination.append(" ON DELETE ", 11);
 
1346
    destination.append(" ON DELETE ");
1278
1347
    transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1279
1348
  }
1280
1349
 
1304
1373
  switch (field_type)
1305
1374
  {
1306
1375
    case Table::Field::DOUBLE:
1307
 
    destination.append(" DOUBLE", 7);
 
1376
    destination.append(" DOUBLE");
1308
1377
    if (field.has_numeric_options()
1309
1378
        && field.numeric_options().has_precision())
1310
1379
    {
1318
1387
    {
1319
1388
      if (field.string_options().has_collation()
1320
1389
          && field.string_options().collation().compare("binary") == 0)
1321
 
        destination.append(" VARBINARY(", 11);
 
1390
        destination.append(" VARBINARY(");
1322
1391
      else
1323
 
        destination.append(" VARCHAR(", 9);
 
1392
        destination.append(" VARCHAR(");
1324
1393
 
1325
1394
      destination.append(boost::lexical_cast<string>(field.string_options().length()));
1326
1395
      destination.append(")");
1330
1399
    {
1331
1400
      if (field.string_options().has_collation()
1332
1401
          && field.string_options().collation().compare("binary") == 0)
1333
 
        destination.append(" BLOB", 5);
 
1402
        destination.append(" BLOB");
1334
1403
      else
1335
 
        destination.append(" TEXT", 5);
 
1404
        destination.append(" TEXT");
1336
1405
    }
1337
1406
    break;
1338
1407
  case Table::Field::ENUM:
1339
1408
    {
1340
1409
      size_t num_field_values= field.enumeration_values().field_value_size();
1341
 
      destination.append(" ENUM(", 6);
 
1410
      destination.append(" ENUM(");
1342
1411
      for (size_t x= 0; x < num_field_values; ++x)
1343
1412
      {
1344
1413
        const string &type= field.enumeration_values().field_value(x);
1354
1423
      break;
1355
1424
    }
1356
1425
  case Table::Field::UUID:
1357
 
    destination.append(" UUID", 5);
 
1426
    destination.append(" UUID");
 
1427
    break;
 
1428
  case Table::Field::BOOLEAN:
 
1429
    destination.append(" BOOLEAN");
1358
1430
    break;
1359
1431
  case Table::Field::INTEGER:
1360
 
    destination.append(" INT", 4);
 
1432
    destination.append(" INT");
1361
1433
    break;
1362
1434
  case Table::Field::BIGINT:
1363
 
    destination.append(" BIGINT", 7);
 
1435
    if (field.has_constraints() and
 
1436
        field.constraints().is_unsigned())
 
1437
    {
 
1438
      destination.append(" BIGINT UNSIGNED");
 
1439
    }
 
1440
    else
 
1441
    {
 
1442
      destination.append(" BIGINT");
 
1443
    }
1364
1444
    break;
1365
1445
  case Table::Field::DECIMAL:
1366
1446
    {
1367
 
      destination.append(" DECIMAL(", 9);
 
1447
      destination.append(" DECIMAL(");
1368
1448
      stringstream ss;
1369
1449
      ss << field.numeric_options().precision() << ",";
1370
1450
      ss << field.numeric_options().scale() << ")";
1372
1452
    }
1373
1453
    break;
1374
1454
  case Table::Field::DATE:
1375
 
    destination.append(" DATE", 5);
1376
 
    break;
1377
 
  case Table::Field::TIMESTAMP:
1378
 
    destination.append(" TIMESTAMP",  10);
1379
 
    break;
 
1455
    destination.append(" DATE");
 
1456
    break;
 
1457
 
 
1458
  case Table::Field::EPOCH:
 
1459
    if (field.time_options().microseconds())
 
1460
    {
 
1461
      destination.append(" TIMESTAMP(6)");
 
1462
    }
 
1463
    else
 
1464
    {
 
1465
      destination.append(" TIMESTAMP");
 
1466
    }
 
1467
    break;
 
1468
 
1380
1469
  case Table::Field::DATETIME:
1381
 
    destination.append(" DATETIME",  9);
1382
 
    break;
1383
 
  }
1384
 
 
1385
 
  if (field.type() == Table::Field::INTEGER || 
1386
 
      field.type() == Table::Field::BIGINT)
1387
 
  {
1388
 
    if (field.has_constraints() &&
1389
 
        field.constraints().has_is_unsigned() &&
1390
 
        field.constraints().is_unsigned())
1391
 
    {
1392
 
      destination.append(" UNSIGNED", 9);
1393
 
    }
 
1470
    destination.append(" DATETIME");
 
1471
    break;
 
1472
  case Table::Field::TIME:
 
1473
    destination.append(" TIME");
 
1474
    break;
1394
1475
  }
1395
1476
 
1396
1477
  if (field.type() == Table::Field::BLOB ||
1399
1480
    if (field.string_options().has_collation()
1400
1481
        && field.string_options().collation().compare("binary"))
1401
1482
    {
1402
 
      destination.append(" COLLATE ", 9);
 
1483
      destination.append(" COLLATE ");
1403
1484
      destination.append(field.string_options().collation());
1404
1485
    }
1405
1486
  }
1406
1487
 
1407
 
  if (field.has_constraints() &&
1408
 
      ! field.constraints().is_nullable())
1409
 
  {
1410
 
    destination.append(" NOT NULL", 9);
1411
 
  }
1412
 
  else if (field.type() == Table::Field::TIMESTAMP)
1413
 
    destination.append(" NULL", 5);
 
1488
  if (field.has_constraints() and field.constraints().is_unique())
 
1489
  {
 
1490
    destination.append(" UNIQUE");
 
1491
  }
 
1492
 
 
1493
  if (field.has_constraints() && field.constraints().is_notnull())
 
1494
  {
 
1495
    destination.append(" NOT NULL");
 
1496
  }
 
1497
  else if (field.type() == Table::Field::EPOCH)
 
1498
  {
 
1499
    destination.append(" NULL");
 
1500
  }
1414
1501
 
1415
1502
  if (field.type() == Table::Field::INTEGER || 
1416
1503
      field.type() == Table::Field::BIGINT)
1419
1506
    if (field.has_numeric_options() &&
1420
1507
        field.numeric_options().is_autoincrement())
1421
1508
    {
1422
 
      destination.append(" AUTO_INCREMENT", 15);
 
1509
      destination.append(" AUTO_INCREMENT");
1423
1510
    }
1424
1511
  }
1425
1512
 
1426
1513
  if (field.options().has_default_value())
1427
1514
  {
1428
 
    destination.append(" DEFAULT ", 9);
 
1515
    destination.append(" DEFAULT ");
1429
1516
    append_escaped_string(&destination, field.options().default_value());
1430
1517
  }
1431
1518
  else if (field.options().has_default_expression())
1432
1519
  {
1433
 
    destination.append(" DEFAULT ", 9);
 
1520
    destination.append(" DEFAULT ");
1434
1521
    destination.append(field.options().default_expression());
1435
1522
  }
1436
1523
  else if (field.options().has_default_bin_value())
1437
1524
  {
1438
1525
    const string &v= field.options().default_bin_value();
1439
1526
    if (v.length() == 0)
1440
 
      destination.append(" DEFAULT ''", 11);
 
1527
    {
 
1528
      destination.append(" DEFAULT ''");
 
1529
    }
1441
1530
    else
1442
1531
    {
1443
 
      destination.append(" DEFAULT 0x", 11);
 
1532
      destination.append(" DEFAULT 0x");
1444
1533
      for (size_t x= 0; x < v.length(); x++)
1445
1534
      {
1446
1535
        char hex[3];
1453
1542
           && field.options().default_null()
1454
1543
           && field.type() != Table::Field::BLOB)
1455
1544
  {
1456
 
    destination.append(" DEFAULT NULL", 13);
 
1545
    destination.append(" DEFAULT NULL");
1457
1546
  }
1458
1547
 
1459
1548
  if (field.has_options() && field.options().has_update_expression())
1460
1549
  {
1461
 
    destination.append(" ON UPDATE ", 11);
 
1550
    destination.append(" ON UPDATE ");
1462
1551
    destination.append(field.options().update_expression());
1463
1552
  }
1464
1553
 
1465
1554
  if (field.has_comment())
1466
1555
  {
1467
 
    destination.append(" COMMENT ", 9);
 
1556
    destination.append(" COMMENT ");
1468
1557
    append_escaped_string(&destination, field.comment(), quoted_default);
1469
1558
  }
1470
1559
  return NONE;
1494
1583
  case DRIZZLE_TYPE_NULL:
1495
1584
    assert(false); /* Not a user definable type */
1496
1585
    return Table::Field::INTEGER; /* unreachable */
 
1586
  case DRIZZLE_TYPE_MICROTIME:
1497
1587
  case DRIZZLE_TYPE_TIMESTAMP:
1498
 
    return Table::Field::TIMESTAMP;
 
1588
    return Table::Field::EPOCH;
1499
1589
  case DRIZZLE_TYPE_LONGLONG:
1500
1590
    return Table::Field::BIGINT;
1501
1591
  case DRIZZLE_TYPE_DATETIME:
1502
1592
    return Table::Field::DATETIME;
 
1593
  case DRIZZLE_TYPE_TIME:
 
1594
    return Table::Field::TIME;
1503
1595
  case DRIZZLE_TYPE_DATE:
1504
1596
    return Table::Field::DATE;
1505
1597
  case DRIZZLE_TYPE_VARCHAR:
1512
1604
    return Table::Field::BLOB;
1513
1605
  case DRIZZLE_TYPE_UUID:
1514
1606
    return Table::Field::UUID;
 
1607
  case DRIZZLE_TYPE_BOOLEAN:
 
1608
    return Table::Field::BOOLEAN;
1515
1609
  }
1516
1610
 
1517
1611
  assert(false);