29
29
* Statement messages to other formats, including SQL strings.
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
#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"
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();
156
157
if (num_keys > 1 && ! already_in_transaction)
157
158
sql_strings.push_back("START TRANSACTION");
159
for (size_t x= 0; x < num_keys; ++x)
160
for (x= 0; x < num_keys; ++x)
161
162
string destination;
874
875
const Schema &schema= statement.schema();
876
destination.append("CREATE SCHEMA ");
877
destination.append("CREATE SCHEMA ", 14);
877
878
destination.push_back(quoted_identifier);
878
879
destination.append(schema.name());
879
880
destination.push_back(quoted_identifier);
881
882
if (schema.has_collation())
883
destination.append(" COLLATE ");
884
destination.append(" COLLATE ", 9);
884
885
destination.append(schema.collation());
887
if (schema.has_replication_options() and schema.replication_options().has_dont_replicate() and schema.replication_options().dont_replicate())
889
destination.append(" REPLICATION = FALSE");
904
900
const TableMetadata &table_metadata= statement.table_metadata();
906
destination.append("DROP TABLE ");
902
destination.append("DROP TABLE ", 11);
908
904
/* Add the IF EXISTS clause if necessary */
909
905
if (statement.has_if_exists_clause() &&
910
906
statement.if_exists_clause() == true)
912
destination.append("IF EXISTS ");
908
destination.append("IF EXISTS ", 10);
915
911
destination.push_back(quoted_identifier);
955
951
const FieldMetadata &variable_metadata= statement.variable_metadata();
956
952
bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
958
destination.append("SET GLOBAL "); /* Only global variables are replicated */
954
destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
959
955
destination.append(variable_metadata.name());
960
956
destination.push_back('=');
987
983
if (sql_variant == ANSI)
988
984
quoted_identifier= '"';
990
destination.append("CREATE ");
986
destination.append("CREATE ", 7);
992
988
if (table.type() == Table::TEMPORARY)
993
destination.append("TEMPORARY ");
989
destination.append("TEMPORARY ", 10);
995
destination.append("TABLE ");
991
destination.append("TABLE ", 6);
998
994
append_escaped_string(&destination, table.schema(), quoted_identifier);
999
995
destination.push_back('.');
1001
997
append_escaped_string(&destination, table.name(), quoted_identifier);
1002
destination.append(" (\n");
998
destination.append(" (\n", 3);
1004
1000
enum TransformSqlError result= NONE;
1005
1001
size_t num_fields= table.field_size();
1021
1017
size_t num_indexes= table.indexes_size();
1023
1019
if (num_indexes > 0)
1024
destination.append(",\n");
1020
destination.append(",\n", 2);
1026
1022
for (size_t x= 0; x < num_indexes; ++x)
1028
1024
const message::Table::Index &index= table.indexes(x);
1031
destination.append(",\n");
1027
destination.append(",\n", 2);
1033
1029
result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
1039
1035
size_t num_foreign_keys= table.fk_constraint_size();
1041
1037
if (num_foreign_keys > 0)
1042
destination.append(",\n");
1038
destination.append(",\n", 2);
1044
1040
for (size_t x= 0; x < num_foreign_keys; ++x)
1046
1042
const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1049
destination.append(",\n");
1045
destination.append(",\n", 2);
1051
1047
result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1057
destination.append("\n)");
1053
destination.append("\n)", 2);
1059
1055
/* Add ENGINE = " clause */
1060
1056
if (table.has_engine())
1062
destination.append(" ENGINE=");
1058
destination.append(" ENGINE=", 8);
1063
1059
destination.append(table.engine().name());
1065
1061
size_t num_engine_options= table.engine().options_size();
1070
1066
const Engine::Option &option= table.engine().options(x);
1071
1067
destination.append(option.name());
1072
destination.append("='");
1068
destination.append("='", 2);
1073
1069
destination.append(option.state());
1074
destination.append("'");
1075
if (x != num_engine_options-1)
1077
destination.append(", ");
1070
destination.append("'", 1);
1071
if(x != num_engine_options-1)
1072
destination.append(", ", 2);
1096
1090
if (options.has_comment())
1098
destination.append(" COMMENT=");
1092
destination.append(" COMMENT=", 9);
1099
1093
append_escaped_string(&destination, options.comment());
1102
1096
if (options.has_collation())
1104
destination.append(" COLLATE = ");
1098
destination.append(" COLLATE = ", 11);
1105
1099
destination.append(options.collation());
1108
1102
if (options.has_data_file_name())
1110
destination.append("\nDATA_FILE_NAME = '");
1104
destination.append("\nDATA_FILE_NAME = '", 19);
1111
1105
destination.append(options.data_file_name());
1112
1106
destination.push_back('\'');
1115
1109
if (options.has_index_file_name())
1117
destination.append("\nINDEX_FILE_NAME = '");
1111
destination.append("\nINDEX_FILE_NAME = '", 20);
1118
1112
destination.append(options.index_file_name());
1119
1113
destination.push_back('\'');
1122
1116
if (options.has_max_rows())
1124
destination.append("\nMAX_ROWS = ");
1118
destination.append("\nMAX_ROWS = ", 12);
1125
1119
destination.append(boost::lexical_cast<string>(options.max_rows()));
1128
1122
if (options.has_min_rows())
1130
destination.append("\nMIN_ROWS = ");
1124
destination.append("\nMIN_ROWS = ", 12);
1131
1125
destination.append(boost::lexical_cast<string>(options.min_rows()));
1134
1128
if (options.has_user_set_auto_increment_value()
1135
1129
&& options.has_auto_increment_value())
1137
destination.append(" AUTO_INCREMENT=");
1131
destination.append(" AUTO_INCREMENT=", 16);
1138
1132
destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
1141
1135
if (options.has_avg_row_length())
1143
destination.append("\nAVG_ROW_LENGTH = ");
1137
destination.append("\nAVG_ROW_LENGTH = ", 18);
1144
1138
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");
1141
if (options.has_checksum() &&
1143
destination.append("\nCHECKSUM = TRUE", 16);
1144
if (options.has_page_checksum() &&
1145
options.page_checksum())
1146
destination.append("\nPAGE_CHECKSUM = TRUE", 21);
1171
1161
destination.append(" ", 2);
1173
1163
if (index.is_primary())
1174
destination.append("PRIMARY ");
1164
destination.append("PRIMARY ", 8);
1175
1165
else if (index.is_unique())
1176
destination.append("UNIQUE ");
1166
destination.append("UNIQUE ", 7);
1178
1168
destination.append("KEY ", 4);
1179
1169
if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1225
1215
case Table::Index::UNKNOWN_INDEX:
1227
1217
case Table::Index::BTREE:
1228
destination.append(" USING BTREE");
1218
destination.append(" USING BTREE", 12);
1230
1220
case Table::Index::RTREE:
1231
destination.append(" USING RTREE");
1221
destination.append(" USING RTREE", 12);
1233
1223
case Table::Index::HASH:
1234
destination.append(" USING HASH");
1224
destination.append(" USING HASH", 11);
1236
1226
case Table::Index::FULLTEXT:
1237
destination.append(" USING FULLTEXT");
1227
destination.append(" USING FULLTEXT", 15);
1241
1231
if (index.has_comment())
1243
destination.append(" COMMENT ");
1233
destination.append(" COMMENT ", 9);
1244
1234
append_escaped_string(&destination, index.comment());
1280
1270
if (sql_variant == ANSI)
1281
1271
quoted_identifier= '"';
1283
destination.append(" ");
1273
destination.append(" ", 2);
1285
1275
if (fkey.has_name())
1287
destination.append("CONSTRAINT ");
1277
destination.append("CONSTRAINT ", 11);
1288
1278
append_escaped_string(&destination, fkey.name(), quoted_identifier);
1289
1279
destination.append(" ", 1);
1292
destination.append("FOREIGN KEY (");
1282
destination.append("FOREIGN KEY (", 13);
1294
1284
for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1300
1290
quoted_identifier);
1303
destination.append(") REFERENCES ");
1293
destination.append(") REFERENCES ", 13);
1305
1295
append_escaped_string(&destination, fkey.references_table_name(),
1306
1296
quoted_identifier);
1307
destination.append(" (");
1297
destination.append(" (", 2);
1309
1299
for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1320
1310
if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1322
destination.append(" ON UPDATE ");
1312
destination.append(" ON UPDATE ", 11);
1323
1313
transformForeignKeyOptionToSql(fkey.update_option(), destination);
1326
1316
if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1328
destination.append(" ON DELETE ");
1318
destination.append(" ON DELETE ", 11);
1329
1319
transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1370
1360
if (field.string_options().has_collation()
1371
1361
&& field.string_options().collation().compare("binary") == 0)
1372
destination.append(" VARBINARY(");
1362
destination.append(" VARBINARY(", 11);
1374
destination.append(" VARCHAR(");
1364
destination.append(" VARCHAR(", 9);
1376
1366
destination.append(boost::lexical_cast<string>(field.string_options().length()));
1377
1367
destination.append(")");
1382
1372
if (field.string_options().has_collation()
1383
1373
&& field.string_options().collation().compare("binary") == 0)
1384
destination.append(" BLOB");
1374
destination.append(" BLOB", 5);
1386
destination.append(" TEXT");
1376
destination.append(" TEXT", 5);
1389
1379
case Table::Field::ENUM:
1391
1381
size_t num_field_values= field.enumeration_values().field_value_size();
1392
destination.append(" ENUM(");
1382
destination.append(" ENUM(", 6);
1393
1383
for (size_t x= 0; x < num_field_values; ++x)
1395
1385
const string &type= field.enumeration_values().field_value(x);
1407
1397
case Table::Field::UUID:
1408
destination.append(" UUID");
1398
destination.append(" UUID", 5);
1410
1400
case Table::Field::BOOLEAN:
1411
destination.append(" BOOLEAN");
1401
destination.append(" BOOLEAN", 8);
1413
1403
case Table::Field::INTEGER:
1414
destination.append(" INT");
1404
destination.append(" INT", 4);
1416
1406
case Table::Field::BIGINT:
1417
if (field.has_constraints() and
1418
field.constraints().is_unsigned())
1420
destination.append(" BIGINT UNSIGNED");
1424
destination.append(" BIGINT");
1407
destination.append(" BIGINT", 7);
1427
1409
case Table::Field::DECIMAL:
1429
destination.append(" DECIMAL(");
1411
destination.append(" DECIMAL(", 9);
1430
1412
stringstream ss;
1431
1413
ss << field.numeric_options().precision() << ",";
1432
1414
ss << field.numeric_options().scale() << ")";
1447
destination.append(" TIMESTAMP");
1429
destination.append(" TIMESTAMP", 10);
1451
1433
case Table::Field::DATETIME:
1452
destination.append(" DATETIME");
1434
destination.append(" DATETIME", 9);
1454
1436
case Table::Field::TIME:
1455
destination.append(" TIME");
1437
destination.append(" TIME", 5);
1441
if (field.type() == Table::Field::INTEGER ||
1442
field.type() == Table::Field::BIGINT)
1444
if (field.has_constraints() &&
1445
field.constraints().has_is_unsigned() &&
1446
field.constraints().is_unsigned())
1448
destination.append(" UNSIGNED", 9);
1459
1452
if (field.type() == Table::Field::BLOB ||
1460
1453
field.type() == Table::Field::VARCHAR)
1462
1455
if (field.string_options().has_collation()
1463
1456
&& field.string_options().collation().compare("binary"))
1465
destination.append(" COLLATE ");
1458
destination.append(" COLLATE ", 9);
1466
1459
destination.append(field.string_options().collation());
1470
if (field.has_constraints() and field.constraints().is_unique())
1472
destination.append(" UNIQUE");
1475
1463
if (field.has_constraints() && field.constraints().is_notnull())
1477
destination.append(" NOT NULL");
1465
destination.append(" NOT NULL", 9);
1479
1467
else if (field.type() == Table::Field::EPOCH)
1481
destination.append(" NULL");
1469
destination.append(" NULL", 5);
1484
1472
if (field.type() == Table::Field::INTEGER ||
1488
1476
if (field.has_numeric_options() &&
1489
1477
field.numeric_options().is_autoincrement())
1491
destination.append(" AUTO_INCREMENT");
1479
destination.append(" AUTO_INCREMENT", 15);
1495
1483
if (field.options().has_default_value())
1497
destination.append(" DEFAULT ");
1485
destination.append(" DEFAULT ", 9);
1498
1486
append_escaped_string(&destination, field.options().default_value());
1500
1488
else if (field.options().has_default_expression())
1502
destination.append(" DEFAULT ");
1490
destination.append(" DEFAULT ", 9);
1503
1491
destination.append(field.options().default_expression());
1505
1493
else if (field.options().has_default_bin_value())
1507
1495
const string &v= field.options().default_bin_value();
1508
1496
if (v.length() == 0)
1510
destination.append(" DEFAULT ''");
1497
destination.append(" DEFAULT ''", 11);
1514
destination.append(" DEFAULT 0x");
1500
destination.append(" DEFAULT 0x", 11);
1515
1501
for (size_t x= 0; x < v.length(); x++)
1524
1510
&& field.options().default_null()
1525
1511
&& field.type() != Table::Field::BLOB)
1527
destination.append(" DEFAULT NULL");
1513
destination.append(" DEFAULT NULL", 13);
1530
1516
if (field.has_options() && field.options().has_update_expression())
1532
destination.append(" ON UPDATE ");
1518
destination.append(" ON UPDATE ", 11);
1533
1519
destination.append(field.options().update_expression());
1536
1522
if (field.has_comment())
1538
destination.append(" COMMENT ");
1524
destination.append(" COMMENT ", 9);
1539
1525
append_escaped_string(&destination, field.comment(), quoted_default);