1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2009 Sun Microsystems
8
* Jay Pipes <joinfu@sun.com>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; version 2 of the License.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
* Implementation of various routines that can be used to convert
28
* Statement messages to other formats, including SQL strings.
31
#include "drizzled/global.h"
33
#include "drizzled/message/statement_transform.h"
34
#include "drizzled/message/transaction.pb.h"
35
#include "drizzled/message/table.pb.h"
41
using namespace drizzled;
43
enum message::TransformSqlError
44
message::transformStatementToSql(const message::Statement &source,
45
vector<string> &sql_strings,
46
enum message::TransformSqlVariant sql_variant)
48
message::TransformSqlError error= NONE;
50
switch (source.type())
52
case message::Statement::INSERT:
54
if (! source.has_insert_header())
56
error= MISSING_HEADER;
59
if (! source.has_insert_data())
65
const message::InsertHeader &insert_header= source.insert_header();
66
const message::InsertData &insert_data= source.insert_data();
67
size_t num_keys= insert_data.record_size();
71
sql_strings.push_back("START TRANSACTION");
73
for (x= 0; x < num_keys; ++x)
77
error= transformInsertRecordToSql(insert_header,
78
insert_data.record(x),
84
sql_strings.push_back(destination);
90
sql_strings.push_back("COMMIT");
92
sql_strings.push_back("ROLLBACK");
96
case message::Statement::UPDATE:
98
if (! source.has_update_header())
100
error= MISSING_HEADER;
103
if (! source.has_update_data())
109
const message::UpdateHeader &update_header= source.update_header();
110
const message::UpdateData &update_data= source.update_data();
111
size_t num_keys= update_data.record_size();
115
sql_strings.push_back("START TRANSACTION");
117
for (x= 0; x < num_keys; ++x)
121
error= transformUpdateRecordToSql(update_header,
122
update_data.record(x),
128
sql_strings.push_back(destination);
134
sql_strings.push_back("COMMIT");
136
sql_strings.push_back("ROLLBACK");
140
case message::Statement::DELETE:
142
if (! source.has_delete_header())
144
error= MISSING_HEADER;
147
if (! source.has_delete_data())
153
const message::DeleteHeader &delete_header= source.delete_header();
154
const message::DeleteData &delete_data= source.delete_data();
155
size_t num_keys= delete_data.record_size();
159
sql_strings.push_back("START TRANSACTION");
161
for (x= 0; x < num_keys; ++x)
165
error= transformDeleteRecordToSql(delete_header,
166
delete_data.record(x),
172
sql_strings.push_back(destination);
178
sql_strings.push_back("COMMIT");
180
sql_strings.push_back("ROLLBACK");
184
case message::Statement::SET_VARIABLE:
186
assert(source.has_set_variable_statement());
188
error= message::transformSetVariableStatementToSql(source.set_variable_statement(),
191
sql_strings.push_back(destination);
194
case message::Statement::RAW_SQL:
196
sql_strings.push_back(source.sql());
202
enum message::TransformSqlError
203
message::transformInsertHeaderToSql(const message::InsertHeader &header,
204
std::string *destination,
205
enum message::TransformSqlVariant sql_variant)
207
char quoted_identifier= '`';
208
if (sql_variant == ANSI)
209
quoted_identifier= '"';
211
destination->assign("INSERT INTO ");
212
destination->push_back(quoted_identifier);
213
destination->append(header.table_metadata().schema_name());
214
destination->push_back(quoted_identifier);
215
destination->push_back('.');
216
destination->push_back(quoted_identifier);
217
destination->append(header.table_metadata().table_name());
218
destination->push_back(quoted_identifier);
219
destination->append(" (");
221
/* Add field list to SQL string... */
222
size_t num_fields= header.field_metadata_size();
225
for (x= 0; x < num_fields; ++x)
227
const message::FieldMetadata &field_metadata= header.field_metadata(x);
229
destination->push_back(',');
231
destination->push_back(quoted_identifier);
232
destination->append(field_metadata.name());
233
destination->push_back(quoted_identifier);
239
enum message::TransformSqlError
240
message::transformInsertRecordToSql(const message::InsertHeader &header,
241
const message::InsertRecord &record,
242
std::string *destination,
243
enum message::TransformSqlVariant sql_variant)
245
enum message::TransformSqlError error= transformInsertHeaderToSql(header,
249
char quoted_identifier= '`';
250
if (sql_variant == ANSI)
251
quoted_identifier= '"';
253
destination->append(") VALUES (");
255
/* Add insert values */
256
size_t num_fields= header.field_metadata_size();
258
bool should_quote_field_value= false;
260
for (x= 0; x < num_fields; ++x)
263
destination->push_back(',');
265
should_quote_field_value= message::shouldQuoteFieldValue(header.field_metadata(x).type());
267
if (should_quote_field_value)
268
destination->push_back('\'');
270
destination->append(record.insert_value(x));
272
if (should_quote_field_value)
273
destination->push_back('\'');
275
destination->push_back(')');
280
enum message::TransformSqlError
281
message::transformInsertStatementToSql(const message::InsertHeader &header,
282
const message::InsertData &data,
283
std::string *destination,
284
enum message::TransformSqlVariant sql_variant)
286
enum message::TransformSqlError error= transformInsertHeaderToSql(header,
290
char quoted_identifier= '`';
291
if (sql_variant == ANSI)
292
quoted_identifier= '"';
294
destination->append(") VALUES (");
296
/* Add insert values */
297
size_t num_records= data.record_size();
298
size_t num_fields= header.field_metadata_size();
300
bool should_quote_field_value= false;
302
for (x= 0; x < num_records; ++x)
305
destination->append("),(");
307
for (y= 0; y < num_fields; ++y)
310
destination->push_back(',');
312
should_quote_field_value= message::shouldQuoteFieldValue(header.field_metadata(y).type());
314
if (should_quote_field_value)
315
destination->push_back('\'');
317
destination->append(data.record(x).insert_value(y));
319
if (should_quote_field_value)
320
destination->push_back('\'');
323
destination->push_back(')');
328
enum message::TransformSqlError
329
message::transformUpdateHeaderToSql(const message::UpdateHeader &header,
330
std::string *destination,
331
enum message::TransformSqlVariant sql_variant)
333
char quoted_identifier= '`';
334
if (sql_variant == ANSI)
335
quoted_identifier= '"';
337
destination->assign("UPDATE ");
338
destination->push_back(quoted_identifier);
339
destination->append(header.table_metadata().schema_name());
340
destination->push_back(quoted_identifier);
341
destination->push_back('.');
342
destination->push_back(quoted_identifier);
343
destination->append(header.table_metadata().table_name());
344
destination->push_back(quoted_identifier);
345
destination->append(" SET ");
347
/* Add field SET list to SQL string... */
348
size_t num_set_fields= header.set_field_metadata_size();
350
bool should_quote_field_value= false;
352
for (x= 0; x < num_set_fields; ++x)
354
const message::FieldMetadata &field_metadata= header.set_field_metadata(x);
356
destination->push_back(',');
358
destination->push_back(quoted_identifier);
359
destination->append(field_metadata.name());
360
destination->push_back(quoted_identifier);
361
destination->push_back('=');
363
should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
365
if (should_quote_field_value)
366
destination->push_back('\'');
368
destination->append(header.set_value(x));
370
if (should_quote_field_value)
371
destination->push_back('\'');
377
enum message::TransformSqlError
378
message::transformUpdateRecordToSql(const message::UpdateHeader &header,
379
const message::UpdateRecord &record,
380
std::string *destination,
381
enum message::TransformSqlVariant sql_variant)
383
enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
387
char quoted_identifier= '`';
388
if (sql_variant == ANSI)
389
quoted_identifier= '"';
391
size_t num_key_fields= header.key_field_metadata_size();
393
bool should_quote_field_value= false;
395
destination->append(" WHERE ");
396
for (x= 0; x < num_key_fields; ++x)
398
const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
401
destination->append(" AND "); /* Always AND condition with a multi-column PK */
403
destination->push_back(quoted_identifier);
404
destination->append(field_metadata.name());
405
destination->push_back(quoted_identifier);
407
destination->push_back('=');
409
should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
411
if (should_quote_field_value)
412
destination->push_back('\'');
414
destination->append(record.key_value(x));
416
if (should_quote_field_value)
417
destination->push_back('\'');
419
if (num_key_fields > 1)
420
destination->push_back(')');
425
enum message::TransformSqlError
426
message::transformUpdateStatementToSql(const message::UpdateHeader &header,
427
const message::UpdateData &data,
428
std::string *destination,
429
enum message::TransformSqlVariant sql_variant)
431
enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
435
char quoted_identifier= '`';
436
if (sql_variant == ANSI)
437
quoted_identifier= '"';
439
/* Add WHERE clause to SQL string... */
440
size_t num_key_fields= header.key_field_metadata_size();
441
size_t num_key_records= data.record_size();
443
bool should_quote_field_value= false;
445
destination->append(" WHERE ");
446
for (x= 0; x < num_key_records; ++x)
449
destination->append(" OR "); /* Always OR condition for multiple key records */
451
if (num_key_fields > 1)
452
destination->push_back('(');
454
for (y= 0; y < num_key_fields; ++y)
456
const message::FieldMetadata &field_metadata= header.key_field_metadata(y);
459
destination->append(" AND "); /* Always AND condition with a multi-column PK */
461
destination->push_back(quoted_identifier);
462
destination->append(field_metadata.name());
463
destination->push_back(quoted_identifier);
465
destination->push_back('=');
467
should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
469
if (should_quote_field_value)
470
destination->push_back('\'');
472
destination->append(data.record(x).key_value(y));
474
if (should_quote_field_value)
475
destination->push_back('\'');
477
if (num_key_fields > 1)
478
destination->push_back(')');
483
enum message::TransformSqlError
484
message::transformDeleteHeaderToSql(const message::DeleteHeader &header,
485
std::string *destination,
486
enum message::TransformSqlVariant sql_variant)
488
char quoted_identifier= '`';
489
if (sql_variant == ANSI)
490
quoted_identifier= '"';
492
destination->assign("DELETE FROM ");
493
destination->push_back(quoted_identifier);
494
destination->append(header.table_metadata().schema_name());
495
destination->push_back(quoted_identifier);
496
destination->push_back('.');
497
destination->push_back(quoted_identifier);
498
destination->append(header.table_metadata().table_name());
499
destination->push_back(quoted_identifier);
504
enum message::TransformSqlError
505
message::transformDeleteRecordToSql(const message::DeleteHeader &header,
506
const message::DeleteRecord &record,
507
std::string *destination,
508
enum message::TransformSqlVariant sql_variant)
510
enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
513
char quoted_identifier= '`';
514
if (sql_variant == ANSI)
515
quoted_identifier= '"';
517
/* Add WHERE clause to SQL string... */
518
uint32_t num_key_fields= header.key_field_metadata_size();
520
bool should_quote_field_value= false;
522
destination->append(" WHERE ");
523
for (x= 0; x < num_key_fields; ++x)
525
const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
528
destination->append(" AND "); /* Always AND condition with a multi-column PK */
530
destination->push_back(quoted_identifier);
531
destination->append(field_metadata.name());
532
destination->push_back(quoted_identifier);
534
destination->push_back('=');
536
should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
538
if (should_quote_field_value)
539
destination->push_back('\'');
541
destination->append(record.key_value(x));
543
if (should_quote_field_value)
544
destination->push_back('\'');
546
if (num_key_fields > 1)
547
destination->push_back(')');
552
enum message::TransformSqlError
553
message::transformDeleteStatementToSql(const message::DeleteHeader &header,
554
const message::DeleteData &data,
555
std::string *destination,
556
enum message::TransformSqlVariant sql_variant)
558
enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
561
char quoted_identifier= '`';
562
if (sql_variant == ANSI)
563
quoted_identifier= '"';
565
/* Add WHERE clause to SQL string... */
566
uint32_t num_key_fields= header.key_field_metadata_size();
567
uint32_t num_key_records= data.record_size();
569
bool should_quote_field_value= false;
571
destination->append(" WHERE ");
572
for (x= 0; x < num_key_records; ++x)
575
destination->append(" OR "); /* Always OR condition for multiple key records */
577
if (num_key_fields > 1)
578
destination->push_back('(');
580
for (y= 0; y < num_key_fields; ++y)
582
const message::FieldMetadata &field_metadata= header.key_field_metadata(y);
585
destination->append(" AND "); /* Always AND condition with a multi-column PK */
587
destination->push_back(quoted_identifier);
588
destination->append(field_metadata.name());
589
destination->push_back(quoted_identifier);
591
destination->push_back('=');
593
should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
595
if (should_quote_field_value)
596
destination->push_back('\'');
598
destination->append(data.record(x).key_value(y));
600
if (should_quote_field_value)
601
destination->push_back('\'');
603
if (num_key_fields > 1)
604
destination->push_back(')');
609
enum message::TransformSqlError
610
message::transformSetVariableStatementToSql(const message::SetVariableStatement &statement,
611
std::string *destination,
612
enum message::TransformSqlVariant sql_variant)
615
const message::FieldMetadata &variable_metadata= statement.variable_metadata();
616
bool should_quote_field_value= message::shouldQuoteFieldValue(variable_metadata.type());
618
destination->append("SET GLOBAL "); /* Only global variables are replicated */
619
destination->append(variable_metadata.name());
620
destination->push_back('=');
622
if (should_quote_field_value)
623
destination->push_back('\'');
625
destination->append(statement.variable_value());
627
if (should_quote_field_value)
628
destination->push_back('\'');
633
bool message::shouldQuoteFieldValue(message::Table::Field::FieldType in_type)
637
case message::Table::Field::DOUBLE:
638
case message::Table::Field::DECIMAL:
639
case message::Table::Field::INTEGER:
640
case message::Table::Field::BIGINT:
641
case message::Table::Field::ENUM: