55
static void escapeEmbeddedQuotes(string &s, const char quote='\'')
59
for (it= s.begin(); it != s.end(); ++it)
63
it= s.insert(it, quote);
64
++it; // advance back to the quote
69
/* Incredibly similar to append_unescaped() in table.cc, but for std::string */
70
static void append_escaped_string(std::string *res, const std::string &input, const char quote='\'')
72
const char *pos= input.c_str();
73
const char *end= input.c_str()+input.length();
74
res->push_back(quote);
76
for (; pos != end ; pos++)
79
if (use_mb(default_charset_info) &&
80
(mblen= my_ismbchar(default_charset_info, pos, end)))
82
res->append(pos, mblen);
90
case 0: /* Must be escaped for 'mysql' */
94
case '\n': /* Must be escaped for logs */
99
res->push_back('\\'); /* This gives better readability */
103
res->push_back('\\'); /* Because of the sql syntax */
104
res->push_back('\\');
107
if (*pos == quote) /* SQL syntax for quoting a quote */
109
res->push_back(quote);
110
res->push_back(quote);
113
res->push_back(*pos);
117
res->push_back(quote);
120
50
enum TransformSqlError
121
51
transformStatementToSql(const Statement &source,
122
52
vector<string> &sql_strings,
411
323
const FieldMetadata &field_metadata= header.field_metadata(x);
413
if (record.is_null(x))
415
should_quote_field_value= false;
419
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
325
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
422
327
if (should_quote_field_value)
423
328
destination.push_back('\'');
425
if (record.is_null(x))
330
if (field_metadata.type() == Table::Field::BLOB)
427
destination.append("NULL");
333
* We do this here because BLOB data is returned
334
* in a string correctly, but calling append()
335
* without a length will result in only the string
336
* up to a \0 being output here.
338
string raw_data(record.insert_value(x));
339
destination.append(raw_data.c_str(), raw_data.size());
431
if (field_metadata.type() == Table::Field::BLOB)
434
* We do this here because BLOB data is returned
435
* in a string correctly, but calling append()
436
* without a length will result in only the string
437
* up to a \0 being output here.
439
string raw_data(record.insert_value(x));
440
destination.append(raw_data.c_str(), raw_data.size());
444
string tmp(record.insert_value(x));
445
escapeEmbeddedQuotes(tmp);
446
destination.append(tmp);
343
destination.append(record.insert_value(x));
450
346
if (should_quote_field_value)
573
467
destination.push_back(quoted_identifier);
574
468
destination.push_back('=');
576
if (record.is_null(x))
578
should_quote_field_value= false;
582
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
470
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
585
472
if (should_quote_field_value)
586
473
destination.push_back('\'');
588
if (record.is_null(x))
475
if (field_metadata.type() == Table::Field::BLOB)
590
destination.append("NULL");
478
* We do this here because BLOB data is returned
479
* in a string correctly, but calling append()
480
* without a length will result in only the string
481
* up to a \0 being output here.
483
string raw_data(record.after_value(x));
484
destination.append(raw_data.c_str(), raw_data.size());
594
if (field_metadata.type() == Table::Field::BLOB)
597
* We do this here because BLOB data is returned
598
* in a string correctly, but calling append()
599
* without a length will result in only the string
600
* up to a \0 being output here.
602
string raw_data(record.after_value(x));
603
destination.append(raw_data.c_str(), raw_data.size());
607
string tmp(record.after_value(x));
608
escapeEmbeddedQuotes(tmp);
609
destination.append(tmp);
488
destination.append(record.after_value(x));
613
491
if (should_quote_field_value)
817
691
enum TransformSqlError
818
transformAlterSchemaStatementToSql(const AlterSchemaStatement &statement,
820
enum TransformSqlVariant sql_variant)
822
const Schema &before= statement.before();
823
const Schema &after= statement.after();
825
/* Make sure we are given the before and after for the same object */
826
if (before.uuid() != after.uuid())
827
return UUID_MISMATCH;
829
char quoted_identifier= '`';
830
if (sql_variant == ANSI)
831
quoted_identifier= '"';
833
destination.append("ALTER SCHEMA ");
834
destination.push_back(quoted_identifier);
835
destination.append(before.name());
836
destination.push_back(quoted_identifier);
839
* Diff our schemas. Currently, only collation can change so a
840
* diff of the two structures is not really necessary.
842
destination.append(" COLLATE = ");
843
destination.append(after.collation());
848
enum TransformSqlError
849
692
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
850
693
string &destination,
851
694
enum TransformSqlVariant sql_variant)
987
825
if (sql_variant == ANSI)
988
826
quoted_identifier= '"';
990
destination.append("CREATE ");
828
destination.append("CREATE ", 7);
992
830
if (table.type() == Table::TEMPORARY)
993
destination.append("TEMPORARY ");
831
destination.append("TEMPORARY ", 10);
995
destination.append("TABLE ");
833
destination.append("TABLE ", 6);
998
append_escaped_string(&destination, table.schema(), quoted_identifier);
836
destination.push_back(quoted_identifier);
837
destination.append(table.schema());
838
destination.push_back(quoted_identifier);
999
839
destination.push_back('.');
1001
append_escaped_string(&destination, table.name(), quoted_identifier);
1002
destination.append(" (\n");
841
destination.push_back(quoted_identifier);
842
destination.append(table.name());
843
destination.push_back(quoted_identifier);
844
destination.append(" (\n", 3);
1004
846
enum TransformSqlError result= NONE;
1005
847
size_t num_fields= table.field_size();
1021
861
size_t num_indexes= table.indexes_size();
1023
863
if (num_indexes > 0)
1024
destination.append(",\n");
864
destination.append(",\n", 2);
1026
866
for (size_t x= 0; x < num_indexes; ++x)
1028
868
const message::Table::Index &index= table.indexes(x);
1031
destination.append(",\n");
871
destination.append(",\n", 2);
1033
873
result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
1035
875
if (result != NONE)
1039
size_t num_foreign_keys= table.fk_constraint_size();
1041
if (num_foreign_keys > 0)
1042
destination.append(",\n");
1044
for (size_t x= 0; x < num_foreign_keys; ++x)
1046
const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1049
destination.append(",\n");
1051
result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1057
destination.append("\n)");
878
destination.append("\n)", 2);
1059
880
/* Add ENGINE = " clause */
1060
881
if (table.has_engine())
1062
destination.append(" ENGINE=");
1063
destination.append(table.engine().name());
883
const Table::StorageEngine &engine= table.engine();
884
destination.append("\nENGINE = ", 10);
885
destination.append(engine.name());
1065
size_t num_engine_options= table.engine().options_size();
1066
if (num_engine_options > 0)
1067
destination.append(" ", 1);
887
size_t num_engine_options= engine.option_size();
1068
888
for (size_t x= 0; x < num_engine_options; ++x)
1070
const Engine::Option &option= table.engine().options(x);
1071
destination.append(option.name());
1072
destination.append("='");
1073
destination.append(option.state());
1074
destination.append("'");
1075
if (x != num_engine_options-1)
1077
destination.append(", ");
890
const Table::StorageEngine::EngineOption &option= engine.option(x);
891
destination.push_back('\n');
892
destination.append(option.option_name());
893
destination.append(" = ", 3);
894
destination.append(option.option_value());
895
destination.push_back('\n');
1093
910
if (sql_variant == ANSI)
1094
911
return NONE; /* ANSI does not support table options... */
1096
915
if (options.has_comment())
1098
destination.append(" COMMENT=");
1099
append_escaped_string(&destination, options.comment());
917
destination.append("\nCOMMENT = '", 12);
918
destination.append(options.comment());
919
destination.push_back('\'');
1102
922
if (options.has_collation())
1104
destination.append(" COLLATE = ");
924
destination.append("\nCOLLATE = ", 11);
1105
925
destination.append(options.collation());
928
if (options.has_auto_increment())
930
ss << options.auto_increment();
931
destination.append("\nAUTOINCREMENT_OFFSET = ", 24);
932
destination.append(ss.str());
936
if (options.has_row_type())
938
ss << options.row_type();
939
destination.append("\nROW_TYPE = ", 12);
940
destination.append(ss.str());
1108
944
if (options.has_data_file_name())
1110
destination.append("\nDATA_FILE_NAME = '");
946
destination.append("\nDATA_FILE_NAME = '", 19);
1111
947
destination.append(options.data_file_name());
1112
948
destination.push_back('\'');
1115
951
if (options.has_index_file_name())
1117
destination.append("\nINDEX_FILE_NAME = '");
953
destination.append("\nINDEX_FILE_NAME = '", 20);
1118
954
destination.append(options.index_file_name());
1119
955
destination.push_back('\'');
1122
958
if (options.has_max_rows())
1124
destination.append("\nMAX_ROWS = ");
1125
destination.append(boost::lexical_cast<string>(options.max_rows()));
960
ss << options.max_rows();
961
destination.append("\nMAX_ROWS = ", 12);
962
destination.append(ss.str());
1128
966
if (options.has_min_rows())
1130
destination.append("\nMIN_ROWS = ");
1131
destination.append(boost::lexical_cast<string>(options.min_rows()));
968
ss << options.min_rows();
969
destination.append("\nMIN_ROWS = ", 12);
970
destination.append(ss.str());
1134
if (options.has_user_set_auto_increment_value()
1135
&& options.has_auto_increment_value())
974
if (options.has_auto_increment_value())
1137
destination.append(" AUTO_INCREMENT=");
1138
destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
976
ss << options.auto_increment_value();
977
destination.append("\nAUTO_INCREMENT = ", 18);
978
destination.append(ss.str());
1141
982
if (options.has_avg_row_length())
1143
destination.append("\nAVG_ROW_LENGTH = ");
1144
destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1147
if (options.has_checksum() && options.checksum())
1148
destination.append("\nCHECKSUM = TRUE");
1150
if (options.has_page_checksum() && options.page_checksum())
1151
destination.append("\nPAGE_CHECKSUM = TRUE");
1153
if (options.has_dont_replicate() and options.dont_replicate())
1155
destination.append(" REPLICATION = FALSE");
984
ss << options.avg_row_length();
985
destination.append("\nAVG_ROW_LENGTH = ", 18);
986
destination.append(ss.str());
990
if (options.has_key_block_size())
992
ss << options.key_block_size();
993
destination.append("\nKEY_BLOCK_SIZE = ", 18);
994
destination.append(ss.str());
998
if (options.has_block_size())
1000
ss << options.block_size();
1001
destination.append("\nBLOCK_SIZE = ", 14);
1002
destination.append(ss.str());
1006
if (options.has_pack_keys() &&
1007
options.pack_keys())
1008
destination.append("\nPACK_KEYS = TRUE", 17);
1009
if (options.has_pack_record() &&
1010
options.pack_record())
1011
destination.append("\nPACK_RECORD = TRUE", 19);
1012
if (options.has_checksum() &&
1014
destination.append("\nCHECKSUM = TRUE", 16);
1015
if (options.has_page_checksum() &&
1016
options.page_checksum())
1017
destination.append("\nPAGE_CHECKSUM = TRUE", 21);
1168
1029
if (sql_variant == ANSI)
1169
1030
quoted_identifier= '"';
1171
destination.append(" ", 2);
1173
1032
if (index.is_primary())
1174
destination.append("PRIMARY ");
1033
destination.append("PRIMARY ", 8);
1175
1034
else if (index.is_unique())
1176
destination.append("UNIQUE ");
1035
destination.append("UNIQUE ", 7);
1178
1037
destination.append("KEY ", 4);
1179
if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1181
destination.push_back(quoted_identifier);
1182
destination.append(index.name());
1183
destination.push_back(quoted_identifier);
1184
destination.append(" (", 2);
1187
destination.append("(", 1);
1038
destination.push_back(quoted_identifier);
1039
destination.append(index.name());
1040
destination.push_back(quoted_identifier);
1041
destination.append(" (", 2);
1189
1043
size_t num_parts= index.index_part_size();
1190
1044
for (size_t x= 0; x < num_parts; ++x)
1221
1084
destination.push_back(')');
1223
switch (index.type())
1225
case Table::Index::UNKNOWN_INDEX:
1227
case Table::Index::BTREE:
1228
destination.append(" USING BTREE");
1230
case Table::Index::RTREE:
1231
destination.append(" USING RTREE");
1233
case Table::Index::HASH:
1234
destination.append(" USING HASH");
1236
case Table::Index::FULLTEXT:
1237
destination.append(" USING FULLTEXT");
1241
if (index.has_comment())
1243
destination.append(" COMMENT ");
1244
append_escaped_string(&destination, index.comment());
1250
static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt, string &destination)
1254
case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1255
destination.append("RESTRICT");
1257
case Table::ForeignKeyConstraint::OPTION_CASCADE:
1258
destination.append("CASCADE");
1260
case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1261
destination.append("SET NULL");
1263
case Table::ForeignKeyConstraint::OPTION_UNDEF:
1264
case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1265
destination.append("NO ACTION");
1267
case Table::ForeignKeyConstraint::OPTION_SET_DEFAULT:
1268
destination.append("SET DEFAULT");
1273
enum TransformSqlError
1274
transformForeignKeyConstraintDefinitionToSql(const Table::ForeignKeyConstraint &fkey,
1276
string &destination,
1277
enum TransformSqlVariant sql_variant)
1279
char quoted_identifier= '`';
1280
if (sql_variant == ANSI)
1281
quoted_identifier= '"';
1283
destination.append(" ");
1285
if (fkey.has_name())
1287
destination.append("CONSTRAINT ");
1288
append_escaped_string(&destination, fkey.name(), quoted_identifier);
1289
destination.append(" ", 1);
1292
destination.append("FOREIGN KEY (");
1294
for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1297
destination.append(", ");
1299
append_escaped_string(&destination, fkey.column_names(x),
1303
destination.append(") REFERENCES ");
1305
append_escaped_string(&destination, fkey.references_table_name(),
1307
destination.append(" (");
1309
for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1312
destination.append(", ");
1314
append_escaped_string(&destination, fkey.references_columns(x),
1318
destination.push_back(')');
1320
if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1322
destination.append(" ON UPDATE ");
1323
transformForeignKeyOptionToSql(fkey.update_option(), destination);
1326
if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1328
destination.append(" ON DELETE ");
1329
transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1338
1092
enum TransformSqlVariant sql_variant)
1340
1094
char quoted_identifier= '`';
1341
char quoted_default;
1343
1095
if (sql_variant == ANSI)
1344
1096
quoted_identifier= '"';
1346
if (sql_variant == DRIZZLE)
1347
quoted_default= '\'';
1349
quoted_default= quoted_identifier;
1351
append_escaped_string(&destination, field.name(), quoted_identifier);
1098
destination.push_back(quoted_identifier);
1099
destination.append(field.name());
1100
destination.push_back(quoted_identifier);
1353
1102
Table::Field::FieldType field_type= field.type();
1355
1104
switch (field_type)
1357
1106
case Table::Field::DOUBLE:
1358
destination.append(" DOUBLE");
1359
if (field.has_numeric_options()
1360
&& field.numeric_options().has_precision())
1363
ss << "(" << field.numeric_options().precision() << ",";
1364
ss << field.numeric_options().scale() << ")";
1365
destination.append(ss.str());
1107
destination.append(" DOUBLE", 7);
1368
1109
case Table::Field::VARCHAR:
1370
if (field.string_options().has_collation()
1371
&& field.string_options().collation().compare("binary") == 0)
1372
destination.append(" VARBINARY(");
1374
destination.append(" VARCHAR(");
1376
destination.append(boost::lexical_cast<string>(field.string_options().length()));
1377
destination.append(")");
1111
destination.append(" VARCHAR(", 9);
1113
ss << field.string_options().length() << ")";
1114
destination.append(ss.str());
1380
1117
case Table::Field::BLOB:
1382
if (field.string_options().has_collation()
1383
&& field.string_options().collation().compare("binary") == 0)
1384
destination.append(" BLOB");
1386
destination.append(" TEXT");
1118
destination.append(" BLOB", 5);
1389
1120
case Table::Field::ENUM:
1391
1122
size_t num_field_values= field.enumeration_values().field_value_size();
1392
destination.append(" ENUM(");
1123
destination.append(" ENUM(", 6);
1393
1124
for (size_t x= 0; x < num_field_values; ++x)
1395
1126
const string &type= field.enumeration_values().field_value(x);
1404
1135
destination.push_back(')');
1407
case Table::Field::UUID:
1408
destination.append(" UUID");
1410
case Table::Field::BOOLEAN:
1411
destination.append(" BOOLEAN");
1413
1138
case Table::Field::INTEGER:
1414
destination.append(" INT");
1139
destination.append(" INT", 4);
1416
1141
case Table::Field::BIGINT:
1417
if (field.has_constraints() and
1418
field.constraints().is_unsigned())
1420
destination.append(" BIGINT UNSIGNED");
1424
destination.append(" BIGINT");
1142
destination.append(" BIGINT", 7);
1427
1144
case Table::Field::DECIMAL:
1429
destination.append(" DECIMAL(");
1146
destination.append(" DECIMAL(", 9);
1430
1147
stringstream ss;
1431
1148
ss << field.numeric_options().precision() << ",";
1432
1149
ss << field.numeric_options().scale() << ")";
1436
1153
case Table::Field::DATE:
1437
destination.append(" DATE");
1440
case Table::Field::EPOCH:
1441
if (field.time_options().microseconds())
1443
destination.append(" TIMESTAMP(6)");
1447
destination.append(" TIMESTAMP");
1154
destination.append(" DATE", 5);
1156
case Table::Field::TIMESTAMP:
1157
destination.append(" TIMESTAMP", 10);
1451
1159
case Table::Field::DATETIME:
1452
destination.append(" DATETIME");
1454
case Table::Field::TIME:
1455
destination.append(" TIME");
1160
destination.append(" DATETIME", 9);
1164
if (field.type() == Table::Field::INTEGER ||
1165
field.type() == Table::Field::BIGINT)
1167
if (field.has_constraints() &&
1168
field.constraints().has_is_unsigned() &&
1169
field.constraints().is_unsigned())
1171
destination.append(" UNSIGNED", 9);
1176
if (! (field.has_constraints() &&
1177
field.constraints().is_nullable()))
1179
destination.append(" NOT", 4);
1181
destination.append(" NULL", 5);
1183
if (field.type() == Table::Field::INTEGER ||
1184
field.type() == Table::Field::BIGINT)
1186
/* AUTO_INCREMENT must be after NOT NULL */
1187
if (field.has_numeric_options() &&
1188
field.numeric_options().is_autoincrement())
1190
destination.append(" AUTO_INCREMENT", 15);
1459
1194
if (field.type() == Table::Field::BLOB ||
1460
1195
field.type() == Table::Field::VARCHAR)
1462
if (field.string_options().has_collation()
1463
&& field.string_options().collation().compare("binary"))
1197
if (field.string_options().has_collation())
1465
destination.append(" COLLATE ");
1199
destination.append(" COLLATE ", 9);
1466
1200
destination.append(field.string_options().collation());
1470
if (field.has_constraints() and field.constraints().is_unique())
1472
destination.append(" UNIQUE");
1475
if (field.has_constraints() && field.constraints().is_notnull())
1477
destination.append(" NOT NULL");
1479
else if (field.type() == Table::Field::EPOCH)
1481
destination.append(" NULL");
1484
if (field.type() == Table::Field::INTEGER ||
1485
field.type() == Table::Field::BIGINT)
1487
/* AUTO_INCREMENT must be after NOT NULL */
1488
if (field.has_numeric_options() &&
1489
field.numeric_options().is_autoincrement())
1491
destination.append(" AUTO_INCREMENT");
1495
1204
if (field.options().has_default_value())
1497
destination.append(" DEFAULT ");
1498
append_escaped_string(&destination, field.options().default_value());
1500
else if (field.options().has_default_expression())
1502
destination.append(" DEFAULT ");
1503
destination.append(field.options().default_expression());
1505
else if (field.options().has_default_bin_value())
1206
destination.append(" DEFAULT ", 9);
1207
destination.push_back(quoted_identifier);
1208
destination.append(field.options().default_value());
1209
destination.push_back(quoted_identifier);
1212
if (field.options().has_default_bin_value())
1507
1214
const string &v= field.options().default_bin_value();
1508
if (v.length() == 0)
1510
destination.append(" DEFAULT ''");
1514
destination.append(" DEFAULT 0x");
1515
for (size_t x= 0; x < v.length(); x++)
1518
snprintf(hex, sizeof(hex), "%.2X", *(v.c_str() + x));
1519
destination.append(hex, 2);
1523
else if (field.options().has_default_null()
1524
&& field.options().default_null()
1525
&& field.type() != Table::Field::BLOB)
1527
destination.append(" DEFAULT NULL");
1215
destination.append(" DEFAULT 0x", 11);
1216
for (size_t x= 0; x < v.length(); x++)
1218
printf("%.2x", *(v.c_str() + x));
1530
if (field.has_options() && field.options().has_update_expression())
1532
destination.append(" ON UPDATE ");
1533
destination.append(field.options().update_expression());
1222
if (field.type() == Table::Field::TIMESTAMP)
1223
if (field.timestamp_options().has_auto_updates() &&
1224
field.timestamp_options().auto_updates())
1225
destination.append(" ON UPDATE CURRENT_TIMESTAMP", 28);
1536
1227
if (field.has_comment())
1538
destination.append(" COMMENT ");
1539
append_escaped_string(&destination, field.comment(), quoted_default);
1229
destination.append(" COMMENT ", 9);
1230
destination.push_back(quoted_identifier);
1231
destination.append(field.comment());
1232
destination.push_back(quoted_identifier);