34 #include <boost/lexical_cast.hpp>
36 #include <drizzled/charset.h>
37 #include <drizzled/message.h>
39 #include <drizzled/message/transaction.pb.h>
40 #include <drizzled/message/access.h>
55 static void escapeEmbeddedQuotes(
string &s,
const char quote=
'\'')
59 for (it= s.begin(); it != s.end(); ++it)
63 it= s.insert(it, quote);
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);
103 res->push_back(
'\\');
104 res->push_back(
'\\');
109 res->push_back(quote);
110 res->push_back(quote);
113 res->push_back(*pos);
117 res->push_back(quote);
120 enum TransformSqlError
121 transformStatementToSql(
const Statement &source,
122 vector<string> &sql_strings,
123 enum TransformSqlVariant sql_variant,
124 bool already_in_transaction)
126 TransformSqlError error= NONE;
128 switch (source.type())
130 case Statement::ROLLBACK_STATEMENT:
134 case Statement::ROLLBACK:
136 sql_strings.push_back(
"ROLLBACK");
139 case Statement::INSERT:
141 if (! source.has_insert_header())
143 error= MISSING_HEADER;
146 if (! source.has_insert_data())
152 const InsertHeader &insert_header= source.insert_header();
153 const InsertData &insert_data= source.insert_data();
154 size_t num_keys= insert_data.record_size();
156 if (num_keys > 1 && ! already_in_transaction)
157 sql_strings.push_back(
"START TRANSACTION");
159 for (
size_t x= 0; x < num_keys; ++x)
163 error= transformInsertRecordToSql(insert_header,
164 insert_data.record(x),
170 sql_strings.push_back(destination);
173 if (num_keys > 1 && ! already_in_transaction)
176 sql_strings.push_back(
"COMMIT");
178 sql_strings.push_back(
"ROLLBACK");
182 case Statement::UPDATE:
184 if (! source.has_update_header())
186 error= MISSING_HEADER;
189 if (! source.has_update_data())
195 const UpdateHeader &update_header= source.update_header();
196 const UpdateData &update_data= source.update_data();
197 size_t num_keys= update_data.record_size();
200 if (num_keys > 1 && ! already_in_transaction)
201 sql_strings.push_back(
"START TRANSACTION");
203 for (x= 0; x < num_keys; ++x)
207 error= transformUpdateRecordToSql(update_header,
208 update_data.record(x),
214 sql_strings.push_back(destination);
217 if (num_keys > 1 && ! already_in_transaction)
220 sql_strings.push_back(
"COMMIT");
222 sql_strings.push_back(
"ROLLBACK");
226 case Statement::DELETE:
228 if (! source.has_delete_header())
230 error= MISSING_HEADER;
233 if (! source.has_delete_data())
239 const DeleteHeader &delete_header= source.delete_header();
240 const DeleteData &delete_data= source.delete_data();
241 size_t num_keys= delete_data.record_size();
244 if (num_keys > 1 && ! already_in_transaction)
245 sql_strings.push_back(
"START TRANSACTION");
247 for (x= 0; x < num_keys; ++x)
251 error= transformDeleteRecordToSql(delete_header,
252 delete_data.record(x),
258 sql_strings.push_back(destination);
261 if (num_keys > 1 && ! already_in_transaction)
264 sql_strings.push_back(
"COMMIT");
266 sql_strings.push_back(
"ROLLBACK");
270 case Statement::CREATE_TABLE:
272 assert(source.has_create_table_statement());
274 error= transformCreateTableStatementToSql(source.create_table_statement(),
277 sql_strings.push_back(destination);
280 case Statement::TRUNCATE_TABLE:
282 assert(source.has_truncate_table_statement());
284 error= transformTruncateTableStatementToSql(source.truncate_table_statement(),
287 sql_strings.push_back(destination);
290 case Statement::DROP_TABLE:
292 assert(source.has_drop_table_statement());
294 error= transformDropTableStatementToSql(source.drop_table_statement(),
297 sql_strings.push_back(destination);
300 case Statement::CREATE_SCHEMA:
302 assert(source.has_create_schema_statement());
304 error= transformCreateSchemaStatementToSql(source.create_schema_statement(),
307 sql_strings.push_back(destination);
310 case Statement::DROP_SCHEMA:
312 assert(source.has_drop_schema_statement());
314 error= transformDropSchemaStatementToSql(source.drop_schema_statement(),
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);
330 case Statement::SET_VARIABLE:
332 assert(source.has_set_variable_statement());
334 error= transformSetVariableStatementToSql(source.set_variable_statement(),
337 sql_strings.push_back(destination);
340 case Statement::RAW_SQL:
342 if (source.has_raw_sql_schema())
344 string destination(
"USE ");
345 destination.append(source.raw_sql_schema());
346 sql_strings.push_back(destination);
348 sql_strings.push_back(source.sql());
352 sql_strings.push_back(source.sql());
358 enum TransformSqlError
359 transformInsertHeaderToSql(
const InsertHeader &header,
361 enum TransformSqlVariant sql_variant)
363 char quoted_identifier=
'`';
364 if (sql_variant == ANSI)
365 quoted_identifier=
'"';
367 destination.assign(
"INSERT INTO ", 12);
368 destination.push_back(quoted_identifier);
369 destination.append(header.table_metadata().schema_name());
370 destination.push_back(quoted_identifier);
371 destination.push_back(
'.');
372 destination.push_back(quoted_identifier);
373 destination.append(header.table_metadata().table_name());
374 destination.push_back(quoted_identifier);
375 destination.append(
" (", 2);
378 size_t num_fields= header.field_metadata_size();
381 for (x= 0; x < num_fields; ++x)
383 const FieldMetadata &field_metadata= header.field_metadata(x);
385 destination.push_back(
',');
387 destination.push_back(quoted_identifier);
388 destination.append(field_metadata.name());
389 destination.push_back(quoted_identifier);
395 enum TransformSqlError
396 transformInsertRecordToSql(
const InsertHeader &header,
397 const InsertRecord &record,
399 enum TransformSqlVariant sql_variant)
401 enum TransformSqlError error= transformInsertHeaderToSql(header,
405 destination.append(
") VALUES (");
408 size_t num_fields= header.field_metadata_size();
410 bool should_quote_field_value=
false;
412 for (x= 0; x < num_fields; ++x)
415 destination.push_back(
',');
417 const FieldMetadata &field_metadata= header.field_metadata(x);
419 if (record.is_null(x))
421 should_quote_field_value=
false;
425 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
428 if (should_quote_field_value)
429 destination.push_back(
'\'');
431 if (record.is_null(x))
433 destination.append(
"NULL");
437 if (field_metadata.type() == Table::Field::BLOB)
445 string raw_data(record.insert_value(x));
446 destination.append(raw_data.c_str(), raw_data.size());
450 string tmp(record.insert_value(x));
451 escapeEmbeddedQuotes(tmp);
452 destination.append(tmp);
456 if (should_quote_field_value)
457 destination.push_back(
'\'');
459 destination.push_back(
')');
464 enum TransformSqlError
465 transformInsertStatementToSql(
const InsertHeader &header,
466 const InsertData &data,
468 enum TransformSqlVariant sql_variant)
470 enum TransformSqlError error= transformInsertHeaderToSql(header,
474 destination.append(
") VALUES (", 10);
477 size_t num_records= data.record_size();
478 size_t num_fields= header.field_metadata_size();
480 bool should_quote_field_value=
false;
482 for (x= 0; x < num_records; ++x)
485 destination.append(
"),(", 3);
487 for (y= 0; y < num_fields; ++y)
490 destination.push_back(
',');
492 const FieldMetadata &field_metadata= header.field_metadata(y);
494 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
496 if (should_quote_field_value)
497 destination.push_back(
'\'');
499 if (field_metadata.type() == Table::Field::BLOB)
507 string raw_data(data.record(x).insert_value(y));
508 destination.append(raw_data.c_str(), raw_data.size());
512 string tmp(data.record(x).insert_value(y));
513 escapeEmbeddedQuotes(tmp);
514 destination.append(tmp);
517 if (should_quote_field_value)
518 destination.push_back(
'\'');
521 destination.push_back(
')');
526 enum TransformSqlError
527 transformUpdateHeaderToSql(
const UpdateHeader &header,
529 enum TransformSqlVariant sql_variant)
531 char quoted_identifier=
'`';
532 if (sql_variant == ANSI)
533 quoted_identifier=
'"';
535 destination.assign(
"UPDATE ", 7);
536 destination.push_back(quoted_identifier);
537 destination.append(header.table_metadata().schema_name());
538 destination.push_back(quoted_identifier);
539 destination.push_back(
'.');
540 destination.push_back(quoted_identifier);
541 destination.append(header.table_metadata().table_name());
542 destination.push_back(quoted_identifier);
543 destination.append(
" SET ", 5);
548 enum TransformSqlError
549 transformUpdateRecordToSql(
const UpdateHeader &header,
550 const UpdateRecord &record,
552 enum TransformSqlVariant sql_variant)
554 enum TransformSqlError error= transformUpdateHeaderToSql(header,
558 char quoted_identifier=
'`';
559 if (sql_variant == ANSI)
560 quoted_identifier=
'"';
563 size_t num_set_fields= header.set_field_metadata_size();
565 bool should_quote_field_value=
false;
567 for (x= 0; x < num_set_fields; ++x)
569 const FieldMetadata &field_metadata= header.set_field_metadata(x);
571 destination.push_back(
',');
573 destination.push_back(quoted_identifier);
574 destination.append(field_metadata.name());
575 destination.push_back(quoted_identifier);
576 destination.push_back(
'=');
578 if (record.is_null(x))
580 should_quote_field_value=
false;
584 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
587 if (should_quote_field_value)
588 destination.push_back(
'\'');
590 if (record.is_null(x))
592 destination.append(
"NULL");
596 if (field_metadata.type() == Table::Field::BLOB)
604 string raw_data(record.after_value(x));
605 destination.append(raw_data.c_str(), raw_data.size());
609 string tmp(record.after_value(x));
610 escapeEmbeddedQuotes(tmp);
611 destination.append(tmp);
615 if (should_quote_field_value)
616 destination.push_back(
'\'');
619 size_t num_key_fields= header.key_field_metadata_size();
621 destination.append(
" WHERE ", 7);
622 for (x= 0; x < num_key_fields; ++x)
624 const FieldMetadata &field_metadata= header.key_field_metadata(x);
627 destination.append(
" AND ", 5);
629 destination.push_back(quoted_identifier);
630 destination.append(field_metadata.name());
631 destination.push_back(quoted_identifier);
633 destination.push_back(
'=');
635 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
637 if (should_quote_field_value)
638 destination.push_back(
'\'');
640 if (field_metadata.type() == Table::Field::BLOB)
648 string raw_data(record.key_value(x));
649 destination.append(raw_data.c_str(), raw_data.size());
653 destination.append(record.key_value(x));
656 if (should_quote_field_value)
657 destination.push_back(
'\'');
663 enum TransformSqlError
664 transformDeleteHeaderToSql(
const DeleteHeader &header,
666 enum TransformSqlVariant sql_variant)
668 char quoted_identifier=
'`';
669 if (sql_variant == ANSI)
670 quoted_identifier=
'"';
672 destination.assign(
"DELETE FROM ", 12);
673 destination.push_back(quoted_identifier);
674 destination.append(header.table_metadata().schema_name());
675 destination.push_back(quoted_identifier);
676 destination.push_back(
'.');
677 destination.push_back(quoted_identifier);
678 destination.append(header.table_metadata().table_name());
679 destination.push_back(quoted_identifier);
684 enum TransformSqlError
685 transformDeleteRecordToSql(
const DeleteHeader &header,
686 const DeleteRecord &record,
688 enum TransformSqlVariant sql_variant)
690 enum TransformSqlError error= transformDeleteHeaderToSql(header,
693 char quoted_identifier=
'`';
694 if (sql_variant == ANSI)
695 quoted_identifier=
'"';
698 uint32_t num_key_fields= header.key_field_metadata_size();
700 bool should_quote_field_value=
false;
702 destination.append(
" WHERE ", 7);
703 for (x= 0; x < num_key_fields; ++x)
705 const FieldMetadata &field_metadata= header.key_field_metadata(x);
708 destination.append(
" AND ", 5);
710 destination.push_back(quoted_identifier);
711 destination.append(field_metadata.name());
712 destination.push_back(quoted_identifier);
714 destination.push_back(
'=');
716 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
718 if (should_quote_field_value)
719 destination.push_back(
'\'');
721 if (field_metadata.type() == Table::Field::BLOB)
729 string raw_data(record.key_value(x));
730 destination.append(raw_data.c_str(), raw_data.size());
734 string tmp(record.key_value(x));
735 escapeEmbeddedQuotes(tmp);
736 destination.append(tmp);
739 if (should_quote_field_value)
740 destination.push_back(
'\'');
746 enum TransformSqlError
747 transformDeleteStatementToSql(
const DeleteHeader &header,
748 const DeleteData &data,
750 enum TransformSqlVariant sql_variant)
752 enum TransformSqlError error= transformDeleteHeaderToSql(header,
755 char quoted_identifier=
'`';
756 if (sql_variant == ANSI)
757 quoted_identifier=
'"';
760 uint32_t num_key_fields= header.key_field_metadata_size();
761 uint32_t num_key_records= data.record_size();
763 bool should_quote_field_value=
false;
765 destination.append(
" WHERE ", 7);
766 for (x= 0; x < num_key_records; ++x)
769 destination.append(
" OR ", 4);
771 if (num_key_fields > 1)
772 destination.push_back(
'(');
774 for (y= 0; y < num_key_fields; ++y)
776 const FieldMetadata &field_metadata= header.key_field_metadata(y);
779 destination.append(
" AND ", 5);
781 destination.push_back(quoted_identifier);
782 destination.append(field_metadata.name());
783 destination.push_back(quoted_identifier);
785 destination.push_back(
'=');
787 should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
789 if (should_quote_field_value)
790 destination.push_back(
'\'');
792 if (field_metadata.type() == Table::Field::BLOB)
800 string raw_data(data.record(x).key_value(y));
801 destination.append(raw_data.c_str(), raw_data.size());
805 string tmp(data.record(x).key_value(y));
806 escapeEmbeddedQuotes(tmp);
807 destination.append(tmp);
810 if (should_quote_field_value)
811 destination.push_back(
'\'');
813 if (num_key_fields > 1)
814 destination.push_back(
')');
819 enum TransformSqlError
820 transformAlterSchemaStatementToSql(
const AlterSchemaStatement &statement,
822 enum TransformSqlVariant sql_variant)
824 const Schema &before= statement.before();
825 const Schema &after= statement.after();
828 if (before.uuid() != after.uuid())
829 return UUID_MISMATCH;
831 char quoted_identifier=
'`';
832 if (sql_variant == ANSI)
833 quoted_identifier=
'"';
835 destination.append(
"ALTER SCHEMA ");
836 destination.push_back(quoted_identifier);
837 destination.append(before.name());
838 destination.push_back(quoted_identifier);
844 destination.append(
" COLLATE = ");
845 destination.append(after.collation());
850 enum TransformSqlError
851 transformDropSchemaStatementToSql(
const DropSchemaStatement &statement,
853 enum TransformSqlVariant sql_variant)
855 char quoted_identifier=
'`';
856 if (sql_variant == ANSI)
857 quoted_identifier=
'"';
859 destination.append(
"DROP SCHEMA ", 12);
860 destination.push_back(quoted_identifier);
861 destination.append(statement.schema_name());
862 destination.push_back(quoted_identifier);
867 enum TransformSqlError
868 transformCreateSchemaStatementToSql(
const CreateSchemaStatement &statement,
870 enum TransformSqlVariant sql_variant)
872 char quoted_identifier=
'`';
873 if (sql_variant == ANSI)
874 quoted_identifier=
'"';
876 const Schema &schema= statement.schema();
878 destination.append(
"CREATE SCHEMA ");
879 destination.push_back(quoted_identifier);
880 destination.append(schema.name());
881 destination.push_back(quoted_identifier);
883 if (schema.has_collation())
885 destination.append(
" COLLATE ");
886 destination.append(schema.collation());
889 if (not message::is_replicated(schema))
891 destination.append(
" REPLICATE = FALSE");
894 if (message::has_definer(schema))
896 destination.append(
" DEFINER ");
897 destination.push_back(
'\'');
898 destination.append(message::definer(schema));
899 destination.push_back(
'\'');
905 enum TransformSqlError
906 transformDropTableStatementToSql(
const DropTableStatement &statement,
908 enum TransformSqlVariant sql_variant)
910 char quoted_identifier=
'`';
911 if (sql_variant == ANSI)
912 quoted_identifier=
'"';
914 const TableMetadata &table_metadata= statement.table_metadata();
916 destination.append(
"DROP TABLE ");
919 if (statement.has_if_exists_clause() &&
920 statement.if_exists_clause() ==
true)
922 destination.append(
"IF EXISTS ");
925 destination.push_back(quoted_identifier);
926 destination.append(table_metadata.schema_name());
927 destination.push_back(quoted_identifier);
928 destination.push_back(
'.');
929 destination.push_back(quoted_identifier);
930 destination.append(table_metadata.table_name());
931 destination.push_back(quoted_identifier);
936 enum TransformSqlError
937 transformTruncateTableStatementToSql(
const TruncateTableStatement &statement,
939 enum TransformSqlVariant sql_variant)
941 char quoted_identifier=
'`';
942 if (sql_variant == ANSI)
943 quoted_identifier=
'"';
945 const TableMetadata &table_metadata= statement.table_metadata();
947 destination.append(
"TRUNCATE TABLE ");
948 destination.push_back(quoted_identifier);
949 destination.append(table_metadata.schema_name());
950 destination.push_back(quoted_identifier);
951 destination.push_back(
'.');
952 destination.push_back(quoted_identifier);
953 destination.append(table_metadata.table_name());
954 destination.push_back(quoted_identifier);
959 enum TransformSqlError
960 transformSetVariableStatementToSql(
const SetVariableStatement &statement,
962 enum TransformSqlVariant sql_variant)
965 const FieldMetadata &variable_metadata= statement.variable_metadata();
966 bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
968 destination.append(
"SET GLOBAL ");
969 destination.append(variable_metadata.name());
970 destination.push_back(
'=');
972 if (should_quote_field_value)
973 destination.push_back(
'\'');
975 destination.append(statement.variable_value());
977 if (should_quote_field_value)
978 destination.push_back(
'\'');
983 enum TransformSqlError
984 transformCreateTableStatementToSql(
const CreateTableStatement &statement,
986 enum TransformSqlVariant sql_variant)
988 return transformTableDefinitionToSql(statement.table(), destination, sql_variant);
991 enum TransformSqlError
992 transformTableDefinitionToSql(
const Table &table,
994 enum TransformSqlVariant sql_variant,
bool with_schema)
996 char quoted_identifier=
'`';
997 if (sql_variant == ANSI)
998 quoted_identifier=
'"';
1000 destination.append(
"CREATE ");
1002 if (table.type() == Table::TEMPORARY)
1003 destination.append(
"TEMPORARY ");
1005 destination.append(
"TABLE ");
1008 append_escaped_string(&destination, table.schema(), quoted_identifier);
1009 destination.push_back(
'.');
1011 append_escaped_string(&destination, table.name(), quoted_identifier);
1012 destination.append(
" (\n");
1014 enum TransformSqlError result= NONE;
1015 size_t num_fields= table.field_size();
1016 for (
size_t x= 0; x < num_fields; ++x)
1018 const Table::Field &field= table.field(x);
1021 destination.append(
",\n");
1023 destination.append(
" ");
1025 result= transformFieldDefinitionToSql(field, destination, sql_variant);
1031 size_t num_indexes= table.indexes_size();
1033 if (num_indexes > 0)
1034 destination.append(
",\n");
1036 for (
size_t x= 0; x < num_indexes; ++x)
1038 const message::Table::Index &index= table.
indexes(x);
1041 destination.append(
",\n");
1043 result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
1049 size_t num_foreign_keys= table.fk_constraint_size();
1051 if (num_foreign_keys > 0)
1052 destination.append(
",\n");
1054 for (
size_t x= 0; x < num_foreign_keys; ++x)
1056 const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1059 destination.append(
",\n");
1061 result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1067 destination.append(
"\n)");
1070 if (table.has_engine())
1072 destination.append(
" ENGINE=");
1073 destination.append(table.engine().name());
1075 size_t num_engine_options= table.engine().options_size();
1076 if (num_engine_options > 0)
1077 destination.append(
" ", 1);
1078 for (
size_t x= 0; x < num_engine_options; ++x)
1080 const Engine::Option &option= table.engine().options(x);
1081 destination.append(option.name());
1082 destination.append(
"='");
1083 destination.append(option.state());
1084 destination.append(
"'");
1085 if (x != num_engine_options-1)
1087 destination.append(
", ");
1092 if (table.has_options())
1093 (
void) transformTableOptionsToSql(table.options(), destination, sql_variant);
1095 if (not message::is_replicated(table))
1097 destination.append(
" REPLICATE = FALSE");
1100 if (message::has_definer(table))
1102 destination.append(
" DEFINER ");
1103 destination.push_back(
'\'');
1104 destination.append(message::definer(table));
1105 destination.push_back(
'\'');
1111 enum TransformSqlError
1112 transformTableOptionsToSql(
const Table::TableOptions &options,
1113 string &destination,
1114 enum TransformSqlVariant sql_variant)
1116 if (sql_variant == ANSI)
1119 if (options.has_comment())
1121 destination.append(
" COMMENT=");
1122 append_escaped_string(&destination, options.comment());
1125 if (options.has_collation())
1127 destination.append(
" COLLATE = ");
1128 destination.append(options.collation());
1131 if (options.has_data_file_name())
1133 destination.append(
"\nDATA_FILE_NAME = '");
1134 destination.append(options.data_file_name());
1135 destination.push_back(
'\'');
1138 if (options.has_index_file_name())
1140 destination.append(
"\nINDEX_FILE_NAME = '");
1141 destination.append(options.index_file_name());
1142 destination.push_back(
'\'');
1145 if (options.has_max_rows())
1147 destination.append(
"\nMAX_ROWS = ");
1148 destination.append(boost::lexical_cast<string>(options.max_rows()));
1151 if (options.has_min_rows())
1153 destination.append(
"\nMIN_ROWS = ");
1154 destination.append(boost::lexical_cast<string>(options.min_rows()));
1157 if (options.has_user_set_auto_increment_value()
1158 && options.has_auto_increment_value())
1160 destination.append(
" AUTO_INCREMENT=");
1161 destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
1164 if (options.has_avg_row_length())
1166 destination.append(
"\nAVG_ROW_LENGTH = ");
1167 destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1170 if (options.has_checksum() && options.checksum())
1171 destination.append(
"\nCHECKSUM = TRUE");
1173 if (options.has_page_checksum() && options.page_checksum())
1174 destination.append(
"\nPAGE_CHECKSUM = TRUE");
1179 enum TransformSqlError
1180 transformIndexDefinitionToSql(
const Table::Index &index,
1182 string &destination,
1183 enum TransformSqlVariant sql_variant)
1185 char quoted_identifier=
'`';
1186 if (sql_variant == ANSI)
1187 quoted_identifier=
'"';
1189 destination.append(
" ", 2);
1191 if (index.is_primary())
1192 destination.append(
"PRIMARY ");
1193 else if (index.is_unique())
1194 destination.append(
"UNIQUE ");
1196 destination.append(
"KEY ", 4);
1197 if (! (index.is_primary() && index.name().compare(
"PRIMARY")==0))
1199 destination.push_back(quoted_identifier);
1200 destination.append(index.name());
1201 destination.push_back(quoted_identifier);
1202 destination.append(
" (", 2);
1205 destination.append(
"(", 1);
1207 size_t num_parts= index.index_part_size();
1208 for (
size_t x= 0; x < num_parts; ++x)
1210 const Table::Index::IndexPart &part= index.index_part(x);
1211 const Table::Field &field= table.field(part.fieldnr());
1214 destination.push_back(
',');
1216 destination.push_back(quoted_identifier);
1217 destination.append(field.name());
1218 destination.push_back(quoted_identifier);
1225 if (field.type() == Table::Field::VARCHAR ||
1226 field.type() == Table::Field::BLOB)
1228 if (part.has_compare_length())
1230 if (part.compare_length() != field.string_options().length())
1232 destination.push_back(
'(');
1233 destination.append(boost::lexical_cast<string>(part.compare_length()));
1234 destination.push_back(
')');
1239 destination.push_back(
')');
1241 switch (index.type())
1243 case Table::Index::UNKNOWN_INDEX:
1245 case Table::Index::BTREE:
1246 destination.append(
" USING BTREE");
1248 case Table::Index::RTREE:
1249 destination.append(
" USING RTREE");
1251 case Table::Index::HASH:
1252 destination.append(
" USING HASH");
1254 case Table::Index::FULLTEXT:
1255 destination.append(
" USING FULLTEXT");
1259 if (index.has_comment())
1261 destination.append(
" COMMENT ");
1262 append_escaped_string(&destination, index.comment());
1268 static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt,
string &destination)
1272 case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1273 destination.append(
"RESTRICT");
1275 case Table::ForeignKeyConstraint::OPTION_CASCADE:
1276 destination.append(
"CASCADE");
1278 case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1279 destination.append(
"SET NULL");
1281 case Table::ForeignKeyConstraint::OPTION_UNDEF:
1282 case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1283 destination.append(
"NO ACTION");
1285 case Table::ForeignKeyConstraint::OPTION_SET_DEFAULT:
1286 destination.append(
"SET DEFAULT");
1291 enum TransformSqlError
1292 transformForeignKeyConstraintDefinitionToSql(
const Table::ForeignKeyConstraint &fkey,
1294 string &destination,
1295 enum TransformSqlVariant sql_variant)
1297 char quoted_identifier=
'`';
1298 if (sql_variant == ANSI)
1299 quoted_identifier=
'"';
1301 destination.append(
" ");
1303 if (fkey.has_name())
1305 destination.append(
"CONSTRAINT ");
1306 append_escaped_string(&destination, fkey.name(), quoted_identifier);
1307 destination.append(
" ", 1);
1310 destination.append(
"FOREIGN KEY (");
1312 for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1315 destination.append(
", ");
1317 append_escaped_string(&destination, fkey.column_names(x),
1321 destination.append(
") REFERENCES ");
1323 append_escaped_string(&destination, fkey.references_table_name(),
1325 destination.append(
" (");
1327 for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1330 destination.append(
", ");
1332 append_escaped_string(&destination, fkey.references_columns(x),
1336 destination.push_back(
')');
1338 if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1340 destination.append(
" ON UPDATE ");
1341 transformForeignKeyOptionToSql(fkey.update_option(), destination);
1344 if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1346 destination.append(
" ON DELETE ");
1347 transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1353 enum TransformSqlError
1354 transformFieldDefinitionToSql(
const Table::Field &field,
1355 string &destination,
1356 enum TransformSqlVariant sql_variant)
1358 char quoted_identifier=
'`';
1359 char quoted_default;
1361 if (sql_variant == ANSI)
1362 quoted_identifier=
'"';
1364 if (sql_variant == DRIZZLE)
1365 quoted_default=
'\'';
1367 quoted_default= quoted_identifier;
1369 append_escaped_string(&destination, field.name(), quoted_identifier);
1371 Table::Field::FieldType field_type= field.type();
1375 case Table::Field::DOUBLE:
1376 destination.append(
" DOUBLE");
1377 if (field.has_numeric_options()
1378 && field.numeric_options().has_precision())
1381 ss <<
"(" << field.numeric_options().precision() <<
",";
1382 ss << field.numeric_options().scale() <<
")";
1383 destination.append(ss.str());
1386 case Table::Field::VARCHAR:
1388 if (field.string_options().has_collation()
1389 && field.string_options().collation().compare(
"binary") == 0)
1390 destination.append(
" VARBINARY(");
1392 destination.append(
" VARCHAR(");
1394 destination.append(boost::lexical_cast<string>(field.string_options().length()));
1395 destination.append(
")");
1398 case Table::Field::BLOB:
1400 if (field.string_options().has_collation()
1401 && field.string_options().collation().compare(
"binary") == 0)
1402 destination.append(
" BLOB");
1404 destination.append(
" TEXT");
1407 case Table::Field::ENUM:
1409 size_t num_field_values= field.enumeration_values().field_value_size();
1410 destination.append(
" ENUM(");
1411 for (
size_t x= 0; x < num_field_values; ++x)
1413 const string &type= field.enumeration_values().field_value(x);
1416 destination.push_back(
',');
1418 destination.push_back(
'\'');
1419 destination.append(type);
1420 destination.push_back(
'\'');
1422 destination.push_back(
')');
1425 case Table::Field::UUID:
1426 destination.append(
" UUID");
1428 case Table::Field::IPV6:
1429 destination.append(
" IPV6");
1431 case Table::Field::BOOLEAN:
1432 destination.append(
" BOOLEAN");
1434 case Table::Field::INTEGER:
1435 destination.append(
" INT");
1437 case Table::Field::BIGINT:
1438 if (field.has_constraints() and
1439 field.constraints().is_unsigned())
1441 destination.append(
" BIGINT UNSIGNED");
1445 destination.append(
" BIGINT");
1448 case Table::Field::DECIMAL:
1450 destination.append(
" DECIMAL(");
1452 ss << field.numeric_options().precision() <<
",";
1453 ss << field.numeric_options().scale() <<
")";
1454 destination.append(ss.str());
1457 case Table::Field::DATE:
1458 destination.append(
" DATE");
1461 case Table::Field::EPOCH:
1462 if (field.time_options().microseconds())
1464 destination.append(
" TIMESTAMP(6)");
1468 destination.append(
" TIMESTAMP");
1472 case Table::Field::DATETIME:
1473 destination.append(
" DATETIME");
1475 case Table::Field::TIME:
1476 destination.append(
" TIME");
1480 if (field.type() == Table::Field::BLOB ||
1481 field.type() == Table::Field::VARCHAR)
1483 if (field.string_options().has_collation()
1484 && field.string_options().collation().compare(
"binary"))
1486 destination.append(
" COLLATE ");
1487 destination.append(field.string_options().collation());
1491 if (field.has_constraints() and field.constraints().is_unique())
1493 destination.append(
" UNIQUE");
1496 if (field.has_constraints() && field.constraints().is_notnull())
1498 destination.append(
" NOT NULL");
1500 else if (field.type() == Table::Field::EPOCH)
1502 destination.append(
" NULL");
1505 if (field.type() == Table::Field::INTEGER ||
1506 field.type() == Table::Field::BIGINT)
1509 if (field.has_numeric_options() &&
1510 field.numeric_options().is_autoincrement())
1512 destination.append(
" AUTO_INCREMENT");
1516 if (field.options().has_default_value())
1518 destination.append(
" DEFAULT ");
1519 append_escaped_string(&destination, field.options().default_value());
1521 else if (field.options().has_default_expression())
1523 destination.append(
" DEFAULT ");
1524 destination.append(field.options().default_expression());
1526 else if (field.options().has_default_bin_value())
1528 const string &v= field.options().default_bin_value();
1529 if (v.length() == 0)
1531 destination.append(
" DEFAULT ''");
1535 destination.append(
" DEFAULT 0x");
1536 for (
size_t x= 0; x < v.length(); x++)
1539 snprintf(hex,
sizeof(hex),
"%.2X", *(v.c_str() + x));
1540 destination.append(hex, 2);
1544 else if (field.options().has_default_null()
1545 && field.options().default_null()
1546 && field.type() != Table::Field::BLOB)
1548 destination.append(
" DEFAULT NULL");
1551 if (field.has_options() && field.options().has_update_expression())
1553 destination.append(
" ON UPDATE ");
1554 destination.append(field.options().update_expression());
1557 if (field.has_comment())
1559 destination.append(
" COMMENT ");
1560 append_escaped_string(&destination, field.comment(), quoted_default);
1565 bool shouldQuoteFieldValue(Table::Field::FieldType in_type)
1569 case Table::Field::DOUBLE:
1570 case Table::Field::DECIMAL:
1571 case Table::Field::INTEGER:
1572 case Table::Field::BIGINT:
1579 Table::Field::FieldType internalFieldTypeToFieldProtoType(
enum enum_field_types type)
1582 case DRIZZLE_TYPE_LONG:
1583 return Table::Field::INTEGER;
1584 case DRIZZLE_TYPE_DOUBLE:
1585 return Table::Field::DOUBLE;
1586 case DRIZZLE_TYPE_NULL:
1588 return Table::Field::INTEGER;
1589 case DRIZZLE_TYPE_MICROTIME:
1590 case DRIZZLE_TYPE_TIMESTAMP:
1591 return Table::Field::EPOCH;
1592 case DRIZZLE_TYPE_LONGLONG:
1593 return Table::Field::BIGINT;
1594 case DRIZZLE_TYPE_DATETIME:
1595 return Table::Field::DATETIME;
1596 case DRIZZLE_TYPE_TIME:
1597 return Table::Field::TIME;
1598 case DRIZZLE_TYPE_DATE:
1599 return Table::Field::DATE;
1600 case DRIZZLE_TYPE_VARCHAR:
1601 return Table::Field::VARCHAR;
1602 case DRIZZLE_TYPE_DECIMAL:
1603 return Table::Field::DECIMAL;
1604 case DRIZZLE_TYPE_ENUM:
1605 return Table::Field::ENUM;
1606 case DRIZZLE_TYPE_BLOB:
1607 return Table::Field::BLOB;
1608 case DRIZZLE_TYPE_UUID:
1609 return Table::Field::UUID;
1610 case DRIZZLE_TYPE_BOOLEAN:
1611 return Table::Field::BOOLEAN;
1612 case DRIZZLE_TYPE_IPV6:
1613 return Table::Field::IPV6;
1617 return Table::Field::INTEGER;
1620 bool transactionContainsBulkSegment(
const Transaction &transaction)
1622 size_t num_statements= transaction.statement_size();
1623 if (num_statements == 0)
1632 for (x= 0; x < num_statements; ++x)
1634 const Statement &statement= transaction.statement(x);
1635 Statement::Type type= statement.type();
1639 case Statement::INSERT:
1640 if (statement.insert_data().segment_id() > 1)
1643 case Statement::UPDATE:
1644 if (statement.update_data().segment_id() > 1)
1647 case Statement::DELETE:
1648 if (statement.delete_data().segment_id() > 1)