~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/unireg.cc

  • Committer: Brian Aker
  • Date: 2009-01-09 22:07:54 UTC
  • Revision ID: brian@tangent.org-20090109220754-1y50h7lqi9i1ifcs
Dead test/wrong test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
15
 
 
16
 
#include "config.h"
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
17
/*
 
18
  Functions to create a unireg form-file from a FIELD and a fieldname-fieldinfo
 
19
  struct.
 
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.
 
24
*/
 
25
 
 
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"
23
 
 
24
 
#include "drizzled/internal/my_sys.h"
25
 
 
26
31
 
27
32
/* For proto */
28
33
#include <string>
29
34
#include <fstream>
30
 
#include <fcntl.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>
36
 
 
37
 
#include <drizzled/table_proto.h>
38
 
#include <drizzled/charset.h>
39
 
 
40
 
#include "drizzled/function/time/typecast.h"
41
 
 
 
35
#include <drizzled/serialize/serialize.h>
42
36
using namespace std;
43
37
 
44
 
namespace drizzled {
45
 
 
46
 
static int fill_table_proto(message::Table &table_proto,
47
 
                            List<CreateField> &create_fields,
48
 
                            HA_CREATE_INFO *create_info,
49
 
                            uint32_t keys,
50
 
                            KeyInfo *key_info)
51
 
{
52
 
  CreateField *field_arg;
53
 
  List_iterator<CreateField> it(create_fields);
54
 
  message::Table::TableOptions *table_options= table_proto.mutable_options();
55
 
 
56
 
  if (create_fields.elements > MAX_FIELDS)
57
 
  {
58
 
    my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
59
 
    return(1);
60
 
  }
61
 
 
62
 
  assert(strcmp(table_proto.engine().name().c_str(),
63
 
                create_info->db_type->getName().c_str())==0);
64
 
 
65
 
  int field_number= 0;
66
 
  bool use_existing_fields= table_proto.field_size() > 0;
 
38
#define FCOMP                   17              /* Bytes for a packed field */
 
39
 
 
40
static unsigned char * pack_screens(List<Create_field> &create_fields,
 
41
                                    uint32_t *info_length, uint32_t *screens,
 
42
                                    bool small_file);
 
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,
 
54
                        ulong data_offset);
 
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,
 
60
                           handler *handler);
 
61
 
 
62
/**
 
63
  An interceptor to hijack ER_TOO_MANY_FIELDS error from
 
64
  pack_screens and retry again without UNIREG screens.
 
65
 
 
66
  XXX: what is a UNIREG  screen?
 
67
*/
 
68
 
 
69
struct Pack_header_error_handler: public Internal_error_handler
 
70
{
 
71
  virtual bool handle_error(uint32_t sql_errno,
 
72
                            const char *message,
 
73
                            DRIZZLE_ERROR::enum_warning_level level,
 
74
                            Session *session);
 
75
  bool is_handled;
 
76
  Pack_header_error_handler() :is_handled(false) {}
 
77
};
 
78
 
 
79
 
 
80
bool
 
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 */)
 
86
{
 
87
  is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
 
88
  return is_handled;
 
89
}
 
90
 
 
91
int mysql_frm_type(char *path, enum legacy_db_type *dbt)
 
92
{
 
93
  int file;
 
94
  unsigned char header[10];
 
95
  int error;
 
96
 
 
97
  *dbt= DB_TYPE_UNKNOWN;
 
98
 
 
99
  file= open(path, O_RDONLY);
 
100
 
 
101
  if(file < 1)
 
102
    return 1;
 
103
 
 
104
  error= read(file, header, sizeof(header));
 
105
  close(file);
 
106
 
 
107
  if (error!=sizeof(header))
 
108
    return 1;
 
109
 
 
110
  /*
 
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)
 
114
  */
 
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)))
 
118
    return 0;
 
119
 
 
120
  *dbt= (enum legacy_db_type) (uint) *(header + 3);
 
121
  return 0;
 
122
}
 
123
 
 
124
/*
 
125
  Create a frm (table definition) file
 
126
 
 
127
  SYNOPSIS
 
128
    mysql_create_frm()
 
129
    session                     Thread handler
 
130
    file_name           Path for file (including database and .frm)
 
131
    db                  Name of database
 
132
    table               Name of table
 
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
 
138
                        create_info->db_type
 
139
  RETURN
 
140
    0  ok
 
141
    1  error
 
142
*/
 
143
 
 
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,
 
149
                      handler *db_file)
 
150
{
 
151
  LEX_STRING str_db_type;
 
152
  uint32_t reclength, info_length, screens, key_info_length, maxlength, tmp_len;
 
153
  ulong key_buff_length;
 
154
  File file;
 
155
  ulong filepos, data_offset;
 
156
  unsigned char fileinfo[64],forminfo[288],*keybuff;
 
157
  TYPELIB formnames;
 
158
  unsigned char *screen_buff;
 
159
  char buff[128];
 
160
  const uint32_t format_section_header_size= 8;
 
161
  uint32_t format_section_len;
 
162
  Pack_header_error_handler pack_header_error_handler;
 
163
  int error;
 
164
 
 
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)))
 
168
    return(1);
 
169
  assert(db_file != NULL);
 
170
 
 
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;
 
175
 
 
176
  session->push_internal_handler(&pack_header_error_handler);
 
177
 
 
178
  error= pack_header(forminfo,
 
179
                     create_fields,info_length,
 
180
                     screens, create_info->table_options,
 
181
                     data_offset, db_file);
 
182
 
 
183
  session->pop_internal_handler();
 
184
 
 
185
  if (error)
 
186
  {
 
187
    free(screen_buff);
 
188
    if (! pack_header_error_handler.is_handled)
 
189
      return(1);
 
190
 
 
191
    // Try again without UNIREG screens (to get more columns)
 
192
    if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
 
193
      return(1);
 
194
    if (pack_header(forminfo,
 
195
                    create_fields,info_length,
 
196
                    screens, create_info->table_options, data_offset, db_file))
 
197
    {
 
198
      free(screen_buff);
 
199
      return(1);
 
200
    }
 
201
  }
 
202
  reclength=uint2korr(forminfo+266);
 
203
 
 
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);
 
207
  /* str_db_type */
 
208
  create_info->extra_size= (2 + str_db_type.length +
 
209
                            2 + create_info->connect_string.length);
 
210
  /*
 
211
    Partition:
 
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
 
215
      => Total 6 byte
 
216
  */
 
217
  create_info->extra_size+= 6;
 
218
 
 
219
  /* Add space for storage type and field format array of fields */
 
220
  format_section_len=
 
221
    format_section_header_size + 1 + create_fields.elements;
 
222
  create_info->extra_size+= format_section_len;
 
223
 
 
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);
 
229
 
 
230
  if (tmp_len < create_info->comment.length)
 
231
  {
 
232
    my_error(ER_WRONG_STRING_LENGTH, MYF(0),
 
233
             create_info->comment.str,"Table COMMENT",
 
234
             (uint) TABLE_COMMENT_MAXLEN);
 
235
    free(screen_buff);
 
236
    return(1);
 
237
  }
 
238
 
 
239
  //if table comment is larger than 180 bytes, store into extra segment.
 
240
  if (create_info->comment.length > 180)
 
241
  {
 
242
    forminfo[46]=255;
 
243
    create_info->extra_size+= 2 + create_info->comment.length;
 
244
  }
 
245
  else{
 
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;
 
249
#ifdef EXTRA_DEBUG
 
250
    /*
 
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.
 
254
    */
 
255
    memset(forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
 
256
#endif
 
257
  }
 
258
 
 
259
  if ((file=create_frm(session, file_name, db, table, reclength, fileinfo,
 
260
                       create_info, keys, key_info)) < 0)
 
261
  {
 
262
    free(screen_buff);
 
263
    return(1);
 
264
  }
 
265
 
 
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,"")))
 
271
    goto err;
 
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);
 
278
 
 
279
 
 
280
  int2store(fileinfo+59,db_file->extra_rec_buf_length());
 
281
 
 
282
  if (pwrite(file, fileinfo, 64, 0L) == 0 ||
 
283
      pwrite(file, keybuff, key_info_length, (ulong) uint2korr(fileinfo+6)) == 0)
 
284
    goto err;
 
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))
 
289
    goto err;
 
290
 
 
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)))
 
295
      goto err;
 
296
 
 
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)))
 
301
    goto err;
 
302
 
 
303
  {
 
304
    memset(buff, 0, 6);
 
305
    if (my_write(file, (unsigned char*) buff, 6, MYF_RW))
 
306
      goto err;
 
307
  }
 
308
 
 
309
  if (forminfo[46] == (unsigned char)255)
 
310
  {
 
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)))
 
316
      goto err;
 
317
  }
 
318
 
 
319
  /* Store storage type and field format array of fields */
 
320
  {
 
321
    /* prepare header */
 
322
    {
 
323
      uint32_t flags= 0;
 
324
 
 
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 */
 
331
    }
 
332
    /* write header */
 
333
    if (my_write(file, (const unsigned char*)buff, format_section_header_size, MYF_RW))
 
334
      goto err;
 
335
    buff[0]= 0;
 
336
    if (my_write(file, (const unsigned char*)buff, 1, MYF_RW))
 
337
      goto err;
 
338
    /* write column info, 1 byte per column */
 
339
    {
 
340
      List_iterator<Create_field> it(create_fields);
 
341
      Create_field *field;
 
342
      unsigned char column_format, write_byte;
 
343
      while ((field=it++))
 
344
      {
 
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))
 
348
          goto err;
 
349
      }
 
350
    }
 
351
  }
 
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))
 
356
    goto err;
 
357
 
 
358
  free(screen_buff);
 
359
  free(keybuff);
 
360
 
 
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))))
 
364
      goto err2;
 
365
 
 
366
  if (my_close(file,MYF(MY_WME)))
 
367
    goto err3;
 
368
 
 
369
  {
 
370
    /*
 
371
      Restore all UCS2 intervals.
 
372
      HEX representation of them is not needed anymore.
 
373
    */
 
374
    List_iterator<Create_field> it(create_fields);
 
375
    Create_field *field;
 
376
    while ((field=it++))
 
377
    {
 
378
      if (field->save_interval)
 
379
      {
 
380
        field->interval= field->save_interval;
 
381
        field->save_interval= 0;
 
382
      }
 
383
    }
 
384
  }
 
385
  return(0);
 
386
 
 
387
err:
 
388
  free(screen_buff);
 
389
  free(keybuff);
 
390
err2:
 
391
  my_close(file,MYF(MY_WME));
 
392
err3:
 
393
  my_delete(file_name,MYF(0));
 
394
  return(1);
 
395
} /* mysql_create_frm */
 
396
 
 
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,
 
401
                             uint32_t keys,
 
402
                             KEY *key_info)
 
403
{
 
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();
 
408
 
 
409
  engine->set_name(create_info->db_type->name);
 
410
 
 
411
  table_proto->set_name(table_name);
 
412
  table_proto->set_type(drizzle::Table::STANDARD);
 
413
 
67
414
  while ((field_arg= it++))
68
415
  {
69
 
    message::Table::Field *attribute;
70
 
 
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 */
74
 
 
75
 
    if (use_existing_fields)
76
 
      attribute= table_proto.mutable_field(field_number++);
77
 
    else
78
 
    {
79
 
      /* Other code paths still have to fill out the proto */
80
 
      attribute= table_proto.add_field();
81
 
 
82
 
      if (field_arg->flags & NOT_NULL_FLAG)
83
 
      {
84
 
        message::Table::Field::FieldConstraints *constraints;
85
 
 
86
 
        constraints= attribute->mutable_constraints();
87
 
        constraints->set_is_nullable(false);
88
 
      }
89
 
 
90
 
      attribute->set_name(field_arg->field_name);
91
 
    }
92
 
 
93
 
    assert((!(field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_nullable());
94
 
    assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
95
 
 
96
 
 
97
 
    message::Table::Field::FieldType parser_type= attribute->type();
98
 
 
99
 
    if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
100
 
    {
101
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
102
 
      return -1;
103
 
    }
104
 
 
105
 
    attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
106
 
 
107
 
    switch (attribute->type()) {
108
 
    default: /* Only deal with types that need extra information */
109
 
      break;
110
 
    case message::Table::Field::DOUBLE:
111
 
      {
112
 
        /*
113
 
         * For DOUBLE, we only add a specific scale and precision iff
114
 
         * the fixed decimal point has been specified...
115
 
         */
116
 
        if (field_arg->decimals != NOT_FIXED_DEC)
117
 
        {
118
 
          message::Table::Field::NumericFieldOptions *numeric_field_options;
119
 
 
120
 
          numeric_field_options= attribute->mutable_numeric_options();
121
 
 
122
 
          numeric_field_options->set_precision(field_arg->length);
123
 
          numeric_field_options->set_scale(field_arg->decimals);
124
 
        }
125
 
      }
126
 
      break;
127
 
    case message::Table::Field::VARCHAR:
128
 
      {
129
 
        message::Table::Field::StringFieldOptions *string_field_options;
 
416
    drizzle::Table::Field *attribute;
 
417
    //drizzle::Table::Field::FieldConstraints *constraints;
 
418
 
 
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);
 
424
      break;
 
425
    case DRIZZLE_TYPE_LONG:
 
426
      attribute->set_type(drizzle::Table::Field::INTEGER);
 
427
      break;
 
428
    case DRIZZLE_TYPE_DOUBLE:
 
429
      attribute->set_type(drizzle::Table::Field::DOUBLE);
 
430
      break;
 
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);
 
435
      break;
 
436
    case DRIZZLE_TYPE_LONGLONG:
 
437
      attribute->set_type(drizzle::Table::Field::BIGINT);
 
438
      break;
 
439
    case DRIZZLE_TYPE_TIME:
 
440
      attribute->set_type(drizzle::Table::Field::TIME);
 
441
      break;
 
442
    case DRIZZLE_TYPE_DATETIME:
 
443
      attribute->set_type(drizzle::Table::Field::DATETIME);
 
444
      break;
 
445
    case DRIZZLE_TYPE_DATE:
 
446
      attribute->set_type(drizzle::Table::Field::DATE);
 
447
      break;
 
448
    case DRIZZLE_TYPE_VARCHAR:
 
449
      {
 
450
        drizzle::Table::Field::StringFieldOptions *string_field_options;
130
451
 
131
452
        string_field_options= attribute->mutable_string_options();
132
 
 
133
 
        if (! use_existing_fields || string_field_options->length()==0)
134
 
          string_field_options->set_length(field_arg->length
135
 
                                           / field_arg->charset->mbmaxlen);
136
 
        else
137
 
          assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
138
 
 
139
 
        if (! string_field_options->has_collation())
140
 
        {
141
 
          string_field_options->set_collation_id(field_arg->charset->number);
142
 
          string_field_options->set_collation(field_arg->charset->name);
143
 
        }
 
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);
 
457
 
144
458
        break;
145
459
      }
146
 
    case message::Table::Field::DECIMAL:
 
460
    case DRIZZLE_TYPE_NEWDECIMAL:
147
461
      {
148
 
        message::Table::Field::NumericFieldOptions *numeric_field_options;
 
462
        drizzle::Table::Field::NumericFieldOptions *numeric_field_options;
149
463
 
 
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);
154
469
        break;
155
470
      }
156
 
    case message::Table::Field::ENUM:
 
471
    case DRIZZLE_TYPE_ENUM:
157
472
      {
158
 
        message::Table::Field::EnumerationValues *enumeration_options;
 
473
        drizzle::Table::Field::SetFieldOptions *set_field_options;
159
474
 
160
475
        assert(field_arg->interval);
161
476
 
162
 
        enumeration_options= attribute->mutable_enumeration_values();
 
477
        attribute->set_type(drizzle::Table::Field::ENUM);
 
478
        set_field_options= attribute->mutable_set_options();
163
479
 
164
480
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
165
481
        {
166
482
          const char *src= field_arg->interval->type_names[pos];
167
483
 
168
 
          enumeration_options->add_field_value(src);
 
484
          set_field_options->add_value(src);
169
485
        }
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());
172
487
        break;
173
488
      }
174
 
    case message::Table::Field::BLOB:
175
 
      {
176
 
        message::Table::Field::StringFieldOptions *string_field_options;
177
 
 
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);
181
 
      }
182
 
 
 
489
    case DRIZZLE_TYPE_BLOB:
 
490
      attribute->set_type(drizzle::Table::Field::BLOB);
183
491
      break;
 
492
    default:
 
493
      assert(1);
184
494
    }
185
495
 
186
 
    assert (!use_existing_fields || parser_type == attribute->type());
187
 
 
188
496
#ifdef NOTDONE
189
497
    field_constraints= attribute->mutable_constraints();
190
498
    constraints->set_is_nullable(field_arg->def->null_value);
191
499
#endif
192
500
 
 
501
    /* Set the comment */
193
502
    if (field_arg->comment.length)
194
 
    {
195
 
      uint32_t tmp_len;
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);
201
 
 
202
 
      if (tmp_len < field_arg->comment.length)
203
 
      {
204
 
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
205
 
                 field_arg->comment.str,"COLUMN COMMENT",
206
 
                 (uint32_t) COLUMN_COMMENT_MAXLEN);
207
 
        return(1);
208
 
      }
209
 
 
210
 
      if (! use_existing_fields)
211
 
        attribute->set_comment(field_arg->comment.str);
212
 
 
213
 
      assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
214
 
    }
215
 
 
216
 
    if (field_arg->unireg_check == Field::NEXT_NUMBER)
217
 
    {
218
 
      message::Table::Field::NumericFieldOptions *field_options;
219
 
      field_options= attribute->mutable_numeric_options();
220
 
      field_options->set_is_autoincrement(true);
221
 
    }
222
 
 
223
 
    if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
224
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
225
 
    {
226
 
      message::Table::Field::FieldOptions *field_options;
227
 
      field_options= attribute->mutable_options();
228
 
      field_options->set_default_expression("CURRENT_TIMESTAMP");
229
 
    }
230
 
 
231
 
    if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
232
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
233
 
    {
234
 
      message::Table::Field::FieldOptions *field_options;
235
 
      field_options= attribute->mutable_options();
236
 
      field_options->set_update_expression("CURRENT_TIMESTAMP");
237
 
    }
238
 
 
239
 
    if (field_arg->def == NULL  && attribute->constraints().is_nullable())
240
 
    {
241
 
      message::Table::Field::FieldOptions *field_options;
242
 
      field_options= attribute->mutable_options();
243
 
 
244
 
      field_options->set_default_null(true);
245
 
    }
246
 
    if (field_arg->def)
247
 
    {
248
 
      message::Table::Field::FieldOptions *field_options;
249
 
      field_options= attribute->mutable_options();
250
 
 
251
 
      if (field_arg->def->is_null())
252
 
      {
253
 
        field_options->set_default_null(true);
254
 
      }
255
 
      else
256
 
      {
257
 
        String d;
258
 
        String *default_value= field_arg->def->val_str(&d);
259
 
 
260
 
        assert(default_value);
261
 
 
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()))
266
 
        {
267
 
          my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
268
 
          return 1;
269
 
        }
270
 
 
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)
274
 
        {
275
 
          DRIZZLE_TIME ltime;
276
 
 
277
 
          if (field_arg->def->get_date(&ltime, TIME_FUZZY_DATE))
278
 
          {
279
 
            my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
280
 
                     default_value->c_str());
281
 
            return 1;
282
 
          }
283
 
 
284
 
          /* We now do the casting down to the appropriate type.
285
 
 
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.
290
 
 
291
 
             the timestamp errors are taken care of elsewhere.
292
 
          */
293
 
 
294
 
          if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
295
 
          {
296
 
            Item *typecast= new Item_datetime_typecast(field_arg->def);
297
 
            typecast->quick_fix_field();
298
 
            typecast->val_str(default_value);
299
 
          }
300
 
          else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
301
 
          {
302
 
            Item *typecast= new Item_date_typecast(field_arg->def);
303
 
            typecast->quick_fix_field();
304
 
            typecast->val_str(default_value);
305
 
          }
306
 
        }
307
 
 
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))
312
 
        {
313
 
          string bin_default;
314
 
          bin_default.assign(default_value->c_ptr(),
315
 
                             default_value->length());
316
 
          field_options->set_default_bin_value(bin_default);
317
 
        }
318
 
        else
319
 
        {
320
 
          field_options->set_default_value(default_value->c_ptr());
321
 
        }
322
 
      }
323
 
    }
324
 
 
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);
330
 
 
331
 
  }
332
 
 
333
 
  assert(! use_existing_fields || (field_number == table_proto.field_size()));
334
 
 
335
 
  if (create_info->table_options & HA_OPTION_PACK_RECORD)
336
 
    table_options->set_pack_record(true);
337
 
 
338
 
  if (table_options->has_comment() && table_options->comment().length() == 0)
339
 
    table_options->clear_comment();
340
 
 
341
 
  if (table_options->has_comment())
342
 
  {
343
 
    uint32_t tmp_len;
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);
349
 
 
350
 
    if (tmp_len < table_options->comment().length())
351
 
    {
352
 
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
353
 
               table_options->comment().c_str(),"Table COMMENT",
354
 
               (uint32_t) TABLE_COMMENT_MAXLEN);
355
 
      return(1);
356
 
    }
357
 
  }
358
 
 
359
 
  if (create_info->default_table_charset)
360
 
  {
361
 
    table_options->set_collation_id(
362
 
                               create_info->default_table_charset->number);
363
 
    table_options->set_collation(create_info->default_table_charset->name);
364
 
  }
365
 
 
366
 
  if (create_info->used_fields & HA_CREATE_USED_AUTO)
367
 
    table_options->set_has_user_set_auto_increment_value(true);
368
 
  else
369
 
    table_options->set_has_user_set_auto_increment_value(false);
 
503
      attribute->set_comment(field_arg->comment.str);
 
504
  }
 
505
 
 
506
  if (create_info->comment.length)
 
507
    table_options->set_comment(create_info->comment.str);
 
508
 
 
509
  if (create_info->table_charset)
 
510
  {
 
511
    table_options->set_collation_id(field_arg->charset->number);
 
512
    table_options->set_collation(field_arg->charset->name);
 
513
  }
 
514
 
 
515
  if (create_info->connect_string.length)
 
516
    table_options->set_connect_string(create_info->connect_string.str);
 
517
 
 
518
  if (create_info->data_file_name)
 
519
    table_options->set_data_file_name(create_info->data_file_name);
 
520
 
 
521
  if (create_info->index_file_name)
 
522
    table_options->set_index_file_name(create_info->index_file_name);
 
523
 
 
524
  if (create_info->max_rows)
 
525
    table_options->set_max_rows(create_info->max_rows);
 
526
 
 
527
  if (create_info->min_rows)
 
528
    table_options->set_min_rows(create_info->min_rows);
370
529
 
371
530
  if (create_info->auto_increment_value)
372
531
    table_options->set_auto_increment_value(create_info->auto_increment_value);
373
532
 
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);
 
535
 
 
536
  if (create_info->key_block_size)
 
537
    table_options->set_key_block_size(create_info->key_block_size);
 
538
 
 
539
  if (create_info->block_size)
 
540
    table_options->set_block_size(create_info->block_size);
 
541
 
 
542
  for (unsigned int i= 0; i < keys; i++)
375
543
  {
376
 
    message::Table::Index *idx;
 
544
    drizzle::Table::Index *idx;
377
545
 
378
 
    idx= table_proto.add_indexes();
 
546
    idx= table_proto->add_index();
379
547
 
380
548
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
381
549
           (key_info[i].comment.length > 0));
382
550
 
383
551
    idx->set_name(key_info[i].name);
384
552
 
385
 
    idx->set_key_length(key_info[i].key_length);
386
 
 
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);
389
555
    else
390
556
      idx->set_is_primary(false);
392
558
    switch(key_info[i].algorithm)
393
559
    {
394
560
    case HA_KEY_ALG_HASH:
395
 
      idx->set_type(message::Table::Index::HASH);
 
561
      idx->set_type(drizzle::Table::Index::HASH);
396
562
      break;
397
563
 
398
564
    case HA_KEY_ALG_BTREE:
399
 
      idx->set_type(message::Table::Index::BTREE);
 
565
      idx->set_type(drizzle::Table::Index::BTREE);
400
566
      break;
401
567
 
 
568
    case HA_KEY_ALG_RTREE:
 
569
    case HA_KEY_ALG_FULLTEXT:
402
570
    case HA_KEY_ALG_UNDEF:
403
 
      idx->set_type(message::Table::Index::UNKNOWN_INDEX);
 
571
      idx->set_type(drizzle::Table::Index::UNKNOWN_INDEX);
404
572
      break;
405
573
 
406
574
    default:
407
575
      abort(); /* Somebody's brain broke. haven't added index type to proto */
 
576
      break;
408
577
    }
409
578
 
410
579
    if (key_info[i].flags & HA_NOSAME)
412
581
    else
413
582
      idx->set_is_unique(false);
414
583
 
415
 
    message::Table::Index::Options *index_options= idx->mutable_options();
416
 
 
417
 
    if (key_info[i].flags & HA_USES_BLOCK_SIZE)
418
 
      index_options->set_key_block_size(key_info[i].block_size);
419
 
 
420
 
    if (key_info[i].flags & HA_PACK_KEY)
421
 
      index_options->set_pack_key(true);
422
 
 
423
 
    if (key_info[i].flags & HA_BINARY_PACK_KEY)
424
 
      index_options->set_binary_pack_key(true);
425
 
 
426
 
    if (key_info[i].flags & HA_VAR_LENGTH_PART)
427
 
      index_options->set_var_length_key(true);
428
 
 
429
 
    if (key_info[i].flags & HA_NULL_PART_KEY)
430
 
      index_options->set_null_part_key(true);
431
 
 
432
 
    if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
433
 
      index_options->set_has_partial_segments(true);
434
 
 
435
 
    if (key_info[i].flags & HA_GENERATED_KEY)
436
 
      index_options->set_auto_generated_key(true);
 
584
    /* FIXME: block_size ? */
 
585
 
 
586
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
 
587
    {
 
588
      drizzle::Table::Index::IndexPart *idxpart;
 
589
      drizzle::Table::Field *field;
 
590
 
 
591
      idxpart= idx->add_index_part();
 
592
 
 
593
      field= idxpart->mutable_field();
 
594
      *field= table_proto->field(key_info[i].key_part[j].fieldnr);
 
595
 
 
596
      idxpart->set_compare_length(key_info[i].key_part[j].length);
 
597
    }
437
598
 
438
599
    if (key_info[i].flags & HA_USES_COMMENT)
439
 
    {
440
 
      uint32_t tmp_len;
441
 
      tmp_len= system_charset_info->cset->charpos(system_charset_info,
442
 
                                                  key_info[i].comment.str,
443
 
                                                  key_info[i].comment.str +
444
 
                                                  key_info[i].comment.length,
445
 
                                                  TABLE_COMMENT_MAXLEN);
446
 
 
447
 
      if (tmp_len < key_info[i].comment.length)
448
 
      {
449
 
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
450
 
                 key_info[i].comment.str,"Index COMMENT",
451
 
                 (uint32_t) TABLE_COMMENT_MAXLEN);
452
 
        return(1);
453
 
      }
454
 
 
455
600
      idx->set_comment(key_info[i].comment.str);
456
 
    }
457
 
    static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
458
 
                                               HA_USES_BLOCK_SIZE | 
459
 
                                               HA_BINARY_PACK_KEY |
460
 
                                               HA_VAR_LENGTH_PART |
461
 
                                               HA_NULL_PART_KEY | 
462
 
                                               HA_KEY_HAS_PART_KEY_SEG |
463
 
                                               HA_GENERATED_KEY |
464
 
                                               HA_USES_COMMENT);
465
 
    if (key_info[i].flags & ~unknown_index_flag)
466
 
      abort(); // Invalid (unknown) index flag.
467
 
 
468
 
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
469
 
    {
470
 
      message::Table::Index::IndexPart *idxpart;
471
 
      const int fieldnr= key_info[i].key_part[j].fieldnr;
472
 
      int mbmaxlen= 1;
473
 
 
474
 
      idxpart= idx->add_index_part();
475
 
 
476
 
      idxpart->set_fieldnr(fieldnr);
477
 
 
478
 
      if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
479
 
          || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
480
 
      {
481
 
        uint32_t collation_id;
482
 
 
483
 
        if (table_proto.field(fieldnr).string_options().has_collation_id())
484
 
          collation_id= table_proto.field(fieldnr).string_options().collation_id();
485
 
        else
486
 
          collation_id= table_proto.options().collation_id();
487
 
 
488
 
        const CHARSET_INFO *cs= get_charset(collation_id);
489
 
 
490
 
        mbmaxlen= cs->mbmaxlen;
491
 
      }
492
 
 
493
 
      idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
494
 
    }
495
 
  }
496
 
 
497
 
  if (not table_proto.IsInitialized())
498
 
  {
499
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), table_proto.InitializationErrorString().c_str());
500
 
    return 1;
501
 
  }
502
 
 
503
 
  /*
504
 
    Here we test to see if we can validate the Table Message before we continue. 
505
 
    We do this by serializing the protobuffer.
506
 
  */
507
 
  {
508
 
    string tmp_string;
509
 
 
510
 
    try {
511
 
      table_proto.SerializeToString(&tmp_string);
512
 
    }
513
 
 
514
 
    catch (...)
515
 
    {
516
 
      my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
517
 
               table_proto.InitializationErrorString().empty() ? "": table_proto.InitializationErrorString().c_str());
518
 
 
519
 
      return 1;
520
 
    }
521
 
  }
522
 
 
523
 
  return 0;
 
601
  }
 
602
}
 
603
 
 
604
int rename_table_proto_file(const char *from, const char* to)
 
605
{
 
606
  string from_path(from);
 
607
  string to_path(to);
 
608
  string file_ext = ".tabledefinition";
 
609
 
 
610
  from_path.append(file_ext);
 
611
  to_path.append(file_ext);
 
612
 
 
613
  return my_rename(from_path.c_str(),to_path.c_str(),MYF(MY_WME));
 
614
}
 
615
 
 
616
int delete_table_proto_file(char *file_name)
 
617
{
 
618
  string new_path(file_name);
 
619
  string file_ext = ".tabledefinition";
 
620
 
 
621
  new_path.append(file_ext);
 
622
  return my_delete(new_path.c_str(), MYF(0));
 
623
}
 
624
 
 
625
bool create_table_proto_file(const char *file_name,
 
626
                             const char *table_name,
 
627
                             HA_CREATE_INFO *create_info,
 
628
                             List<Create_field> &create_fields,
 
629
                             uint32_t keys,
 
630
                             KEY *key_info)
 
631
{
 
632
  drizzle::Table table_proto;
 
633
  string new_path(file_name);
 
634
  string file_ext = ".tabledefinition";
 
635
 
 
636
  fill_table_proto(&table_proto, table_name, create_fields, create_info,
 
637
                   keys, key_info);
 
638
 
 
639
  new_path.replace(new_path.find(".frm"), file_ext.length(), file_ext );
 
640
 
 
641
  fstream output(new_path.c_str(), ios::out | ios::trunc | ios::binary);
 
642
  if (!table_proto.SerializeToOstream(&output))
 
643
  {
 
644
    fprintf(stderr, "Failed to write schema.\n");
 
645
 
 
646
    return true;
 
647
  }
 
648
 
 
649
  return false;
524
650
}
525
651
 
526
652
/*
527
 
  Create a table definition proto file and the tables
 
653
  Create a frm (table definition) file and the tables
528
654
 
529
655
  SYNOPSIS
530
656
    rea_create_table()
536
662
    create_fields       Fields to create
537
663
    keys                number of keys to create
538
664
    key_info            Keys to create
 
665
    file                Handler to use
 
666
    is_like             is true for mysql_create_like_schema_frm
539
667
 
540
668
  RETURN
541
669
    0  ok
542
670
    1  error
543
671
*/
544
672
 
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,
 
678
                     bool is_like)
551
679
{
552
 
  assert(table_proto.has_name());
553
 
  if (fill_table_proto(table_proto, create_fields, create_info,
554
 
                       keys, key_info))
555
 
    return false;
556
 
 
557
 
  assert(table_proto.name() == identifier.getTableName());
558
 
 
559
 
  if (plugin::StorageEngine::createTable(*session,
560
 
                                         identifier,
561
 
                                         table_proto))
562
 
  {
563
 
    return false;
564
 
  }
565
 
 
566
 
  return true;
567
 
 
 
680
  char frm_name[FN_REFLEN];
 
681
 
 
682
  /* Proto will blow up unless we give a name */
 
683
  assert(table_name);
 
684
 
 
685
  /* For is_like we return once the file has been created */
 
686
  if (is_like)
 
687
  {
 
688
    if (mysql_create_frm(session, path, db, table_name, create_info,
 
689
                         create_fields, keys, key_info, file))
 
690
      return 1;
 
691
 
 
692
    if (create_table_proto_file(path, table_name, create_info,
 
693
                                create_fields, keys, key_info))
 
694
      return 1;
 
695
 
 
696
    return 0;
 
697
  }
 
698
  /* Here we need to build the full frm from the path */
 
699
  else
 
700
  {
 
701
    sprintf(frm_name,"%s%s", path, reg_ext);
 
702
 
 
703
    if (mysql_create_frm(session, frm_name, db, table_name, create_info,
 
704
                         create_fields, keys, key_info, file))
 
705
      return 1;
 
706
 
 
707
    if (create_table_proto_file(frm_name, table_name, create_info,
 
708
                                create_fields, keys, key_info))
 
709
      return 1;
 
710
  }
 
711
 
 
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))
 
717
    goto err_handler;
 
718
  if (ha_create_table(session, path, db, table_name,
 
719
                      create_info,0))
 
720
    goto err_handler;
 
721
  return 0;
 
722
 
 
723
err_handler:
 
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);
 
727
 
 
728
  return 1;
568
729
} /* rea_create_table */
569
730
 
570
 
} /* namespace drizzled */
571
 
 
 
731
 
 
732
        /* Pack screens to a screen for save in a form-file */
 
733
 
 
734
static unsigned char *pack_screens(List<Create_field> &create_fields,
 
735
                           uint32_t *info_length, uint32_t *screens,
 
736
                           bool small_file)
 
737
{
 
738
  register uint32_t i;
 
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);
 
744
 
 
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);
 
747
 
 
748
  *screens=(fields-1)/fields_on_screen+1;
 
749
  length= (*screens) * (SC_INFO_LENGTH+cols_half_len+4);
 
750
 
 
751
  Create_field *field;
 
752
  while ((field=it++))
 
753
    length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
 
754
 
 
755
  if (!(info=(unsigned char*) malloc(length)))
 
756
    return(0);
 
757
 
 
758
  start_screen=0;
 
759
  row=end_row;
 
760
  pos=info;
 
761
  it.rewind();
 
762
  for (i=0 ; i < fields ; i++)
 
763
  {
 
764
    Create_field *cfield=it++;
 
765
    if (row++ == end_row)
 
766
    {
 
767
      if (i)
 
768
      {
 
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);
 
773
      }
 
774
      row= start_row;
 
775
      start_screen=pos;
 
776
      pos+=4;
 
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;
 
783
    }
 
784
    length= (uint32_t) strlen(cfield->field_name);
 
785
    if (length > cols-3)
 
786
      length=cols-3;
 
787
 
 
788
    if (!small_file)
 
789
    {
 
790
      pos[0]=(unsigned char) row;
 
791
      pos[1]=0;
 
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;
 
796
    }
 
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));
 
800
  }
 
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);
 
805
 
 
806
  *info_length=(uint) (pos-info);
 
807
  return(info);
 
808
} /* pack_screens */
 
809
 
 
810
 
 
811
        /* Pack keyinfo and keynames to keybuff for save in form-file. */
 
812
 
 
813
static uint32_t pack_keys(unsigned char *keybuff, uint32_t key_count, KEY *keyinfo,
 
814
                      ulong data_offset)
 
815
{
 
816
  uint32_t key_parts,length;
 
817
  unsigned char *pos, *keyname_pos;
 
818
  KEY *key,*end;
 
819
  KEY_PART_INFO *key_part,*key_part_end;
 
820
 
 
821
 
 
822
  pos=keybuff+6;
 
823
  key_parts=0;
 
824
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
 
825
  {
 
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);
 
831
    pos+=8;
 
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 ;
 
835
         key_part++)
 
836
 
 
837
    {
 
838
      uint32_t offset;
 
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);
 
845
      pos+=9;
 
846
    }
 
847
  }
 
848
        /* Save keynames */
 
849
  keyname_pos=pos;
 
850
  *pos++=(unsigned char) NAMES_SEP_CHAR;
 
851
  for (key=keyinfo ; key != end ; key++)
 
852
  {
 
853
    unsigned char *tmp=(unsigned char*) strcpy((char*) pos,key->name);
 
854
    tmp+= strlen(key->name);
 
855
    *tmp++= (unsigned char) NAMES_SEP_CHAR;
 
856
    *tmp=0;
 
857
    pos=tmp;
 
858
  }
 
859
  *(pos++)=0;
 
860
 
 
861
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
 
862
  {
 
863
    if (key->flags & HA_USES_COMMENT)
 
864
    {
 
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;
 
868
      pos= tmp;
 
869
    }
 
870
  }
 
871
 
 
872
  if (key_count > 127 || key_parts > 127)
 
873
  {
 
874
    keybuff[0]= (key_count & 0x7f) | 0x80;
 
875
    keybuff[1]= key_count >> 7;
 
876
    int2store(keybuff+2,key_parts);
 
877
  }
 
878
  else
 
879
  {
 
880
    keybuff[0]=(unsigned char) key_count;
 
881
    keybuff[1]=(unsigned char) key_parts;
 
882
    keybuff[2]= keybuff[3]= 0;
 
883
  }
 
884
  length=(uint) (pos-keyname_pos);
 
885
  int2store(keybuff+4,length);
 
886
  return((uint) (pos-keybuff));
 
887
} /* pack_keys */
 
888
 
 
889
 
 
890
/* Make formheader */
 
891
 
 
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)
 
896
{
 
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;
 
900
 
 
901
 
 
902
  if (create_fields.elements > MAX_FIELDS)
 
903
  {
 
904
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
 
905
    return(1);
 
906
  }
 
907
 
 
908
  totlength= 0L;
 
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;
 
912
  n_length=2L;
 
913
 
 
914
        /* Check fields */
 
915
 
 
916
  List_iterator<Create_field> it(create_fields);
 
917
  Create_field *field;
 
918
  while ((field=it++))
 
919
  {
 
920
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
 
921
                                                     field->comment.str,
 
922
                                                     field->comment.str +
 
923
                                                     field->comment.length,
 
924
                                                     COLUMN_COMMENT_MAXLEN);
 
925
 
 
926
    if (tmp_len < field->comment.length)
 
927
    {
 
928
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
 
929
               field->comment.str,"COLUMN COMMENT",
 
930
               (uint) COLUMN_COMMENT_MAXLEN);
 
931
      return(1);
 
932
    }
 
933
    if (field->vcol_info)
 
934
    {
 
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);
 
940
 
 
941
      if (tmp_len < field->vcol_info->expr_str.length)
 
942
      {
 
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);
 
946
        return(1);
 
947
      }
 
948
      /*
 
949
        Sum up the length of the expression string and mandatory header bytes
 
950
        to the total length.
 
951
      */
 
952
      vcol_info_length+= field->vcol_info->expr_str.length+(uint)FRM_VCOL_HEADER_SIZE;
 
953
    }
 
954
 
 
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)
 
959
    {
 
960
      field->unireg_check= (Field::utype) ((uint) field->unireg_check |
 
961
                                           MTYP_NOEMPTY_BIT);
 
962
      no_empty++;
 
963
    }
 
964
    /*
 
965
      We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
 
966
      as auto-update field.
 
967
    */
 
968
    if (field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
 
969
        MTYP_TYPENR(field->unireg_check) != Field::NONE &&
 
970
        !time_stamp_pos)
 
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;
 
978
    if (field->interval)
 
979
    {
 
980
      uint32_t old_int_count=int_count;
 
981
 
 
982
      if (field->charset->mbminlen > 1)
 
983
      {
 
984
        /*
 
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.
 
991
        */
 
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);
 
1001
 
 
1002
        for (uint32_t pos= 0; pos < field->interval->count; pos++)
 
1003
        {
 
1004
          char *dst;
 
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 +
 
1011
                                                                   1);
 
1012
          octet2hex(dst, src, length);
 
1013
        }
 
1014
      }
 
1015
 
 
1016
      field->interval_id=get_interval_id(&int_count,create_fields,field);
 
1017
      if (old_int_count != int_count)
 
1018
      {
 
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;
 
1022
      }
 
1023
    }
 
1024
    if (f_maybe_null(field->pack_flag))
 
1025
      null_fields++;
 
1026
  }
 
1027
  int_length+=int_count*2;                      // 255 prefix + 0 suffix
 
1028
 
 
1029
        /* Save values in forminfo */
 
1030
 
 
1031
  if (reclength > (ulong) file->max_record_length())
 
1032
  {
 
1033
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0), (uint) file->max_record_length());
 
1034
    return(1);
 
1035
  }
 
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 ||
 
1040
      int_count > 255)
 
1041
  {
 
1042
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
 
1043
    return(1);
 
1044
  }
 
1045
 
 
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 */
 
1067
  return(0);
 
1068
} /* pack_header */
 
1069
 
 
1070
 
 
1071
        /* get each unique interval each own id */
 
1072
 
 
1073
static uint32_t get_interval_id(uint32_t *int_count,List<Create_field> &create_fields,
 
1074
                            Create_field *last_field)
 
1075
{
 
1076
  List_iterator<Create_field> it(create_fields);
 
1077
  Create_field *field;
 
1078
  TYPELIB *interval=last_field->interval;
 
1079
 
 
1080
  while ((field=it++) != last_field)
 
1081
  {
 
1082
    if (field->interval_id && field->interval->count == interval->count)
 
1083
    {
 
1084
      const char **a,**b;
 
1085
      for (a=field->interval->type_names, b=interval->type_names ;
 
1086
           *a && !strcmp(*a,*b);
 
1087
           a++,b++) ;
 
1088
 
 
1089
      if (! *a)
 
1090
      {
 
1091
        return field->interval_id;              // Re-use last interval
 
1092
      }
 
1093
    }
 
1094
  }
 
1095
  return ++*int_count;                          // New unique interval
 
1096
}
 
1097
 
 
1098
 
 
1099
        /* Save fields, fieldnames and intervals */
 
1100
 
 
1101
static bool pack_fields(File file, List<Create_field> &create_fields,
 
1102
                        ulong data_offset)
 
1103
{
 
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;
 
1108
 
 
1109
 
 
1110
        /* Write field info */
 
1111
 
 
1112
  List_iterator<Create_field> it(create_fields);
 
1113
 
 
1114
  int_count=0;
 
1115
  while ((field=it++))
 
1116
  {
 
1117
    uint32_t recpos;
 
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;
 
1130
    if (field->charset)
 
1131
      buff[14]= (unsigned char) field->charset->number;
 
1132
    else
 
1133
      buff[14]= 0;                              // Numerical
 
1134
    if (field->vcol_info)
 
1135
    {
 
1136
      /*
 
1137
        Use the interval_id place in the .frm file to store the length of
 
1138
        virtual field's data.
 
1139
      */
 
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;
 
1144
    }
 
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))
 
1149
      return(1);
 
1150
  }
 
1151
 
 
1152
        /* Write fieldnames */
 
1153
  buff[0]=(unsigned char) NAMES_SEP_CHAR;
 
1154
  if (my_write(file, buff, 1, MYF_RW))
 
1155
    return(1);
 
1156
  i=0;
 
1157
  it.rewind();
 
1158
  while ((field=it++))
 
1159
  {
 
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)
 
1164
      *pos++=0;
 
1165
    if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW))
 
1166
      return(1);
 
1167
    i++;
 
1168
  }
 
1169
 
 
1170
        /* Write intervals */
 
1171
  if (int_count)
 
1172
  {
 
1173
    String tmp((char*) buff,sizeof(buff), &my_charset_bin);
 
1174
    tmp.length(0);
 
1175
    it.rewind();
 
1176
    int_count=0;
 
1177
    while ((field=it++))
 
1178
    {
 
1179
      if (field->interval_id > int_count)
 
1180
      {
 
1181
        unsigned char  sep= 0;
 
1182
        unsigned char  occ[256];
 
1183
        uint32_t           i;
 
1184
        unsigned char *val= NULL;
 
1185
 
 
1186
        memset(occ, 0, sizeof(occ));
 
1187
 
 
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;
 
1191
 
 
1192
        if (!occ[(unsigned char)NAMES_SEP_CHAR])
 
1193
          sep= (unsigned char) NAMES_SEP_CHAR;
 
1194
        else if (!occ[(unsigned int)','])
 
1195
          sep= ',';
 
1196
        else
 
1197
        {
 
1198
          for (uint32_t i=1; i<256; i++)
 
1199
          {
 
1200
            if(!occ[i])
 
1201
            {
 
1202
              sep= i;
 
1203
              break;
 
1204
            }
 
1205
          }
 
1206
 
 
1207
          if(!sep)    /* disaster, enum uses all characters, none left as separator */
 
1208
          {
 
1209
            my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
 
1210
                       MYF(0));
 
1211
            return(1);
 
1212
          }
 
1213
        }
 
1214
 
 
1215
        int_count= field->interval_id;
 
1216
        tmp.append(sep);
 
1217
        for (const char **pos=field->interval->type_names ; *pos ; pos++)
 
1218
        {
 
1219
          tmp.append(*pos);
 
1220
          tmp.append(sep);
 
1221
        }
 
1222
        tmp.append('\0');                      // End of intervall
 
1223
      }
 
1224
    }
 
1225
    if (my_write(file,(unsigned char*) tmp.ptr(),tmp.length(),MYF_RW))
 
1226
      return(1);
 
1227
  }
 
1228
  if (comment_length)
 
1229
  {
 
1230
    it.rewind();
 
1231
    int_count=0;
 
1232
    while ((field=it++))
 
1233
    {
 
1234
      if (field->comment.length)
 
1235
        if (my_write(file, (unsigned char*) field->comment.str, field->comment.length,
 
1236
                     MYF_RW))
 
1237
          return(1);
 
1238
    }
 
1239
  }
 
1240
  if (vcol_info_length)
 
1241
  {
 
1242
    it.rewind();
 
1243
    int_count=0;
 
1244
    while ((field=it++))
 
1245
    {
 
1246
      /*
 
1247
        Pack each virtual field as follows:
 
1248
        byte 1      = 1 (always 1 to allow for future extensions)
 
1249
        byte 2      = sql_type
 
1250
        byte 3      = flags (as of now, 0 - no flags, 1 - field is physically stored)
 
1251
        byte 4-...  = virtual column expression (text data)
 
1252
      */
 
1253
      if (field->vcol_info && field->vcol_info->expr_str.length)
 
1254
      {
 
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))
 
1259
          return(1);
 
1260
        if (my_write(file,
 
1261
                     (unsigned char*) field->vcol_info->expr_str.str,
 
1262
                     field->vcol_info->expr_str.length,
 
1263
                     MYF_RW))
 
1264
          return(1);
 
1265
      }
 
1266
    }
 
1267
  }
 
1268
  return(0);
 
1269
}
 
1270
 
 
1271
 
 
1272
/* save an empty record on start of formfile */
 
1273
 
 
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,
 
1278
                           uint32_t reclength,
 
1279
                           ulong data_offset,
 
1280
                           handler *handler)
 
1281
{
 
1282
  int error= 0;
 
1283
  Field::utype type;
 
1284
  uint32_t null_count;
 
1285
  unsigned char *buff,*null_pos;
 
1286
  Table table;
 
1287
  TABLE_SHARE share;
 
1288
  Create_field *field;
 
1289
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
 
1290
 
 
1291
 
 
1292
  /* We need a table to generate columns for default values */
 
1293
  memset(&table, 0, sizeof(table));
 
1294
  memset(&share, 0, sizeof(share));
 
1295
  table.s= &share;
 
1296
 
 
1297
  if (!(buff=(unsigned char*) malloc((size_t) reclength)))
 
1298
  {
 
1299
    return(1);
 
1300
  }
 
1301
  memset(buff, 0, (size_t) reclength);
 
1302
 
 
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;
 
1306
 
 
1307
  null_count=0;
 
1308
  if (!(table_options & HA_OPTION_PACK_RECORD))
 
1309
  {
 
1310
    null_count++;                       // Need one bit for delete mark
 
1311
    *buff|= 1;
 
1312
  }
 
1313
  null_pos= buff;
 
1314
 
 
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++))
 
1318
  {
 
1319
    /*
 
1320
      regfield don't have to be deleted as it's allocated with sql_alloc()
 
1321
    */
 
1322
    Field *regfield= make_field(&share,
 
1323
                                buff+field->offset + data_offset,
 
1324
                                field->length,
 
1325
                                null_pos + null_count / 8,
 
1326
                                null_count & 7,
 
1327
                                field->pack_flag,
 
1328
                                field->sql_type,
 
1329
                                field->charset,
 
1330
                                field->unireg_check,
 
1331
                                field->save_interval ? field->save_interval :
 
1332
                                field->interval,
 
1333
                                field->field_name);
 
1334
    if (!regfield)
 
1335
    {
 
1336
      error= 1;
 
1337
      goto err;                                 // End of memory
 
1338
    }
 
1339
 
 
1340
    /* save_in_field() will access regfield->table->in_use */
 
1341
    regfield->init(&table);
 
1342
 
 
1343
    if (!(field->flags & NOT_NULL_FLAG))
 
1344
    {
 
1345
      *regfield->null_ptr|= regfield->null_bit;
 
1346
      null_count++;
 
1347
    }
 
1348
 
 
1349
    type= (Field::utype) MTYP_TYPENR(field->unireg_check);
 
1350
 
 
1351
    if (field->def)
 
1352
    {
 
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)
 
1356
      {
 
1357
        my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
 
1358
        error= 1;
 
1359
        delete regfield; //To avoid memory leak
 
1360
        goto err;
 
1361
      }
 
1362
    }
 
1363
    else if (regfield->real_type() == DRIZZLE_TYPE_ENUM &&
 
1364
             (field->flags & NOT_NULL_FLAG))
 
1365
    {
 
1366
      regfield->set_notnull();
 
1367
      regfield->store((int64_t) 1, true);
 
1368
    }
 
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);
 
1373
    else
 
1374
      regfield->reset();
 
1375
  }
 
1376
  assert(data_offset == ((null_count + 7) / 8));
 
1377
 
 
1378
  /*
 
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.
 
1381
  */
 
1382
  if (null_count & 7)
 
1383
    *(null_pos + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
 
1384
 
 
1385
  error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0;
 
1386
 
 
1387
err:
 
1388
  free(buff);
 
1389
  session->count_cuted_fields= old_count_cuted_fields;
 
1390
  return(error);
 
1391
} /* make_empty_rec */