54
static void escapeEmbeddedQuotes(string &s, const char quote='\'')
58
for (it= s.begin(); it != s.end(); ++it)
62
it= s.insert(it, quote);
63
++it; // advance back to the quote
68
/* Incredibly similar to append_unescaped() in table.cc, but for std::string */
69
static void append_escaped_string(std::string *res, const std::string &input, const char quote='\'')
71
const char *pos= input.c_str();
72
const char *end= input.c_str()+input.length();
73
res->push_back(quote);
75
for (; pos != end ; pos++)
78
if (use_mb(default_charset_info) &&
79
(mblen= my_ismbchar(default_charset_info, pos, end)))
81
res->append(pos, mblen);
89
case 0: /* Must be escaped for 'mysql' */
93
case '\n': /* Must be escaped for logs */
98
res->push_back('\\'); /* This gives better readability */
102
res->push_back('\\'); /* Because of the sql syntax */
103
res->push_back('\\');
106
if (*pos == quote) /* SQL syntax for quoting a quote */
108
res->push_back(quote);
109
res->push_back(quote);
112
res->push_back(*pos);
116
res->push_back(quote);
50
119
enum TransformSqlError
51
120
transformStatementToSql(const Statement &source,
52
121
vector<string> &sql_strings,
323
392
const FieldMetadata &field_metadata= header.field_metadata(x);
325
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
394
if (record.is_null(x))
396
should_quote_field_value= false;
400
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
327
403
if (should_quote_field_value)
328
404
destination.push_back('\'');
330
if (field_metadata.type() == Table::Field::BLOB)
406
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());
408
destination.append("NULL");
343
destination.append(record.insert_value(x));
412
if (field_metadata.type() == Table::Field::BLOB)
415
* We do this here because BLOB data is returned
416
* in a string correctly, but calling append()
417
* without a length will result in only the string
418
* up to a \0 being output here.
420
string raw_data(record.insert_value(x));
421
destination.append(raw_data.c_str(), raw_data.size());
425
string tmp(record.insert_value(x));
426
escapeEmbeddedQuotes(tmp);
427
destination.append(tmp);
346
431
if (should_quote_field_value)
467
554
destination.push_back(quoted_identifier);
468
555
destination.push_back('=');
470
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
557
if (record.is_null(x))
559
should_quote_field_value= false;
563
should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
472
566
if (should_quote_field_value)
473
567
destination.push_back('\'');
475
if (field_metadata.type() == Table::Field::BLOB)
569
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());
571
destination.append("NULL");
488
destination.append(record.after_value(x));
575
if (field_metadata.type() == Table::Field::BLOB)
578
* We do this here because BLOB data is returned
579
* in a string correctly, but calling append()
580
* without a length will result in only the string
581
* up to a \0 being output here.
583
string raw_data(record.after_value(x));
584
destination.append(raw_data.c_str(), raw_data.size());
588
string tmp(record.after_value(x));
589
escapeEmbeddedQuotes(tmp);
590
destination.append(tmp);
491
594
if (should_quote_field_value)
831
938
destination.append("TEMPORARY ", 10);
833
940
destination.append("TABLE ", 6);
834
destination.push_back(quoted_identifier);
835
destination.append(table.name());
836
destination.push_back(quoted_identifier);
943
append_escaped_string(&destination, table.schema(), quoted_identifier);
944
destination.push_back('.');
946
append_escaped_string(&destination, table.name(), quoted_identifier);
837
947
destination.append(" (\n", 3);
839
949
enum TransformSqlError result= NONE;
868
980
if (result != NONE)
984
size_t num_foreign_keys= table.fk_constraint_size();
986
if (num_foreign_keys > 0)
987
destination.append(",\n", 2);
989
for (size_t x= 0; x < num_foreign_keys; ++x)
991
const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
994
destination.append(",\n", 2);
996
result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
871
1002
destination.append("\n)", 2);
873
1004
/* Add ENGINE = " clause */
874
1005
if (table.has_engine())
876
const Table::StorageEngine &engine= table.engine();
877
destination.append("\nENGINE = ", 10);
878
destination.append(engine.name());
1007
destination.append(" ENGINE=", 8);
1008
destination.append(table.engine().name());
880
size_t num_engine_options= engine.option_size();
1010
size_t num_engine_options= table.engine().options_size();
1011
if (num_engine_options > 0)
1012
destination.append(" ", 1);
881
1013
for (size_t x= 0; x < num_engine_options; ++x)
883
const Table::StorageEngine::EngineOption &option= engine.option(x);
884
destination.push_back('\n');
885
destination.append(option.option_name());
886
destination.append(" = ", 3);
887
destination.append(option.option_value());
888
destination.push_back('\n');
1015
const Engine::Option &option= table.engine().options(x);
1016
destination.append(option.name());
1017
destination.append("='", 2);
1018
destination.append(option.state());
1019
destination.append("'", 1);
1020
if(x != num_engine_options-1)
1021
destination.append(", ", 2);
908
1041
if (options.has_comment())
910
destination.append("\nCOMMENT = '", 12);
911
destination.append(options.comment());
912
destination.push_back('\'');
1043
destination.append(" COMMENT=", 9);
1044
append_escaped_string(&destination, options.comment());
915
1047
if (options.has_collation())
917
destination.append("\nCOLLATE = ", 11);
1049
destination.append(" COLLATE = ", 11);
918
1050
destination.append(options.collation());
921
if (options.has_auto_increment())
923
ss << options.auto_increment();
924
destination.append("\nAUTOINCREMENT_OFFSET = ", 24);
925
destination.append(ss.str());
929
if (options.has_row_type())
931
ss << options.row_type();
932
destination.append("\nROW_TYPE = ", 12);
933
destination.append(ss.str());
937
1053
if (options.has_data_file_name())
939
1055
destination.append("\nDATA_FILE_NAME = '", 19);
983
if (options.has_key_block_size())
985
ss << options.key_block_size();
986
destination.append("\nKEY_BLOCK_SIZE = ", 18);
987
destination.append(ss.str());
991
if (options.has_block_size())
993
ss << options.block_size();
994
destination.append("\nBLOCK_SIZE = ", 14);
995
destination.append(ss.str());
999
if (options.has_pack_keys() &&
1000
options.pack_keys())
1001
destination.append("\nPACK_KEYS = TRUE", 17);
1002
if (options.has_pack_record() &&
1003
options.pack_record())
1004
destination.append("\nPACK_RECORD = TRUE", 19);
1005
1100
if (options.has_checksum() &&
1006
1101
options.checksum())
1007
1102
destination.append("\nCHECKSUM = TRUE", 16);
1022
1117
if (sql_variant == ANSI)
1023
1118
quoted_identifier= '"';
1120
destination.append(" ", 2);
1025
1122
if (index.is_primary())
1026
1123
destination.append("PRIMARY ", 8);
1027
1124
else if (index.is_unique())
1028
1125
destination.append("UNIQUE ", 7);
1030
1127
destination.append("KEY ", 4);
1031
destination.push_back(quoted_identifier);
1032
destination.append(index.name());
1033
destination.push_back(quoted_identifier);
1034
destination.append(" (", 2);
1128
if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1130
destination.push_back(quoted_identifier);
1131
destination.append(index.name());
1132
destination.push_back(quoted_identifier);
1133
destination.append(" (", 2);
1136
destination.append("(", 1);
1036
1138
size_t num_parts= index.index_part_size();
1037
1139
for (size_t x= 0; x < num_parts; ++x)
1057
1159
if (part.has_compare_length())
1059
size_t compare_length_in_chars= part.compare_length();
1061
/* hack: compare_length() is bytes, not chars, but
1062
* only for VARCHAR. Ass. */
1063
if (field.type() == Table::Field::VARCHAR)
1064
compare_length_in_chars/= 4;
1066
if (compare_length_in_chars != field.string_options().length())
1161
if (part.compare_length() != field.string_options().length())
1068
1163
stringstream ss;
1069
1164
destination.push_back('(');
1070
ss << compare_length_in_chars;
1165
ss << part.compare_length();
1071
1166
destination.append(ss.str());
1072
1167
destination.push_back(')');
1077
1172
destination.push_back(')');
1174
switch (index.type())
1176
case Table::Index::UNKNOWN_INDEX:
1178
case Table::Index::BTREE:
1179
destination.append(" USING BTREE", 12);
1181
case Table::Index::RTREE:
1182
destination.append(" USING RTREE", 12);
1184
case Table::Index::HASH:
1185
destination.append(" USING HASH", 11);
1187
case Table::Index::FULLTEXT:
1188
destination.append(" USING FULLTEXT", 15);
1192
if (index.has_comment())
1194
destination.append(" COMMENT ", 9);
1195
append_escaped_string(&destination, index.comment());
1201
static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt, string &destination)
1205
case Table::ForeignKeyConstraint::OPTION_UNDEF:
1207
case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1208
destination.append("RESTRICT");
1210
case Table::ForeignKeyConstraint::OPTION_CASCADE:
1211
destination.append("CASCADE");
1213
case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1214
destination.append("SET NULL");
1216
case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1217
destination.append("NO ACTION");
1219
case Table::ForeignKeyConstraint::OPTION_DEFAULT:
1220
destination.append("SET DEFAULT");
1225
enum TransformSqlError
1226
transformForeignKeyConstraintDefinitionToSql(const Table::ForeignKeyConstraint &fkey,
1228
string &destination,
1229
enum TransformSqlVariant sql_variant)
1231
char quoted_identifier= '`';
1232
if (sql_variant == ANSI)
1233
quoted_identifier= '"';
1235
destination.append(" ", 2);
1237
if (fkey.has_name())
1239
destination.append("CONSTRAINT ", 11);
1240
append_escaped_string(&destination, fkey.name(), quoted_identifier);
1241
destination.append(" ", 1);
1244
destination.append("FOREIGN KEY (", 13);
1246
for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1249
destination.append(", ");
1251
append_escaped_string(&destination, fkey.column_names(x),
1255
destination.append(") REFERENCES ", 13);
1257
append_escaped_string(&destination, fkey.references_table_name(),
1259
destination.append(" (", 2);
1261
for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1264
destination.append(", ");
1266
append_escaped_string(&destination, fkey.references_columns(x),
1270
destination.push_back(')');
1272
if (fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1274
destination.append(" ON UPDATE ", 11);
1275
transformForeignKeyOptionToSql(fkey.update_option(), destination);
1278
if (fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1280
destination.append(" ON DELETE ", 11);
1281
transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1085
1290
enum TransformSqlVariant sql_variant)
1087
1292
char quoted_identifier= '`';
1293
char quoted_default;
1088
1295
if (sql_variant == ANSI)
1089
1296
quoted_identifier= '"';
1091
destination.push_back(quoted_identifier);
1092
destination.append(field.name());
1093
destination.push_back(quoted_identifier);
1298
if (sql_variant == DRIZZLE)
1299
quoted_default= '\'';
1301
quoted_default= quoted_identifier;
1303
append_escaped_string(&destination, field.name(), quoted_identifier);
1095
1305
Table::Field::FieldType field_type= field.type();
1099
1309
case Table::Field::DOUBLE:
1100
1310
destination.append(" DOUBLE", 7);
1311
if (field.has_numeric_options()
1312
&& field.numeric_options().has_precision())
1315
ss << "(" << field.numeric_options().precision() << ",";
1316
ss << field.numeric_options().scale() << ")";
1317
destination.append(ss.str());
1102
1320
case Table::Field::VARCHAR:
1104
destination.append(" VARCHAR(", 9);
1322
if (field.string_options().has_collation()
1323
&& field.string_options().collation().compare("binary") == 0)
1324
destination.append(" VARBINARY(", 11);
1326
destination.append(" VARCHAR(", 9);
1105
1328
stringstream ss;
1106
1329
ss << field.string_options().length() << ")";
1107
1330
destination.append(ss.str());
1110
1333
case Table::Field::BLOB:
1111
destination.append(" BLOB", 5);
1335
if (field.string_options().has_collation()
1336
&& field.string_options().collation().compare("binary") == 0)
1337
destination.append(" BLOB", 5);
1339
destination.append(" TEXT", 5);
1113
1342
case Table::Field::ENUM:
1115
size_t num_field_values= field.set_options().field_value_size();
1344
size_t num_field_values= field.enumeration_values().field_value_size();
1116
1345
destination.append(" ENUM(", 6);
1117
1346
for (size_t x= 0; x < num_field_values; ++x)
1119
const string &type= field.set_options().field_value(x);
1348
const string &type= field.enumeration_values().field_value(x);
1122
1351
destination.push_back(',');
1397
if (field.type() == Table::Field::BLOB ||
1398
field.type() == Table::Field::VARCHAR)
1400
if (field.string_options().has_collation()
1401
&& field.string_options().collation().compare("binary"))
1403
destination.append(" COLLATE ", 9);
1404
destination.append(field.string_options().collation());
1169
if (! (field.has_constraints() &&
1170
field.constraints().is_nullable()))
1408
if (field.has_constraints() &&
1409
! field.constraints().is_nullable())
1172
destination.append(" NOT", 4);
1411
destination.append(" NOT NULL", 9);
1174
destination.append(" NULL", 5);
1413
else if (field.type() == Table::Field::TIMESTAMP)
1414
destination.append(" NULL", 5);
1176
1416
if (field.type() == Table::Field::INTEGER ||
1177
1417
field.type() == Table::Field::BIGINT)
1187
if (field.type() == Table::Field::BLOB ||
1188
field.type() == Table::Field::VARCHAR)
1190
if (field.string_options().has_collation())
1192
destination.append(" COLLATE ", 9);
1193
destination.append(field.string_options().collation());
1197
1427
if (field.options().has_default_value())
1199
1429
destination.append(" DEFAULT ", 9);
1200
destination.push_back(quoted_identifier);
1201
destination.append(field.options().default_value());
1202
destination.push_back(quoted_identifier);
1205
if (field.options().has_default_bin_value())
1430
append_escaped_string(&destination, field.options().default_value());
1432
else if (field.options().has_default_expression())
1434
destination.append(" DEFAULT ", 9);
1435
destination.append(field.options().default_expression());
1437
else if (field.options().has_default_bin_value())
1207
1439
const string &v= field.options().default_bin_value();
1208
destination.append(" DEFAULT 0x", 11);
1209
for (size_t x= 0; x < v.length(); x++)
1440
if (v.length() == 0)
1441
destination.append(" DEFAULT ''", 11);
1211
printf("%.2x", *(v.c_str() + x));
1444
destination.append(" DEFAULT 0x", 11);
1445
for (size_t x= 0; x < v.length(); x++)
1448
snprintf(hex, sizeof(hex), "%.2X", *(v.c_str() + x));
1449
destination.append(hex, 2);
1453
else if (field.options().has_default_null()
1454
&& field.options().default_null()
1455
&& field.type() != Table::Field::BLOB)
1457
destination.append(" DEFAULT NULL", 13);
1215
if (field.type() == Table::Field::TIMESTAMP)
1216
if (field.timestamp_options().has_auto_updates() &&
1217
field.timestamp_options().auto_updates())
1218
destination.append(" ON UPDATE CURRENT_TIMESTAMP", 28);
1460
if (field.has_options() && field.options().has_update_expression())
1462
destination.append(" ON UPDATE ", 11);
1463
destination.append(field.options().update_expression());
1220
1466
if (field.has_comment())
1222
1468
destination.append(" COMMENT ", 9);
1223
destination.push_back(quoted_identifier);
1224
destination.append(field.comment());
1225
destination.push_back(quoted_identifier);
1469
append_escaped_string(&destination, field.comment(), quoted_default);
1274
1517
return Table::Field::INTEGER; /* unreachable */
1520
bool transactionContainsBulkSegment(const Transaction &transaction)
1522
size_t num_statements= transaction.statement_size();
1523
if (num_statements == 0)
1527
* Only INSERT, UPDATE, and DELETE statements can possibly
1528
* have bulk segments. So, we loop through the statements
1529
* checking for segment_id > 1 in those specific submessages.
1532
for (x= 0; x < num_statements; ++x)
1534
const Statement &statement= transaction.statement(x);
1535
Statement::Type type= statement.type();
1539
case Statement::INSERT:
1540
if (statement.insert_data().segment_id() > 1)
1543
case Statement::UPDATE:
1544
if (statement.update_data().segment_id() > 1)
1547
case Statement::DELETE:
1548
if (statement.delete_data().segment_id() > 1)
1277
1558
} /* namespace message */
1278
1559
} /* namespace drizzled */