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);
50
120
enum TransformSqlError
51
121
transformStatementToSql(const Statement &source,
52
122
vector<string> &sql_strings,
323
398
const FieldMetadata &field_metadata= header.field_metadata(x);
325
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
400
if (record.is_null(x))
402
should_quote_field_value= false;
406
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
327
409
if (should_quote_field_value)
328
410
destination.push_back('\'');
330
if (field_metadata.type() == Table::Field::BLOB)
412
if (record.is_null(x))
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());
414
destination.append("NULL");
343
destination.append(record.insert_value(x));
418
if (field_metadata.type() == Table::Field::BLOB)
421
* We do this here because BLOB data is returned
422
* in a string correctly, but calling append()
423
* without a length will result in only the string
424
* up to a \0 being output here.
426
string raw_data(record.insert_value(x));
427
destination.append(raw_data.c_str(), raw_data.size());
431
string tmp(record.insert_value(x));
432
escapeEmbeddedQuotes(tmp);
433
destination.append(tmp);
346
437
if (should_quote_field_value)
467
560
destination.push_back(quoted_identifier);
468
561
destination.push_back('=');
470
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
563
if (record.is_null(x))
565
should_quote_field_value= false;
569
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
472
572
if (should_quote_field_value)
473
573
destination.push_back('\'');
475
if (field_metadata.type() == Table::Field::BLOB)
575
if (record.is_null(x))
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());
577
destination.append("NULL");
488
destination.append(record.after_value(x));
581
if (field_metadata.type() == Table::Field::BLOB)
584
* We do this here because BLOB data is returned
585
* in a string correctly, but calling append()
586
* without a length will result in only the string
587
* up to a \0 being output here.
589
string raw_data(record.after_value(x));
590
destination.append(raw_data.c_str(), raw_data.size());
594
string tmp(record.after_value(x));
595
escapeEmbeddedQuotes(tmp);
596
destination.append(tmp);
491
600
if (should_quote_field_value)
833
946
destination.append("TABLE ", 6);
836
destination.push_back(quoted_identifier);
837
destination.append(table.schema());
838
destination.push_back(quoted_identifier);
949
append_escaped_string(&destination, table.schema(), quoted_identifier);
839
950
destination.push_back('.');
841
destination.push_back(quoted_identifier);
842
destination.append(table.name());
843
destination.push_back(quoted_identifier);
952
append_escaped_string(&destination, table.name(), quoted_identifier);
844
953
destination.append(" (\n", 3);
846
955
enum TransformSqlError result= NONE;
875
986
if (result != NONE)
990
size_t num_foreign_keys= table.fk_constraint_size();
992
if (num_foreign_keys > 0)
993
destination.append(",\n", 2);
995
for (size_t x= 0; x < num_foreign_keys; ++x)
997
const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1000
destination.append(",\n", 2);
1002
result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
878
1008
destination.append("\n)", 2);
880
1010
/* Add ENGINE = " clause */
881
1011
if (table.has_engine())
883
const Table::StorageEngine &engine= table.engine();
884
destination.append("\nENGINE = ", 10);
885
destination.append(engine.name());
1013
destination.append(" ENGINE=", 8);
1014
destination.append(table.engine().name());
887
size_t num_engine_options= engine.option_size();
1016
size_t num_engine_options= table.engine().options_size();
1017
if (num_engine_options > 0)
1018
destination.append(" ", 1);
888
1019
for (size_t x= 0; x < num_engine_options; ++x)
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');
1021
const Engine::Option &option= table.engine().options(x);
1022
destination.append(option.name());
1023
destination.append("='", 2);
1024
destination.append(option.state());
1025
destination.append("'", 1);
1026
if(x != num_engine_options-1)
1027
destination.append(", ", 2);
910
1042
if (sql_variant == ANSI)
911
1043
return NONE; /* ANSI does not support table options... */
915
1045
if (options.has_comment())
917
destination.append("\nCOMMENT = '", 12);
918
destination.append(options.comment());
919
destination.push_back('\'');
1047
destination.append(" COMMENT=", 9);
1048
append_escaped_string(&destination, options.comment());
922
1051
if (options.has_collation())
924
destination.append("\nCOLLATE = ", 11);
1053
destination.append(" COLLATE = ", 11);
925
1054
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());
944
1057
if (options.has_data_file_name())
946
1059
destination.append("\nDATA_FILE_NAME = '", 19);
958
1071
if (options.has_max_rows())
960
ss << options.max_rows();
961
1073
destination.append("\nMAX_ROWS = ", 12);
962
destination.append(ss.str());
1074
destination.append(boost::lexical_cast<string>(options.max_rows()));
966
1077
if (options.has_min_rows())
968
ss << options.min_rows();
969
1079
destination.append("\nMIN_ROWS = ", 12);
970
destination.append(ss.str());
1080
destination.append(boost::lexical_cast<string>(options.min_rows()));
974
if (options.has_auto_increment_value())
1083
if (options.has_user_set_auto_increment_value()
1084
&& options.has_auto_increment_value())
976
ss << options.auto_increment_value();
977
destination.append("\nAUTO_INCREMENT = ", 18);
978
destination.append(ss.str());
1086
destination.append(" AUTO_INCREMENT=", 16);
1087
destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
982
1090
if (options.has_avg_row_length())
984
ss << options.avg_row_length();
985
1092
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);
1093
destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1012
1096
if (options.has_checksum() &&
1013
1097
options.checksum())
1014
1098
destination.append("\nCHECKSUM = TRUE", 16);
1029
1113
if (sql_variant == ANSI)
1030
1114
quoted_identifier= '"';
1116
destination.append(" ", 2);
1032
1118
if (index.is_primary())
1033
1119
destination.append("PRIMARY ", 8);
1034
1120
else if (index.is_unique())
1035
1121
destination.append("UNIQUE ", 7);
1037
1123
destination.append("KEY ", 4);
1038
destination.push_back(quoted_identifier);
1039
destination.append(index.name());
1040
destination.push_back(quoted_identifier);
1041
destination.append(" (", 2);
1124
if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1126
destination.push_back(quoted_identifier);
1127
destination.append(index.name());
1128
destination.push_back(quoted_identifier);
1129
destination.append(" (", 2);
1132
destination.append("(", 1);
1043
1134
size_t num_parts= index.index_part_size();
1044
1135
for (size_t x= 0; x < num_parts; ++x)
1064
1155
if (part.has_compare_length())
1066
size_t compare_length_in_chars= part.compare_length();
1068
/* hack: compare_length() is bytes, not chars, but
1069
* only for VARCHAR. Ass. */
1070
if (field.type() == Table::Field::VARCHAR)
1071
compare_length_in_chars/= 4;
1073
if (compare_length_in_chars != field.string_options().length())
1157
if (part.compare_length() != field.string_options().length())
1076
1159
destination.push_back('(');
1077
ss << compare_length_in_chars;
1078
destination.append(ss.str());
1160
destination.append(boost::lexical_cast<string>(part.compare_length()));
1079
1161
destination.push_back(')');
1084
1166
destination.push_back(')');
1168
switch (index.type())
1170
case Table::Index::UNKNOWN_INDEX:
1172
case Table::Index::BTREE:
1173
destination.append(" USING BTREE", 12);
1175
case Table::Index::RTREE:
1176
destination.append(" USING RTREE", 12);
1178
case Table::Index::HASH:
1179
destination.append(" USING HASH", 11);
1181
case Table::Index::FULLTEXT:
1182
destination.append(" USING FULLTEXT", 15);
1186
if (index.has_comment())
1188
destination.append(" COMMENT ", 9);
1189
append_escaped_string(&destination, index.comment());
1195
static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt, string &destination)
1199
case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1200
destination.append("RESTRICT");
1202
case Table::ForeignKeyConstraint::OPTION_CASCADE:
1203
destination.append("CASCADE");
1205
case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1206
destination.append("SET NULL");
1208
case Table::ForeignKeyConstraint::OPTION_UNDEF:
1209
case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1210
destination.append("NO ACTION");
1212
case Table::ForeignKeyConstraint::OPTION_SET_DEFAULT:
1213
destination.append("SET DEFAULT");
1218
enum TransformSqlError
1219
transformForeignKeyConstraintDefinitionToSql(const Table::ForeignKeyConstraint &fkey,
1221
string &destination,
1222
enum TransformSqlVariant sql_variant)
1224
char quoted_identifier= '`';
1225
if (sql_variant == ANSI)
1226
quoted_identifier= '"';
1228
destination.append(" ", 2);
1230
if (fkey.has_name())
1232
destination.append("CONSTRAINT ", 11);
1233
append_escaped_string(&destination, fkey.name(), quoted_identifier);
1234
destination.append(" ", 1);
1237
destination.append("FOREIGN KEY (", 13);
1239
for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1242
destination.append(", ");
1244
append_escaped_string(&destination, fkey.column_names(x),
1248
destination.append(") REFERENCES ", 13);
1250
append_escaped_string(&destination, fkey.references_table_name(),
1252
destination.append(" (", 2);
1254
for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1257
destination.append(", ");
1259
append_escaped_string(&destination, fkey.references_columns(x),
1263
destination.push_back(')');
1265
if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1267
destination.append(" ON UPDATE ", 11);
1268
transformForeignKeyOptionToSql(fkey.update_option(), destination);
1271
if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1273
destination.append(" ON DELETE ", 11);
1274
transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1092
1283
enum TransformSqlVariant sql_variant)
1094
1285
char quoted_identifier= '`';
1286
char quoted_default;
1095
1288
if (sql_variant == ANSI)
1096
1289
quoted_identifier= '"';
1098
destination.push_back(quoted_identifier);
1099
destination.append(field.name());
1100
destination.push_back(quoted_identifier);
1291
if (sql_variant == DRIZZLE)
1292
quoted_default= '\'';
1294
quoted_default= quoted_identifier;
1296
append_escaped_string(&destination, field.name(), quoted_identifier);
1102
1298
Table::Field::FieldType field_type= field.type();
1106
1302
case Table::Field::DOUBLE:
1107
1303
destination.append(" DOUBLE", 7);
1304
if (field.has_numeric_options()
1305
&& field.numeric_options().has_precision())
1308
ss << "(" << field.numeric_options().precision() << ",";
1309
ss << field.numeric_options().scale() << ")";
1310
destination.append(ss.str());
1109
1313
case Table::Field::VARCHAR:
1111
destination.append(" VARCHAR(", 9);
1113
ss << field.string_options().length() << ")";
1114
destination.append(ss.str());
1315
if (field.string_options().has_collation()
1316
&& field.string_options().collation().compare("binary") == 0)
1317
destination.append(" VARBINARY(", 11);
1319
destination.append(" VARCHAR(", 9);
1321
destination.append(boost::lexical_cast<string>(field.string_options().length()));
1322
destination.append(")");
1117
1325
case Table::Field::BLOB:
1118
destination.append(" BLOB", 5);
1327
if (field.string_options().has_collation()
1328
&& field.string_options().collation().compare("binary") == 0)
1329
destination.append(" BLOB", 5);
1331
destination.append(" TEXT", 5);
1120
1334
case Table::Field::ENUM:
1389
if (field.type() == Table::Field::BLOB ||
1390
field.type() == Table::Field::VARCHAR)
1392
if (field.string_options().has_collation()
1393
&& field.string_options().collation().compare("binary"))
1395
destination.append(" COLLATE ", 9);
1396
destination.append(field.string_options().collation());
1176
if (! (field.has_constraints() &&
1177
field.constraints().is_nullable()))
1400
if (field.has_constraints() &&
1401
! field.constraints().is_nullable())
1179
destination.append(" NOT", 4);
1403
destination.append(" NOT NULL", 9);
1181
destination.append(" NULL", 5);
1405
else if (field.type() == Table::Field::TIMESTAMP)
1406
destination.append(" NULL", 5);
1183
1408
if (field.type() == Table::Field::INTEGER ||
1184
1409
field.type() == Table::Field::BIGINT)
1194
if (field.type() == Table::Field::BLOB ||
1195
field.type() == Table::Field::VARCHAR)
1197
if (field.string_options().has_collation())
1199
destination.append(" COLLATE ", 9);
1200
destination.append(field.string_options().collation());
1204
1419
if (field.options().has_default_value())
1206
1421
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())
1422
append_escaped_string(&destination, field.options().default_value());
1424
else if (field.options().has_default_expression())
1426
destination.append(" DEFAULT ", 9);
1427
destination.append(field.options().default_expression());
1429
else if (field.options().has_default_bin_value())
1214
1431
const string &v= field.options().default_bin_value();
1215
destination.append(" DEFAULT 0x", 11);
1216
for (size_t x= 0; x < v.length(); x++)
1432
if (v.length() == 0)
1433
destination.append(" DEFAULT ''", 11);
1218
printf("%.2x", *(v.c_str() + x));
1436
destination.append(" DEFAULT 0x", 11);
1437
for (size_t x= 0; x < v.length(); x++)
1440
snprintf(hex, sizeof(hex), "%.2X", *(v.c_str() + x));
1441
destination.append(hex, 2);
1445
else if (field.options().has_default_null()
1446
&& field.options().default_null()
1447
&& field.type() != Table::Field::BLOB)
1449
destination.append(" DEFAULT NULL", 13);
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);
1452
if (field.has_options() && field.options().has_update_expression())
1454
destination.append(" ON UPDATE ", 11);
1455
destination.append(field.options().update_expression());
1227
1458
if (field.has_comment())
1229
1460
destination.append(" COMMENT ", 9);
1230
destination.push_back(quoted_identifier);
1231
destination.append(field.comment());
1232
destination.push_back(quoted_identifier);
1461
append_escaped_string(&destination, field.comment(), quoted_default);