~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

OK, Sun Studio still didn't like that...seems to think that inline means something different than other compilers think it is...

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