~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/statement_transform.cc

pandora-build v0.72 - Moved remaining hard-coded tests into pandora-build
macros.
Add PANDORA_DRIZZLE_BUILD to run the extra checks that drizzle needs that 
plugins would also need to run so we can just use that macro in generated
external plugin builds.
Added support to register_plugins for external plugin building.
Renamed register_plugins.py to pandora-plugin.

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