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 */
16
#include <drizzled/server_includes.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"
24
#include <drizzled/plugin/storage_engine.h>
26
#include "drizzled/internal/my_sys.h"
33
24
#include <drizzled/message/schema.pb.h>
34
25
#include <drizzled/message/table.pb.h>
35
26
#include <google/protobuf/io/zero_copy_stream.h>
36
27
#include <google/protobuf/io/zero_copy_stream_impl.h>
37
#include <google/protobuf/message.h>
39
29
#include <drizzled/table_proto.h>
40
#include <drizzled/charset.h>
42
#include "drizzled/function/time/typecast.h"
44
30
using namespace std;
48
bool fill_table_proto(message::Table &table_proto,
49
List<CreateField> &create_fields,
50
HA_CREATE_INFO *create_info,
31
using namespace drizzled;
33
int fill_table_proto(message::Table *table_proto,
34
const char *table_name,
35
List<CreateField> &create_fields,
36
HA_CREATE_INFO *create_info,
54
40
CreateField *field_arg;
55
41
List_iterator<CreateField> it(create_fields);
56
message::Table::TableOptions *table_options= table_proto.mutable_options();
42
message::Table::TableOptions *table_options= table_proto->mutable_options();
58
44
if (create_fields.elements > MAX_FIELDS)
60
46
my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
64
assert(strcmp(table_proto.engine().name().c_str(),
50
assert(strcmp(table_proto->engine().name().c_str(),
65
51
create_info->db_type->getName().c_str())==0);
68
bool use_existing_fields= table_proto.field_size() > 0;
53
assert(strcmp(table_proto->name().c_str(),table_name)==0);
69
55
while ((field_arg= it++))
71
57
message::Table::Field *attribute;
73
/* some (one) code path for CREATE TABLE fills the proto
74
out more than the others, so we already have partially
75
filled out Field messages */
77
if (use_existing_fields)
79
attribute= table_proto.mutable_field(field_number++);
83
/* Other code paths still have to fill out the proto */
84
attribute= table_proto.add_field();
86
if (field_arg->flags & NOT_NULL_FLAG)
88
attribute->mutable_constraints()->set_is_notnull(true);
91
if (field_arg->flags & UNSIGNED_FLAG and
92
(field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
94
field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
95
attribute->mutable_constraints()->set_is_unsigned(true);
98
attribute->set_name(field_arg->field_name);
101
assert(((field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_notnull());
102
assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
105
message::Table::Field::FieldType parser_type= attribute->type();
107
if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
109
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
113
if (field_arg->flags & UNSIGNED_FLAG and
114
(field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
116
message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
118
field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
119
constraints->set_is_unsigned(true);
122
attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
124
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:
133
case message::Table::Field::DOUBLE:
136
* For DOUBLE, we only add a specific scale and precision iff
137
* the fixed decimal point has been specified...
139
if (field_arg->decimals != NOT_FIXED_DEC)
141
message::Table::Field::NumericFieldOptions *numeric_field_options;
143
numeric_field_options= attribute->mutable_numeric_options();
145
numeric_field_options->set_precision(field_arg->length);
146
numeric_field_options->set_scale(field_arg->decimals);
150
case message::Table::Field::VARCHAR:
59
attribute= table_proto->add_field();
60
attribute->set_name(field_arg->field_name);
62
attribute->set_pack_flag(field_arg->pack_flag); /* TODO: MUST DIE */
64
if(f_maybe_null(field_arg->pack_flag))
66
message::Table::Field::FieldConstraints *constraints;
68
constraints= attribute->mutable_constraints();
69
constraints->set_is_nullable(true);
72
switch (field_arg->sql_type) {
73
case DRIZZLE_TYPE_TINY:
74
attribute->set_type(message::Table::Field::TINYINT);
76
case DRIZZLE_TYPE_LONG:
77
attribute->set_type(message::Table::Field::INTEGER);
79
case DRIZZLE_TYPE_DOUBLE:
80
attribute->set_type(message::Table::Field::DOUBLE);
82
case DRIZZLE_TYPE_NULL :
83
assert(1); /* Not a user definable type */
84
case DRIZZLE_TYPE_TIMESTAMP:
85
attribute->set_type(message::Table::Field::TIMESTAMP);
87
case DRIZZLE_TYPE_LONGLONG:
88
attribute->set_type(message::Table::Field::BIGINT);
90
case DRIZZLE_TYPE_DATETIME:
91
attribute->set_type(message::Table::Field::DATETIME);
93
case DRIZZLE_TYPE_DATE:
94
attribute->set_type(message::Table::Field::DATE);
96
case DRIZZLE_TYPE_VARCHAR:
152
98
message::Table::Field::StringFieldOptions *string_field_options;
154
100
string_field_options= attribute->mutable_string_options();
156
if (! use_existing_fields || string_field_options->length()==0)
157
string_field_options->set_length(field_arg->length
158
/ field_arg->charset->mbmaxlen);
160
assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
162
if (! string_field_options->has_collation())
164
string_field_options->set_collation_id(field_arg->charset->number);
165
string_field_options->set_collation(field_arg->charset->name);
101
attribute->set_type(message::Table::Field::VARCHAR);
102
string_field_options->set_length(field_arg->length
103
/ field_arg->charset->mbmaxlen);
104
string_field_options->set_collation_id(field_arg->charset->number);
105
string_field_options->set_collation(field_arg->charset->name);
169
case message::Table::Field::DECIMAL:
109
case DRIZZLE_TYPE_NEWDECIMAL:
171
111
message::Table::Field::NumericFieldOptions *numeric_field_options;
113
attribute->set_type(message::Table::Field::DECIMAL);
173
114
numeric_field_options= attribute->mutable_numeric_options();
174
115
/* This is magic, I hate magic numbers -Brian */
175
116
numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
176
117
numeric_field_options->set_scale(field_arg->decimals);
179
case message::Table::Field::ENUM:
120
case DRIZZLE_TYPE_ENUM:
181
message::Table::Field::EnumerationValues *enumeration_options;
122
message::Table::Field::SetFieldOptions *set_field_options;
183
124
assert(field_arg->interval);
185
enumeration_options= attribute->mutable_enumeration_values();
126
attribute->set_type(message::Table::Field::ENUM);
127
set_field_options= attribute->mutable_set_options();
187
129
for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
189
131
const char *src= field_arg->interval->type_names[pos];
191
enumeration_options->add_field_value(src);
133
set_field_options->add_field_value(src);
193
enumeration_options->set_collation_id(field_arg->charset->number);
194
enumeration_options->set_collation(field_arg->charset->name);
135
set_field_options->set_count_elements(set_field_options->field_value_size());
136
set_field_options->set_collation_id(field_arg->charset->number);
137
set_field_options->set_collation(field_arg->charset->name);
140
case DRIZZLE_TYPE_BLOB:
142
attribute->set_type(message::Table::Field::BLOB);
198
case message::Table::Field::BLOB:
200
144
message::Table::Field::StringFieldOptions *string_field_options;
202
146
string_field_options= attribute->mutable_string_options();
236
189
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
237
190
field_arg->comment.str,"COLUMN COMMENT",
238
191
(uint32_t) COLUMN_COMMENT_MAXLEN);
242
if (! use_existing_fields)
243
attribute->set_comment(field_arg->comment.str);
245
assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
195
attribute->set_comment(field_arg->comment.str);
248
if (field_arg->unireg_check == Field::NEXT_NUMBER)
198
if(field_arg->unireg_check == Field::NEXT_NUMBER)
250
200
message::Table::Field::NumericFieldOptions *field_options;
251
201
field_options= attribute->mutable_numeric_options();
252
202
field_options->set_is_autoincrement(true);
255
if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
256
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
258
message::Table::Field::FieldOptions *field_options;
259
field_options= attribute->mutable_options();
260
field_options->set_default_expression("CURRENT_TIMESTAMP");
263
if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
264
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
266
message::Table::Field::FieldOptions *field_options;
267
field_options= attribute->mutable_options();
268
field_options->set_update_expression("CURRENT_TIMESTAMP");
271
if (field_arg->def == NULL && not attribute->constraints().is_notnull())
273
message::Table::Field::FieldOptions *field_options;
274
field_options= attribute->mutable_options();
276
field_options->set_default_null(true);
280
message::Table::Field::FieldOptions *field_options;
281
field_options= attribute->mutable_options();
283
if (field_arg->def->is_null())
205
if(field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
206
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
208
message::Table::Field::FieldOptions *field_options;
209
field_options= attribute->mutable_options();
210
field_options->set_default_value("NOW()");
213
if(field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
214
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
216
message::Table::Field::FieldOptions *field_options;
217
field_options= attribute->mutable_options();
218
field_options->set_update_value("NOW()");
223
message::Table::Field::FieldOptions *field_options;
224
field_options= attribute->mutable_options();
226
if(field_arg->def->is_null())
285
228
field_options->set_default_null(true);
292
235
assert(default_value);
294
if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
237
if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
295
238
|| field_arg->sql_type==DRIZZLE_TYPE_BLOB)
296
239
&& ((field_arg->length / field_arg->charset->mbmaxlen)
297
240
< default_value->length()))
299
242
my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
303
if (field_arg->sql_type == DRIZZLE_TYPE_DATE
304
|| field_arg->sql_type == DRIZZLE_TYPE_TIME
305
|| field_arg->sql_type == DRIZZLE_TYPE_DATETIME
306
|| field_arg->sql_type == DRIZZLE_TYPE_MICROTIME
307
|| field_arg->sql_type == DRIZZLE_TYPE_TIMESTAMP)
311
if (field_arg->def->get_date(ltime, TIME_FUZZY_DATE))
313
my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
314
default_value->c_str());
318
/* We now do the casting down to the appropriate type.
320
Yes, this implicit casting is balls.
321
It was previously done on reading the proto back in,
322
but we really shouldn't store the bogus things in the proto,
323
and instead do the casting behaviour here.
325
the timestamp errors are taken care of elsewhere.
328
if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
330
Item *typecast= new Item_datetime_typecast(field_arg->def);
331
typecast->quick_fix_field();
332
typecast->val_str(default_value);
334
else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
336
Item *typecast= new Item_date_typecast(field_arg->def);
337
typecast->quick_fix_field();
338
typecast->val_str(default_value);
342
if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
246
if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
343
247
&& field_arg->charset==&my_charset_bin)
344
248
|| (field_arg->sql_type==DRIZZLE_TYPE_BLOB
345
249
&& field_arg->charset==&my_charset_bin))
482
421
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
483
422
key_info[i].comment.str,"Index COMMENT",
484
423
(uint32_t) TABLE_COMMENT_MAXLEN);
488
427
idx->set_comment(key_info[i].comment.str);
490
static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
495
HA_KEY_HAS_PART_KEY_SEG |
498
if (key_info[i].flags & ~unknown_index_flag)
429
if(key_info[i].flags & ~(HA_NOSAME | HA_PACK_KEY | HA_USES_BLOCK_SIZE | HA_BINARY_PACK_KEY | HA_VAR_LENGTH_PART | HA_NULL_PART_KEY | HA_KEY_HAS_PART_KEY_SEG | HA_GENERATED_KEY | HA_USES_COMMENT))
499
430
abort(); // Invalid (unknown) index flag.
501
432
for(unsigned int j=0; j< key_info[i].key_parts; j++)
503
434
message::Table::Index::IndexPart *idxpart;
504
const int fieldnr= key_info[i].key_part[j].fieldnr;
507
436
idxpart= idx->add_index_part();
509
idxpart->set_fieldnr(fieldnr);
511
if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
512
|| table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
514
uint32_t collation_id;
516
if (table_proto.field(fieldnr).string_options().has_collation_id())
517
collation_id= table_proto.field(fieldnr).string_options().collation_id();
519
collation_id= table_proto.options().collation_id();
521
const CHARSET_INFO *cs= get_charset(collation_id);
523
mbmaxlen= cs->mbmaxlen;
526
idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
530
if (not table_proto.IsInitialized())
532
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
533
table_proto.name().c_str(),
534
table_proto.InitializationErrorString().c_str());
540
Here we test to see if we can validate the Table Message before we continue.
541
We do this by serializing the protobuffer.
547
table_proto.SerializeToString(&tmp_string);
552
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
553
table_proto.name().c_str(),
554
table_proto.InitializationErrorString().c_str());
438
idxpart->set_fieldnr(key_info[i].key_part[j].fieldnr);
440
idxpart->set_compare_length(key_info[i].key_part[j].length);
442
idxpart->set_key_type(key_info[i].key_part[j].key_type);
450
int rename_table_proto_file(const char *from, const char* to)
452
string from_path(from);
454
string file_ext = ".dfe";
456
from_path.append(file_ext);
457
to_path.append(file_ext);
459
return my_rename(from_path.c_str(),to_path.c_str(),MYF(MY_WME));
462
int delete_table_proto_file(const char *file_name)
464
string new_path(file_name);
465
string file_ext = ".dfe";
467
new_path.append(file_ext);
468
return my_delete(new_path.c_str(), MYF(0));
471
int drizzle_write_proto_file(const std::string file_name,
472
message::Table *table_proto)
474
int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, my_umask);
479
google::protobuf::io::ZeroCopyOutputStream* output=
480
new google::protobuf::io::FileOutputStream(fd);
482
if (table_proto->SerializeToZeroCopyStream(output) == false)
573
504
create_fields Fields to create
574
505
keys number of keys to create
575
506
key_info Keys to create
508
is_like is true for mysql_create_like_schema_frm
582
bool rea_create_table(Session *session,
583
const identifier::Table &identifier,
584
message::Table &table_proto,
585
HA_CREATE_INFO *create_info,
586
List<CreateField> &create_fields,
587
uint32_t keys, KeyInfo *key_info)
515
int rea_create_table(Session *session, const char *path,
516
const char *db, const char *table_name,
517
message::Table *table_proto,
518
HA_CREATE_INFO *create_info,
519
List<CreateField> &create_fields,
520
uint32_t keys, KEY *key_info)
589
assert(table_proto.has_name());
590
if (fill_table_proto(table_proto, create_fields, create_info,
596
assert(table_proto.name() == identifier.getTableName());
598
if (not plugin::StorageEngine::createTable(*session,
522
/* Proto will blow up unless we give a name */
525
if (fill_table_proto(table_proto, table_name, create_fields, create_info,
529
string new_path(path);
530
string file_ext = ".dfe";
532
new_path.append(file_ext);
536
StorageEngine* engine= ha_resolve_by_name(session,
537
table_proto->engine().name());
538
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
539
err= drizzle_write_proto_file(new_path, table_proto);
544
my_error(ER_BAD_DB_ERROR,MYF(0),db);
546
my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,err);
551
if (ha_create_table(session, path, db, table_name,
552
create_info,0, table_proto))
557
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
558
delete_table_proto_file(path);
607
561
} /* rea_create_table */
609
} /* namespace drizzled */