~stewart/drizzle/embedded-innodb-create-table-with-index

« back to all changes in this revision

Viewing changes to drizzled/message/statement_transform.cc

  • Committer: Stewart Smith
  • Date: 2010-03-11 01:15:57 UTC
  • mfrom: (1319.1.29)
  • Revision ID: stewart@flamingspork.com-20100311011557-49r2ye69bqh4abti
Merged embedded-innodb-rnd-read into embedded-innodb-create-table-with-index.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
4
 *  Copyright (C) 2009 Sun Microsystems
 
5
 *  Copyright (c) 2010 Jay Pipes
5
6
 *
6
7
 *  Authors:
7
8
 *
8
 
 *    Jay Pipes <joinfu@sun.com>
 
9
 *    Jay Pipes <jaypipes@gmail.com>
9
10
 *
10
11
 *  This program is free software; you can redistribute it and/or modify
11
12
 *  it under the terms of the GNU General Public License as published by
36
37
 
37
38
#include <string>
38
39
#include <vector>
 
40
#include <sstream>
39
41
 
40
42
using namespace std;
41
43
 
42
44
namespace drizzled
43
45
{
44
46
 
45
 
enum message::TransformSqlError
46
 
message::transformStatementToSql(const message::Statement &source,
47
 
                                 vector<string> &sql_strings,
48
 
                                 enum message::TransformSqlVariant sql_variant,
49
 
                                 bool already_in_transaction)
50
 
{
51
 
  message::TransformSqlError error= NONE;
 
47
namespace message
 
48
{
 
49
 
 
50
enum TransformSqlError
 
51
transformStatementToSql(const Statement &source,
 
52
                        vector<string> &sql_strings,
 
53
                        enum TransformSqlVariant sql_variant,
 
54
                        bool already_in_transaction)
 
55
{
 
56
  TransformSqlError error= NONE;
52
57
 
53
58
  switch (source.type())
54
59
  {
55
 
  case message::Statement::INSERT:
 
60
  case Statement::INSERT:
56
61
    {
57
62
      if (! source.has_insert_header())
58
63
      {
65
70
        return error;
66
71
      }
67
72
 
68
 
      const message::InsertHeader &insert_header= source.insert_header();
69
 
      const message::InsertData &insert_data= source.insert_data();
 
73
      const InsertHeader &insert_header= source.insert_header();
 
74
      const InsertData &insert_data= source.insert_data();
70
75
      size_t num_keys= insert_data.record_size();
71
76
      size_t x;
72
77
 
79
84
 
80
85
        error= transformInsertRecordToSql(insert_header,
81
86
                                          insert_data.record(x),
82
 
                                          &destination,
 
87
                                          destination,
83
88
                                          sql_variant);
84
89
        if (error != NONE)
85
90
          break;
96
101
      }
97
102
    }
98
103
    break;
99
 
  case message::Statement::UPDATE:
 
104
  case Statement::UPDATE:
100
105
    {
101
106
      if (! source.has_update_header())
102
107
      {
109
114
        return error;
110
115
      }
111
116
 
112
 
      const message::UpdateHeader &update_header= source.update_header();
113
 
      const message::UpdateData &update_data= source.update_data();
 
117
      const UpdateHeader &update_header= source.update_header();
 
118
      const UpdateData &update_data= source.update_data();
114
119
      size_t num_keys= update_data.record_size();
115
120
      size_t x;
116
121
 
123
128
 
124
129
        error= transformUpdateRecordToSql(update_header,
125
130
                                          update_data.record(x),
126
 
                                          &destination,
 
131
                                          destination,
127
132
                                          sql_variant);
128
133
        if (error != NONE)
129
134
          break;
140
145
      }
141
146
    }
142
147
    break;
143
 
  case message::Statement::DELETE:
 
148
  case Statement::DELETE:
144
149
    {
145
150
      if (! source.has_delete_header())
146
151
      {
153
158
        return error;
154
159
      }
155
160
 
156
 
      const message::DeleteHeader &delete_header= source.delete_header();
157
 
      const message::DeleteData &delete_data= source.delete_data();
 
161
      const DeleteHeader &delete_header= source.delete_header();
 
162
      const DeleteData &delete_data= source.delete_data();
158
163
      size_t num_keys= delete_data.record_size();
159
164
      size_t x;
160
165
 
167
172
 
168
173
        error= transformDeleteRecordToSql(delete_header,
169
174
                                          delete_data.record(x),
170
 
                                          &destination,
 
175
                                          destination,
171
176
                                          sql_variant);
172
177
        if (error != NONE)
173
178
          break;
184
189
      }
185
190
    }
186
191
    break;
187
 
  case message::Statement::TRUNCATE_TABLE:
 
192
  case Statement::CREATE_TABLE:
 
193
    {
 
194
      assert(source.has_create_table_statement());
 
195
      string destination;
 
196
      error= transformCreateTableStatementToSql(source.create_table_statement(),
 
197
                                                destination,
 
198
                                                sql_variant);
 
199
      sql_strings.push_back(destination);
 
200
    }
 
201
    break;
 
202
  case Statement::TRUNCATE_TABLE:
188
203
    {
189
204
      assert(source.has_truncate_table_statement());
190
205
      string destination;
191
 
      error= message::transformTruncateTableStatementToSql(source.truncate_table_statement(),
192
 
                                                           &destination,
193
 
                                                           sql_variant);
194
 
      sql_strings.push_back(destination);
195
 
    }
196
 
    break;
197
 
  case message::Statement::SET_VARIABLE:
 
206
      error= transformTruncateTableStatementToSql(source.truncate_table_statement(),
 
207
                                                  destination,
 
208
                                                  sql_variant);
 
209
      sql_strings.push_back(destination);
 
210
    }
 
211
    break;
 
212
  case Statement::DROP_TABLE:
 
213
    {
 
214
      assert(source.has_drop_table_statement());
 
215
      string destination;
 
216
      error= transformDropTableStatementToSql(source.drop_table_statement(),
 
217
                                              destination,
 
218
                                              sql_variant);
 
219
      sql_strings.push_back(destination);
 
220
    }
 
221
    break;
 
222
  case Statement::CREATE_SCHEMA:
 
223
    {
 
224
      assert(source.has_create_schema_statement());
 
225
      string destination;
 
226
      error= transformCreateSchemaStatementToSql(source.create_schema_statement(),
 
227
                                                 destination,
 
228
                                                 sql_variant);
 
229
      sql_strings.push_back(destination);
 
230
    }
 
231
    break;
 
232
  case Statement::DROP_SCHEMA:
 
233
    {
 
234
      assert(source.has_drop_schema_statement());
 
235
      string destination;
 
236
      error= transformDropSchemaStatementToSql(source.drop_schema_statement(),
 
237
                                               destination,
 
238
                                               sql_variant);
 
239
      sql_strings.push_back(destination);
 
240
    }
 
241
    break;
 
242
  case Statement::SET_VARIABLE:
198
243
    {
199
244
      assert(source.has_set_variable_statement());
200
245
      string destination;
201
 
      error= message::transformSetVariableStatementToSql(source.set_variable_statement(),
202
 
                                                       &destination,
203
 
                                                       sql_variant);
 
246
      error= transformSetVariableStatementToSql(source.set_variable_statement(),
 
247
                                                destination,
 
248
                                                sql_variant);
204
249
      sql_strings.push_back(destination);
205
250
    }
206
251
    break;
207
 
  case message::Statement::RAW_SQL:
 
252
  case Statement::RAW_SQL:
208
253
  default:
209
254
    sql_strings.push_back(source.sql());
210
255
    break;
212
257
  return error;
213
258
}
214
259
 
215
 
enum message::TransformSqlError
216
 
message::transformInsertHeaderToSql(const message::InsertHeader &header,
217
 
                                    std::string *destination,
218
 
                                    enum message::TransformSqlVariant sql_variant)
 
260
enum TransformSqlError
 
261
transformInsertHeaderToSql(const InsertHeader &header,
 
262
                           string &destination,
 
263
                           enum TransformSqlVariant sql_variant)
219
264
{
220
265
  char quoted_identifier= '`';
221
266
  if (sql_variant == ANSI)
222
267
    quoted_identifier= '"';
223
268
 
224
 
  destination->assign("INSERT INTO ", 12);
225
 
  destination->push_back(quoted_identifier);
226
 
  destination->append(header.table_metadata().schema_name());
227
 
  destination->push_back(quoted_identifier);
228
 
  destination->push_back('.');
229
 
  destination->push_back(quoted_identifier);
230
 
  destination->append(header.table_metadata().table_name());
231
 
  destination->push_back(quoted_identifier);
232
 
  destination->append(" (", 2);
 
269
  destination.assign("INSERT INTO ", 12);
 
270
  destination.push_back(quoted_identifier);
 
271
  destination.append(header.table_metadata().schema_name());
 
272
  destination.push_back(quoted_identifier);
 
273
  destination.push_back('.');
 
274
  destination.push_back(quoted_identifier);
 
275
  destination.append(header.table_metadata().table_name());
 
276
  destination.push_back(quoted_identifier);
 
277
  destination.append(" (", 2);
233
278
 
234
279
  /* Add field list to SQL string... */
235
280
  size_t num_fields= header.field_metadata_size();
237
282
 
238
283
  for (x= 0; x < num_fields; ++x)
239
284
  {
240
 
    const message::FieldMetadata &field_metadata= header.field_metadata(x);
 
285
    const FieldMetadata &field_metadata= header.field_metadata(x);
241
286
    if (x != 0)
242
 
      destination->push_back(',');
 
287
      destination.push_back(',');
243
288
    
244
 
    destination->push_back(quoted_identifier);
245
 
    destination->append(field_metadata.name());
246
 
    destination->push_back(quoted_identifier);
 
289
    destination.push_back(quoted_identifier);
 
290
    destination.append(field_metadata.name());
 
291
    destination.push_back(quoted_identifier);
247
292
  }
248
293
 
249
294
  return NONE;
250
295
}
251
296
 
252
 
enum message::TransformSqlError
253
 
message::transformInsertRecordToSql(const message::InsertHeader &header,
254
 
                                    const message::InsertRecord &record,
255
 
                                    std::string *destination,
256
 
                                    enum message::TransformSqlVariant sql_variant)
 
297
enum TransformSqlError
 
298
transformInsertRecordToSql(const InsertHeader &header,
 
299
                           const InsertRecord &record,
 
300
                           string &destination,
 
301
                           enum TransformSqlVariant sql_variant)
257
302
{
258
 
  enum message::TransformSqlError error= transformInsertHeaderToSql(header,
259
 
                                                                    destination,
260
 
                                                                    sql_variant);
 
303
  enum TransformSqlError error= transformInsertHeaderToSql(header,
 
304
                                                           destination,
 
305
                                                           sql_variant);
261
306
 
262
307
  char quoted_identifier= '`';
263
308
  if (sql_variant == ANSI)
264
309
    quoted_identifier= '"';
265
310
 
266
 
  destination->append(") VALUES (");
 
311
  destination.append(") VALUES (");
267
312
 
268
313
  /* Add insert values */
269
314
  size_t num_fields= header.field_metadata_size();
273
318
  for (x= 0; x < num_fields; ++x)
274
319
  {
275
320
    if (x != 0)
276
 
      destination->push_back(',');
277
 
 
278
 
    const message::FieldMetadata &field_metadata= header.field_metadata(x);
279
 
 
280
 
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
321
      destination.push_back(',');
 
322
 
 
323
    const FieldMetadata &field_metadata= header.field_metadata(x);
 
324
 
 
325
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
281
326
 
282
327
    if (should_quote_field_value)
283
 
      destination->push_back('\'');
 
328
      destination.push_back('\'');
284
329
 
285
 
    if (field_metadata.type() == message::Table::Field::BLOB)
 
330
    if (field_metadata.type() == Table::Field::BLOB)
286
331
    {
287
332
      /* 
288
333
        * We do this here because BLOB data is returned
291
336
        * up to a \0 being output here.
292
337
        */
293
338
      string raw_data(record.insert_value(x));
294
 
      destination->append(raw_data.c_str(), raw_data.size());
 
339
      destination.append(raw_data.c_str(), raw_data.size());
295
340
    }
296
341
    else
297
342
    {
298
 
      destination->append(record.insert_value(x));
 
343
      destination.append(record.insert_value(x));
299
344
    }
300
345
 
301
346
    if (should_quote_field_value)
302
 
      destination->push_back('\'');
 
347
      destination.push_back('\'');
303
348
  }
304
 
  destination->push_back(')');
 
349
  destination.push_back(')');
305
350
 
306
351
  return error;
307
352
}
308
353
 
309
 
enum message::TransformSqlError
310
 
message::transformInsertStatementToSql(const message::InsertHeader &header,
311
 
                                       const message::InsertData &data,
312
 
                                       std::string *destination,
313
 
                                       enum message::TransformSqlVariant sql_variant)
 
354
enum TransformSqlError
 
355
transformInsertStatementToSql(const InsertHeader &header,
 
356
                              const InsertData &data,
 
357
                              string &destination,
 
358
                              enum TransformSqlVariant sql_variant)
314
359
{
315
 
  enum message::TransformSqlError error= transformInsertHeaderToSql(header,
316
 
                                                                    destination,
317
 
                                                                    sql_variant);
 
360
  enum TransformSqlError error= transformInsertHeaderToSql(header,
 
361
                                                           destination,
 
362
                                                           sql_variant);
318
363
 
319
364
  char quoted_identifier= '`';
320
365
  if (sql_variant == ANSI)
321
366
    quoted_identifier= '"';
322
367
 
323
 
  destination->append(") VALUES (", 10);
 
368
  destination.append(") VALUES (", 10);
324
369
 
325
370
  /* Add insert values */
326
371
  size_t num_records= data.record_size();
331
376
  for (x= 0; x < num_records; ++x)
332
377
  {
333
378
    if (x != 0)
334
 
      destination->append("),(", 3);
 
379
      destination.append("),(", 3);
335
380
 
336
381
    for (y= 0; y < num_fields; ++y)
337
382
    {
338
383
      if (y != 0)
339
 
        destination->push_back(',');
 
384
        destination.push_back(',');
340
385
 
341
 
      const message::FieldMetadata &field_metadata= header.field_metadata(y);
 
386
      const FieldMetadata &field_metadata= header.field_metadata(y);
342
387
      
343
 
      should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
388
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
344
389
 
345
390
      if (should_quote_field_value)
346
 
        destination->push_back('\'');
 
391
        destination.push_back('\'');
347
392
 
348
 
      if (field_metadata.type() == message::Table::Field::BLOB)
 
393
      if (field_metadata.type() == Table::Field::BLOB)
349
394
      {
350
395
        /* 
351
396
         * We do this here because BLOB data is returned
354
399
         * up to a \0 being output here.
355
400
         */
356
401
        string raw_data(data.record(x).insert_value(y));
357
 
        destination->append(raw_data.c_str(), raw_data.size());
 
402
        destination.append(raw_data.c_str(), raw_data.size());
358
403
      }
359
404
      else
360
405
      {
361
 
        destination->append(data.record(x).insert_value(y));
 
406
        destination.append(data.record(x).insert_value(y));
362
407
      }
363
408
 
364
409
      if (should_quote_field_value)
365
 
        destination->push_back('\'');
 
410
        destination.push_back('\'');
366
411
    }
367
412
  }
368
 
  destination->push_back(')');
 
413
  destination.push_back(')');
369
414
 
370
415
  return error;
371
416
}
372
417
 
373
 
enum message::TransformSqlError
374
 
message::transformUpdateHeaderToSql(const message::UpdateHeader &header,
375
 
                                    std::string *destination,
376
 
                                    enum message::TransformSqlVariant sql_variant)
 
418
enum TransformSqlError
 
419
transformUpdateHeaderToSql(const UpdateHeader &header,
 
420
                           string &destination,
 
421
                           enum TransformSqlVariant sql_variant)
377
422
{
378
423
  char quoted_identifier= '`';
379
424
  if (sql_variant == ANSI)
380
425
    quoted_identifier= '"';
381
426
 
382
 
  destination->assign("UPDATE ", 7);
383
 
  destination->push_back(quoted_identifier);
384
 
  destination->append(header.table_metadata().schema_name());
385
 
  destination->push_back(quoted_identifier);
386
 
  destination->push_back('.');
387
 
  destination->push_back(quoted_identifier);
388
 
  destination->append(header.table_metadata().table_name());
389
 
  destination->push_back(quoted_identifier);
390
 
  destination->append(" SET ", 5);
 
427
  destination.assign("UPDATE ", 7);
 
428
  destination.push_back(quoted_identifier);
 
429
  destination.append(header.table_metadata().schema_name());
 
430
  destination.push_back(quoted_identifier);
 
431
  destination.push_back('.');
 
432
  destination.push_back(quoted_identifier);
 
433
  destination.append(header.table_metadata().table_name());
 
434
  destination.push_back(quoted_identifier);
 
435
  destination.append(" SET ", 5);
391
436
 
392
437
  return NONE;
393
438
}
394
439
 
395
 
enum message::TransformSqlError
396
 
message::transformUpdateRecordToSql(const message::UpdateHeader &header,
397
 
                                    const message::UpdateRecord &record,
398
 
                                    std::string *destination,
399
 
                                    enum message::TransformSqlVariant sql_variant)
 
440
enum TransformSqlError
 
441
transformUpdateRecordToSql(const UpdateHeader &header,
 
442
                           const UpdateRecord &record,
 
443
                           string &destination,
 
444
                           enum TransformSqlVariant sql_variant)
400
445
{
401
 
  enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
402
 
                                                                    destination,
403
 
                                                                    sql_variant);
 
446
  enum TransformSqlError error= transformUpdateHeaderToSql(header,
 
447
                                                           destination,
 
448
                                                           sql_variant);
404
449
 
405
450
  char quoted_identifier= '`';
406
451
  if (sql_variant == ANSI)
413
458
 
414
459
  for (x= 0; x < num_set_fields; ++x)
415
460
  {
416
 
    const message::FieldMetadata &field_metadata= header.set_field_metadata(x);
 
461
    const FieldMetadata &field_metadata= header.set_field_metadata(x);
417
462
    if (x != 0)
418
 
      destination->push_back(',');
 
463
      destination.push_back(',');
419
464
    
420
 
    destination->push_back(quoted_identifier);
421
 
    destination->append(field_metadata.name());
422
 
    destination->push_back(quoted_identifier);
423
 
    destination->push_back('=');
 
465
    destination.push_back(quoted_identifier);
 
466
    destination.append(field_metadata.name());
 
467
    destination.push_back(quoted_identifier);
 
468
    destination.push_back('=');
424
469
 
425
 
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
470
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
426
471
 
427
472
    if (should_quote_field_value)
428
 
      destination->push_back('\'');
 
473
      destination.push_back('\'');
429
474
 
430
 
    if (field_metadata.type() == message::Table::Field::BLOB)
 
475
    if (field_metadata.type() == Table::Field::BLOB)
431
476
    {
432
477
      /* 
433
478
       * We do this here because BLOB data is returned
436
481
       * up to a \0 being output here.
437
482
       */
438
483
      string raw_data(record.after_value(x));
439
 
      destination->append(raw_data.c_str(), raw_data.size());
 
484
      destination.append(raw_data.c_str(), raw_data.size());
440
485
    }
441
486
    else
442
487
    {
443
 
      destination->append(record.after_value(x));
 
488
      destination.append(record.after_value(x));
444
489
    }
445
490
 
446
491
    if (should_quote_field_value)
447
 
      destination->push_back('\'');
 
492
      destination.push_back('\'');
448
493
  }
449
494
 
450
495
  size_t num_key_fields= header.key_field_metadata_size();
451
496
 
452
 
  destination->append(" WHERE ", 7);
 
497
  destination.append(" WHERE ", 7);
453
498
  for (x= 0; x < num_key_fields; ++x) 
454
499
  {
455
 
    const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
 
500
    const FieldMetadata &field_metadata= header.key_field_metadata(x);
456
501
    
457
502
    if (x != 0)
458
 
      destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
459
 
 
460
 
    destination->push_back(quoted_identifier);
461
 
    destination->append(field_metadata.name());
462
 
    destination->push_back(quoted_identifier);
463
 
 
464
 
    destination->push_back('=');
465
 
 
466
 
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
503
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
504
 
 
505
    destination.push_back(quoted_identifier);
 
506
    destination.append(field_metadata.name());
 
507
    destination.push_back(quoted_identifier);
 
508
 
 
509
    destination.push_back('=');
 
510
 
 
511
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
467
512
 
468
513
    if (should_quote_field_value)
469
 
      destination->push_back('\'');
 
514
      destination.push_back('\'');
470
515
 
471
 
    if (field_metadata.type() == message::Table::Field::BLOB)
 
516
    if (field_metadata.type() == Table::Field::BLOB)
472
517
    {
473
518
      /* 
474
519
       * We do this here because BLOB data is returned
477
522
       * up to a \0 being output here.
478
523
       */
479
524
      string raw_data(record.key_value(x));
480
 
      destination->append(raw_data.c_str(), raw_data.size());
 
525
      destination.append(raw_data.c_str(), raw_data.size());
481
526
    }
482
527
    else
483
528
    {
484
 
      destination->append(record.key_value(x));
 
529
      destination.append(record.key_value(x));
485
530
    }
486
531
 
487
532
    if (should_quote_field_value)
488
 
      destination->push_back('\'');
 
533
      destination.push_back('\'');
489
534
  }
490
 
  if (num_key_fields > 1)
491
 
    destination->push_back(')');
492
535
 
493
536
  return error;
494
537
}
495
538
 
496
 
enum message::TransformSqlError
497
 
message::transformDeleteHeaderToSql(const message::DeleteHeader &header,
498
 
                                    std::string *destination,
499
 
                                    enum message::TransformSqlVariant sql_variant)
 
539
enum TransformSqlError
 
540
transformDeleteHeaderToSql(const DeleteHeader &header,
 
541
                           string &destination,
 
542
                           enum TransformSqlVariant sql_variant)
500
543
{
501
544
  char quoted_identifier= '`';
502
545
  if (sql_variant == ANSI)
503
546
    quoted_identifier= '"';
504
547
 
505
 
  destination->assign("DELETE FROM ", 12);
506
 
  destination->push_back(quoted_identifier);
507
 
  destination->append(header.table_metadata().schema_name());
508
 
  destination->push_back(quoted_identifier);
509
 
  destination->push_back('.');
510
 
  destination->push_back(quoted_identifier);
511
 
  destination->append(header.table_metadata().table_name());
512
 
  destination->push_back(quoted_identifier);
 
548
  destination.assign("DELETE FROM ", 12);
 
549
  destination.push_back(quoted_identifier);
 
550
  destination.append(header.table_metadata().schema_name());
 
551
  destination.push_back(quoted_identifier);
 
552
  destination.push_back('.');
 
553
  destination.push_back(quoted_identifier);
 
554
  destination.append(header.table_metadata().table_name());
 
555
  destination.push_back(quoted_identifier);
513
556
 
514
557
  return NONE;
515
558
}
516
559
 
517
 
enum message::TransformSqlError
518
 
message::transformDeleteRecordToSql(const message::DeleteHeader &header,
519
 
                                    const message::DeleteRecord &record,
520
 
                                    std::string *destination,
521
 
                                    enum message::TransformSqlVariant sql_variant)
 
560
enum TransformSqlError
 
561
transformDeleteRecordToSql(const DeleteHeader &header,
 
562
                           const DeleteRecord &record,
 
563
                           string &destination,
 
564
                           enum TransformSqlVariant sql_variant)
522
565
{
523
 
  enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
524
 
                                                                    destination,
525
 
                                                                    sql_variant);
 
566
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
 
567
                                                           destination,
 
568
                                                           sql_variant);
526
569
  char quoted_identifier= '`';
527
570
  if (sql_variant == ANSI)
528
571
    quoted_identifier= '"';
532
575
  uint32_t x;
533
576
  bool should_quote_field_value= false;
534
577
 
535
 
  destination->append(" WHERE ", 7);
 
578
  destination.append(" WHERE ", 7);
536
579
  for (x= 0; x < num_key_fields; ++x) 
537
580
  {
538
 
    const message::FieldMetadata &field_metadata= header.key_field_metadata(x);
 
581
    const FieldMetadata &field_metadata= header.key_field_metadata(x);
539
582
    
540
583
    if (x != 0)
541
 
      destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
542
 
 
543
 
    destination->push_back(quoted_identifier);
544
 
    destination->append(field_metadata.name());
545
 
    destination->push_back(quoted_identifier);
546
 
 
547
 
    destination->push_back('=');
548
 
 
549
 
    should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
584
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
585
 
 
586
    destination.push_back(quoted_identifier);
 
587
    destination.append(field_metadata.name());
 
588
    destination.push_back(quoted_identifier);
 
589
 
 
590
    destination.push_back('=');
 
591
 
 
592
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
550
593
 
551
594
    if (should_quote_field_value)
552
 
      destination->push_back('\'');
 
595
      destination.push_back('\'');
553
596
 
554
 
    if (field_metadata.type() == message::Table::Field::BLOB)
 
597
    if (field_metadata.type() == Table::Field::BLOB)
555
598
    {
556
599
      /* 
557
600
       * We do this here because BLOB data is returned
560
603
       * up to a \0 being output here.
561
604
       */
562
605
      string raw_data(record.key_value(x));
563
 
      destination->append(raw_data.c_str(), raw_data.size());
 
606
      destination.append(raw_data.c_str(), raw_data.size());
564
607
    }
565
608
    else
566
609
    {
567
 
      destination->append(record.key_value(x));
 
610
      destination.append(record.key_value(x));
568
611
    }
569
612
 
570
613
    if (should_quote_field_value)
571
 
      destination->push_back('\'');
 
614
      destination.push_back('\'');
572
615
  }
573
616
 
574
617
  return error;
575
618
}
576
619
 
577
 
enum message::TransformSqlError
578
 
message::transformDeleteStatementToSql(const message::DeleteHeader &header,
579
 
                                       const message::DeleteData &data,
580
 
                                       std::string *destination,
581
 
                                       enum message::TransformSqlVariant sql_variant)
 
620
enum TransformSqlError
 
621
transformDeleteStatementToSql(const DeleteHeader &header,
 
622
                              const DeleteData &data,
 
623
                              string &destination,
 
624
                              enum TransformSqlVariant sql_variant)
582
625
{
583
 
  enum message::TransformSqlError error= transformDeleteHeaderToSql(header,
584
 
                                                                    destination,
585
 
                                                                    sql_variant);
 
626
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
 
627
                                                           destination,
 
628
                                                           sql_variant);
586
629
  char quoted_identifier= '`';
587
630
  if (sql_variant == ANSI)
588
631
    quoted_identifier= '"';
593
636
  uint32_t x, y;
594
637
  bool should_quote_field_value= false;
595
638
 
596
 
  destination->append(" WHERE ", 7);
 
639
  destination.append(" WHERE ", 7);
597
640
  for (x= 0; x < num_key_records; ++x)
598
641
  {
599
642
    if (x != 0)
600
 
      destination->append(" OR ", 4); /* Always OR condition for multiple key records */
 
643
      destination.append(" OR ", 4); /* Always OR condition for multiple key records */
601
644
 
602
645
    if (num_key_fields > 1)
603
 
      destination->push_back('(');
 
646
      destination.push_back('(');
604
647
 
605
648
    for (y= 0; y < num_key_fields; ++y) 
606
649
    {
607
 
      const message::FieldMetadata &field_metadata= header.key_field_metadata(y);
 
650
      const FieldMetadata &field_metadata= header.key_field_metadata(y);
608
651
      
609
652
      if (y != 0)
610
 
        destination->append(" AND ", 5); /* Always AND condition with a multi-column PK */
611
 
 
612
 
      destination->push_back(quoted_identifier);
613
 
      destination->append(field_metadata.name());
614
 
      destination->push_back(quoted_identifier);
615
 
 
616
 
      destination->push_back('=');
617
 
 
618
 
      should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
 
653
        destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
 
654
 
 
655
      destination.push_back(quoted_identifier);
 
656
      destination.append(field_metadata.name());
 
657
      destination.push_back(quoted_identifier);
 
658
 
 
659
      destination.push_back('=');
 
660
 
 
661
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
619
662
 
620
663
      if (should_quote_field_value)
621
 
        destination->push_back('\'');
 
664
        destination.push_back('\'');
622
665
 
623
 
      if (field_metadata.type() == message::Table::Field::BLOB)
 
666
      if (field_metadata.type() == Table::Field::BLOB)
624
667
      {
625
668
        /* 
626
669
         * We do this here because BLOB data is returned
629
672
         * up to a \0 being output here.
630
673
         */
631
674
        string raw_data(data.record(x).key_value(y));
632
 
        destination->append(raw_data.c_str(), raw_data.size());
 
675
        destination.append(raw_data.c_str(), raw_data.size());
633
676
      }
634
677
      else
635
678
      {
636
 
        destination->append(data.record(x).key_value(y));
 
679
        destination.append(data.record(x).key_value(y));
637
680
      }
638
681
 
639
682
      if (should_quote_field_value)
640
 
        destination->push_back('\'');
 
683
        destination.push_back('\'');
641
684
    }
642
685
    if (num_key_fields > 1)
643
 
      destination->push_back(')');
 
686
      destination.push_back(')');
644
687
  }
645
688
  return error;
646
689
}
647
690
 
648
 
enum message::TransformSqlError
649
 
message::transformTruncateTableStatementToSql(const message::TruncateTableStatement &statement,
650
 
                                              std::string *destination,
651
 
                                              enum message::TransformSqlVariant sql_variant)
652
 
{
653
 
  char quoted_identifier= '`';
654
 
  if (sql_variant == ANSI)
655
 
    quoted_identifier= '"';
656
 
 
657
 
  const message::TableMetadata &table_metadata= statement.table_metadata();
658
 
 
659
 
  destination->append("TRUNCATE TABLE ", 15);
660
 
  destination->push_back(quoted_identifier);
661
 
  destination->append(table_metadata.schema_name());
662
 
  destination->push_back(quoted_identifier);
663
 
  destination->push_back('.');
664
 
  destination->push_back(quoted_identifier);
665
 
  destination->append(table_metadata.table_name());
666
 
  destination->push_back(quoted_identifier);
667
 
 
668
 
  return NONE;
669
 
}
670
 
 
671
 
enum message::TransformSqlError
672
 
message::transformSetVariableStatementToSql(const message::SetVariableStatement &statement,
673
 
                                            std::string *destination,
674
 
                                            enum message::TransformSqlVariant sql_variant)
 
691
enum TransformSqlError
 
692
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
 
693
                                  string &destination,
 
694
                                  enum TransformSqlVariant sql_variant)
 
695
{
 
696
  char quoted_identifier= '`';
 
697
  if (sql_variant == ANSI)
 
698
    quoted_identifier= '"';
 
699
 
 
700
  destination.append("DROP SCHEMA ", 12);
 
701
  destination.push_back(quoted_identifier);
 
702
  destination.append(statement.schema_name());
 
703
  destination.push_back(quoted_identifier);
 
704
 
 
705
  return NONE;
 
706
}
 
707
 
 
708
enum TransformSqlError
 
709
transformCreateSchemaStatementToSql(const CreateSchemaStatement &statement,
 
710
                                    string &destination,
 
711
                                    enum TransformSqlVariant sql_variant)
 
712
{
 
713
  char quoted_identifier= '`';
 
714
  if (sql_variant == ANSI)
 
715
    quoted_identifier= '"';
 
716
 
 
717
  const Schema &schema= statement.schema();
 
718
 
 
719
  destination.append("CREATE SCHEMA ", 14);
 
720
  destination.push_back(quoted_identifier);
 
721
  destination.append(schema.name());
 
722
  destination.push_back(quoted_identifier);
 
723
 
 
724
  if (schema.has_collation())
 
725
  {
 
726
    destination.append(" COLLATE ", 9);
 
727
    destination.append(schema.collation());
 
728
  }
 
729
 
 
730
  return NONE;
 
731
}
 
732
 
 
733
enum TransformSqlError
 
734
transformDropTableStatementToSql(const DropTableStatement &statement,
 
735
                                 string &destination,
 
736
                                 enum TransformSqlVariant sql_variant)
 
737
{
 
738
  char quoted_identifier= '`';
 
739
  if (sql_variant == ANSI)
 
740
    quoted_identifier= '"';
 
741
 
 
742
  const TableMetadata &table_metadata= statement.table_metadata();
 
743
 
 
744
  destination.append("DROP TABLE ", 11);
 
745
 
 
746
  /* Add the IF EXISTS clause if necessary */
 
747
  if (statement.has_if_exists_clause() &&
 
748
      statement.if_exists_clause() == true)
 
749
  {
 
750
    destination.append("IF EXISTS ", 10);
 
751
  }
 
752
 
 
753
  destination.push_back(quoted_identifier);
 
754
  destination.append(table_metadata.schema_name());
 
755
  destination.push_back(quoted_identifier);
 
756
  destination.push_back('.');
 
757
  destination.push_back(quoted_identifier);
 
758
  destination.append(table_metadata.table_name());
 
759
  destination.push_back(quoted_identifier);
 
760
 
 
761
  return NONE;
 
762
}
 
763
 
 
764
enum TransformSqlError
 
765
transformTruncateTableStatementToSql(const TruncateTableStatement &statement,
 
766
                                     string &destination,
 
767
                                     enum TransformSqlVariant sql_variant)
 
768
{
 
769
  char quoted_identifier= '`';
 
770
  if (sql_variant == ANSI)
 
771
    quoted_identifier= '"';
 
772
 
 
773
  const TableMetadata &table_metadata= statement.table_metadata();
 
774
 
 
775
  destination.append("TRUNCATE TABLE ", 15);
 
776
  destination.push_back(quoted_identifier);
 
777
  destination.append(table_metadata.schema_name());
 
778
  destination.push_back(quoted_identifier);
 
779
  destination.push_back('.');
 
780
  destination.push_back(quoted_identifier);
 
781
  destination.append(table_metadata.table_name());
 
782
  destination.push_back(quoted_identifier);
 
783
 
 
784
  return NONE;
 
785
}
 
786
 
 
787
enum TransformSqlError
 
788
transformSetVariableStatementToSql(const SetVariableStatement &statement,
 
789
                                   string &destination,
 
790
                                   enum TransformSqlVariant sql_variant)
675
791
{
676
792
  (void) sql_variant;
677
 
  const message::FieldMetadata &variable_metadata= statement.variable_metadata();
678
 
  bool should_quote_field_value= message::shouldQuoteFieldValue(variable_metadata.type());
679
 
 
680
 
  destination->append("SET GLOBAL ", 11); /* Only global variables are replicated */
681
 
  destination->append(variable_metadata.name());
682
 
  destination->push_back('=');
683
 
 
684
 
  if (should_quote_field_value)
685
 
    destination->push_back('\'');
686
 
  
687
 
  destination->append(statement.variable_value());
688
 
 
689
 
  if (should_quote_field_value)
690
 
    destination->push_back('\'');
691
 
 
692
 
  return NONE;
693
 
}
694
 
 
695
 
bool message::shouldQuoteFieldValue(message::Table::Field::FieldType in_type)
 
793
  const FieldMetadata &variable_metadata= statement.variable_metadata();
 
794
  bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
 
795
 
 
796
  destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
 
797
  destination.append(variable_metadata.name());
 
798
  destination.push_back('=');
 
799
 
 
800
  if (should_quote_field_value)
 
801
    destination.push_back('\'');
 
802
  
 
803
  destination.append(statement.variable_value());
 
804
 
 
805
  if (should_quote_field_value)
 
806
    destination.push_back('\'');
 
807
 
 
808
  return NONE;
 
809
}
 
810
 
 
811
enum TransformSqlError
 
812
transformCreateTableStatementToSql(const CreateTableStatement &statement,
 
813
                                   string &destination,
 
814
                                   enum TransformSqlVariant sql_variant)
 
815
{
 
816
  return transformTableDefinitionToSql(statement.table(), destination, sql_variant);
 
817
}
 
818
 
 
819
enum TransformSqlError
 
820
transformTableDefinitionToSql(const Table &table,
 
821
                              string &destination,
 
822
                              enum TransformSqlVariant sql_variant)
 
823
{
 
824
  char quoted_identifier= '`';
 
825
  if (sql_variant == ANSI)
 
826
    quoted_identifier= '"';
 
827
 
 
828
  destination.append("CREATE ", 7);
 
829
 
 
830
  if (table.type() == Table::TEMPORARY)
 
831
    destination.append("TEMPORARY ", 10);
 
832
  
 
833
  destination.append("TABLE ", 6);
 
834
  destination.push_back(quoted_identifier);
 
835
  destination.append(table.name());
 
836
  destination.push_back(quoted_identifier);
 
837
  destination.append(" (\n", 3);
 
838
 
 
839
  enum TransformSqlError result= NONE;
 
840
  size_t num_fields= table.field_size();
 
841
  for (size_t x= 0; x < num_fields; ++x)
 
842
  {
 
843
    const Table::Field &field= table.field(x);
 
844
 
 
845
    if (x != 0)
 
846
      destination.append(",\n", 2);
 
847
 
 
848
    result= transformFieldDefinitionToSql(field, destination, sql_variant);
 
849
    
 
850
    if (result != NONE)
 
851
      return result;
 
852
  }
 
853
 
 
854
  size_t num_indexes= table.indexes_size();
 
855
  
 
856
  if (num_indexes > 0)
 
857
    destination.append(",\n", 2);
 
858
 
 
859
  for (size_t x= 0; x < num_indexes; ++x)
 
860
  {
 
861
    const message::Table::Index &index= table.indexes(x);
 
862
 
 
863
    if (x != 0)
 
864
      destination.append(",\n", 2);
 
865
 
 
866
    result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
 
867
    
 
868
    if (result != NONE)
 
869
      return result;
 
870
  }
 
871
  destination.append("\n)", 2);
 
872
 
 
873
  /* Add ENGINE = " clause */
 
874
  if (table.has_engine())
 
875
  {
 
876
    const Table::StorageEngine &engine= table.engine();
 
877
    destination.append("\nENGINE = ", 10);
 
878
    destination.append(engine.name());
 
879
 
 
880
    size_t num_engine_options= engine.option_size();
 
881
    for (size_t x= 0; x < num_engine_options; ++x)
 
882
    {
 
883
      const Table::StorageEngine::EngineOption &option= engine.option(x);
 
884
      destination.push_back('\n');
 
885
      destination.append(option.option_name());
 
886
      destination.append(" = ", 3);
 
887
      destination.append(option.option_value());
 
888
      destination.push_back('\n');
 
889
    }
 
890
  }
 
891
 
 
892
  if (table.has_options())
 
893
    (void) transformTableOptionsToSql(table.options(), destination, sql_variant);
 
894
 
 
895
  return NONE;
 
896
}
 
897
 
 
898
enum TransformSqlError
 
899
transformTableOptionsToSql(const Table::TableOptions &options,
 
900
                           string &destination,
 
901
                           enum TransformSqlVariant sql_variant)
 
902
{
 
903
  if (sql_variant == ANSI)
 
904
    return NONE; /* ANSI does not support table options... */
 
905
 
 
906
  stringstream ss;
 
907
 
 
908
  if (options.has_comment())
 
909
  {
 
910
    destination.append("\nCOMMENT = '", 12);
 
911
    destination.append(options.comment());
 
912
    destination.push_back('\'');
 
913
  }
 
914
 
 
915
  if (options.has_collation())
 
916
  {
 
917
    destination.append("\nCOLLATE = ", 11);
 
918
    destination.append(options.collation());
 
919
  }
 
920
 
 
921
  if (options.has_auto_increment())
 
922
  {
 
923
    ss << options.auto_increment();
 
924
    destination.append("\nAUTOINCREMENT_OFFSET = ", 24);
 
925
    destination.append(ss.str());
 
926
    ss.clear();
 
927
  }
 
928
  
 
929
  if (options.has_row_type())
 
930
  {
 
931
    ss << options.row_type();
 
932
    destination.append("\nROW_TYPE = ", 12);
 
933
    destination.append(ss.str());
 
934
    ss.clear();
 
935
  }
 
936
 
 
937
  if (options.has_data_file_name())
 
938
  {
 
939
    destination.append("\nDATA_FILE_NAME = '", 19);
 
940
    destination.append(options.data_file_name());
 
941
    destination.push_back('\'');
 
942
  }
 
943
 
 
944
  if (options.has_index_file_name())
 
945
  {
 
946
    destination.append("\nINDEX_FILE_NAME = '", 20);
 
947
    destination.append(options.index_file_name());
 
948
    destination.push_back('\'');
 
949
  }
 
950
 
 
951
  if (options.has_max_rows())
 
952
  {
 
953
    ss << options.max_rows();
 
954
    destination.append("\nMAX_ROWS = ", 12);
 
955
    destination.append(ss.str());
 
956
    ss.clear();
 
957
  }
 
958
 
 
959
  if (options.has_min_rows())
 
960
  {
 
961
    ss << options.min_rows();
 
962
    destination.append("\nMIN_ROWS = ", 12);
 
963
    destination.append(ss.str());
 
964
    ss.clear();
 
965
  }
 
966
 
 
967
  if (options.has_auto_increment_value())
 
968
  {
 
969
    ss << options.auto_increment_value();
 
970
    destination.append("\nAUTO_INCREMENT = ", 18);
 
971
    destination.append(ss.str());
 
972
    ss.clear();
 
973
  }
 
974
 
 
975
  if (options.has_avg_row_length())
 
976
  {
 
977
    ss << options.avg_row_length();
 
978
    destination.append("\nAVG_ROW_LENGTH = ", 18);
 
979
    destination.append(ss.str());
 
980
    ss.clear();
 
981
  }
 
982
 
 
983
  if (options.has_key_block_size())
 
984
  {
 
985
    ss << options.key_block_size();
 
986
    destination.append("\nKEY_BLOCK_SIZE = ", 18);
 
987
    destination.append(ss.str());
 
988
    ss.clear();
 
989
  }
 
990
 
 
991
  if (options.has_block_size())
 
992
  {
 
993
    ss << options.block_size();
 
994
    destination.append("\nBLOCK_SIZE = ", 14);
 
995
    destination.append(ss.str());
 
996
    ss.clear();
 
997
  }
 
998
 
 
999
  if (options.has_pack_keys() &&
 
1000
      options.pack_keys())
 
1001
    destination.append("\nPACK_KEYS = TRUE", 17);
 
1002
  if (options.has_pack_record() &&
 
1003
      options.pack_record())
 
1004
    destination.append("\nPACK_RECORD = TRUE", 19);
 
1005
  if (options.has_checksum() &&
 
1006
      options.checksum())
 
1007
    destination.append("\nCHECKSUM = TRUE", 16);
 
1008
  if (options.has_page_checksum() &&
 
1009
      options.page_checksum())
 
1010
    destination.append("\nPAGE_CHECKSUM = TRUE", 21);
 
1011
 
 
1012
  return NONE;
 
1013
}
 
1014
 
 
1015
enum TransformSqlError
 
1016
transformIndexDefinitionToSql(const Table::Index &index,
 
1017
                              const Table &table,
 
1018
                              string &destination,
 
1019
                              enum TransformSqlVariant sql_variant)
 
1020
{
 
1021
  char quoted_identifier= '`';
 
1022
  if (sql_variant == ANSI)
 
1023
    quoted_identifier= '"';
 
1024
 
 
1025
  if (index.is_primary())
 
1026
    destination.append("PRIMARY ", 8);
 
1027
  else if (index.is_unique())
 
1028
    destination.append("UNIQUE ", 7);
 
1029
 
 
1030
  destination.append("KEY ", 4);
 
1031
  destination.push_back(quoted_identifier);
 
1032
  destination.append(index.name());
 
1033
  destination.push_back(quoted_identifier);
 
1034
  destination.append(" (", 2);
 
1035
  
 
1036
  size_t num_parts= index.index_part_size();
 
1037
  for (size_t x= 0; x < num_parts; ++x)
 
1038
  {
 
1039
    const Table::Index::IndexPart &part= index.index_part(x);
 
1040
    const Table::Field &field= table.field(part.fieldnr());
 
1041
 
 
1042
    if (x != 0)
 
1043
      destination.push_back(',');
 
1044
    
 
1045
    destination.push_back(quoted_identifier);
 
1046
    destination.append(field.name());
 
1047
    destination.push_back(quoted_identifier);
 
1048
 
 
1049
    /* 
 
1050
     * If the index part's field type is VARCHAR or TEXT
 
1051
     * then check for a prefix length then is different
 
1052
     * from the field's full length...
 
1053
     */
 
1054
    if (field.type() == Table::Field::VARCHAR ||
 
1055
        field.type() == Table::Field::BLOB)
 
1056
    {
 
1057
      if (part.has_compare_length())
 
1058
      {
 
1059
        size_t compare_length_in_chars= part.compare_length();
 
1060
        
 
1061
        /* hack: compare_length() is bytes, not chars, but
 
1062
         * only for VARCHAR. Ass. */
 
1063
        if (field.type() == Table::Field::VARCHAR)
 
1064
          compare_length_in_chars/= 4;
 
1065
 
 
1066
        if (compare_length_in_chars != field.string_options().length())
 
1067
        {
 
1068
          stringstream ss;
 
1069
          destination.push_back('(');
 
1070
          ss << compare_length_in_chars;
 
1071
          destination.append(ss.str());
 
1072
          destination.push_back(')');
 
1073
        }
 
1074
      }
 
1075
    }
 
1076
  }
 
1077
  destination.push_back(')');
 
1078
 
 
1079
  return NONE;
 
1080
}
 
1081
 
 
1082
enum TransformSqlError
 
1083
transformFieldDefinitionToSql(const Table::Field &field,
 
1084
                              string &destination,
 
1085
                              enum TransformSqlVariant sql_variant)
 
1086
{
 
1087
  char quoted_identifier= '`';
 
1088
  if (sql_variant == ANSI)
 
1089
    quoted_identifier= '"';
 
1090
 
 
1091
  destination.push_back(quoted_identifier);
 
1092
  destination.append(field.name());
 
1093
  destination.push_back(quoted_identifier);
 
1094
 
 
1095
  Table::Field::FieldType field_type= field.type();
 
1096
 
 
1097
  switch (field_type)
 
1098
  {
 
1099
    case Table::Field::DOUBLE:
 
1100
    destination.append(" DOUBLE", 7);
 
1101
    break;
 
1102
  case Table::Field::VARCHAR:
 
1103
    {
 
1104
      destination.append(" VARCHAR(", 9);
 
1105
      stringstream ss;
 
1106
      ss << field.string_options().length() << ")";
 
1107
      destination.append(ss.str());
 
1108
    }
 
1109
    break;
 
1110
  case Table::Field::BLOB:
 
1111
    destination.append(" BLOB", 5);
 
1112
    break;
 
1113
  case Table::Field::ENUM:
 
1114
    {
 
1115
      size_t num_field_values= field.set_options().field_value_size();
 
1116
      destination.append(" ENUM(", 6);
 
1117
      for (size_t x= 0; x < num_field_values; ++x)
 
1118
      {
 
1119
        const string &type= field.set_options().field_value(x);
 
1120
 
 
1121
        if (x != 0)
 
1122
          destination.push_back(',');
 
1123
 
 
1124
        destination.push_back('\'');
 
1125
        destination.append(type);
 
1126
        destination.push_back('\'');
 
1127
      }
 
1128
      destination.push_back(')');
 
1129
      break;
 
1130
    }
 
1131
  case Table::Field::INTEGER:
 
1132
    destination.append(" INT", 4);
 
1133
    break;
 
1134
  case Table::Field::BIGINT:
 
1135
    destination.append(" BIGINT", 7);
 
1136
    break;
 
1137
  case Table::Field::DECIMAL:
 
1138
    {
 
1139
      destination.append(" DECIMAL(", 9);
 
1140
      stringstream ss;
 
1141
      ss << field.numeric_options().precision() << ",";
 
1142
      ss << field.numeric_options().scale() << ")";
 
1143
      destination.append(ss.str());
 
1144
    }
 
1145
    break;
 
1146
  case Table::Field::DATE:
 
1147
    destination.append(" DATE", 5);
 
1148
    break;
 
1149
  case Table::Field::TIMESTAMP:
 
1150
    destination.append(" TIMESTAMP",  10);
 
1151
    break;
 
1152
  case Table::Field::DATETIME:
 
1153
    destination.append(" DATETIME",  9);
 
1154
    break;
 
1155
  }
 
1156
 
 
1157
  if (field.type() == Table::Field::INTEGER || 
 
1158
      field.type() == Table::Field::BIGINT)
 
1159
  {
 
1160
    if (field.has_constraints() &&
 
1161
        field.constraints().has_is_unsigned() &&
 
1162
        field.constraints().is_unsigned())
 
1163
    {
 
1164
      destination.append(" UNSIGNED", 9);
 
1165
    }
 
1166
  }
 
1167
 
 
1168
 
 
1169
  if (! (field.has_constraints() &&
 
1170
         field.constraints().is_nullable()))
 
1171
  {
 
1172
    destination.append(" NOT", 4);
 
1173
  }
 
1174
  destination.append(" NULL", 5);
 
1175
 
 
1176
  if (field.type() == Table::Field::INTEGER || 
 
1177
      field.type() == Table::Field::BIGINT)
 
1178
  {
 
1179
    /* AUTO_INCREMENT must be after NOT NULL */
 
1180
    if (field.has_numeric_options() &&
 
1181
        field.numeric_options().is_autoincrement())
 
1182
    {
 
1183
      destination.append(" AUTO_INCREMENT", 15);
 
1184
    }
 
1185
  }
 
1186
 
 
1187
  if (field.type() == Table::Field::BLOB ||
 
1188
      field.type() == Table::Field::VARCHAR)
 
1189
  {
 
1190
    if (field.string_options().has_collation())
 
1191
    {
 
1192
      destination.append(" COLLATE ", 9);
 
1193
      destination.append(field.string_options().collation());
 
1194
    }
 
1195
  }
 
1196
 
 
1197
  if (field.options().has_default_value())
 
1198
  {
 
1199
    destination.append(" DEFAULT ", 9);
 
1200
    destination.push_back(quoted_identifier);
 
1201
    destination.append(field.options().default_value());
 
1202
    destination.push_back(quoted_identifier);
 
1203
  }
 
1204
 
 
1205
  if (field.options().has_default_bin_value())
 
1206
  {
 
1207
    const string &v= field.options().default_bin_value();
 
1208
    destination.append(" DEFAULT 0x", 11);
 
1209
    for (size_t x= 0; x < v.length(); x++)
 
1210
    {
 
1211
      printf("%.2x", *(v.c_str() + x));
 
1212
    }
 
1213
  }
 
1214
 
 
1215
  if (field.type() == Table::Field::TIMESTAMP)
 
1216
    if (field.timestamp_options().has_auto_updates() &&
 
1217
        field.timestamp_options().auto_updates())
 
1218
      destination.append(" ON UPDATE CURRENT_TIMESTAMP", 28);
 
1219
 
 
1220
  if (field.has_comment())
 
1221
  {
 
1222
    destination.append(" COMMENT ", 9);
 
1223
    destination.push_back(quoted_identifier);
 
1224
    destination.append(field.comment());
 
1225
    destination.push_back(quoted_identifier);
 
1226
  }
 
1227
  return NONE;
 
1228
}
 
1229
 
 
1230
bool shouldQuoteFieldValue(Table::Field::FieldType in_type)
696
1231
{
697
1232
  switch (in_type)
698
1233
  {
699
 
  case message::Table::Field::DOUBLE:
700
 
  case message::Table::Field::DECIMAL:
701
 
  case message::Table::Field::INTEGER:
702
 
  case message::Table::Field::BIGINT:
703
 
  case message::Table::Field::ENUM:
 
1234
  case Table::Field::DOUBLE:
 
1235
  case Table::Field::DECIMAL:
 
1236
  case Table::Field::INTEGER:
 
1237
  case Table::Field::BIGINT:
 
1238
  case Table::Field::ENUM:
704
1239
    return false;
705
1240
  default:
706
1241
    return true;
707
1242
  } 
708
1243
}
709
1244
 
710
 
drizzled::message::Table::Field::FieldType message::internalFieldTypeToFieldProtoType(enum enum_field_types type)
 
1245
Table::Field::FieldType internalFieldTypeToFieldProtoType(enum enum_field_types type)
711
1246
{
712
1247
  switch (type) {
713
1248
  case DRIZZLE_TYPE_LONG:
714
 
    return message::Table::Field::INTEGER;
 
1249
    return Table::Field::INTEGER;
715
1250
  case DRIZZLE_TYPE_DOUBLE:
716
 
    return message::Table::Field::DOUBLE;
 
1251
    return Table::Field::DOUBLE;
717
1252
  case DRIZZLE_TYPE_NULL:
718
1253
    assert(false); /* Not a user definable type */
719
 
    return message::Table::Field::INTEGER; /* unreachable */
 
1254
    return Table::Field::INTEGER; /* unreachable */
720
1255
  case DRIZZLE_TYPE_TIMESTAMP:
721
 
    return message::Table::Field::TIMESTAMP;
 
1256
    return Table::Field::TIMESTAMP;
722
1257
  case DRIZZLE_TYPE_LONGLONG:
723
 
    return message::Table::Field::BIGINT;
 
1258
    return Table::Field::BIGINT;
724
1259
  case DRIZZLE_TYPE_DATETIME:
725
 
    return message::Table::Field::DATETIME;
 
1260
    return Table::Field::DATETIME;
726
1261
  case DRIZZLE_TYPE_DATE:
727
 
    return message::Table::Field::DATE;
 
1262
    return Table::Field::DATE;
728
1263
  case DRIZZLE_TYPE_VARCHAR:
729
 
    return message::Table::Field::VARCHAR;
 
1264
    return Table::Field::VARCHAR;
730
1265
  case DRIZZLE_TYPE_DECIMAL:
731
 
    return message::Table::Field::DECIMAL;
 
1266
    return Table::Field::DECIMAL;
732
1267
  case DRIZZLE_TYPE_ENUM:
733
 
    return message::Table::Field::ENUM;
 
1268
    return Table::Field::ENUM;
734
1269
  case DRIZZLE_TYPE_BLOB:
735
 
    return message::Table::Field::BLOB;
 
1270
    return Table::Field::BLOB;
736
1271
  }
737
1272
 
738
1273
  assert(false);
739
 
  return message::Table::Field::INTEGER; /* unreachable */
 
1274
  return Table::Field::INTEGER; /* unreachable */
740
1275
}
741
1276
 
 
1277
} /* namespace message */
742
1278
} /* namespace drizzled */