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>
148
152
const InsertHeader &insert_header= source.insert_header();
149
153
const InsertData &insert_data= source.insert_data();
150
154
size_t num_keys= insert_data.record_size();
153
156
if (num_keys > 1 && ! already_in_transaction)
154
157
sql_strings.push_back("START TRANSACTION");
156
for (x= 0; x < num_keys; ++x)
159
for (size_t x= 0; x < num_keys; ++x)
158
161
string destination;
314
317
sql_strings.push_back(destination);
320
case Statement::ALTER_SCHEMA:
322
assert(source.has_alter_schema_statement());
324
error= transformAlterSchemaStatementToSql(source.alter_schema_statement(),
327
sql_strings.push_back(destination);
317
330
case Statement::SET_VARIABLE:
319
332
assert(source.has_set_variable_statement());
804
817
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
805
849
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
806
850
string &destination,
807
851
enum TransformSqlVariant sql_variant)
830
874
const Schema &schema= statement.schema();
832
destination.append("CREATE SCHEMA ", 14);
876
destination.append("CREATE SCHEMA ");
833
877
destination.push_back(quoted_identifier);
834
878
destination.append(schema.name());
835
879
destination.push_back(quoted_identifier);
837
881
if (schema.has_collation())
839
destination.append(" COLLATE ", 9);
883
destination.append(" COLLATE ");
840
884
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");
855
904
const TableMetadata &table_metadata= statement.table_metadata();
857
destination.append("DROP TABLE ", 11);
906
destination.append("DROP TABLE ");
859
908
/* Add the IF EXISTS clause if necessary */
860
909
if (statement.has_if_exists_clause() &&
861
910
statement.if_exists_clause() == true)
863
destination.append("IF EXISTS ", 10);
912
destination.append("IF EXISTS ");
866
915
destination.push_back(quoted_identifier);
906
955
const FieldMetadata &variable_metadata= statement.variable_metadata();
907
956
bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
909
destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
958
destination.append("SET GLOBAL "); /* Only global variables are replicated */
910
959
destination.append(variable_metadata.name());
911
960
destination.push_back('=');
938
987
if (sql_variant == ANSI)
939
988
quoted_identifier= '"';
941
destination.append("CREATE ", 7);
990
destination.append("CREATE ");
943
992
if (table.type() == Table::TEMPORARY)
944
destination.append("TEMPORARY ", 10);
993
destination.append("TEMPORARY ");
946
destination.append("TABLE ", 6);
995
destination.append("TABLE ");
949
998
append_escaped_string(&destination, table.schema(), quoted_identifier);
950
999
destination.push_back('.');
952
1001
append_escaped_string(&destination, table.name(), quoted_identifier);
953
destination.append(" (\n", 3);
1002
destination.append(" (\n");
955
1004
enum TransformSqlError result= NONE;
956
1005
size_t num_fields= table.field_size();
972
1021
size_t num_indexes= table.indexes_size();
974
1023
if (num_indexes > 0)
975
destination.append(",\n", 2);
1024
destination.append(",\n");
977
1026
for (size_t x= 0; x < num_indexes; ++x)
979
1028
const message::Table::Index &index= table.indexes(x);
982
destination.append(",\n", 2);
1031
destination.append(",\n");
984
1033
result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
990
1039
size_t num_foreign_keys= table.fk_constraint_size();
992
1041
if (num_foreign_keys > 0)
993
destination.append(",\n", 2);
1042
destination.append(",\n");
995
1044
for (size_t x= 0; x < num_foreign_keys; ++x)
997
1046
const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1000
destination.append(",\n", 2);
1049
destination.append(",\n");
1002
1051
result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1008
destination.append("\n)", 2);
1057
destination.append("\n)");
1010
1059
/* Add ENGINE = " clause */
1011
1060
if (table.has_engine())
1013
destination.append(" ENGINE=", 8);
1062
destination.append(" ENGINE=");
1014
1063
destination.append(table.engine().name());
1016
1065
size_t num_engine_options= table.engine().options_size();
1021
1070
const Engine::Option &option= table.engine().options(x);
1022
1071
destination.append(option.name());
1023
destination.append("='", 2);
1072
destination.append("='");
1024
1073
destination.append(option.state());
1025
destination.append("'", 1);
1026
if(x != num_engine_options-1)
1027
destination.append(", ", 2);
1074
destination.append("'");
1075
if (x != num_engine_options-1)
1077
destination.append(", ");
1045
1096
if (options.has_comment())
1047
destination.append(" COMMENT=", 9);
1098
destination.append(" COMMENT=");
1048
1099
append_escaped_string(&destination, options.comment());
1051
1102
if (options.has_collation())
1053
destination.append(" COLLATE = ", 11);
1104
destination.append(" COLLATE = ");
1054
1105
destination.append(options.collation());
1057
1108
if (options.has_data_file_name())
1059
destination.append("\nDATA_FILE_NAME = '", 19);
1110
destination.append("\nDATA_FILE_NAME = '");
1060
1111
destination.append(options.data_file_name());
1061
1112
destination.push_back('\'');
1064
1115
if (options.has_index_file_name())
1066
destination.append("\nINDEX_FILE_NAME = '", 20);
1117
destination.append("\nINDEX_FILE_NAME = '");
1067
1118
destination.append(options.index_file_name());
1068
1119
destination.push_back('\'');
1071
1122
if (options.has_max_rows())
1073
destination.append("\nMAX_ROWS = ", 12);
1124
destination.append("\nMAX_ROWS = ");
1074
1125
destination.append(boost::lexical_cast<string>(options.max_rows()));
1077
1128
if (options.has_min_rows())
1079
destination.append("\nMIN_ROWS = ", 12);
1130
destination.append("\nMIN_ROWS = ");
1080
1131
destination.append(boost::lexical_cast<string>(options.min_rows()));
1083
1134
if (options.has_user_set_auto_increment_value()
1084
1135
&& options.has_auto_increment_value())
1086
destination.append(" AUTO_INCREMENT=", 16);
1137
destination.append(" AUTO_INCREMENT=");
1087
1138
destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
1090
1141
if (options.has_avg_row_length())
1092
destination.append("\nAVG_ROW_LENGTH = ", 18);
1143
destination.append("\nAVG_ROW_LENGTH = ");
1093
1144
destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1096
if (options.has_checksum() &&
1098
destination.append("\nCHECKSUM = TRUE", 16);
1099
if (options.has_page_checksum() &&
1100
options.page_checksum())
1101
destination.append("\nPAGE_CHECKSUM = TRUE", 21);
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");
1116
1171
destination.append(" ", 2);
1118
1173
if (index.is_primary())
1119
destination.append("PRIMARY ", 8);
1174
destination.append("PRIMARY ");
1120
1175
else if (index.is_unique())
1121
destination.append("UNIQUE ", 7);
1176
destination.append("UNIQUE ");
1123
1178
destination.append("KEY ", 4);
1124
1179
if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1170
1225
case Table::Index::UNKNOWN_INDEX:
1172
1227
case Table::Index::BTREE:
1173
destination.append(" USING BTREE", 12);
1228
destination.append(" USING BTREE");
1175
1230
case Table::Index::RTREE:
1176
destination.append(" USING RTREE", 12);
1231
destination.append(" USING RTREE");
1178
1233
case Table::Index::HASH:
1179
destination.append(" USING HASH", 11);
1234
destination.append(" USING HASH");
1181
1236
case Table::Index::FULLTEXT:
1182
destination.append(" USING FULLTEXT", 15);
1237
destination.append(" USING FULLTEXT");
1186
1241
if (index.has_comment())
1188
destination.append(" COMMENT ", 9);
1243
destination.append(" COMMENT ");
1189
1244
append_escaped_string(&destination, index.comment());
1207
1260
case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1208
1261
destination.append("SET NULL");
1263
case Table::ForeignKeyConstraint::OPTION_UNDEF:
1210
1264
case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1211
1265
destination.append("NO ACTION");
1213
case Table::ForeignKeyConstraint::OPTION_DEFAULT:
1267
case Table::ForeignKeyConstraint::OPTION_SET_DEFAULT:
1214
1268
destination.append("SET DEFAULT");
1226
1280
if (sql_variant == ANSI)
1227
1281
quoted_identifier= '"';
1229
destination.append(" ", 2);
1283
destination.append(" ");
1231
1285
if (fkey.has_name())
1233
destination.append("CONSTRAINT ", 11);
1287
destination.append("CONSTRAINT ");
1234
1288
append_escaped_string(&destination, fkey.name(), quoted_identifier);
1235
1289
destination.append(" ", 1);
1238
destination.append("FOREIGN KEY (", 13);
1292
destination.append("FOREIGN KEY (");
1240
1294
for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1246
1300
quoted_identifier);
1249
destination.append(") REFERENCES ", 13);
1303
destination.append(") REFERENCES ");
1251
1305
append_escaped_string(&destination, fkey.references_table_name(),
1252
1306
quoted_identifier);
1253
destination.append(" (", 2);
1307
destination.append(" (");
1255
1309
for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1264
1318
destination.push_back(')');
1266
if (fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1320
if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1268
destination.append(" ON UPDATE ", 11);
1322
destination.append(" ON UPDATE ");
1269
1323
transformForeignKeyOptionToSql(fkey.update_option(), destination);
1272
if (fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1326
if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1274
destination.append(" ON DELETE ", 11);
1328
destination.append(" ON DELETE ");
1275
1329
transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1316
1370
if (field.string_options().has_collation()
1317
1371
&& field.string_options().collation().compare("binary") == 0)
1318
destination.append(" VARBINARY(", 11);
1372
destination.append(" VARBINARY(");
1320
destination.append(" VARCHAR(", 9);
1374
destination.append(" VARCHAR(");
1322
1376
destination.append(boost::lexical_cast<string>(field.string_options().length()));
1323
1377
destination.append(")");
1328
1382
if (field.string_options().has_collation()
1329
1383
&& field.string_options().collation().compare("binary") == 0)
1330
destination.append(" BLOB", 5);
1384
destination.append(" BLOB");
1332
destination.append(" TEXT", 5);
1386
destination.append(" TEXT");
1335
1389
case Table::Field::ENUM:
1337
1391
size_t num_field_values= field.enumeration_values().field_value_size();
1338
destination.append(" ENUM(", 6);
1392
destination.append(" ENUM(");
1339
1393
for (size_t x= 0; x < num_field_values; ++x)
1341
1395
const string &type= field.enumeration_values().field_value(x);
1350
1404
destination.push_back(')');
1407
case Table::Field::UUID:
1408
destination.append(" UUID");
1410
case Table::Field::BOOLEAN:
1411
destination.append(" BOOLEAN");
1353
1413
case Table::Field::INTEGER:
1354
destination.append(" INT", 4);
1414
destination.append(" INT");
1356
1416
case Table::Field::BIGINT:
1357
destination.append(" BIGINT", 7);
1417
if (field.has_constraints() and
1418
field.constraints().is_unsigned())
1420
destination.append(" BIGINT UNSIGNED");
1424
destination.append(" BIGINT");
1359
1427
case Table::Field::DECIMAL:
1361
destination.append(" DECIMAL(", 9);
1429
destination.append(" DECIMAL(");
1362
1430
stringstream ss;
1363
1431
ss << field.numeric_options().precision() << ",";
1364
1432
ss << field.numeric_options().scale() << ")";
1368
1436
case Table::Field::DATE:
1369
destination.append(" DATE", 5);
1371
case Table::Field::TIMESTAMP:
1372
destination.append(" TIMESTAMP", 10);
1437
destination.append(" DATE");
1440
case Table::Field::EPOCH:
1441
if (field.time_options().microseconds())
1443
destination.append(" TIMESTAMP(6)");
1447
destination.append(" TIMESTAMP");
1374
1451
case Table::Field::DATETIME:
1375
destination.append(" DATETIME", 9);
1379
if (field.type() == Table::Field::INTEGER ||
1380
field.type() == Table::Field::BIGINT)
1382
if (field.has_constraints() &&
1383
field.constraints().has_is_unsigned() &&
1384
field.constraints().is_unsigned())
1386
destination.append(" UNSIGNED", 9);
1452
destination.append(" DATETIME");
1454
case Table::Field::TIME:
1455
destination.append(" TIME");
1390
1459
if (field.type() == Table::Field::BLOB ||
1393
1462
if (field.string_options().has_collation()
1394
1463
&& field.string_options().collation().compare("binary"))
1396
destination.append(" COLLATE ", 9);
1465
destination.append(" COLLATE ");
1397
1466
destination.append(field.string_options().collation());
1401
if (field.has_constraints() &&
1402
! field.constraints().is_nullable())
1404
destination.append(" NOT NULL", 9);
1406
else if (field.type() == Table::Field::TIMESTAMP)
1407
destination.append(" NULL", 5);
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");
1409
1484
if (field.type() == Table::Field::INTEGER ||
1410
1485
field.type() == Table::Field::BIGINT)
1413
1488
if (field.has_numeric_options() &&
1414
1489
field.numeric_options().is_autoincrement())
1416
destination.append(" AUTO_INCREMENT", 15);
1491
destination.append(" AUTO_INCREMENT");
1420
1495
if (field.options().has_default_value())
1422
destination.append(" DEFAULT ", 9);
1497
destination.append(" DEFAULT ");
1423
1498
append_escaped_string(&destination, field.options().default_value());
1425
1500
else if (field.options().has_default_expression())
1427
destination.append(" DEFAULT ", 9);
1502
destination.append(" DEFAULT ");
1428
1503
destination.append(field.options().default_expression());
1430
1505
else if (field.options().has_default_bin_value())
1432
1507
const string &v= field.options().default_bin_value();
1433
1508
if (v.length() == 0)
1434
destination.append(" DEFAULT ''", 11);
1510
destination.append(" DEFAULT ''");
1437
destination.append(" DEFAULT 0x", 11);
1514
destination.append(" DEFAULT 0x");
1438
1515
for (size_t x= 0; x < v.length(); x++)
1447
1524
&& field.options().default_null()
1448
1525
&& field.type() != Table::Field::BLOB)
1450
destination.append(" DEFAULT NULL", 13);
1527
destination.append(" DEFAULT NULL");
1453
1530
if (field.has_options() && field.options().has_update_expression())
1455
destination.append(" ON UPDATE ", 11);
1532
destination.append(" ON UPDATE ");
1456
1533
destination.append(field.options().update_expression());
1459
1536
if (field.has_comment())
1461
destination.append(" COMMENT ", 9);
1538
destination.append(" COMMENT ");
1462
1539
append_escaped_string(&destination, field.comment(), quoted_default);
1488
1565
case DRIZZLE_TYPE_NULL:
1489
1566
assert(false); /* Not a user definable type */
1490
1567
return Table::Field::INTEGER; /* unreachable */
1568
case DRIZZLE_TYPE_MICROTIME:
1491
1569
case DRIZZLE_TYPE_TIMESTAMP:
1492
return Table::Field::TIMESTAMP;
1570
return Table::Field::EPOCH;
1493
1571
case DRIZZLE_TYPE_LONGLONG:
1494
1572
return Table::Field::BIGINT;
1495
1573
case DRIZZLE_TYPE_DATETIME:
1496
1574
return Table::Field::DATETIME;
1575
case DRIZZLE_TYPE_TIME:
1576
return Table::Field::TIME;
1497
1577
case DRIZZLE_TYPE_DATE:
1498
1578
return Table::Field::DATE;
1499
1579
case DRIZZLE_TYPE_VARCHAR: