00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017 #include <drizzled/error.h>
00018 #include <drizzled/session.h>
00019 #include <drizzled/unireg.h>
00020 #include <drizzled/sql_table.h>
00021 #include <drizzled/global_charset_info.h>
00022 #include <drizzled/message/statement_transform.h>
00023
00024 #include <drizzled/plugin/storage_engine.h>
00025
00026 #include <drizzled/internal/my_sys.h>
00027 #include <drizzled/typelib.h>
00028
00029
00030 #include <string>
00031 #include <fstream>
00032 #include <fcntl.h>
00033 #include <drizzled/message/schema.h>
00034 #include <drizzled/message/table.h>
00035 #include <google/protobuf/io/zero_copy_stream.h>
00036 #include <google/protobuf/io/zero_copy_stream_impl.h>
00037 #include <google/protobuf/message.h>
00038
00039 #include <drizzled/table_proto.h>
00040 #include <drizzled/charset.h>
00041
00042 #include <drizzled/function/time/typecast.h>
00043
00044 using namespace std;
00045
00046 namespace drizzled {
00047
00048 static
00049 bool fill_table_proto(identifier::Table::const_reference identifier,
00050 message::Table &table_proto,
00051 List<CreateField> &create_fields,
00052 HA_CREATE_INFO *create_info,
00053 uint32_t keys,
00054 KeyInfo *key_info)
00055 {
00056 CreateField *field_arg;
00057 List<CreateField>::iterator it(create_fields.begin());
00058 message::Table::TableOptions *table_options= table_proto.mutable_options();
00059
00060 if (create_fields.size() > MAX_FIELDS)
00061 {
00062 my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
00063 return true;
00064 }
00065
00066 assert(strcmp(table_proto.engine().name().c_str(),
00067 create_info->db_type->getName().c_str())==0);
00068
00069 message::schema::shared_ptr schema_message= plugin::StorageEngine::getSchemaDefinition(identifier);
00070
00071 if (schema_message and not message::is_replicated(*schema_message))
00072 {
00073 message::set_is_replicated(table_proto, false);
00074 }
00075
00076 int field_number= 0;
00077 bool use_existing_fields= table_proto.field_size() > 0;
00078 while ((field_arg= it++))
00079 {
00080 message::Table::Field *attribute;
00081
00082
00083
00084
00085
00086 if (use_existing_fields)
00087 {
00088 attribute= table_proto.mutable_field(field_number++);
00089 }
00090 else
00091 {
00092
00093 attribute= table_proto.add_field();
00094
00095 if (field_arg->flags & NOT_NULL_FLAG)
00096 {
00097 attribute->mutable_constraints()->set_is_notnull(true);
00098 }
00099
00100 if (field_arg->flags & UNSIGNED_FLAG and
00101 (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
00102 {
00103 field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
00104 attribute->mutable_constraints()->set_is_unsigned(true);
00105 }
00106
00107 attribute->set_name(field_arg->field_name);
00108 }
00109
00110 assert(((field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_notnull());
00111 assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
00112
00113
00114 message::Table::Field::FieldType parser_type= attribute->type();
00115
00116 if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
00117 {
00118 my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
00119 return true;
00120 }
00121
00122 if (field_arg->flags & UNSIGNED_FLAG and
00123 (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
00124 {
00125 message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
00126
00127 field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
00128 constraints->set_is_unsigned(true);
00129 }
00130
00131 attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
00132
00133 switch (attribute->type()) {
00134 case message::Table::Field::BIGINT:
00135 case message::Table::Field::INTEGER:
00136 case message::Table::Field::DATE:
00137 case message::Table::Field::DATETIME:
00138 case message::Table::Field::UUID:
00139 case message::Table::Field::TIME:
00140 case message::Table::Field::BOOLEAN:
00141 break;
00142 case message::Table::Field::DOUBLE:
00143 {
00144
00145
00146
00147
00148 if (field_arg->decimals != NOT_FIXED_DEC)
00149 {
00150 message::Table::Field::NumericFieldOptions *numeric_field_options;
00151
00152 numeric_field_options= attribute->mutable_numeric_options();
00153
00154 numeric_field_options->set_precision(field_arg->length);
00155 numeric_field_options->set_scale(field_arg->decimals);
00156 }
00157 }
00158 break;
00159 case message::Table::Field::VARCHAR:
00160 {
00161 message::Table::Field::StringFieldOptions *string_field_options;
00162
00163 string_field_options= attribute->mutable_string_options();
00164
00165 if (! use_existing_fields || string_field_options->length()==0)
00166 string_field_options->set_length(field_arg->length
00167 / field_arg->charset->mbmaxlen);
00168 else
00169 assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
00170
00171 if (! string_field_options->has_collation())
00172 {
00173 string_field_options->set_collation_id(field_arg->charset->number);
00174 string_field_options->set_collation(field_arg->charset->name);
00175 }
00176 break;
00177 }
00178 case message::Table::Field::DECIMAL:
00179 {
00180 message::Table::Field::NumericFieldOptions *numeric_field_options;
00181
00182 numeric_field_options= attribute->mutable_numeric_options();
00183
00184 numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
00185 numeric_field_options->set_scale(field_arg->decimals);
00186 break;
00187 }
00188 case message::Table::Field::ENUM:
00189 {
00190 message::Table::Field::EnumerationValues *enumeration_options;
00191
00192 assert(field_arg->interval);
00193
00194 enumeration_options= attribute->mutable_enumeration_values();
00195
00196 for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
00197 {
00198 const char *src= field_arg->interval->type_names[pos];
00199
00200 enumeration_options->add_field_value(src);
00201 }
00202 enumeration_options->set_collation_id(field_arg->charset->number);
00203 enumeration_options->set_collation(field_arg->charset->name);
00204 break;
00205 }
00206
00207 case message::Table::Field::BLOB:
00208 {
00209 message::Table::Field::StringFieldOptions *string_field_options;
00210
00211 string_field_options= attribute->mutable_string_options();
00212 string_field_options->set_collation_id(field_arg->charset->number);
00213 string_field_options->set_collation(field_arg->charset->name);
00214 }
00215
00216 break;
00217
00218 case message::Table::Field::EPOCH:
00219 {
00220 if (field_arg->sql_type == DRIZZLE_TYPE_MICROTIME)
00221 attribute->mutable_time_options()->set_microseconds(true);
00222 }
00223
00224 break;
00225 }
00226
00227 assert (!use_existing_fields || parser_type == attribute->type());
00228
00229 #ifdef NOTDONE
00230 field_constraints= attribute->mutable_constraints();
00231 constraints->set_is_nullable(field_arg->def->null_value);
00232 #endif
00233
00234 if (field_arg->comment.length)
00235 {
00236 uint32_t tmp_len;
00237 tmp_len= system_charset_info->cset->charpos(system_charset_info,
00238 field_arg->comment.str,
00239 field_arg->comment.str +
00240 field_arg->comment.length,
00241 COLUMN_COMMENT_MAXLEN);
00242
00243 if (tmp_len < field_arg->comment.length)
00244 {
00245 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
00246 field_arg->comment.str,"COLUMN COMMENT",
00247 (uint32_t) COLUMN_COMMENT_MAXLEN);
00248 return true;
00249 }
00250
00251 if (! use_existing_fields)
00252 attribute->set_comment(field_arg->comment.str);
00253
00254 assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
00255 }
00256
00257 if (field_arg->unireg_check == Field::NEXT_NUMBER)
00258 {
00259 message::Table::Field::NumericFieldOptions *field_options;
00260 field_options= attribute->mutable_numeric_options();
00261 field_options->set_is_autoincrement(true);
00262 }
00263
00264 if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
00265 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
00266 {
00267 message::Table::Field::FieldOptions *field_options;
00268 field_options= attribute->mutable_options();
00269 field_options->set_default_expression("CURRENT_TIMESTAMP");
00270 }
00271
00272 if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
00273 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
00274 {
00275 message::Table::Field::FieldOptions *field_options;
00276 field_options= attribute->mutable_options();
00277 field_options->set_update_expression("CURRENT_TIMESTAMP");
00278 }
00279
00280 if (field_arg->def == NULL && not attribute->constraints().is_notnull())
00281 {
00282 message::Table::Field::FieldOptions *field_options;
00283 field_options= attribute->mutable_options();
00284
00285 field_options->set_default_null(true);
00286 }
00287 if (field_arg->def)
00288 {
00289 message::Table::Field::FieldOptions *field_options;
00290 field_options= attribute->mutable_options();
00291
00292 if (field_arg->def->is_null())
00293 {
00294 field_options->set_default_null(true);
00295 }
00296 else
00297 {
00298 String d;
00299 String *default_value= field_arg->def->val_str(&d);
00300
00301 assert(default_value);
00302
00303 if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
00304 || field_arg->sql_type==DRIZZLE_TYPE_BLOB)
00305 && ((field_arg->length / field_arg->charset->mbmaxlen)
00306 < default_value->length()))
00307 {
00308 my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
00309 return true;
00310 }
00311
00312 if (field::isDateTime(field_arg->sql_type))
00313 {
00314 type::Time ltime;
00315
00316 if (field_arg->def->get_date(ltime, TIME_FUZZY_DATE))
00317 {
00318 my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
00319 default_value->c_str());
00320 return true;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
00334 {
00335 Item *typecast= new Item_datetime_typecast(field_arg->def);
00336 typecast->quick_fix_field();
00337 typecast->val_str(default_value);
00338 }
00339 else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
00340 {
00341 Item *typecast= new Item_date_typecast(field_arg->def);
00342 typecast->quick_fix_field();
00343 typecast->val_str(default_value);
00344 }
00345 }
00346
00347 if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
00348 && field_arg->charset==&my_charset_bin)
00349 || (field_arg->sql_type==DRIZZLE_TYPE_BLOB
00350 && field_arg->charset==&my_charset_bin))
00351 {
00352 string bin_default;
00353 bin_default.assign(default_value->c_ptr(),
00354 default_value->length());
00355 field_options->set_default_bin_value(bin_default);
00356 }
00357 else
00358 {
00359 field_options->set_default_value(default_value->c_ptr());
00360 }
00361 }
00362 }
00363
00364 assert(field_arg->unireg_check == Field::NONE
00365 || field_arg->unireg_check == Field::NEXT_NUMBER
00366 || field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
00367 || field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
00368 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD);
00369
00370 }
00371
00372 assert(! use_existing_fields || (field_number == table_proto.field_size()));
00373
00374 if (create_info->table_options & HA_OPTION_PACK_RECORD)
00375 table_options->set_pack_record(true);
00376
00377 if (table_options->has_comment() && table_options->comment().length() == 0)
00378 table_options->clear_comment();
00379
00380 if (table_options->has_comment())
00381 {
00382 uint32_t tmp_len;
00383 tmp_len= system_charset_info->cset->charpos(system_charset_info,
00384 table_options->comment().c_str(),
00385 table_options->comment().c_str() +
00386 table_options->comment().length(),
00387 TABLE_COMMENT_MAXLEN);
00388
00389 if (tmp_len < table_options->comment().length())
00390 {
00391 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
00392 table_options->comment().c_str(),"Table COMMENT",
00393 (uint32_t) TABLE_COMMENT_MAXLEN);
00394 return true;
00395 }
00396 }
00397
00398 if (create_info->default_table_charset)
00399 {
00400 table_options->set_collation_id(create_info->default_table_charset->number);
00401 table_options->set_collation(create_info->default_table_charset->name);
00402 }
00403
00404 if (create_info->used_fields & HA_CREATE_USED_AUTO)
00405 table_options->set_has_user_set_auto_increment_value(true);
00406 else
00407 table_options->set_has_user_set_auto_increment_value(false);
00408
00409 if (create_info->auto_increment_value)
00410 table_options->set_auto_increment_value(create_info->auto_increment_value);
00411
00412 for (uint32_t i= 0; i < keys; i++)
00413 {
00414 message::Table::Index *idx;
00415
00416 idx= table_proto.add_indexes();
00417
00418 assert(test(key_info[i].flags & HA_USES_COMMENT) ==
00419 (key_info[i].comment.length > 0));
00420
00421 idx->set_name(key_info[i].name);
00422
00423 idx->set_key_length(key_info[i].key_length);
00424
00425 if (is_primary_key_name(key_info[i].name))
00426 idx->set_is_primary(true);
00427 else
00428 idx->set_is_primary(false);
00429
00430 switch(key_info[i].algorithm)
00431 {
00432 case HA_KEY_ALG_HASH:
00433 idx->set_type(message::Table::Index::HASH);
00434 break;
00435
00436 case HA_KEY_ALG_BTREE:
00437 idx->set_type(message::Table::Index::BTREE);
00438 break;
00439
00440 case HA_KEY_ALG_UNDEF:
00441 idx->set_type(message::Table::Index::UNKNOWN_INDEX);
00442 break;
00443
00444 default:
00445 abort();
00446 }
00447
00448 if (key_info[i].flags & HA_NOSAME)
00449 idx->set_is_unique(true);
00450 else
00451 idx->set_is_unique(false);
00452
00453 message::Table::Index::Options *index_options= idx->mutable_options();
00454
00455 if (key_info[i].flags & HA_USES_BLOCK_SIZE)
00456 index_options->set_key_block_size(key_info[i].block_size);
00457
00458 if (key_info[i].flags & HA_PACK_KEY)
00459 index_options->set_pack_key(true);
00460
00461 if (key_info[i].flags & HA_BINARY_PACK_KEY)
00462 index_options->set_binary_pack_key(true);
00463
00464 if (key_info[i].flags & HA_VAR_LENGTH_PART)
00465 index_options->set_var_length_key(true);
00466
00467 if (key_info[i].flags & HA_NULL_PART_KEY)
00468 index_options->set_null_part_key(true);
00469
00470 if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
00471 index_options->set_has_partial_segments(true);
00472
00473 if (key_info[i].flags & HA_GENERATED_KEY)
00474 index_options->set_auto_generated_key(true);
00475
00476 if (key_info[i].flags & HA_USES_COMMENT)
00477 {
00478 uint32_t tmp_len;
00479 tmp_len= system_charset_info->cset->charpos(system_charset_info,
00480 key_info[i].comment.str,
00481 key_info[i].comment.str +
00482 key_info[i].comment.length,
00483 TABLE_COMMENT_MAXLEN);
00484
00485 if (tmp_len < key_info[i].comment.length)
00486 {
00487 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
00488 key_info[i].comment.str,"Index COMMENT",
00489 (uint32_t) TABLE_COMMENT_MAXLEN);
00490 return true;
00491 }
00492
00493 idx->set_comment(key_info[i].comment.str);
00494 }
00495 static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
00496 HA_USES_BLOCK_SIZE |
00497 HA_BINARY_PACK_KEY |
00498 HA_VAR_LENGTH_PART |
00499 HA_NULL_PART_KEY |
00500 HA_KEY_HAS_PART_KEY_SEG |
00501 HA_GENERATED_KEY |
00502 HA_USES_COMMENT);
00503 if (key_info[i].flags & ~unknown_index_flag)
00504 abort();
00505
00506 for(unsigned int j=0; j< key_info[i].key_parts; j++)
00507 {
00508 message::Table::Index::IndexPart *idxpart;
00509 const int fieldnr= key_info[i].key_part[j].fieldnr;
00510 int mbmaxlen= 1;
00511
00512 idxpart= idx->add_index_part();
00513
00514 idxpart->set_fieldnr(fieldnr);
00515
00516 if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
00517 || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
00518 {
00519 uint32_t collation_id;
00520
00521 if (table_proto.field(fieldnr).string_options().has_collation_id())
00522 collation_id= table_proto.field(fieldnr).string_options().collation_id();
00523 else
00524 collation_id= table_proto.options().collation_id();
00525
00526 const CHARSET_INFO *cs= get_charset(collation_id);
00527
00528 mbmaxlen= cs->mbmaxlen;
00529 }
00530
00531 idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
00532 }
00533 }
00534
00535 if (not table_proto.IsInitialized())
00536 {
00537 my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
00538 table_proto.name().c_str(),
00539 table_proto.InitializationErrorString().c_str());
00540
00541 return true;
00542 }
00543
00544
00545
00546
00547
00548 {
00549 string tmp_string;
00550
00551 try {
00552 table_proto.SerializeToString(&tmp_string);
00553 }
00554
00555 catch (...)
00556 {
00557 my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
00558 table_proto.name().c_str(),
00559 table_proto.InitializationErrorString().c_str());
00560
00561 return true;
00562 }
00563 }
00564
00565 return false;
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 bool rea_create_table(Session *session,
00588 const identifier::Table &identifier,
00589 message::Table &table_proto,
00590 HA_CREATE_INFO *create_info,
00591 List<CreateField> &create_fields,
00592 uint32_t keys, KeyInfo *key_info)
00593 {
00594 assert(table_proto.has_name());
00595
00596 if (fill_table_proto(identifier,
00597 table_proto, create_fields, create_info,
00598 keys, key_info))
00599 {
00600 return false;
00601 }
00602
00603 assert(table_proto.name() == identifier.getTableName());
00604
00605 if (not plugin::StorageEngine::createTable(*session,
00606 identifier,
00607 table_proto))
00608 {
00609 return false;
00610 }
00611
00612 return true;
00613
00614 }
00615
00616 }
00617