~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

  • Committer: Stewart Smith
  • Date: 2011-01-14 05:18:23 UTC
  • mto: (2086.1.3 build)
  • mto: This revision was merged to the branch mainline in revision 2087.
  • Revision ID: stewart@flamingspork.com-20110114051823-14fyn2kvg8pc5a15
\r and trailing whitespace removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
#include "config.h"
17
17
#include <drizzled/error.h>
32
32
#include <drizzled/message/table.pb.h>
33
33
#include <google/protobuf/io/zero_copy_stream.h>
34
34
#include <google/protobuf/io/zero_copy_stream_impl.h>
 
35
#include <google/protobuf/message.h>
35
36
 
36
37
#include <drizzled/table_proto.h>
 
38
#include <drizzled/charset.h>
 
39
 
 
40
#include "drizzled/function/time/typecast.h"
37
41
 
38
42
using namespace std;
39
43
 
40
44
namespace drizzled {
41
45
 
42
 
static int fill_table_proto(message::Table &table_proto,
43
 
                            const std::string &table_name,
44
 
                            List<CreateField> &create_fields,
45
 
                            HA_CREATE_INFO *create_info,
46
 
                            uint32_t keys,
47
 
                            KEY *key_info)
 
46
bool fill_table_proto(message::Table &table_proto,
 
47
                      List<CreateField> &create_fields,
 
48
                      HA_CREATE_INFO *create_info,
 
49
                      uint32_t keys,
 
50
                      KeyInfo *key_info)
48
51
{
49
52
  CreateField *field_arg;
50
53
  List_iterator<CreateField> it(create_fields);
53
56
  if (create_fields.elements > MAX_FIELDS)
54
57
  {
55
58
    my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
56
 
    return(1);
 
59
    return true;
57
60
  }
58
61
 
59
62
  assert(strcmp(table_proto.engine().name().c_str(),
60
63
                create_info->db_type->getName().c_str())==0);
61
64
 
62
 
  assert(table_proto.name() == table_name);
63
 
 
64
65
  int field_number= 0;
65
66
  bool use_existing_fields= table_proto.field_size() > 0;
66
67
  while ((field_arg= it++))
72
73
       filled out Field messages */
73
74
 
74
75
    if (use_existing_fields)
 
76
    {
75
77
      attribute= table_proto.mutable_field(field_number++);
 
78
    }
76
79
    else
77
80
    {
78
81
      /* Other code paths still have to fill out the proto */
80
83
 
81
84
      if (field_arg->flags & NOT_NULL_FLAG)
82
85
      {
83
 
        message::Table::Field::FieldConstraints *constraints;
 
86
        attribute->mutable_constraints()->set_is_notnull(true);
 
87
      }
84
88
 
85
 
        constraints= attribute->mutable_constraints();
86
 
        constraints->set_is_nullable(false);
 
89
      if (field_arg->flags & UNSIGNED_FLAG and 
 
90
          (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
 
91
      {
 
92
        field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
 
93
        attribute->mutable_constraints()->set_is_unsigned(true);
87
94
      }
88
95
 
89
96
      attribute->set_name(field_arg->field_name);
90
97
    }
91
98
 
92
 
    assert((!(field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_nullable());
 
99
    assert(((field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_notnull());
93
100
    assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
94
101
 
95
102
 
96
103
    message::Table::Field::FieldType parser_type= attribute->type();
97
104
 
 
105
    if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
 
106
    {
 
107
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
 
108
      return true;
 
109
    }
 
110
 
 
111
    if (field_arg->flags & UNSIGNED_FLAG and 
 
112
       (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
 
113
    {
 
114
      message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
 
115
 
 
116
      field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
 
117
      constraints->set_is_unsigned(true);
 
118
    }
 
119
 
98
120
    attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
99
121
 
100
122
    switch (attribute->type()) {
101
 
    default: /* Only deal with types that need extra information */
 
123
    case message::Table::Field::BIGINT:
 
124
    case message::Table::Field::INTEGER:
 
125
    case message::Table::Field::DATE:
 
126
    case message::Table::Field::DATETIME:
 
127
    case message::Table::Field::UUID:
 
128
    case message::Table::Field::TIME:
 
129
    case message::Table::Field::BOOLEAN:
102
130
      break;
103
131
    case message::Table::Field::DOUBLE:
104
132
      {
164
192
        enumeration_options->set_collation(field_arg->charset->name);
165
193
        break;
166
194
      }
 
195
 
167
196
    case message::Table::Field::BLOB:
168
197
      {
169
198
        message::Table::Field::StringFieldOptions *string_field_options;
174
203
      }
175
204
 
176
205
      break;
 
206
 
 
207
    case message::Table::Field::EPOCH:
 
208
      {
 
209
        if (field_arg->sql_type == DRIZZLE_TYPE_MICROTIME)
 
210
          attribute->mutable_time_options()->set_microseconds(true);
 
211
      }
 
212
 
 
213
      break;
177
214
    }
178
215
 
179
216
    assert (!use_existing_fields || parser_type == attribute->type());
183
220
    constraints->set_is_nullable(field_arg->def->null_value);
184
221
#endif
185
222
 
186
 
    switch(field_arg->column_format())
187
 
    {
188
 
    case COLUMN_FORMAT_TYPE_NOT_USED:
189
 
      break;
190
 
    case COLUMN_FORMAT_TYPE_DEFAULT:
191
 
      attribute->set_format(message::Table::Field::DefaultFormat);
192
 
      break;
193
 
    case COLUMN_FORMAT_TYPE_FIXED:
194
 
      attribute->set_format(message::Table::Field::FixedFormat);
195
 
      break;
196
 
    case COLUMN_FORMAT_TYPE_DYNAMIC:
197
 
      attribute->set_format(message::Table::Field::DynamicFormat);
198
 
      break;
199
 
    default:
200
 
      assert(0); /* Tell us, since this shouldn't happend */
201
 
    }
202
 
 
203
223
    if (field_arg->comment.length)
204
224
    {
205
225
      uint32_t tmp_len;
214
234
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
215
235
                 field_arg->comment.str,"COLUMN COMMENT",
216
236
                 (uint32_t) COLUMN_COMMENT_MAXLEN);
217
 
        return(1);
 
237
        return true;
218
238
      }
219
239
 
220
240
      if (! use_existing_fields)
235
255
    {
236
256
      message::Table::Field::FieldOptions *field_options;
237
257
      field_options= attribute->mutable_options();
238
 
      field_options->set_default_value("NOW()");
 
258
      field_options->set_default_expression("CURRENT_TIMESTAMP");
239
259
    }
240
260
 
241
261
    if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
243
263
    {
244
264
      message::Table::Field::FieldOptions *field_options;
245
265
      field_options= attribute->mutable_options();
246
 
      field_options->set_update_value("NOW()");
 
266
      field_options->set_update_expression("CURRENT_TIMESTAMP");
247
267
    }
248
268
 
249
 
    if (field_arg->def == NULL  && attribute->constraints().is_nullable())
 
269
    if (field_arg->def == NULL  && not attribute->constraints().is_notnull())
250
270
    {
251
271
      message::Table::Field::FieldOptions *field_options;
252
272
      field_options= attribute->mutable_options();
275
295
           < default_value->length()))
276
296
        {
277
297
          my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
278
 
          return 1;
 
298
          return true;
279
299
        }
280
300
 
 
301
        if (field_arg->sql_type == DRIZZLE_TYPE_DATE
 
302
            || field_arg->sql_type == DRIZZLE_TYPE_TIME
 
303
            || field_arg->sql_type == DRIZZLE_TYPE_DATETIME
 
304
            || field_arg->sql_type == DRIZZLE_TYPE_MICROTIME
 
305
            || field_arg->sql_type == DRIZZLE_TYPE_TIMESTAMP)
 
306
        {
 
307
          type::Time ltime;
 
308
 
 
309
          if (field_arg->def->get_date(&ltime, TIME_FUZZY_DATE))
 
310
          {
 
311
            my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
 
312
                     default_value->c_str());
 
313
            return true;
 
314
          }
 
315
 
 
316
          /* We now do the casting down to the appropriate type.
 
317
 
 
318
             Yes, this implicit casting is balls.
 
319
             It was previously done on reading the proto back in,
 
320
             but we really shouldn't store the bogus things in the proto,
 
321
             and instead do the casting behaviour here.
 
322
 
 
323
             the timestamp errors are taken care of elsewhere.
 
324
          */
 
325
 
 
326
          if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
 
327
          {
 
328
            Item *typecast= new Item_datetime_typecast(field_arg->def);
 
329
            typecast->quick_fix_field();
 
330
            typecast->val_str(default_value);
 
331
          }
 
332
          else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
 
333
          {
 
334
            Item *typecast= new Item_date_typecast(field_arg->def);
 
335
            typecast->quick_fix_field();
 
336
            typecast->val_str(default_value);
 
337
          }
 
338
        }
 
339
 
281
340
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
282
341
            && field_arg->charset==&my_charset_bin)
283
342
           || (field_arg->sql_type==DRIZZLE_TYPE_BLOB
308
367
  if (create_info->table_options & HA_OPTION_PACK_RECORD)
309
368
    table_options->set_pack_record(true);
310
369
 
 
370
  if (table_options->has_comment() && table_options->comment().length() == 0)
 
371
    table_options->clear_comment();
 
372
 
311
373
  if (table_options->has_comment())
312
374
  {
313
375
    uint32_t tmp_len;
322
384
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
323
385
               table_options->comment().c_str(),"Table COMMENT",
324
386
               (uint32_t) TABLE_COMMENT_MAXLEN);
325
 
      return(1);
 
387
      return true;
326
388
    }
327
389
  }
328
390
 
329
391
  if (create_info->default_table_charset)
330
392
  {
331
 
    table_options->set_collation_id(
332
 
                               create_info->default_table_charset->number);
 
393
    table_options->set_collation_id(create_info->default_table_charset->number);
333
394
    table_options->set_collation(create_info->default_table_charset->name);
334
395
  }
335
396
 
 
397
  if (create_info->used_fields & HA_CREATE_USED_AUTO)
 
398
    table_options->set_has_user_set_auto_increment_value(true);
 
399
  else
 
400
    table_options->set_has_user_set_auto_increment_value(false);
 
401
 
336
402
  if (create_info->auto_increment_value)
337
403
    table_options->set_auto_increment_value(create_info->auto_increment_value);
338
404
 
377
443
    else
378
444
      idx->set_is_unique(false);
379
445
 
380
 
    message::Table::Index::IndexOptions *index_options= idx->mutable_options();
 
446
    message::Table::Index::Options *index_options= idx->mutable_options();
381
447
 
382
448
    if (key_info[i].flags & HA_USES_BLOCK_SIZE)
383
449
      index_options->set_key_block_size(key_info[i].block_size);
414
480
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
415
481
                 key_info[i].comment.str,"Index COMMENT",
416
482
                 (uint32_t) TABLE_COMMENT_MAXLEN);
417
 
        return(1);
 
483
        return true;
418
484
      }
419
485
 
420
486
      idx->set_comment(key_info[i].comment.str);
421
487
    }
422
 
    if (key_info[i].flags & 
423
 
        ~(HA_NOSAME | HA_PACK_KEY | HA_USES_BLOCK_SIZE | 
424
 
          HA_BINARY_PACK_KEY | HA_VAR_LENGTH_PART | HA_NULL_PART_KEY | 
425
 
          HA_KEY_HAS_PART_KEY_SEG | HA_GENERATED_KEY | HA_USES_COMMENT))
 
488
    static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
 
489
                                               HA_USES_BLOCK_SIZE | 
 
490
                                               HA_BINARY_PACK_KEY |
 
491
                                               HA_VAR_LENGTH_PART |
 
492
                                               HA_NULL_PART_KEY | 
 
493
                                               HA_KEY_HAS_PART_KEY_SEG |
 
494
                                               HA_GENERATED_KEY |
 
495
                                               HA_USES_COMMENT);
 
496
    if (key_info[i].flags & ~unknown_index_flag)
426
497
      abort(); // Invalid (unknown) index flag.
427
498
 
428
499
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
429
500
    {
430
501
      message::Table::Index::IndexPart *idxpart;
 
502
      const int fieldnr= key_info[i].key_part[j].fieldnr;
 
503
      int mbmaxlen= 1;
431
504
 
432
505
      idxpart= idx->add_index_part();
433
506
 
434
 
      idxpart->set_fieldnr(key_info[i].key_part[j].fieldnr);
435
 
 
436
 
      idxpart->set_compare_length(key_info[i].key_part[j].length);
437
 
 
438
 
      idxpart->set_key_type(key_info[i].key_part[j].key_type);
439
 
 
440
 
    }
441
 
  }
442
 
 
443
 
  return 0;
 
507
      idxpart->set_fieldnr(fieldnr);
 
508
 
 
509
      if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
 
510
          || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
 
511
      {
 
512
        uint32_t collation_id;
 
513
 
 
514
        if (table_proto.field(fieldnr).string_options().has_collation_id())
 
515
          collation_id= table_proto.field(fieldnr).string_options().collation_id();
 
516
        else
 
517
          collation_id= table_proto.options().collation_id();
 
518
 
 
519
        const CHARSET_INFO *cs= get_charset(collation_id);
 
520
 
 
521
        mbmaxlen= cs->mbmaxlen;
 
522
      }
 
523
 
 
524
      idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
 
525
    }
 
526
  }
 
527
 
 
528
  if (not table_proto.IsInitialized())
 
529
  {
 
530
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
 
531
             table_proto.name().c_str(),
 
532
             table_proto.InitializationErrorString().c_str());
 
533
 
 
534
    return true;
 
535
  }
 
536
 
 
537
  /*
 
538
    Here we test to see if we can validate the Table Message before we continue. 
 
539
    We do this by serializing the protobuffer.
 
540
  */
 
541
  {
 
542
    string tmp_string;
 
543
 
 
544
    try {
 
545
      table_proto.SerializeToString(&tmp_string);
 
546
    }
 
547
 
 
548
    catch (...)
 
549
    {
 
550
      my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
 
551
               table_proto.name().c_str(),
 
552
               table_proto.InitializationErrorString().c_str());
 
553
 
 
554
      return true;
 
555
    }
 
556
  }
 
557
 
 
558
  return false;
444
559
}
445
560
 
446
561
/*
463
578
*/
464
579
 
465
580
bool rea_create_table(Session *session,
466
 
                      TableIdentifier &identifier,
 
581
                      const TableIdentifier &identifier,
467
582
                      message::Table &table_proto,
468
583
                      HA_CREATE_INFO *create_info,
469
584
                      List<CreateField> &create_fields,
470
 
                      uint32_t keys, KEY *key_info)
 
585
                      uint32_t keys, KeyInfo *key_info)
471
586
{
472
 
  if (fill_table_proto(table_proto, identifier.getTableName(), create_fields, create_info,
 
587
  assert(table_proto.has_name());
 
588
  if (fill_table_proto(table_proto, create_fields, create_info,
473
589
                       keys, key_info))
 
590
  {
474
591
    return false;
 
592
  }
 
593
 
 
594
  assert(table_proto.name() == identifier.getTableName());
475
595
 
476
596
  if (plugin::StorageEngine::createTable(*session,
477
597
                                         identifier,
478
 
                                         false, table_proto))
 
598
                                         table_proto))
479
599
  {
480
600
    return false;
481
601
  }