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 */
18
Functions to create a unireg form-file from a FIELD and a fieldname-fieldinfo
20
In the following functions FIELD * is an ordinary field-structure with
21
the following exeptions:
22
sc_length,typepos,row,kol,dtype,regnr and field need not to be set.
23
str is a (long) to record position where 0 is the first position.
26
#include <drizzled/server_includes.h>
17
27
#include <drizzled/error.h>
28
#include <drizzled/virtual_column_info.h>
18
29
#include <drizzled/session.h>
19
30
#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/internal/my_sys.h"
31
#include <drizzled/message/schema.pb.h>
32
#include <drizzled/message/table.pb.h>
33
#include <google/protobuf/io/zero_copy_stream.h>
34
#include <google/protobuf/io/zero_copy_stream_impl.h>
35
#include <google/protobuf/message.h>
37
#include <drizzled/table_proto.h>
38
#include <drizzled/charset.h>
40
#include "drizzled/function/time/typecast.h"
35
#include <drizzled/serialize/serialize.h>
42
36
using namespace std;
46
static int fill_table_proto(message::Table &table_proto,
47
List<CreateField> &create_fields,
48
HA_CREATE_INFO *create_info,
52
CreateField *field_arg;
53
List_iterator<CreateField> it(create_fields);
54
message::Table::TableOptions *table_options= table_proto.mutable_options();
56
if (create_fields.elements > MAX_FIELDS)
58
my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
62
assert(strcmp(table_proto.engine().name().c_str(),
63
create_info->db_type->getName().c_str())==0);
66
bool use_existing_fields= table_proto.field_size() > 0;
38
#define FCOMP 17 /* Bytes for a packed field */
40
static unsigned char * pack_screens(List<Create_field> &create_fields,
41
uint32_t *info_length, uint32_t *screens,
43
static uint32_t pack_keys(unsigned char *keybuff,uint32_t key_count,
44
KEY *key_info, ulong data_offset);
45
static bool pack_header(unsigned char *forminfo,
46
List<Create_field> &create_fields,
47
uint32_t info_length, uint32_t screens,
48
uint32_t table_options,
49
ulong data_offset, handler *file);
50
static uint32_t get_interval_id(uint32_t *int_count,
51
List<Create_field> &create_fields,
52
Create_field *last_field);
53
static bool pack_fields(File file, List<Create_field> &create_fields,
55
static bool make_empty_rec(Session *session, int file,
56
enum legacy_db_type table_type,
57
uint32_t table_options,
58
List<Create_field> &create_fields,
59
uint32_t reclength, ulong data_offset,
63
An interceptor to hijack ER_TOO_MANY_FIELDS error from
64
pack_screens and retry again without UNIREG screens.
66
XXX: what is a UNIREG screen?
69
struct Pack_header_error_handler: public Internal_error_handler
71
virtual bool handle_error(uint32_t sql_errno,
73
DRIZZLE_ERROR::enum_warning_level level,
76
Pack_header_error_handler() :is_handled(false) {}
81
Pack_header_error_handler::
82
handle_error(uint32_t sql_errno,
83
const char * /* message */,
84
DRIZZLE_ERROR::enum_warning_level /* level */,
85
Session * /* session */)
87
is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
91
int mysql_frm_type(char *path, enum legacy_db_type *dbt)
94
unsigned char header[10];
97
*dbt= DB_TYPE_UNKNOWN;
99
file= open(path, O_RDONLY);
104
error= read(file, header, sizeof(header));
107
if (error!=sizeof(header))
111
This is just a check for DB_TYPE. We'll return default unknown type
112
if the following test is true (arg #3). This should not have effect
113
on return value from this function (default FRMTYPE_TABLE)
115
if (header[0] != (unsigned char)254 || header[1] != 1 ||
116
(header[2] != FRM_VER && header[2] != FRM_VER+1 &&
117
(header[2] < FRM_VER+3 || header[2] > FRM_VER+4)))
120
*dbt= (enum legacy_db_type) (uint) *(header + 3);
125
Create a frm (table definition) file
129
session Thread handler
130
file_name Path for file (including database and .frm)
133
create_info create info parameters
134
create_fields Fields to create
135
keys number of keys to create
136
key_info Keys to create
137
db_file Handler to use. May be zero, in which case we use
144
bool mysql_create_frm(Session *session, const char *file_name,
145
const char *db, const char *table,
146
HA_CREATE_INFO *create_info,
147
List<Create_field> &create_fields,
148
uint32_t keys, KEY *key_info,
151
LEX_STRING str_db_type;
152
uint32_t reclength, info_length, screens, key_info_length, maxlength, tmp_len;
153
ulong key_buff_length;
155
ulong filepos, data_offset;
156
unsigned char fileinfo[64],forminfo[288],*keybuff;
158
unsigned char *screen_buff;
160
const uint32_t format_section_header_size= 8;
161
uint32_t format_section_len;
162
Pack_header_error_handler pack_header_error_handler;
165
assert(*fn_rext((char*)file_name)); // Check .frm extension
166
formnames.type_names=0;
167
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
169
assert(db_file != NULL);
171
/* If fixed row records, we need one bit to check for deleted rows */
172
if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
173
create_info->null_bits++;
174
data_offset= (create_info->null_bits + 7) / 8;
176
session->push_internal_handler(&pack_header_error_handler);
178
error= pack_header(forminfo,
179
create_fields,info_length,
180
screens, create_info->table_options,
181
data_offset, db_file);
183
session->pop_internal_handler();
188
if (! pack_header_error_handler.is_handled)
191
// Try again without UNIREG screens (to get more columns)
192
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
194
if (pack_header(forminfo,
195
create_fields,info_length,
196
screens, create_info->table_options, data_offset, db_file))
202
reclength=uint2korr(forminfo+266);
204
/* Calculate extra data segment length */
205
str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type);
206
str_db_type.length= strlen(str_db_type.str);
208
create_info->extra_size= (2 + str_db_type.length +
209
2 + create_info->connect_string.length);
212
Length of partition info = 4 byte
213
Potential NULL byte at end of partition info string = 1 byte
214
Indicator if auto-partitioned table = 1 byte
217
create_info->extra_size+= 6;
219
/* Add space for storage type and field format array of fields */
221
format_section_header_size + 1 + create_fields.elements;
222
create_info->extra_size+= format_section_len;
224
tmp_len= system_charset_info->cset->charpos(system_charset_info,
225
create_info->comment.str,
226
create_info->comment.str +
227
create_info->comment.length,
228
TABLE_COMMENT_MAXLEN);
230
if (tmp_len < create_info->comment.length)
232
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
233
create_info->comment.str,"Table COMMENT",
234
(uint) TABLE_COMMENT_MAXLEN);
239
//if table comment is larger than 180 bytes, store into extra segment.
240
if (create_info->comment.length > 180)
243
create_info->extra_size+= 2 + create_info->comment.length;
246
strncpy((char*) forminfo+47, create_info->comment.str ?
247
create_info->comment.str : "", create_info->comment.length);
248
forminfo[46]=(unsigned char) create_info->comment.length;
251
EXTRA_DEBUG causes strmake() to initialize its buffer behind the
252
payload with a magic value to detect wrong buffer-sizes. We
253
explicitly zero that segment again.
255
memset(forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
259
if ((file=create_frm(session, file_name, db, table, reclength, fileinfo,
260
create_info, keys, key_info)) < 0)
266
key_buff_length= uint4korr(fileinfo+47);
267
keybuff=(unsigned char*) malloc(key_buff_length);
268
key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
269
get_form_pos(file,fileinfo,&formnames);
270
if (!(filepos=make_new_entry(file,fileinfo,&formnames,"")))
272
maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000));
273
int2store(forminfo+2,maxlength);
274
int4store(fileinfo+10,(ulong) (filepos+maxlength));
275
fileinfo[26]= (unsigned char) test((create_info->max_rows == 1) &&
276
(create_info->min_rows == 1) && (keys == 0));
277
int2store(fileinfo+28,key_info_length);
280
int2store(fileinfo+59,db_file->extra_rec_buf_length());
282
if (pwrite(file, fileinfo, 64, 0L) == 0 ||
283
pwrite(file, keybuff, key_info_length, (ulong) uint2korr(fileinfo+6)) == 0)
285
lseek(file, (off_t)(uint2korr(fileinfo+6) + key_buff_length), SEEK_SET);
286
if (make_empty_rec(session,file,ha_legacy_type(create_info->db_type),
287
create_info->table_options,
288
create_fields,reclength, data_offset, db_file))
291
int2store(buff, create_info->connect_string.length);
292
if (my_write(file, (const unsigned char*)buff, 2, MYF(MY_NABP)) ||
293
my_write(file, (const unsigned char*)create_info->connect_string.str,
294
create_info->connect_string.length, MYF(MY_NABP)))
297
int2store(buff, str_db_type.length);
298
if (my_write(file, (const unsigned char*)buff, 2, MYF(MY_NABP)) ||
299
my_write(file, (const unsigned char*)str_db_type.str,
300
str_db_type.length, MYF(MY_NABP)))
305
if (my_write(file, (unsigned char*) buff, 6, MYF_RW))
309
if (forminfo[46] == (unsigned char)255)
311
unsigned char comment_length_buff[2];
312
int2store(comment_length_buff,create_info->comment.length);
313
if (my_write(file, comment_length_buff, 2, MYF(MY_NABP)) ||
314
my_write(file, (unsigned char*)create_info->comment.str,
315
create_info->comment.length, MYF(MY_NABP)))
319
/* Store storage type and field format array of fields */
325
memset(buff, 0, format_section_header_size);
326
/* length of section 2 bytes*/
327
int2store(buff+0, format_section_len);
328
/* flags of section 4 bytes*/
329
int4store(buff+2, flags);
330
/* 2 bytes left for future use */
333
if (my_write(file, (const unsigned char*)buff, format_section_header_size, MYF_RW))
336
if (my_write(file, (const unsigned char*)buff, 1, MYF_RW))
338
/* write column info, 1 byte per column */
340
List_iterator<Create_field> it(create_fields);
342
unsigned char column_format, write_byte;
345
column_format= (unsigned char)field->column_format();
346
write_byte= (column_format << COLUMN_FORMAT_SHIFT);
347
if (my_write(file, &write_byte, 1, MYF_RW))
352
lseek(file,filepos,SEEK_SET);
353
if (my_write(file, forminfo, 288, MYF_RW) ||
354
my_write(file, screen_buff, info_length, MYF_RW) ||
355
pack_fields(file, create_fields, data_offset))
361
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
362
(my_sync(file, MYF(MY_WME)) ||
363
my_sync_dir_by_file(file_name, MYF(MY_WME))))
366
if (my_close(file,MYF(MY_WME)))
371
Restore all UCS2 intervals.
372
HEX representation of them is not needed anymore.
374
List_iterator<Create_field> it(create_fields);
378
if (field->save_interval)
380
field->interval= field->save_interval;
381
field->save_interval= 0;
391
my_close(file,MYF(MY_WME));
393
my_delete(file_name,MYF(0));
395
} /* mysql_create_frm */
397
static void fill_table_proto(drizzle::Table *table_proto,
398
const char *table_name,
399
List<Create_field> &create_fields,
400
HA_CREATE_INFO *create_info,
404
Create_field *field_arg;
405
List_iterator<Create_field> it(create_fields);
406
drizzle::Table::StorageEngine *engine= table_proto->mutable_engine();
407
drizzle::Table::TableOptions *table_options= table_proto->mutable_options();
409
engine->set_name(create_info->db_type->name);
411
table_proto->set_name(table_name);
412
table_proto->set_type(drizzle::Table::STANDARD);
67
414
while ((field_arg= it++))
69
message::Table::Field *attribute;
71
/* some (one) code path for CREATE TABLE fills the proto
72
out more than the others, so we already have partially
73
filled out Field messages */
75
if (use_existing_fields)
76
attribute= table_proto.mutable_field(field_number++);
79
/* Other code paths still have to fill out the proto */
80
attribute= table_proto.add_field();
82
if (field_arg->flags & NOT_NULL_FLAG)
84
message::Table::Field::FieldConstraints *constraints;
86
constraints= attribute->mutable_constraints();
87
constraints->set_is_nullable(false);
90
attribute->set_name(field_arg->field_name);
93
assert((!(field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_nullable());
94
assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
97
message::Table::Field::FieldType parser_type= attribute->type();
99
if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
101
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
105
attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
107
switch (attribute->type()) {
108
default: /* Only deal with types that need extra information */
110
case message::Table::Field::DOUBLE:
113
* For DOUBLE, we only add a specific scale and precision iff
114
* the fixed decimal point has been specified...
116
if (field_arg->decimals != NOT_FIXED_DEC)
118
message::Table::Field::NumericFieldOptions *numeric_field_options;
120
numeric_field_options= attribute->mutable_numeric_options();
122
numeric_field_options->set_precision(field_arg->length);
123
numeric_field_options->set_scale(field_arg->decimals);
127
case message::Table::Field::VARCHAR:
129
message::Table::Field::StringFieldOptions *string_field_options;
416
drizzle::Table::Field *attribute;
417
//drizzle::Table::Field::FieldConstraints *constraints;
419
attribute= table_proto->add_field();
420
attribute->set_name(field_arg->field_name);
421
switch (field_arg->sql_type) {
422
case DRIZZLE_TYPE_TINY:
423
attribute->set_type(drizzle::Table::Field::TINYINT);
425
case DRIZZLE_TYPE_LONG:
426
attribute->set_type(drizzle::Table::Field::INTEGER);
428
case DRIZZLE_TYPE_DOUBLE:
429
attribute->set_type(drizzle::Table::Field::DOUBLE);
431
case DRIZZLE_TYPE_NULL :
432
assert(1); /* Not a user definable type */
433
case DRIZZLE_TYPE_TIMESTAMP:
434
attribute->set_type(drizzle::Table::Field::TIMESTAMP);
436
case DRIZZLE_TYPE_LONGLONG:
437
attribute->set_type(drizzle::Table::Field::BIGINT);
439
case DRIZZLE_TYPE_TIME:
440
attribute->set_type(drizzle::Table::Field::TIME);
442
case DRIZZLE_TYPE_DATETIME:
443
attribute->set_type(drizzle::Table::Field::DATETIME);
445
case DRIZZLE_TYPE_DATE:
446
attribute->set_type(drizzle::Table::Field::DATE);
448
case DRIZZLE_TYPE_VARCHAR:
450
drizzle::Table::Field::StringFieldOptions *string_field_options;
131
452
string_field_options= attribute->mutable_string_options();
133
if (! use_existing_fields || string_field_options->length()==0)
134
string_field_options->set_length(field_arg->length
135
/ field_arg->charset->mbmaxlen);
137
assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
139
if (! string_field_options->has_collation())
141
string_field_options->set_collation_id(field_arg->charset->number);
142
string_field_options->set_collation(field_arg->charset->name);
453
attribute->set_type(drizzle::Table::Field::VARCHAR);
454
string_field_options->set_length(field_arg->char_length);
455
string_field_options->set_collation_id(field_arg->charset->number);
456
string_field_options->set_collation(field_arg->charset->name);
146
case message::Table::Field::DECIMAL:
460
case DRIZZLE_TYPE_NEWDECIMAL:
148
message::Table::Field::NumericFieldOptions *numeric_field_options;
462
drizzle::Table::Field::NumericFieldOptions *numeric_field_options;
464
attribute->set_type(drizzle::Table::Field::DECIMAL);
150
465
numeric_field_options= attribute->mutable_numeric_options();
151
466
/* This is magic, I hate magic numbers -Brian */
152
467
numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
153
468
numeric_field_options->set_scale(field_arg->decimals);
156
case message::Table::Field::ENUM:
471
case DRIZZLE_TYPE_ENUM:
158
message::Table::Field::EnumerationValues *enumeration_options;
473
drizzle::Table::Field::SetFieldOptions *set_field_options;
160
475
assert(field_arg->interval);
162
enumeration_options= attribute->mutable_enumeration_values();
477
attribute->set_type(drizzle::Table::Field::ENUM);
478
set_field_options= attribute->mutable_set_options();
164
480
for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
166
482
const char *src= field_arg->interval->type_names[pos];
168
enumeration_options->add_field_value(src);
484
set_field_options->add_value(src);
170
enumeration_options->set_collation_id(field_arg->charset->number);
171
enumeration_options->set_collation(field_arg->charset->name);
486
set_field_options->set_count_elements(set_field_options->value_size());
174
case message::Table::Field::BLOB:
176
message::Table::Field::StringFieldOptions *string_field_options;
178
string_field_options= attribute->mutable_string_options();
179
string_field_options->set_collation_id(field_arg->charset->number);
180
string_field_options->set_collation(field_arg->charset->name);
489
case DRIZZLE_TYPE_BLOB:
490
attribute->set_type(drizzle::Table::Field::BLOB);
186
assert (!use_existing_fields || parser_type == attribute->type());
189
497
field_constraints= attribute->mutable_constraints();
190
498
constraints->set_is_nullable(field_arg->def->null_value);
501
/* Set the comment */
193
502
if (field_arg->comment.length)
196
tmp_len= system_charset_info->cset->charpos(system_charset_info,
197
field_arg->comment.str,
198
field_arg->comment.str +
199
field_arg->comment.length,
200
COLUMN_COMMENT_MAXLEN);
202
if (tmp_len < field_arg->comment.length)
204
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
205
field_arg->comment.str,"COLUMN COMMENT",
206
(uint32_t) COLUMN_COMMENT_MAXLEN);
210
if (! use_existing_fields)
211
attribute->set_comment(field_arg->comment.str);
213
assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
216
if (field_arg->unireg_check == Field::NEXT_NUMBER)
218
message::Table::Field::NumericFieldOptions *field_options;
219
field_options= attribute->mutable_numeric_options();
220
field_options->set_is_autoincrement(true);
223
if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
224
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
226
message::Table::Field::FieldOptions *field_options;
227
field_options= attribute->mutable_options();
228
field_options->set_default_expression("CURRENT_TIMESTAMP");
231
if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
232
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
234
message::Table::Field::FieldOptions *field_options;
235
field_options= attribute->mutable_options();
236
field_options->set_update_expression("CURRENT_TIMESTAMP");
239
if (field_arg->def == NULL && attribute->constraints().is_nullable())
241
message::Table::Field::FieldOptions *field_options;
242
field_options= attribute->mutable_options();
244
field_options->set_default_null(true);
248
message::Table::Field::FieldOptions *field_options;
249
field_options= attribute->mutable_options();
251
if (field_arg->def->is_null())
253
field_options->set_default_null(true);
258
String *default_value= field_arg->def->val_str(&d);
260
assert(default_value);
262
if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
263
|| field_arg->sql_type==DRIZZLE_TYPE_BLOB)
264
&& ((field_arg->length / field_arg->charset->mbmaxlen)
265
< default_value->length()))
267
my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
271
if (field_arg->sql_type == DRIZZLE_TYPE_DATE
272
|| field_arg->sql_type == DRIZZLE_TYPE_DATETIME
273
|| field_arg->sql_type == DRIZZLE_TYPE_TIMESTAMP)
277
if (field_arg->def->get_date(<ime, TIME_FUZZY_DATE))
279
my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
280
default_value->c_str());
284
/* We now do the casting down to the appropriate type.
286
Yes, this implicit casting is balls.
287
It was previously done on reading the proto back in,
288
but we really shouldn't store the bogus things in the proto,
289
and instead do the casting behaviour here.
291
the timestamp errors are taken care of elsewhere.
294
if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
296
Item *typecast= new Item_datetime_typecast(field_arg->def);
297
typecast->quick_fix_field();
298
typecast->val_str(default_value);
300
else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
302
Item *typecast= new Item_date_typecast(field_arg->def);
303
typecast->quick_fix_field();
304
typecast->val_str(default_value);
308
if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
309
&& field_arg->charset==&my_charset_bin)
310
|| (field_arg->sql_type==DRIZZLE_TYPE_BLOB
311
&& field_arg->charset==&my_charset_bin))
314
bin_default.assign(default_value->c_ptr(),
315
default_value->length());
316
field_options->set_default_bin_value(bin_default);
320
field_options->set_default_value(default_value->c_ptr());
325
assert(field_arg->unireg_check == Field::NONE
326
|| field_arg->unireg_check == Field::NEXT_NUMBER
327
|| field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
328
|| field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
329
|| field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD);
333
assert(! use_existing_fields || (field_number == table_proto.field_size()));
335
if (create_info->table_options & HA_OPTION_PACK_RECORD)
336
table_options->set_pack_record(true);
338
if (table_options->has_comment() && table_options->comment().length() == 0)
339
table_options->clear_comment();
341
if (table_options->has_comment())
344
tmp_len= system_charset_info->cset->charpos(system_charset_info,
345
table_options->comment().c_str(),
346
table_options->comment().c_str() +
347
table_options->comment().length(),
348
TABLE_COMMENT_MAXLEN);
350
if (tmp_len < table_options->comment().length())
352
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
353
table_options->comment().c_str(),"Table COMMENT",
354
(uint32_t) TABLE_COMMENT_MAXLEN);
359
if (create_info->default_table_charset)
361
table_options->set_collation_id(
362
create_info->default_table_charset->number);
363
table_options->set_collation(create_info->default_table_charset->name);
366
if (create_info->used_fields & HA_CREATE_USED_AUTO)
367
table_options->set_has_user_set_auto_increment_value(true);
369
table_options->set_has_user_set_auto_increment_value(false);
503
attribute->set_comment(field_arg->comment.str);
506
if (create_info->comment.length)
507
table_options->set_comment(create_info->comment.str);
509
if (create_info->table_charset)
511
table_options->set_collation_id(field_arg->charset->number);
512
table_options->set_collation(field_arg->charset->name);
515
if (create_info->connect_string.length)
516
table_options->set_connect_string(create_info->connect_string.str);
518
if (create_info->data_file_name)
519
table_options->set_data_file_name(create_info->data_file_name);
521
if (create_info->index_file_name)
522
table_options->set_index_file_name(create_info->index_file_name);
524
if (create_info->max_rows)
525
table_options->set_max_rows(create_info->max_rows);
527
if (create_info->min_rows)
528
table_options->set_min_rows(create_info->min_rows);
371
530
if (create_info->auto_increment_value)
372
531
table_options->set_auto_increment_value(create_info->auto_increment_value);
374
for (uint32_t i= 0; i < keys; i++)
533
if (create_info->avg_row_length)
534
table_options->set_avg_row_length(create_info->avg_row_length);
536
if (create_info->key_block_size)
537
table_options->set_key_block_size(create_info->key_block_size);
539
if (create_info->block_size)
540
table_options->set_block_size(create_info->block_size);
542
for (unsigned int i= 0; i < keys; i++)
376
message::Table::Index *idx;
544
drizzle::Table::Index *idx;
378
idx= table_proto.add_indexes();
546
idx= table_proto->add_index();
380
548
assert(test(key_info[i].flags & HA_USES_COMMENT) ==
381
549
(key_info[i].comment.length > 0));
383
551
idx->set_name(key_info[i].name);
385
idx->set_key_length(key_info[i].key_length);
387
if (is_primary_key_name(key_info[i].name))
553
if(is_primary_key_name(key_info[i].name))
388
554
idx->set_is_primary(true);
390
556
idx->set_is_primary(false);
536
662
create_fields Fields to create
537
663
keys number of keys to create
538
664
key_info Keys to create
666
is_like is true for mysql_create_like_schema_frm
545
bool rea_create_table(Session *session,
546
const TableIdentifier &identifier,
547
message::Table &table_proto,
548
HA_CREATE_INFO *create_info,
549
List<CreateField> &create_fields,
550
uint32_t keys, KeyInfo *key_info)
673
int rea_create_table(Session *session, const char *path,
674
const char *db, const char *table_name,
675
HA_CREATE_INFO *create_info,
676
List<Create_field> &create_fields,
677
uint32_t keys, KEY *key_info, handler *file,
552
assert(table_proto.has_name());
553
if (fill_table_proto(table_proto, create_fields, create_info,
557
assert(table_proto.name() == identifier.getTableName());
559
if (plugin::StorageEngine::createTable(*session,
680
char frm_name[FN_REFLEN];
682
/* Proto will blow up unless we give a name */
685
/* For is_like we return once the file has been created */
688
if (mysql_create_frm(session, path, db, table_name, create_info,
689
create_fields, keys, key_info, file))
692
if (create_table_proto_file(path, table_name, create_info,
693
create_fields, keys, key_info))
698
/* Here we need to build the full frm from the path */
701
sprintf(frm_name,"%s%s", path, reg_ext);
703
if (mysql_create_frm(session, frm_name, db, table_name, create_info,
704
create_fields, keys, key_info, file))
707
if (create_table_proto_file(frm_name, table_name, create_info,
708
create_fields, keys, key_info))
712
// Make sure mysql_create_frm din't remove extension
713
assert(*fn_rext(frm_name));
714
if (session->variables.keep_files_on_create)
715
create_info->options|= HA_CREATE_KEEP_FILES;
716
if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
718
if (ha_create_table(session, path, db, table_name,
724
file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
725
my_delete(frm_name, MYF(0));
726
delete_table_proto_file(frm_name);
568
729
} /* rea_create_table */
570
} /* namespace drizzled */
732
/* Pack screens to a screen for save in a form-file */
734
static unsigned char *pack_screens(List<Create_field> &create_fields,
735
uint32_t *info_length, uint32_t *screens,
739
uint32_t row,start_row,end_row,fields_on_screen;
740
uint32_t length,cols, cols_half_len;
741
unsigned char *info,*pos,*start_screen;
742
uint32_t fields=create_fields.elements;
743
List_iterator<Create_field> it(create_fields);
745
start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
746
cols_half_len= (uint32_t)(cols >> 1);
748
*screens=(fields-1)/fields_on_screen+1;
749
length= (*screens) * (SC_INFO_LENGTH+cols_half_len+4);
753
length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
755
if (!(info=(unsigned char*) malloc(length)))
762
for (i=0 ; i < fields ; i++)
764
Create_field *cfield=it++;
765
if (row++ == end_row)
769
length=(uint) (pos-start_screen);
770
int2store(start_screen,length);
771
start_screen[2]=(unsigned char) (fields_on_screen+1);
772
start_screen[3]=(unsigned char) (fields_on_screen);
777
pos[0]= (unsigned char) start_row-2; /* Header string */
778
pos[1]= (unsigned char) (cols >> 2);
779
pos[2]= (unsigned char) (cols >> 1) +1;
780
memset((char*)pos+3,' ',cols_half_len);
781
pos[cols_half_len+3]= '\0';
782
pos+= cols_half_len+4;
784
length= (uint32_t) strlen(cfield->field_name);
790
pos[0]=(unsigned char) row;
792
pos[2]=(unsigned char) (length+1);
793
strncpy((char*)pos+3,cfield->field_name, length);
794
pos[length + 3]= '\0';
795
pos+= length + 3 + 1;
797
cfield->row=(uint8_t) row;
798
cfield->col=(uint8_t) (length+1);
799
cfield->sc_length=(uint8_t) cmin(cfield->length,(uint32_t)cols-(length+2));
801
length=(uint) (pos-start_screen);
802
int2store(start_screen,length);
803
start_screen[2]=(unsigned char) (row-start_row+2);
804
start_screen[3]=(unsigned char) (row-start_row+1);
806
*info_length=(uint) (pos-info);
811
/* Pack keyinfo and keynames to keybuff for save in form-file. */
813
static uint32_t pack_keys(unsigned char *keybuff, uint32_t key_count, KEY *keyinfo,
816
uint32_t key_parts,length;
817
unsigned char *pos, *keyname_pos;
819
KEY_PART_INFO *key_part,*key_part_end;
824
for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
826
int2store(pos, (key->flags ^ HA_NOSAME));
827
int2store(pos+2,key->key_length);
828
pos[4]= (unsigned char) key->key_parts;
829
pos[5]= (unsigned char) key->algorithm;
830
int2store(pos+6, key->block_size);
832
key_parts+=key->key_parts;
833
for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
834
key_part != key_part_end ;
839
int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
840
offset= (uint) (key_part->offset+data_offset+1);
841
int2store(pos+2, offset);
842
pos[4]=0; // Sort order
843
int2store(pos+5,key_part->key_type);
844
int2store(pos+7,key_part->length);
850
*pos++=(unsigned char) NAMES_SEP_CHAR;
851
for (key=keyinfo ; key != end ; key++)
853
unsigned char *tmp=(unsigned char*) strcpy((char*) pos,key->name);
854
tmp+= strlen(key->name);
855
*tmp++= (unsigned char) NAMES_SEP_CHAR;
861
for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
863
if (key->flags & HA_USES_COMMENT)
865
int2store(pos, key->comment.length);
866
unsigned char *tmp= (unsigned char*)strncpy((char*) pos+2,key->comment.str,key->comment.length);
867
tmp+= key->comment.length;
872
if (key_count > 127 || key_parts > 127)
874
keybuff[0]= (key_count & 0x7f) | 0x80;
875
keybuff[1]= key_count >> 7;
876
int2store(keybuff+2,key_parts);
880
keybuff[0]=(unsigned char) key_count;
881
keybuff[1]=(unsigned char) key_parts;
882
keybuff[2]= keybuff[3]= 0;
884
length=(uint) (pos-keyname_pos);
885
int2store(keybuff+4,length);
886
return((uint) (pos-keybuff));
890
/* Make formheader */
892
static bool pack_header(unsigned char *forminfo,
893
List<Create_field> &create_fields,
894
uint32_t info_length, uint32_t screens, uint32_t table_options,
895
ulong data_offset, handler *file)
897
uint32_t length,int_count,int_length,no_empty, int_parts;
898
uint32_t time_stamp_pos,null_fields;
899
ulong reclength, totlength, n_length, com_length, vcol_info_length;
902
if (create_fields.elements > MAX_FIELDS)
904
my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
909
reclength= data_offset;
910
no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
911
com_length=vcol_info_length=0;
916
List_iterator<Create_field> it(create_fields);
920
uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
923
field->comment.length,
924
COLUMN_COMMENT_MAXLEN);
926
if (tmp_len < field->comment.length)
928
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
929
field->comment.str,"COLUMN COMMENT",
930
(uint) COLUMN_COMMENT_MAXLEN);
933
if (field->vcol_info)
935
tmp_len= system_charset_info->cset->charpos(system_charset_info,
936
field->vcol_info->expr_str.str,
937
field->vcol_info->expr_str.str +
938
field->vcol_info->expr_str.length,
939
VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
941
if (tmp_len < field->vcol_info->expr_str.length)
943
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
944
field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
945
(uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
949
Sum up the length of the expression string and mandatory header bytes
952
vcol_info_length+= field->vcol_info->expr_str.length+(uint)FRM_VCOL_HEADER_SIZE;
955
totlength+= field->length;
956
com_length+= field->comment.length;
957
if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
958
field->unireg_check & MTYP_NOEMPTY_BIT)
960
field->unireg_check= (Field::utype) ((uint) field->unireg_check |
965
We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
966
as auto-update field.
968
if (field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
969
MTYP_TYPENR(field->unireg_check) != Field::NONE &&
971
time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
972
length=field->pack_length;
973
if ((uint) field->offset+ (uint) data_offset+ length > reclength)
974
reclength=(uint) (field->offset+ data_offset + length);
975
n_length+= (ulong) strlen(field->field_name)+1;
976
field->interval_id=0;
977
field->save_interval= 0;
980
uint32_t old_int_count=int_count;
982
if (field->charset->mbminlen > 1)
985
Escape UCS2 intervals using HEX notation to avoid
986
problems with delimiters between enum elements.
987
As the original representation is still needed in
988
the function make_empty_rec to create a record of
989
filled with default values it is saved in save_interval
990
The HEX representation is created from this copy.
992
field->save_interval= field->interval;
993
field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
994
*field->interval= *field->save_interval;
995
field->interval->type_names=
996
(const char **) sql_alloc(sizeof(char*) *
997
(field->interval->count+1));
998
field->interval->type_names[field->interval->count]= 0;
999
field->interval->type_lengths=
1000
(uint32_t *) sql_alloc(sizeof(uint) * field->interval->count);
1002
for (uint32_t pos= 0; pos < field->interval->count; pos++)
1005
const char *src= field->save_interval->type_names[pos];
1006
uint32_t hex_length;
1007
length= field->save_interval->type_lengths[pos];
1008
hex_length= length * 2;
1009
field->interval->type_lengths[pos]= hex_length;
1010
field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length +
1012
octet2hex(dst, src, length);
1016
field->interval_id=get_interval_id(&int_count,create_fields,field);
1017
if (old_int_count != int_count)
1019
for (const char **pos=field->interval->type_names ; *pos ; pos++)
1020
int_length+=(uint) strlen(*pos)+1; // field + suffix prefix
1021
int_parts+=field->interval->count+1;
1024
if (f_maybe_null(field->pack_flag))
1027
int_length+=int_count*2; // 255 prefix + 0 suffix
1029
/* Save values in forminfo */
1031
if (reclength > (ulong) file->max_record_length())
1033
my_error(ER_TOO_BIG_ROWSIZE, MYF(0), (uint) file->max_record_length());
1036
/* Hack to avoid bugs with small static rows in MySQL */
1037
reclength=cmax((ulong)file->min_record_length(table_options),reclength);
1038
if (info_length+(ulong) create_fields.elements*FCOMP+288+
1039
n_length+int_length+com_length+vcol_info_length > 65535L ||
1042
my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
1046
memset(forminfo, 0, 288);
1047
length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
1048
com_length+vcol_info_length);
1049
int2store(forminfo,length);
1050
forminfo[256] = (uint8_t) screens;
1051
int2store(forminfo+258,create_fields.elements);
1052
int2store(forminfo+260,info_length);
1053
int2store(forminfo+262,totlength);
1054
int2store(forminfo+264,no_empty);
1055
int2store(forminfo+266,reclength);
1056
int2store(forminfo+268,n_length);
1057
int2store(forminfo+270,int_count);
1058
int2store(forminfo+272,int_parts);
1059
int2store(forminfo+274,int_length);
1060
int2store(forminfo+276,time_stamp_pos);
1061
int2store(forminfo+278,80); /* Columns needed */
1062
int2store(forminfo+280,22); /* Rows needed */
1063
int2store(forminfo+282,null_fields);
1064
int2store(forminfo+284,com_length);
1065
int2store(forminfo+286,vcol_info_length);
1066
/* forminfo+288 is free to use for additional information */
1071
/* get each unique interval each own id */
1073
static uint32_t get_interval_id(uint32_t *int_count,List<Create_field> &create_fields,
1074
Create_field *last_field)
1076
List_iterator<Create_field> it(create_fields);
1077
Create_field *field;
1078
TYPELIB *interval=last_field->interval;
1080
while ((field=it++) != last_field)
1082
if (field->interval_id && field->interval->count == interval->count)
1085
for (a=field->interval->type_names, b=interval->type_names ;
1086
*a && !strcmp(*a,*b);
1091
return field->interval_id; // Re-use last interval
1095
return ++*int_count; // New unique interval
1099
/* Save fields, fieldnames and intervals */
1101
static bool pack_fields(File file, List<Create_field> &create_fields,
1104
register uint32_t i;
1105
uint32_t int_count, comment_length=0, vcol_info_length=0;
1106
unsigned char buff[MAX_FIELD_WIDTH];
1107
Create_field *field;
1110
/* Write field info */
1112
List_iterator<Create_field> it(create_fields);
1115
while ((field=it++))
1118
uint32_t cur_vcol_expr_len= 0;
1119
buff[0]= (unsigned char) field->row;
1120
buff[1]= (unsigned char) field->col;
1121
buff[2]= (unsigned char) field->sc_length;
1122
int2store(buff+3, field->length);
1123
/* The +1 is here becasue the col offset in .frm file have offset 1 */
1124
recpos= field->offset+1 + (uint) data_offset;
1125
int3store(buff+5,recpos);
1126
int2store(buff+8,field->pack_flag);
1127
int2store(buff+10,field->unireg_check);
1128
buff[12]= (unsigned char) field->interval_id;
1129
buff[13]= (unsigned char) field->sql_type;
1131
buff[14]= (unsigned char) field->charset->number;
1133
buff[14]= 0; // Numerical
1134
if (field->vcol_info)
1137
Use the interval_id place in the .frm file to store the length of
1138
virtual field's data.
1140
buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
1141
(uint)FRM_VCOL_HEADER_SIZE;
1142
vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE;
1143
buff[13]= (unsigned char) DRIZZLE_TYPE_VIRTUAL;
1145
int2store(buff+15, field->comment.length);
1146
comment_length+= field->comment.length;
1147
set_if_bigger(int_count,field->interval_id);
1148
if (my_write(file, buff, FCOMP, MYF_RW))
1152
/* Write fieldnames */
1153
buff[0]=(unsigned char) NAMES_SEP_CHAR;
1154
if (my_write(file, buff, 1, MYF_RW))
1158
while ((field=it++))
1160
char *pos= strcpy((char*) buff,field->field_name);
1161
pos+= strlen(field->field_name);
1162
*pos++=NAMES_SEP_CHAR;
1163
if (i == create_fields.elements-1)
1165
if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW))
1170
/* Write intervals */
1173
String tmp((char*) buff,sizeof(buff), &my_charset_bin);
1177
while ((field=it++))
1179
if (field->interval_id > int_count)
1181
unsigned char sep= 0;
1182
unsigned char occ[256];
1184
unsigned char *val= NULL;
1186
memset(occ, 0, sizeof(occ));
1188
for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
1189
for (uint32_t j = 0; j < field->interval->type_lengths[i]; j++)
1190
occ[(unsigned int) (val[j])]= 1;
1192
if (!occ[(unsigned char)NAMES_SEP_CHAR])
1193
sep= (unsigned char) NAMES_SEP_CHAR;
1194
else if (!occ[(unsigned int)','])
1198
for (uint32_t i=1; i<256; i++)
1207
if(!sep) /* disaster, enum uses all characters, none left as separator */
1209
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
1215
int_count= field->interval_id;
1217
for (const char **pos=field->interval->type_names ; *pos ; pos++)
1222
tmp.append('\0'); // End of intervall
1225
if (my_write(file,(unsigned char*) tmp.ptr(),tmp.length(),MYF_RW))
1232
while ((field=it++))
1234
if (field->comment.length)
1235
if (my_write(file, (unsigned char*) field->comment.str, field->comment.length,
1240
if (vcol_info_length)
1244
while ((field=it++))
1247
Pack each virtual field as follows:
1248
byte 1 = 1 (always 1 to allow for future extensions)
1250
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
1251
byte 4-... = virtual column expression (text data)
1253
if (field->vcol_info && field->vcol_info->expr_str.length)
1255
buff[0]= (unsigned char)1;
1256
buff[1]= (unsigned char) field->sql_type;
1257
buff[2]= (unsigned char) field->is_stored;
1258
if (my_write(file, buff, 3, MYF_RW))
1261
(unsigned char*) field->vcol_info->expr_str.str,
1262
field->vcol_info->expr_str.length,
1272
/* save an empty record on start of formfile */
1274
static bool make_empty_rec(Session *session, File file,
1275
enum legacy_db_type table_type __attribute__((unused)),
1276
uint32_t table_options,
1277
List<Create_field> &create_fields,
1284
uint32_t null_count;
1285
unsigned char *buff,*null_pos;
1288
Create_field *field;
1289
enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
1292
/* We need a table to generate columns for default values */
1293
memset(&table, 0, sizeof(table));
1294
memset(&share, 0, sizeof(share));
1297
if (!(buff=(unsigned char*) malloc((size_t) reclength)))
1301
memset(buff, 0, (size_t) reclength);
1303
table.in_use= session;
1304
table.s->db_low_byte_first= handler->low_byte_first();
1305
table.s->blob_ptr_size= portable_sizeof_char_ptr;
1308
if (!(table_options & HA_OPTION_PACK_RECORD))
1310
null_count++; // Need one bit for delete mark
1315
List_iterator<Create_field> it(create_fields);
1316
session->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
1317
while ((field=it++))
1320
regfield don't have to be deleted as it's allocated with sql_alloc()
1322
Field *regfield= make_field(&share,
1323
buff+field->offset + data_offset,
1325
null_pos + null_count / 8,
1330
field->unireg_check,
1331
field->save_interval ? field->save_interval :
1337
goto err; // End of memory
1340
/* save_in_field() will access regfield->table->in_use */
1341
regfield->init(&table);
1343
if (!(field->flags & NOT_NULL_FLAG))
1345
*regfield->null_ptr|= regfield->null_bit;
1349
type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1353
int res= field->def->save_in_field(regfield, 1);
1354
/* If not ok or warning of level 'note' */
1355
if (res != 0 && res != 3)
1357
my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1359
delete regfield; //To avoid memory leak
1363
else if (regfield->real_type() == DRIZZLE_TYPE_ENUM &&
1364
(field->flags & NOT_NULL_FLAG))
1366
regfield->set_notnull();
1367
regfield->store((int64_t) 1, true);
1369
else if (type == Field::YES) // Old unireg type
1370
regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),system_charset_info);
1371
else if (type == Field::NO) // Old unireg type
1372
regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
1376
assert(data_offset == ((null_count + 7) / 8));
1379
We need to set the unused bits to 1. If the number of bits is a multiple
1380
of 8 there are no unused bits.
1383
*(null_pos + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1385
error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0;
1389
session->count_cuted_fields= old_count_cuted_fields;
1391
} /* make_empty_rec */