~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/statement_transform.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2009 Sun Microsystems
 
5
 *
 
6
 *  Authors:
 
7
 *
 
8
 *    Jay Pipes <joinfu@sun.com>
 
9
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
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
 
22
 */
 
23
 
 
24
/**
 
25
 * @file
 
26
 *
 
27
 * Implementation of various routines that can be used to convert
 
28
 * Statement messages to other formats, including SQL strings.
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
 
 
33
#include "drizzled/message/statement_transform.h"
 
34
#include "drizzled/message/transaction.pb.h"
 
35
#include "drizzled/message/table.pb.h"
 
36
 
 
37
#include <string>
 
38
#include <vector>
 
39
 
 
40
using namespace std;
 
41
using namespace drizzled;
 
42
 
 
43
enum message::TransformSqlError
 
44
message::transformStatementToSql(const message::Statement &source,
 
45
                                 vector<string> &sql_strings,
 
46
                                 enum message::TransformSqlVariant sql_variant,
 
47
                                 bool already_in_transaction)
 
48
{
 
49
  message::TransformSqlError error= NONE;
 
50
 
 
51
  switch (source.type())
 
52
  {
 
53
  case message::Statement::INSERT:
 
54
    {
 
55
      if (! source.has_insert_header())
 
56
      {
 
57
        error= MISSING_HEADER;
 
58
        return error;
 
59
      }
 
60
      if (! source.has_insert_data())
 
61
      {
 
62
        error= MISSING_DATA;
 
63
        return error;
 
64
      }
 
65
 
 
66
      const message::InsertHeader &insert_header= source.insert_header();
 
67
      const message::InsertData &insert_data= source.insert_data();
 
68
      size_t num_keys= insert_data.record_size();
 
69
      size_t x;
 
70
 
 
71
      if (num_keys > 1 && ! already_in_transaction)
 
72
        sql_strings.push_back("START TRANSACTION");
 
73
 
 
74
      for (x= 0; x < num_keys; ++x)
 
75
      {
 
76
        string destination;
 
77
 
 
78
        error= transformInsertRecordToSql(insert_header,
 
79
                                          insert_data.record(x),
 
80
                                          &destination,
 
81
                                          sql_variant);
 
82
        if (error != NONE)
 
83
          break;
 
84
 
 
85
        sql_strings.push_back(destination);
 
86
      }
 
87
 
 
88
      if (num_keys > 1 && ! already_in_transaction)
 
89
      {
 
90
        if (error == NONE)
 
91
          sql_strings.push_back("COMMIT");
 
92
        else
 
93
          sql_strings.push_back("ROLLBACK");
 
94
      }
 
95
    }
 
96
    break;
 
97
  case message::Statement::UPDATE:
 
98
    {
 
99
      if (! source.has_update_header())
 
100
      {
 
101
        error= MISSING_HEADER;
 
102
        return error;
 
103
      }
 
104
      if (! source.has_update_data())
 
105
      {
 
106
        error= MISSING_DATA;
 
107
        return error;
 
108
      }
 
109
 
 
110
      const message::UpdateHeader &update_header= source.update_header();
 
111
      const message::UpdateData &update_data= source.update_data();
 
112
      size_t num_keys= update_data.record_size();
 
113
      size_t x;
 
114
 
 
115
      if (num_keys > 1 && ! already_in_transaction)
 
116
        sql_strings.push_back("START TRANSACTION");
 
117
 
 
118
      for (x= 0; x < num_keys; ++x)
 
119
      {
 
120
        string destination;
 
121
 
 
122
        error= transformUpdateRecordToSql(update_header,
 
123
                                          update_data.record(x),
 
124
                                          &destination,
 
125
                                          sql_variant);
 
126
        if (error != NONE)
 
127
          break;
 
128
 
 
129
        sql_strings.push_back(destination);
 
130
      }
 
131
 
 
132
      if (num_keys > 1 && ! already_in_transaction)
 
133
      {
 
134
        if (error == NONE)
 
135
          sql_strings.push_back("COMMIT");
 
136
        else
 
137
          sql_strings.push_back("ROLLBACK");
 
138
      }
 
139
    }
 
140
    break;
 
141
  case message::Statement::DELETE:
 
142
    {
 
143
      if (! source.has_delete_header())
 
144
      {
 
145
        error= MISSING_HEADER;
 
146
        return error;
 
147
      }
 
148
      if (! source.has_delete_data())
 
149
      {
 
150
        error= MISSING_DATA;
 
151
        return error;
 
152
      }
 
153
 
 
154
      const message::DeleteHeader &delete_header= source.delete_header();
 
155
      const message::DeleteData &delete_data= source.delete_data();
 
156
      size_t num_keys= delete_data.record_size();
 
157
      size_t x;
 
158
 
 
159
      if (num_keys > 1 && ! already_in_transaction)
 
160
        sql_strings.push_back("START TRANSACTION");
 
161
 
 
162
      for (x= 0; x < num_keys; ++x)
 
163
      {
 
164
        string destination;
 
165
 
 
166
        error= transformDeleteRecordToSql(delete_header,
 
167
                                          delete_data.record(x),
 
168
                                          &destination,
 
169
                                          sql_variant);
 
170
        if (error != NONE)
 
171
          break;
 
172
 
 
173
        sql_strings.push_back(destination);
 
174
      }
 
175
 
 
176
      if (num_keys > 1 && ! already_in_transaction)
 
177
      {
 
178
        if (error == NONE)
 
179
          sql_strings.push_back("COMMIT");
 
180
        else
 
181
          sql_strings.push_back("ROLLBACK");
 
182
      }
 
183
    }
 
184
    break;
 
185
  case message::Statement::TRUNCATE_TABLE:
 
186
    {
 
187
      assert(source.has_truncate_table_statement());
 
188
      string destination;
 
189
      error= message::transformTruncateTableStatementToSql(source.truncate_table_statement(),
 
190
                                                           &destination,
 
191
                                                           sql_variant);
 
192
      sql_strings.push_back(destination);
 
193
    }
 
194
    break;
 
195
  case message::Statement::SET_VARIABLE:
 
196
    {
 
197
      assert(source.has_set_variable_statement());
 
198
      string destination;
 
199
      error= message::transformSetVariableStatementToSql(source.set_variable_statement(),
 
200
                                                       &destination,
 
201
                                                       sql_variant);
 
202
      sql_strings.push_back(destination);
 
203
    }
 
204
    break;
 
205
  case message::Statement::RAW_SQL:
 
206
  default:
 
207
    sql_strings.push_back(source.sql());
 
208
    break;
 
209
  }
 
210
  return error;
 
211
}
 
212
 
 
213
enum message::TransformSqlError
 
214
message::transformInsertHeaderToSql(const message::InsertHeader &header,
 
215
                                    std::string *destination,
 
216
                                    enum message::TransformSqlVariant sql_variant)
 
217
{
 
218
  char quoted_identifier= '`';
 
219
  if (sql_variant == ANSI)
 
220
    quoted_identifier= '"';
 
221
 
 
222
  destination->assign("INSERT INTO ", 12);
 
223
  destination->push_back(quoted_identifier);
 
224
  destination->append(header.table_metadata().schema_name());
 
225
  destination->push_back(quoted_identifier);
 
226
  destination->push_back('.');
 
227
  destination->push_back(quoted_identifier);
 
228
  destination->append(header.table_metadata().table_name());
 
229
  destination->push_back(quoted_identifier);
 
230
  destination->append(" (", 2);
 
231
 
 
232
  /* Add field list to SQL string... */
 
233
  size_t num_fields= header.field_metadata_size();
 
234
  size_t x;
 
235
 
 
236
  for (x= 0; x < num_fields; ++x)
 
237
  {
 
238
    const message::FieldMetadata &field_metadata= header.field_metadata(x);
 
239
    if (x != 0)
 
240
      destination->push_back(',');
 
241
    
 
242
    destination->push_back(quoted_identifier);
 
243
    destination->append(field_metadata.name());
 
244
    destination->push_back(quoted_identifier);
 
245
  }
 
246
 
 
247
  return NONE;
 
248
}
 
249
 
 
250
enum message::TransformSqlError
 
251
message::transformInsertRecordToSql(const message::InsertHeader &header,
 
252
                                    const message::InsertRecord &record,
 
253
                                    std::string *destination,
 
254
                                    enum message::TransformSqlVariant sql_variant)
 
255
{
 
256
  enum message::TransformSqlError error= transformInsertHeaderToSql(header,
 
257
                                                                    destination,
 
258
                                                                    sql_variant);
 
259
 
 
260
  char quoted_identifier= '`';
 
261
  if (sql_variant == ANSI)
 
262
    quoted_identifier= '"';
 
263
 
 
264
  destination->append(") VALUES (");
 
265
 
 
266
  /* Add insert values */
 
267
  size_t num_fields= header.field_metadata_size();
 
268
  size_t x;
 
269
  bool should_quote_field_value= false;
 
270
  
 
271
  for (x= 0; x < num_fields; ++x)
 
272
  {
 
273
    if (x != 0)
 
274
      destination->push_back(',');
 
275
 
 
276
    const message::FieldMetadata &field_metadata= header.field_metadata(x);
 
277
 
 
278
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
279
 
 
280
    if (should_quote_field_value)
 
281
      destination->push_back('\'');
 
282
 
 
283
    if (field_metadata.type() == message::Table::Field::BLOB)
 
284
    {
 
285
      /* 
 
286
        * We do this here because BLOB data is returned
 
287
        * in a string correctly, but calling append()
 
288
        * without a length will result in only the string
 
289
        * up to a \0 being output here.
 
290
        */
 
291
      string raw_data(record.insert_value(x));
 
292
      destination->append(raw_data.c_str(), raw_data.size());
 
293
    }
 
294
    else
 
295
    {
 
296
      destination->append(record.insert_value(x));
 
297
    }
 
298
 
 
299
    if (should_quote_field_value)
 
300
      destination->push_back('\'');
 
301
  }
 
302
  destination->push_back(')');
 
303
 
 
304
  return error;
 
305
}
 
306
 
 
307
enum message::TransformSqlError
 
308
message::transformInsertStatementToSql(const message::InsertHeader &header,
 
309
                                       const message::InsertData &data,
 
310
                                       std::string *destination,
 
311
                                       enum message::TransformSqlVariant sql_variant)
 
312
{
 
313
  enum message::TransformSqlError error= transformInsertHeaderToSql(header,
 
314
                                                                    destination,
 
315
                                                                    sql_variant);
 
316
 
 
317
  char quoted_identifier= '`';
 
318
  if (sql_variant == ANSI)
 
319
    quoted_identifier= '"';
 
320
 
 
321
  destination->append(") VALUES (", 10);
 
322
 
 
323
  /* Add insert values */
 
324
  size_t num_records= data.record_size();
 
325
  size_t num_fields= header.field_metadata_size();
 
326
  size_t x, y;
 
327
  bool should_quote_field_value= false;
 
328
  
 
329
  for (x= 0; x < num_records; ++x)
 
330
  {
 
331
    if (x != 0)
 
332
      destination->append("),(", 3);
 
333
 
 
334
    for (y= 0; y < num_fields; ++y)
 
335
    {
 
336
      if (y != 0)
 
337
        destination->push_back(',');
 
338
 
 
339
      const message::FieldMetadata &field_metadata= header.field_metadata(y);
 
340
      
 
341
      should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
342
 
 
343
      if (should_quote_field_value)
 
344
        destination->push_back('\'');
 
345
 
 
346
      if (field_metadata.type() == message::Table::Field::BLOB)
 
347
      {
 
348
        /* 
 
349
         * We do this here because BLOB data is returned
 
350
         * in a string correctly, but calling append()
 
351
         * without a length will result in only the string
 
352
         * up to a \0 being output here.
 
353
         */
 
354
        string raw_data(data.record(x).insert_value(y));
 
355
        destination->append(raw_data.c_str(), raw_data.size());
 
356
      }
 
357
      else
 
358
      {
 
359
        destination->append(data.record(x).insert_value(y));
 
360
      }
 
361
 
 
362
      if (should_quote_field_value)
 
363
        destination->push_back('\'');
 
364
    }
 
365
  }
 
366
  destination->push_back(')');
 
367
 
 
368
  return error;
 
369
}
 
370
 
 
371
enum message::TransformSqlError
 
372
message::transformUpdateHeaderToSql(const message::UpdateHeader &header,
 
373
                                    std::string *destination,
 
374
                                    enum message::TransformSqlVariant sql_variant)
 
375
{
 
376
  char quoted_identifier= '`';
 
377
  if (sql_variant == ANSI)
 
378
    quoted_identifier= '"';
 
379
 
 
380
  destination->assign("UPDATE ", 7);
 
381
  destination->push_back(quoted_identifier);
 
382
  destination->append(header.table_metadata().schema_name());
 
383
  destination->push_back(quoted_identifier);
 
384
  destination->push_back('.');
 
385
  destination->push_back(quoted_identifier);
 
386
  destination->append(header.table_metadata().table_name());
 
387
  destination->push_back(quoted_identifier);
 
388
  destination->append(" SET ", 5);
 
389
 
 
390
  return NONE;
 
391
}
 
392
 
 
393
enum message::TransformSqlError
 
394
message::transformUpdateRecordToSql(const message::UpdateHeader &header,
 
395
                                    const message::UpdateRecord &record,
 
396
                                    std::string *destination,
 
397
                                    enum message::TransformSqlVariant sql_variant)
 
398
{
 
399
  enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
 
400
                                                                    destination,
 
401
                                                                    sql_variant);
 
402
 
 
403
  char quoted_identifier= '`';
 
404
  if (sql_variant == ANSI)
 
405
    quoted_identifier= '"';
 
406
 
 
407
  /* Add field SET list to SQL string... */
 
408
  size_t num_set_fields= header.set_field_metadata_size();
 
409
  size_t x;
 
410
  bool should_quote_field_value= false;
 
411
 
 
412
  for (x= 0; x < num_set_fields; ++x)
 
413
  {
 
414
    const message::FieldMetadata &field_metadata= header.set_field_metadata(x);
 
415
    if (x != 0)
 
416
      destination->push_back(',');
 
417
    
 
418
    destination->push_back(quoted_identifier);
 
419
    destination->append(field_metadata.name());
 
420
    destination->push_back(quoted_identifier);
 
421
    destination->push_back('=');
 
422
 
 
423
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
424
 
 
425
    if (should_quote_field_value)
 
426
      destination->push_back('\'');
 
427
 
 
428
    if (field_metadata.type() == message::Table::Field::BLOB)
 
429
    {
 
430
      /* 
 
431
       * We do this here because BLOB data is returned
 
432
       * in a string correctly, but calling append()
 
433
       * without a length will result in only the string
 
434
       * up to a \0 being output here.
 
435
       */
 
436
      string raw_data(record.after_value(x));
 
437
      destination->append(raw_data.c_str(), raw_data.size());
 
438
    }
 
439
    else
 
440
    {
 
441
      destination->append(record.after_value(x));
 
442
    }
 
443
 
 
444
    if (should_quote_field_value)
 
445
      destination->push_back('\'');
 
446
  }
 
447
 
 
448
  size_t num_key_fields= header.key_field_metadata_size();
 
449
 
 
450
  destination->append(" WHERE ", 7);
 
451
  for (x= 0; x < num_key_fields; ++x) 
 
452
  {
 
453
    const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
 
454
    
 
455
    if (x != 0)
 
456
      destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
457
 
 
458
    destination->push_back(quoted_identifier);
 
459
    destination->append(field_metadata.name());
 
460
    destination->push_back(quoted_identifier);
 
461
 
 
462
    destination->push_back('=');
 
463
 
 
464
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
465
 
 
466
    if (should_quote_field_value)
 
467
      destination->push_back('\'');
 
468
 
 
469
    if (field_metadata.type() == message::Table::Field::BLOB)
 
470
    {
 
471
      /* 
 
472
       * We do this here because BLOB data is returned
 
473
       * in a string correctly, but calling append()
 
474
       * without a length will result in only the string
 
475
       * up to a \0 being output here.
 
476
       */
 
477
      string raw_data(record.key_value(x));
 
478
      destination->append(raw_data.c_str(), raw_data.size());
 
479
    }
 
480
    else
 
481
    {
 
482
      destination->append(record.key_value(x));
 
483
    }
 
484
 
 
485
    if (should_quote_field_value)
 
486
      destination->push_back('\'');
 
487
  }
 
488
  if (num_key_fields > 1)
 
489
    destination->push_back(')');
 
490
 
 
491
  return error;
 
492
}
 
493
 
 
494
enum message::TransformSqlError
 
495
message::transformDeleteHeaderToSql(const message::DeleteHeader &header,
 
496
                                    std::string *destination,
 
497
                                    enum message::TransformSqlVariant sql_variant)
 
498
{
 
499
  char quoted_identifier= '`';
 
500
  if (sql_variant == ANSI)
 
501
    quoted_identifier= '"';
 
502
 
 
503
  destination->assign("DELETE FROM ", 12);
 
504
  destination->push_back(quoted_identifier);
 
505
  destination->append(header.table_metadata().schema_name());
 
506
  destination->push_back(quoted_identifier);
 
507
  destination->push_back('.');
 
508
  destination->push_back(quoted_identifier);
 
509
  destination->append(header.table_metadata().table_name());
 
510
  destination->push_back(quoted_identifier);
 
511
 
 
512
  return NONE;
 
513
}
 
514
 
 
515
enum message::TransformSqlError
 
516
message::transformDeleteRecordToSql(const message::DeleteHeader &header,
 
517
                                    const message::DeleteRecord &record,
 
518
                                    std::string *destination,
 
519
                                    enum message::TransformSqlVariant sql_variant)
 
520
{
 
521
  enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
 
522
                                                                    destination,
 
523
                                                                    sql_variant);
 
524
  char quoted_identifier= '`';
 
525
  if (sql_variant == ANSI)
 
526
    quoted_identifier= '"';
 
527
 
 
528
  /* Add WHERE clause to SQL string... */
 
529
  uint32_t num_key_fields= header.key_field_metadata_size();
 
530
  uint32_t x;
 
531
  bool should_quote_field_value= false;
 
532
 
 
533
  destination->append(" WHERE ", 7);
 
534
  for (x= 0; x < num_key_fields; ++x) 
 
535
  {
 
536
    const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
 
537
    
 
538
    if (x != 0)
 
539
      destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
540
 
 
541
    destination->push_back(quoted_identifier);
 
542
    destination->append(field_metadata.name());
 
543
    destination->push_back(quoted_identifier);
 
544
 
 
545
    destination->push_back('=');
 
546
 
 
547
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
548
 
 
549
    if (should_quote_field_value)
 
550
      destination->push_back('\'');
 
551
 
 
552
    if (field_metadata.type() == message::Table::Field::BLOB)
 
553
    {
 
554
      /* 
 
555
       * We do this here because BLOB data is returned
 
556
       * in a string correctly, but calling append()
 
557
       * without a length will result in only the string
 
558
       * up to a \0 being output here.
 
559
       */
 
560
      string raw_data(record.key_value(x));
 
561
      destination->append(raw_data.c_str(), raw_data.size());
 
562
    }
 
563
    else
 
564
    {
 
565
      destination->append(record.key_value(x));
 
566
    }
 
567
 
 
568
    if (should_quote_field_value)
 
569
      destination->push_back('\'');
 
570
  }
 
571
 
 
572
  return error;
 
573
}
 
574
 
 
575
enum message::TransformSqlError
 
576
message::transformDeleteStatementToSql(const message::DeleteHeader &header,
 
577
                                       const message::DeleteData &data,
 
578
                                       std::string *destination,
 
579
                                       enum message::TransformSqlVariant sql_variant)
 
580
{
 
581
  enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
 
582
                                                                    destination,
 
583
                                                                    sql_variant);
 
584
  char quoted_identifier= '`';
 
585
  if (sql_variant == ANSI)
 
586
    quoted_identifier= '"';
 
587
 
 
588
  /* Add WHERE clause to SQL string... */
 
589
  uint32_t num_key_fields= header.key_field_metadata_size();
 
590
  uint32_t num_key_records= data.record_size();
 
591
  uint32_t x, y;
 
592
  bool should_quote_field_value= false;
 
593
 
 
594
  destination->append(" WHERE ", 7);
 
595
  for (x= 0; x < num_key_records; ++x)
 
596
  {
 
597
    if (x != 0)
 
598
      destination->append(" OR ", 4); /* Always OR condition for multiple key records */
 
599
 
 
600
    if (num_key_fields > 1)
 
601
      destination->push_back('(');
 
602
 
 
603
    for (y= 0; y < num_key_fields; ++y) 
 
604
    {
 
605
      const message::FieldMetadata &field_metadata= header.key_field_metadata(y);
 
606
      
 
607
      if (y != 0)
 
608
        destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
609
 
 
610
      destination->push_back(quoted_identifier);
 
611
      destination->append(field_metadata.name());
 
612
      destination->push_back(quoted_identifier);
 
613
 
 
614
      destination->push_back('=');
 
615
 
 
616
      should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
617
 
 
618
      if (should_quote_field_value)
 
619
        destination->push_back('\'');
 
620
 
 
621
      if (field_metadata.type() == message::Table::Field::BLOB)
 
622
      {
 
623
        /* 
 
624
         * We do this here because BLOB data is returned
 
625
         * in a string correctly, but calling append()
 
626
         * without a length will result in only the string
 
627
         * up to a \0 being output here.
 
628
         */
 
629
        string raw_data(data.record(x).key_value(y));
 
630
        destination->append(raw_data.c_str(), raw_data.size());
 
631
      }
 
632
      else
 
633
      {
 
634
        destination->append(data.record(x).key_value(y));
 
635
      }
 
636
 
 
637
      if (should_quote_field_value)
 
638
        destination->push_back('\'');
 
639
    }
 
640
    if (num_key_fields > 1)
 
641
      destination->push_back(')');
 
642
  }
 
643
  return error;
 
644
}
 
645
 
 
646
enum message::TransformSqlError
 
647
message::transformTruncateTableStatementToSql(const message::TruncateTableStatement &statement,
 
648
                                              std::string *destination,
 
649
                                              enum message::TransformSqlVariant sql_variant)
 
650
{
 
651
  char quoted_identifier= '`';
 
652
  if (sql_variant == ANSI)
 
653
    quoted_identifier= '"';
 
654
 
 
655
  const message::TableMetadata &table_metadata= statement.table_metadata();
 
656
 
 
657
  destination->append("TRUNCATE TABLE ", 15);
 
658
  destination->push_back(quoted_identifier);
 
659
  destination->append(table_metadata.schema_name());
 
660
  destination->push_back(quoted_identifier);
 
661
  destination->push_back('.');
 
662
  destination->push_back(quoted_identifier);
 
663
  destination->append(table_metadata.table_name());
 
664
  destination->push_back(quoted_identifier);
 
665
 
 
666
  return NONE;
 
667
}
 
668
 
 
669
enum message::TransformSqlError
 
670
message::transformSetVariableStatementToSql(const message::SetVariableStatement &statement,
 
671
                                            std::string *destination,
 
672
                                            enum message::TransformSqlVariant sql_variant)
 
673
{
 
674
  (void) sql_variant;
 
675
  const message::FieldMetadata &variable_metadata= statement.variable_metadata();
 
676
  bool should_quote_field_value= message::shouldQuoteFieldValue(variable_metadata.type());
 
677
 
 
678
  destination->append("SET GLOBAL ", 11); /* Only global variables are replicated */
 
679
  destination->append(variable_metadata.name());
 
680
  destination->push_back('=');
 
681
 
 
682
  if (should_quote_field_value)
 
683
    destination->push_back('\'');
 
684
  
 
685
  destination->append(statement.variable_value());
 
686
 
 
687
  if (should_quote_field_value)
 
688
    destination->push_back('\'');
 
689
 
 
690
  return NONE;
 
691
}
 
692
 
 
693
bool message::shouldQuoteFieldValue(message::Table::Field::FieldType in_type)
 
694
{
 
695
  switch (in_type)
 
696
  {
 
697
  case message::Table::Field::DOUBLE:
 
698
  case message::Table::Field::DECIMAL:
 
699
  case message::Table::Field::INTEGER:
 
700
  case message::Table::Field::BIGINT:
 
701
  case message::Table::Field::ENUM:
 
702
    return false;
 
703
  default:
 
704
    return true;
 
705
  } 
 
706
}