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 */
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>
36
37
#include <drizzled/table_proto.h>
38
#include <drizzled/charset.h>
40
#include "drizzled/function/time/typecast.h"
38
42
using namespace std;
40
44
namespace drizzled {
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
bool fill_table_proto(message::Table &table_proto,
47
List<CreateField> &create_fields,
48
HA_CREATE_INFO *create_info,
49
52
CreateField *field_arg;
50
53
List_iterator<CreateField> it(create_fields);
53
56
if (create_fields.elements > MAX_FIELDS)
55
58
my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
59
62
assert(strcmp(table_proto.engine().name().c_str(),
60
63
create_info->db_type->getName().c_str())==0);
62
assert(table_proto.name() == table_name);
64
65
int field_number= 0;
65
66
bool use_existing_fields= table_proto.field_size() > 0;
66
67
while ((field_arg= it++))
81
84
if (field_arg->flags & NOT_NULL_FLAG)
83
message::Table::Field::FieldConstraints *constraints;
86
attribute->mutable_constraints()->set_is_notnull(true);
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))
92
field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
93
attribute->mutable_constraints()->set_is_unsigned(true);
89
96
attribute->set_name(field_arg->field_name);
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);
96
103
message::Table::Field::FieldType parser_type= attribute->type();
105
if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
107
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
111
if (field_arg->flags & UNSIGNED_FLAG and
112
(field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
114
message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
116
field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
117
constraints->set_is_unsigned(true);
98
120
attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
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:
103
131
case message::Table::Field::DOUBLE:
183
220
constraints->set_is_nullable(field_arg->def->null_value);
186
switch(field_arg->column_format())
188
case COLUMN_FORMAT_TYPE_NOT_USED:
190
case COLUMN_FORMAT_TYPE_DEFAULT:
191
attribute->set_format(message::Table::Field::DefaultFormat);
193
case COLUMN_FORMAT_TYPE_FIXED:
194
attribute->set_format(message::Table::Field::FixedFormat);
196
case COLUMN_FORMAT_TYPE_DYNAMIC:
197
attribute->set_format(message::Table::Field::DynamicFormat);
200
assert(0); /* Tell us, since this shouldn't happend */
203
223
if (field_arg->comment.length)
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);
220
240
if (! use_existing_fields)
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");
241
261
if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
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");
249
if (field_arg->def == NULL && attribute->constraints().is_nullable())
269
if (field_arg->def == NULL && not attribute->constraints().is_notnull())
251
271
message::Table::Field::FieldOptions *field_options;
252
272
field_options= attribute->mutable_options();
275
295
< default_value->length()))
277
297
my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
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)
309
if (field_arg->def->get_date(<ime, TIME_FUZZY_DATE))
311
my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
312
default_value->c_str());
316
/* We now do the casting down to the appropriate type.
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.
323
the timestamp errors are taken care of elsewhere.
326
if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
328
Item *typecast= new Item_datetime_typecast(field_arg->def);
329
typecast->quick_fix_field();
330
typecast->val_str(default_value);
332
else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
334
Item *typecast= new Item_date_typecast(field_arg->def);
335
typecast->quick_fix_field();
336
typecast->val_str(default_value);
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);
370
if (table_options->has_comment() && table_options->comment().length() == 0)
371
table_options->clear_comment();
311
373
if (table_options->has_comment())
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);
329
391
if (create_info->default_table_charset)
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);
397
if (create_info->used_fields & HA_CREATE_USED_AUTO)
398
table_options->set_has_user_set_auto_increment_value(true);
400
table_options->set_has_user_set_auto_increment_value(false);
336
402
if (create_info->auto_increment_value)
337
403
table_options->set_auto_increment_value(create_info->auto_increment_value);
378
444
idx->set_is_unique(false);
380
message::Table::Index::IndexOptions *index_options= idx->mutable_options();
446
message::Table::Index::Options *index_options= idx->mutable_options();
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);
420
486
idx->set_comment(key_info[i].comment.str);
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 |
493
HA_KEY_HAS_PART_KEY_SEG |
496
if (key_info[i].flags & ~unknown_index_flag)
426
497
abort(); // Invalid (unknown) index flag.
428
499
for(unsigned int j=0; j< key_info[i].key_parts; j++)
430
501
message::Table::Index::IndexPart *idxpart;
502
const int fieldnr= key_info[i].key_part[j].fieldnr;
432
505
idxpart= idx->add_index_part();
434
idxpart->set_fieldnr(key_info[i].key_part[j].fieldnr);
436
idxpart->set_compare_length(key_info[i].key_part[j].length);
438
idxpart->set_key_type(key_info[i].key_part[j].key_type);
507
idxpart->set_fieldnr(fieldnr);
509
if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
510
|| table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
512
uint32_t collation_id;
514
if (table_proto.field(fieldnr).string_options().has_collation_id())
515
collation_id= table_proto.field(fieldnr).string_options().collation_id();
517
collation_id= table_proto.options().collation_id();
519
const CHARSET_INFO *cs= get_charset(collation_id);
521
mbmaxlen= cs->mbmaxlen;
524
idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
528
if (not table_proto.IsInitialized())
530
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
531
table_proto.name().c_str(),
532
table_proto.InitializationErrorString().c_str());
538
Here we test to see if we can validate the Table Message before we continue.
539
We do this by serializing the protobuffer.
545
table_proto.SerializeToString(&tmp_string);
550
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
551
table_proto.name().c_str(),
552
table_proto.InitializationErrorString().c_str());
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)
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,
594
assert(table_proto.name() == identifier.getTableName());
476
596
if (plugin::StorageEngine::createTable(*session,