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/sql_table.h>
00020 #include <drizzled/message/statement_transform.h>
00021
00022 #include <drizzled/plugin/storage_engine.h>
00023
00024 #include <drizzled/internal/my_sys.h>
00025 #include <drizzled/typelib.h>
00026 #include <drizzled/util/test.h>
00027
00028
00029 #include <string>
00030 #include <fstream>
00031 #include <fcntl.h>
00032 #include <drizzled/message/schema.h>
00033 #include <drizzled/message/table.h>
00034 #include <google/protobuf/io/zero_copy_stream.h>
00035 #include <google/protobuf/io/zero_copy_stream_impl.h>
00036 #include <google/protobuf/message.h>
00037
00038 #include <drizzled/table_proto.h>
00039 #include <drizzled/charset.h>
00040 #include <drizzled/create_field.h>
00041 #include <drizzled/function/time/typecast.h>
00042
00043 using namespace std;
00044
00045 namespace drizzled {
00046
00047 static
00048 bool fill_table_proto(const identifier::Table& identifier,
00049 message::Table &table_proto,
00050 List<CreateField> &create_fields,
00051 HA_CREATE_INFO *create_info,
00052 uint32_t keys,
00053 KeyInfo *key_info)
00054 {
00055 CreateField *field_arg;
00056 List<CreateField>::iterator it(create_fields.begin());
00057 message::Table::TableOptions *table_options= table_proto.mutable_options();
00058
00059 if (create_fields.size() > MAX_FIELDS)
00060 {
00061 my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
00062 return true;
00063 }
00064
00065 assert(strcmp(table_proto.engine().name().c_str(),
00066 create_info->db_type->getName().c_str())==0);
00067
00068 message::schema::shared_ptr schema_message= plugin::StorageEngine::getSchemaDefinition(identifier);
00069
00070 if (schema_message and not message::is_replicated(*schema_message))
00071 {
00072 message::set_is_replicated(table_proto, false);
00073 }
00074
00075 int field_number= 0;
00076 bool use_existing_fields= table_proto.field_size() > 0;
00077 while ((field_arg= it++))
00078 {
00079 message::Table::Field *attribute;
00080
00081
00082
00083
00084
00085 if (use_existing_fields)
00086 {
00087 attribute= table_proto.mutable_field(field_number++);
00088 }
00089 else
00090 {
00091
00092 attribute= table_proto.add_field();
00093
00094 if (field_arg->flags & NOT_NULL_FLAG)
00095 {
00096 attribute->mutable_constraints()->set_is_notnull(true);
00097 }
00098
00099 if (field_arg->flags & UNSIGNED_FLAG and
00100 (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
00101 {
00102 field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
00103 attribute->mutable_constraints()->set_is_unsigned(true);
00104 }
00105
00106 attribute->set_name(field_arg->field_name);
00107 }
00108
00109 assert(((field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_notnull());
00110 assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
00111
00112
00113 message::Table::Field::FieldType parser_type= attribute->type();
00114
00115 if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
00116 {
00117 my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
00118 return true;
00119 }
00120
00121 if (field_arg->flags & UNSIGNED_FLAG and
00122 (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
00123 {
00124 message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
00125
00126 field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
00127 constraints->set_is_unsigned(true);
00128 }
00129
00130 attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
00131
00132 switch (attribute->type()) {
00133 case message::Table::Field::BIGINT:
00134 case message::Table::Field::INTEGER:
00135 case message::Table::Field::DATE:
00136 case message::Table::Field::DATETIME:
00137 case message::Table::Field::UUID:
00138 case message::Table::Field::IPV6:
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 (not field_arg->comment.empty())
00235 {
00236 uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
00237 field_arg->comment.begin(),
00238 field_arg->comment.end(),
00239 COLUMN_COMMENT_MAXLEN);
00240
00241 if (tmp_len < field_arg->comment.size())
00242 {
00243 my_error(ER_WRONG_STRING_LENGTH, MYF(0), field_arg->comment.data(), "COLUMN COMMENT", (uint32_t) COLUMN_COMMENT_MAXLEN);
00244 return true;
00245 }
00246
00247 if (not use_existing_fields)
00248 attribute->set_comment(field_arg->comment.data());
00249
00250 assert(strcmp(attribute->comment().c_str(), field_arg->comment.data())==0);
00251 }
00252
00253 if (field_arg->unireg_check == Field::NEXT_NUMBER)
00254 {
00255 message::Table::Field::NumericFieldOptions *field_options;
00256 field_options= attribute->mutable_numeric_options();
00257 field_options->set_is_autoincrement(true);
00258 }
00259
00260 if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
00261 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
00262 {
00263 message::Table::Field::FieldOptions *field_options;
00264 field_options= attribute->mutable_options();
00265 field_options->set_default_expression("CURRENT_TIMESTAMP");
00266 }
00267
00268 if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
00269 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
00270 {
00271 message::Table::Field::FieldOptions *field_options;
00272 field_options= attribute->mutable_options();
00273 field_options->set_update_expression("CURRENT_TIMESTAMP");
00274 }
00275
00276 if (field_arg->def == NULL && not attribute->constraints().is_notnull())
00277 {
00278 message::Table::Field::FieldOptions *field_options;
00279 field_options= attribute->mutable_options();
00280
00281 field_options->set_default_null(true);
00282 }
00283 if (field_arg->def)
00284 {
00285 message::Table::Field::FieldOptions *field_options;
00286 field_options= attribute->mutable_options();
00287
00288 if (field_arg->def->is_null())
00289 {
00290 field_options->set_default_null(true);
00291 }
00292 else
00293 {
00294 String d;
00295 String *default_value= field_arg->def->val_str(&d);
00296
00297 assert(default_value);
00298
00299 if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
00300 || field_arg->sql_type==DRIZZLE_TYPE_BLOB)
00301 && ((field_arg->length / field_arg->charset->mbmaxlen)
00302 < default_value->length()))
00303 {
00304 my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
00305 return true;
00306 }
00307
00308 if (field::isDateTime(field_arg->sql_type))
00309 {
00310 type::Time ltime;
00311
00312 if (field_arg->def->get_date(ltime, TIME_FUZZY_DATE))
00313 {
00314 my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
00315 default_value->c_str());
00316 return true;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
00330 {
00331 Item *typecast= new Item_datetime_typecast(field_arg->def);
00332 typecast->quick_fix_field();
00333 typecast->val_str(default_value);
00334 }
00335 else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
00336 {
00337 Item *typecast= new Item_date_typecast(field_arg->def);
00338 typecast->quick_fix_field();
00339 typecast->val_str(default_value);
00340 }
00341 }
00342
00343 if ((field_arg->sql_type == DRIZZLE_TYPE_VARCHAR && field_arg->charset == &my_charset_bin)
00344 || (field_arg->sql_type == DRIZZLE_TYPE_BLOB && field_arg->charset == &my_charset_bin))
00345 {
00346 field_options->set_default_bin_value(string(default_value->c_ptr(), default_value->length()));
00347 }
00348 else
00349 {
00350 field_options->set_default_value(default_value->c_ptr());
00351 }
00352 }
00353 }
00354
00355 assert(field_arg->unireg_check == Field::NONE
00356 || field_arg->unireg_check == Field::NEXT_NUMBER
00357 || field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
00358 || field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
00359 || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD);
00360
00361 }
00362
00363 assert(! use_existing_fields || (field_number == table_proto.field_size()));
00364
00365 if (create_info->table_options & HA_OPTION_PACK_RECORD)
00366 table_options->set_pack_record(true);
00367
00368 if (table_options->has_comment() && table_options->comment().length() == 0)
00369 table_options->clear_comment();
00370
00371 if (table_options->has_comment())
00372 {
00373 uint32_t tmp_len;
00374 tmp_len= system_charset_info->cset->charpos(system_charset_info,
00375 table_options->comment().c_str(),
00376 table_options->comment().c_str() +
00377 table_options->comment().length(),
00378 TABLE_COMMENT_MAXLEN);
00379
00380 if (tmp_len < table_options->comment().length())
00381 {
00382 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
00383 table_options->comment().c_str(),"Table COMMENT",
00384 (uint32_t) TABLE_COMMENT_MAXLEN);
00385 return true;
00386 }
00387 }
00388
00389 if (create_info->default_table_charset)
00390 {
00391 table_options->set_collation_id(create_info->default_table_charset->number);
00392 table_options->set_collation(create_info->default_table_charset->name);
00393 }
00394
00395 if (create_info->used_fields & HA_CREATE_USED_AUTO)
00396 table_options->set_has_user_set_auto_increment_value(true);
00397 else
00398 table_options->set_has_user_set_auto_increment_value(false);
00399
00400 if (create_info->auto_increment_value)
00401 table_options->set_auto_increment_value(create_info->auto_increment_value);
00402
00403 for (uint32_t i= 0; i < keys; i++)
00404 {
00405 message::Table::Index *idx= table_proto.add_indexes();
00406
00407 assert(test(key_info[i].flags & HA_USES_COMMENT) == (key_info[i].comment.size() > 0));
00408
00409 idx->set_name(key_info[i].name);
00410 idx->set_key_length(key_info[i].key_length);
00411 idx->set_is_primary(is_primary_key(key_info[i].name));
00412
00413 switch(key_info[i].algorithm)
00414 {
00415 case HA_KEY_ALG_HASH:
00416 idx->set_type(message::Table::Index::HASH);
00417 break;
00418
00419 case HA_KEY_ALG_BTREE:
00420 idx->set_type(message::Table::Index::BTREE);
00421 break;
00422
00423 case HA_KEY_ALG_UNDEF:
00424 {
00425 idx->set_type(create_info->db_type->default_index_type());
00426 break;
00427 }
00428 }
00429
00430 if (key_info[i].flags & HA_NOSAME)
00431 idx->set_is_unique(true);
00432 else
00433 idx->set_is_unique(false);
00434
00435 message::Table::Index::Options *index_options= idx->mutable_options();
00436
00437 if (key_info[i].flags & HA_USES_BLOCK_SIZE)
00438 index_options->set_key_block_size(key_info[i].block_size);
00439
00440 if (key_info[i].flags & HA_PACK_KEY)
00441 index_options->set_pack_key(true);
00442
00443 if (key_info[i].flags & HA_BINARY_PACK_KEY)
00444 index_options->set_binary_pack_key(true);
00445
00446 if (key_info[i].flags & HA_VAR_LENGTH_PART)
00447 index_options->set_var_length_key(true);
00448
00449 if (key_info[i].flags & HA_NULL_PART_KEY)
00450 index_options->set_null_part_key(true);
00451
00452 if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
00453 index_options->set_has_partial_segments(true);
00454
00455 if (key_info[i].flags & HA_GENERATED_KEY)
00456 index_options->set_auto_generated_key(true);
00457
00458 if (key_info[i].flags & HA_USES_COMMENT)
00459 {
00460 uint32_t tmp_len;
00461 tmp_len= system_charset_info->cset->charpos(system_charset_info,
00462 key_info[i].comment.begin(),
00463 key_info[i].comment.end(),
00464 TABLE_COMMENT_MAXLEN);
00465
00466 if (tmp_len < key_info[i].comment.size())
00467 {
00468 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
00469 key_info[i].comment.data(), "Index COMMENT",
00470 (uint32_t) TABLE_COMMENT_MAXLEN);
00471 return true;
00472 }
00473
00474 idx->set_comment(key_info[i].comment.data());
00475 }
00476 static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
00477 HA_USES_BLOCK_SIZE |
00478 HA_BINARY_PACK_KEY |
00479 HA_VAR_LENGTH_PART |
00480 HA_NULL_PART_KEY |
00481 HA_KEY_HAS_PART_KEY_SEG |
00482 HA_GENERATED_KEY |
00483 HA_USES_COMMENT);
00484 if (key_info[i].flags & ~unknown_index_flag)
00485 abort();
00486
00487 for(unsigned int j=0; j< key_info[i].key_parts; j++)
00488 {
00489 message::Table::Index::IndexPart *idxpart;
00490 const int fieldnr= key_info[i].key_part[j].fieldnr;
00491 int mbmaxlen= 1;
00492
00493 idxpart= idx->add_index_part();
00494
00495 idxpart->set_fieldnr(fieldnr);
00496
00497 if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
00498 || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
00499 {
00500 uint32_t collation_id;
00501
00502 if (table_proto.field(fieldnr).string_options().has_collation_id())
00503 collation_id= table_proto.field(fieldnr).string_options().collation_id();
00504 else
00505 collation_id= table_proto.options().collation_id();
00506
00507 const charset_info_st *cs= get_charset(collation_id);
00508
00509 mbmaxlen= cs->mbmaxlen;
00510 }
00511
00512 idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
00513 }
00514 }
00515
00516 if (not table_proto.IsInitialized())
00517 {
00518 my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
00519 table_proto.name().c_str(),
00520 table_proto.InitializationErrorString().c_str());
00521
00522 return true;
00523 }
00524
00525
00526
00527
00528
00529 {
00530 string tmp_string;
00531
00532 try {
00533 table_proto.SerializeToString(&tmp_string);
00534 }
00535
00536 catch (...)
00537 {
00538 my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
00539 table_proto.name().c_str(),
00540 table_proto.InitializationErrorString().c_str());
00541
00542 return true;
00543 }
00544 }
00545
00546 return false;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 bool rea_create_table(Session *session,
00569 const identifier::Table &identifier,
00570 message::Table &table_proto,
00571 HA_CREATE_INFO *create_info,
00572 List<CreateField> &create_fields,
00573 uint32_t keys, KeyInfo *key_info)
00574 {
00575 assert(table_proto.has_name());
00576
00577 if (fill_table_proto(identifier,
00578 table_proto, create_fields, create_info,
00579 keys, key_info))
00580 {
00581 return false;
00582 }
00583
00584 assert(table_proto.name() == identifier.getTableName());
00585
00586 if (not plugin::StorageEngine::createTable(*session,
00587 identifier,
00588 table_proto))
00589 {
00590 return false;
00591 }
00592
00593 return true;
00594
00595 }
00596
00597 }
00598