~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
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
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
26
#include <drizzled/server_includes.h>
549 by Monty Taylor
Took gettext.h out of header files.
27
#include <drizzled/error.h>
584.1.13 by Monty Taylor
Split out a little more code. Removed table_list.h from common_includes.
28
#include <drizzled/virtual_column_info.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
29
#include <drizzled/session.h>
670.2.4 by Monty Taylor
Removed more stuff from the headers.
30
#include <drizzled/unireg.h>
1 by brian
clean slate
31
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
32
/* For proto */
33
#include <string>
34
#include <fstream>
35
#include <drizzled/serialize/serialize.h>
36
using namespace std;
37
1 by brian
clean slate
38
#define FCOMP			17		/* Bytes for a packed field */
39
481 by Brian Aker
Remove all of uchar.
40
static unsigned char * pack_screens(List<Create_field> &create_fields,
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
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);
481 by Brian Aker
Remove all of uchar.
45
static bool pack_header(unsigned char *forminfo,
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
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);
1 by brian
clean slate
53
static bool pack_fields(File file, List<Create_field> &create_fields,
54
                        ulong data_offset);
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
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,
1 by brian
clean slate
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
{
482 by Brian Aker
Remove uint.
71
  virtual bool handle_error(uint32_t sql_errno,
1 by brian
clean slate
72
                            const char *message,
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
73
                            DRIZZLE_ERROR::enum_warning_level level,
520.1.22 by Brian Aker
Second pass of thd cleanup
74
                            Session *session);
1 by brian
clean slate
75
  bool is_handled;
163 by Brian Aker
Merge Monty's code.
76
  Pack_header_error_handler() :is_handled(false) {}
1 by brian
clean slate
77
};
78
79
80
bool
81
Pack_header_error_handler::
482 by Brian Aker
Remove uint.
82
handle_error(uint32_t sql_errno,
1 by brian
clean slate
83
             const char * /* message */,
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
84
             DRIZZLE_ERROR::enum_warning_level /* level */,
520.1.22 by Brian Aker
Second pass of thd cleanup
85
             Session * /* session */)
1 by brian
clean slate
86
{
87
  is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
88
  return is_handled;
89
}
90
673.3.12 by Stewart Smith
fix RENAME TABLE
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
1 by brian
clean slate
124
/*
125
  Create a frm (table definition) file
126
127
  SYNOPSIS
128
    mysql_create_frm()
520.1.22 by Brian Aker
Second pass of thd cleanup
129
    session			Thread handler
1 by brian
clean slate
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
520.1.22 by Brian Aker
Second pass of thd cleanup
144
bool mysql_create_frm(Session *session, const char *file_name,
1 by brian
clean slate
145
                      const char *db, const char *table,
146
		      HA_CREATE_INFO *create_info,
147
		      List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
148
		      uint32_t keys, KEY *key_info,
1 by brian
clean slate
149
		      handler *db_file)
150
{
151
  LEX_STRING str_db_type;
482 by Brian Aker
Remove uint.
152
  uint32_t reclength, info_length, screens, key_info_length, maxlength, tmp_len;
1 by brian
clean slate
153
  ulong key_buff_length;
154
  File file;
155
  ulong filepos, data_offset;
481 by Brian Aker
Remove all of uchar.
156
  unsigned char fileinfo[64],forminfo[288],*keybuff;
1 by brian
clean slate
157
  TYPELIB formnames;
481 by Brian Aker
Remove all of uchar.
158
  unsigned char *screen_buff;
1 by brian
clean slate
159
  char buff[128];
482 by Brian Aker
Remove uint.
160
  const uint32_t format_section_header_size= 8;
161
  uint32_t format_section_len;
1 by brian
clean slate
162
  Pack_header_error_handler pack_header_error_handler;
163
  int error;
164
51.2.2 by Patrick Galbraith
Removed DBUGs from
165
  assert(*fn_rext((char*)file_name)); // Check .frm extension
1 by brian
clean slate
166
  formnames.type_names=0;
167
  if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
168
    return(1);
169
  assert(db_file != NULL);
1 by brian
clean slate
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
520.1.22 by Brian Aker
Second pass of thd cleanup
176
  session->push_internal_handler(&pack_header_error_handler);
1 by brian
clean slate
177
411 by Brian Aker
Removed legacy bits around enum.
178
  error= pack_header(forminfo,
1 by brian
clean slate
179
                     create_fields,info_length,
180
                     screens, create_info->table_options,
181
                     data_offset, db_file);
182
520.1.22 by Brian Aker
Second pass of thd cleanup
183
  session->pop_internal_handler();
1 by brian
clean slate
184
185
  if (error)
186
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
187
    free(screen_buff);
1 by brian
clean slate
188
    if (! pack_header_error_handler.is_handled)
51.2.2 by Patrick Galbraith
Removed DBUGs from
189
      return(1);
1 by brian
clean slate
190
191
    // Try again without UNIREG screens (to get more columns)
192
    if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
193
      return(1);
411 by Brian Aker
Removed legacy bits around enum.
194
    if (pack_header(forminfo,
1 by brian
clean slate
195
                    create_fields,info_length,
196
		    screens, create_info->table_options, data_offset, db_file))
197
    {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
198
      free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
199
      return(1);
1 by brian
clean slate
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=
106 by Brian Aker
Tablespace removal.
221
    format_section_header_size + 1 + create_fields.elements;
1 by brian
clean slate
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 +
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
227
                                              create_info->comment.length,
1 by brian
clean slate
228
                                              TABLE_COMMENT_MAXLEN);
229
230
  if (tmp_len < create_info->comment.length)
231
  {
232
    my_error(ER_WRONG_STRING_LENGTH, MYF(0),
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
233
             create_info->comment.str,"Table COMMENT",
1 by brian
clean slate
234
             (uint) TABLE_COMMENT_MAXLEN);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
235
    free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
236
    return(1);
1 by brian
clean slate
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{
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
246
    strncpy((char*) forminfo+47, create_info->comment.str ?
1 by brian
clean slate
247
            create_info->comment.str : "", create_info->comment.length);
481 by Brian Aker
Remove all of uchar.
248
    forminfo[46]=(unsigned char) create_info->comment.length;
1 by brian
clean slate
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
    */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
255
    memset(forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
1 by brian
clean slate
256
#endif
257
  }
258
520.1.22 by Brian Aker
Second pass of thd cleanup
259
  if ((file=create_frm(session, file_name, db, table, reclength, fileinfo,
1 by brian
clean slate
260
		       create_info, keys, key_info)) < 0)
261
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
262
    free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
263
    return(1);
1 by brian
clean slate
264
  }
265
266
  key_buff_length= uint4korr(fileinfo+47);
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
267
  keybuff=(unsigned char*) malloc(key_buff_length);
1 by brian
clean slate
268
  key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
269
  get_form_pos(file,fileinfo,&formnames);
1 by brian
clean slate
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));
481 by Brian Aker
Remove all of uchar.
275
  fileinfo[26]= (unsigned char) test((create_info->max_rows == 1) &&
1 by brian
clean slate
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
31 by Brian Aker
Removed my versions of pread/pwrite from the Kernel
282
  if (pwrite(file, fileinfo, 64, 0L) == 0 ||
283
      pwrite(file, keybuff, key_info_length, (ulong) uint2korr(fileinfo+6)) == 0)
1 by brian
clean slate
284
    goto err;
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
285
  lseek(file, (off_t)(uint2korr(fileinfo+6) + key_buff_length), SEEK_SET);
520.1.22 by Brian Aker
Second pass of thd cleanup
286
  if (make_empty_rec(session,file,ha_legacy_type(create_info->db_type),
1 by brian
clean slate
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);
481 by Brian Aker
Remove all of uchar.
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,
1 by brian
clean slate
294
               create_info->connect_string.length, MYF(MY_NABP)))
295
      goto err;
296
297
  int2store(buff, str_db_type.length);
481 by Brian Aker
Remove all of uchar.
298
  if (my_write(file, (const unsigned char*)buff, 2, MYF(MY_NABP)) ||
299
      my_write(file, (const unsigned char*)str_db_type.str,
1 by brian
clean slate
300
               str_db_type.length, MYF(MY_NABP)))
301
    goto err;
302
303
  {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
304
    memset(buff, 0, 6);
481 by Brian Aker
Remove all of uchar.
305
    if (my_write(file, (unsigned char*) buff, 6, MYF_RW))
1 by brian
clean slate
306
      goto err;
307
  }
308
481 by Brian Aker
Remove all of uchar.
309
  if (forminfo[46] == (unsigned char)255)
1 by brian
clean slate
310
  {
481 by Brian Aker
Remove all of uchar.
311
    unsigned char comment_length_buff[2];
1 by brian
clean slate
312
    int2store(comment_length_buff,create_info->comment.length);
313
    if (my_write(file, comment_length_buff, 2, MYF(MY_NABP)) ||
481 by Brian Aker
Remove all of uchar.
314
        my_write(file, (unsigned char*)create_info->comment.str,
1 by brian
clean slate
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
    {
482 by Brian Aker
Remove uint.
323
      uint32_t flags= 0;
1 by brian
clean slate
324
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
325
      memset(buff, 0, format_section_header_size);
1 by brian
clean slate
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 */
481 by Brian Aker
Remove all of uchar.
333
    if (my_write(file, (const unsigned char*)buff, format_section_header_size, MYF_RW))
1 by brian
clean slate
334
      goto err;
335
    buff[0]= 0;
481 by Brian Aker
Remove all of uchar.
336
    if (my_write(file, (const unsigned char*)buff, 1, MYF_RW))
1 by brian
clean slate
337
      goto err;
338
    /* write column info, 1 byte per column */
339
    {
340
      List_iterator<Create_field> it(create_fields);
341
      Create_field *field;
481 by Brian Aker
Remove all of uchar.
342
      unsigned char column_format, write_byte;
1 by brian
clean slate
343
      while ((field=it++))
344
      {
481 by Brian Aker
Remove all of uchar.
345
        column_format= (unsigned char)field->column_format();
101 by Brian Aker
Second pass on storage_type.
346
        write_byte= (column_format << COLUMN_FORMAT_SHIFT);
1 by brian
clean slate
347
        if (my_write(file, &write_byte, 1, MYF_RW))
348
          goto err;
349
      }
350
    }
351
  }
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
352
  lseek(file,filepos,SEEK_SET);
1 by brian
clean slate
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
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
358
  free(screen_buff);
359
  free(keybuff);
1 by brian
clean slate
360
377.1.2 by Brian Aker
Remove random dead variables.
361
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1 by brian
clean slate
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
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
370
    /*
1 by brian
clean slate
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
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
385
  return(0);
1 by brian
clean slate
386
387
err:
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
388
  free(screen_buff);
389
  free(keybuff);
1 by brian
clean slate
390
err2:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
391
  my_close(file,MYF(MY_WME));
1 by brian
clean slate
392
err3:
393
  my_delete(file_name,MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
394
  return(1);
1 by brian
clean slate
395
} /* mysql_create_frm */
396
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
397
static void fill_table_proto(drizzle::Table *table_proto,
398
                             const char *table_name,
399
                             List<Create_field> &create_fields,
590.1.2 by Stewart Smith
store indexes in table definition protobuf
400
                             HA_CREATE_INFO *create_info,
401
                             uint32_t keys,
402
                             KEY *key_info)
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
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
414
  while ((field_arg= it++))
415
  {
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;
587 by Brian Aker
Merge stewert
445
    case DRIZZLE_TYPE_DATE:
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
446
      attribute->set_type(drizzle::Table::Field::DATE);
447
      break;
448
    case DRIZZLE_TYPE_VARCHAR:
449
      {
450
        drizzle::Table::Field::StringFieldOptions *string_field_options;
451
452
        string_field_options= attribute->mutable_string_options();
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
458
        break;
459
      }
460
    case DRIZZLE_TYPE_NEWDECIMAL:
461
      {
462
        drizzle::Table::Field::NumericFieldOptions *numeric_field_options;
463
464
        attribute->set_type(drizzle::Table::Field::DECIMAL);
465
        numeric_field_options= attribute->mutable_numeric_options();
466
        /* This is magic, I hate magic numbers -Brian */
467
        numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
468
        numeric_field_options->set_scale(field_arg->decimals);
469
        break;
470
      }
471
    case DRIZZLE_TYPE_ENUM:
472
      {
473
        drizzle::Table::Field::SetFieldOptions *set_field_options;
474
475
        assert(field_arg->interval);
476
477
        attribute->set_type(drizzle::Table::Field::ENUM);
478
        set_field_options= attribute->mutable_set_options();
479
480
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
481
        {
482
          const char *src= field_arg->interval->type_names[pos];
483
484
          set_field_options->add_value(src);
485
        }
486
        set_field_options->set_count_elements(set_field_options->value_size());
487
        break;
488
      }
489
    case DRIZZLE_TYPE_BLOB:
490
      attribute->set_type(drizzle::Table::Field::BLOB);
491
      break;
492
    default:
493
      assert(1);
494
    }
495
496
#ifdef NOTDONE
497
    field_constraints= attribute->mutable_constraints();
498
    constraints->set_is_nullable(field_arg->def->null_value);
499
#endif
500
501
    /* Set the comment */
502
    if (field_arg->comment.length)
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);
529
530
  if (create_info->auto_increment_value)
531
    table_options->set_auto_increment_value(create_info->auto_increment_value);
532
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);
590.1.2 by Stewart Smith
store indexes in table definition protobuf
541
542
  for (unsigned int i= 0; i < keys; i++)
543
  {
544
    drizzle::Table::Index *idx;
545
546
    idx= table_proto->add_index();
547
548
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
549
           (key_info[i].comment.length > 0));
550
551
    idx->set_name(key_info[i].name);
552
553
    if(is_primary_key_name(key_info[i].name))
554
      idx->set_is_primary(true);
555
    else
556
      idx->set_is_primary(false);
557
558
    switch(key_info[i].algorithm)
559
    {
560
    case HA_KEY_ALG_HASH:
561
      idx->set_type(drizzle::Table::Index::HASH);
562
      break;
563
564
    case HA_KEY_ALG_BTREE:
565
      idx->set_type(drizzle::Table::Index::BTREE);
566
      break;
567
568
    case HA_KEY_ALG_RTREE:
569
    case HA_KEY_ALG_FULLTEXT:
570
    case HA_KEY_ALG_UNDEF:
571
      idx->set_type(drizzle::Table::Index::UNKNOWN_INDEX);
572
      break;
573
574
    default:
575
      abort(); /* Somebody's brain broke. haven't added index type to proto */
576
      break;
577
    }
578
579
    if (key_info[i].flags & HA_NOSAME)
580
      idx->set_is_unique(true);
581
    else
582
      idx->set_is_unique(false);
583
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
    }
598
599
    if (key_info[i].flags & HA_USES_COMMENT)
600
      idx->set_comment(key_info[i].comment.str);
601
  }
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
602
}
603
584.2.7 by Stewart Smith
rename and delete tabledefinition protobuf file
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
757 by Brian Aker
Fix for multple execution path for FRM creation.
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)
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
631
{
632
  drizzle::Table table_proto;
633
  string new_path(file_name);
634
  string file_ext = ".tabledefinition";
635
590.1.2 by Stewart Smith
store indexes in table definition protobuf
636
  fill_table_proto(&table_proto, table_name, create_fields, create_info,
637
                   keys, key_info);
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
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");
757 by Brian Aker
Fix for multple execution path for FRM creation.
645
646
    return true;
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
647
  }
648
757 by Brian Aker
Fix for multple execution path for FRM creation.
649
  return false;
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
650
}
1 by brian
clean slate
651
652
/*
653
  Create a frm (table definition) file and the tables
654
655
  SYNOPSIS
656
    rea_create_table()
520.1.22 by Brian Aker
Second pass of thd cleanup
657
    session			Thread handler
1 by brian
clean slate
658
    path		Name of file (including database, without .frm)
659
    db			Data base name
660
    table_name		Table name
661
    create_info		create info parameters
662
    create_fields	Fields to create
663
    keys		number of keys to create
664
    key_info		Keys to create
665
    file		Handler to use
757 by Brian Aker
Fix for multple execution path for FRM creation.
666
    is_like             is true for mysql_create_like_schema_frm
1 by brian
clean slate
667
668
  RETURN
669
    0  ok
670
    1  error
671
*/
672
520.1.22 by Brian Aker
Second pass of thd cleanup
673
int rea_create_table(Session *session, const char *path,
1 by brian
clean slate
674
                     const char *db, const char *table_name,
675
                     HA_CREATE_INFO *create_info,
676
                     List<Create_field> &create_fields,
757 by Brian Aker
Fix for multple execution path for FRM creation.
677
                     uint32_t keys, KEY *key_info, handler *file,
678
                     bool is_like)
1 by brian
clean slate
679
{
680
  char frm_name[FN_REFLEN];
757 by Brian Aker
Fix for multple execution path for FRM creation.
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
  }
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
711
1 by brian
clean slate
712
  // Make sure mysql_create_frm din't remove extension
51.2.2 by Patrick Galbraith
Removed DBUGs from
713
  assert(*fn_rext(frm_name));
520.1.22 by Brian Aker
Second pass of thd cleanup
714
  if (session->variables.keep_files_on_create)
1 by brian
clean slate
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;
757 by Brian Aker
Fix for multple execution path for FRM creation.
718
  if (ha_create_table(session, path, db, table_name,
719
                      create_info,0))
1 by brian
clean slate
720
    goto err_handler;
757 by Brian Aker
Fix for multple execution path for FRM creation.
721
  return 0;
1 by brian
clean slate
722
723
err_handler:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
724
  file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
1 by brian
clean slate
725
  my_delete(frm_name, MYF(0));
757 by Brian Aker
Fix for multple execution path for FRM creation.
726
  delete_table_proto_file(frm_name);
727
728
  return 1;
1 by brian
clean slate
729
} /* rea_create_table */
730
731
732
	/* Pack screens to a screen for save in a form-file */
733
481 by Brian Aker
Remove all of uchar.
734
static unsigned char *pack_screens(List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
735
                           uint32_t *info_length, uint32_t *screens,
1 by brian
clean slate
736
                           bool small_file)
737
{
482 by Brian Aker
Remove uint.
738
  register uint32_t i;
739
  uint32_t row,start_row,end_row,fields_on_screen;
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
740
  uint32_t length,cols, cols_half_len;
481 by Brian Aker
Remove all of uchar.
741
  unsigned char *info,*pos,*start_screen;
482 by Brian Aker
Remove uint.
742
  uint32_t fields=create_fields.elements;
1 by brian
clean slate
743
  List_iterator<Create_field> it(create_fields);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
744
1 by brian
clean slate
745
  start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
746
  cols_half_len= (uint32_t)(cols >> 1);
1 by brian
clean slate
747
748
  *screens=(fields-1)/fields_on_screen+1;
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
749
  length= (*screens) * (SC_INFO_LENGTH+cols_half_len+4);
1 by brian
clean slate
750
751
  Create_field *field;
752
  while ((field=it++))
753
    length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
754
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
755
  if (!(info=(unsigned char*) malloc(length)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
756
    return(0);
1 by brian
clean slate
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
      {
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
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);
1 by brian
clean slate
773
      }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
774
      row= start_row;
1 by brian
clean slate
775
      start_screen=pos;
776
      pos+=4;
481 by Brian Aker
Remove all of uchar.
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;
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
780
      memset((char*)pos+3,' ',cols_half_len);
781
      pos[cols_half_len+3]= '\0';
782
      pos+= cols_half_len+4;
1 by brian
clean slate
783
    }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
784
    length= (uint32_t) strlen(cfield->field_name);
1 by brian
clean slate
785
    if (length > cols-3)
786
      length=cols-3;
787
788
    if (!small_file)
789
    {
481 by Brian Aker
Remove all of uchar.
790
      pos[0]=(unsigned char) row;
1 by brian
clean slate
791
      pos[1]=0;
481 by Brian Aker
Remove all of uchar.
792
      pos[2]=(unsigned char) (length+1);
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
793
      strncpy((char*)pos+3,cfield->field_name, length);
794
      pos[length + 3]= '\0';
795
      pos+= length + 3 + 1;
1 by brian
clean slate
796
    }
206 by Brian Aker
Removed final uint dead types.
797
    cfield->row=(uint8_t) row;
798
    cfield->col=(uint8_t) (length+1);
398.1.4 by Monty Taylor
Renamed max/min.
799
    cfield->sc_length=(uint8_t) cmin(cfield->length,(uint32_t)cols-(length+2));
1 by brian
clean slate
800
  }
801
  length=(uint) (pos-start_screen);
802
  int2store(start_screen,length);
481 by Brian Aker
Remove all of uchar.
803
  start_screen[2]=(unsigned char) (row-start_row+2);
804
  start_screen[3]=(unsigned char) (row-start_row+1);
1 by brian
clean slate
805
806
  *info_length=(uint) (pos-info);
51.2.2 by Patrick Galbraith
Removed DBUGs from
807
  return(info);
1 by brian
clean slate
808
} /* pack_screens */
809
810
811
	/* Pack keyinfo and keynames to keybuff for save in form-file. */
812
482 by Brian Aker
Remove uint.
813
static uint32_t pack_keys(unsigned char *keybuff, uint32_t key_count, KEY *keyinfo,
1 by brian
clean slate
814
                      ulong data_offset)
815
{
482 by Brian Aker
Remove uint.
816
  uint32_t key_parts,length;
481 by Brian Aker
Remove all of uchar.
817
  unsigned char *pos, *keyname_pos;
1 by brian
clean slate
818
  KEY *key,*end;
819
  KEY_PART_INFO *key_part,*key_part_end;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
820
1 by brian
clean slate
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);
481 by Brian Aker
Remove all of uchar.
828
    pos[4]= (unsigned char) key->key_parts;
829
    pos[5]= (unsigned char) key->algorithm;
1 by brian
clean slate
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
    {
482 by Brian Aker
Remove uint.
838
      uint32_t offset;
1 by brian
clean slate
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;
481 by Brian Aker
Remove all of uchar.
850
  *pos++=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
851
  for (key=keyinfo ; key != end ; key++)
852
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
853
    unsigned char *tmp=(unsigned char*) strcpy((char*) pos,key->name);
854
    tmp+= strlen(key->name);
481 by Brian Aker
Remove all of uchar.
855
    *tmp++= (unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
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);
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
866
      unsigned char *tmp= (unsigned char*)strncpy((char*) pos+2,key->comment.str,key->comment.length);
867
      tmp+= key->comment.length;
1 by brian
clean slate
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
  {
481 by Brian Aker
Remove all of uchar.
880
    keybuff[0]=(unsigned char) key_count;
881
    keybuff[1]=(unsigned char) key_parts;
1 by brian
clean slate
882
    keybuff[2]= keybuff[3]= 0;
883
  }
884
  length=(uint) (pos-keyname_pos);
885
  int2store(keybuff+4,length);
51.2.2 by Patrick Galbraith
Removed DBUGs from
886
  return((uint) (pos-keybuff));
1 by brian
clean slate
887
} /* pack_keys */
888
889
77.1.45 by Monty Taylor
Warning fixes.
890
/* Make formheader */
1 by brian
clean slate
891
481 by Brian Aker
Remove all of uchar.
892
static bool pack_header(unsigned char *forminfo,
77.1.45 by Monty Taylor
Warning fixes.
893
                        List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
894
                        uint32_t info_length, uint32_t screens, uint32_t table_options,
1 by brian
clean slate
895
                        ulong data_offset, handler *file)
896
{
482 by Brian Aker
Remove uint.
897
  uint32_t length,int_count,int_length,no_empty, int_parts;
898
  uint32_t time_stamp_pos,null_fields;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
899
  ulong reclength, totlength, n_length, com_length, vcol_info_length;
77.1.45 by Monty Taylor
Warning fixes.
900
1 by brian
clean slate
901
902
  if (create_fields.elements > MAX_FIELDS)
903
  {
904
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
905
    return(1);
1 by brian
clean slate
906
  }
907
908
  totlength= 0L;
909
  reclength= data_offset;
910
  no_empty=int_count=int_parts=int_length=time_stamp_pos=null_fields=
383.7.1 by Andrey Zhakov
Initial submit of code and tests
911
    com_length=vcol_info_length=0;
1 by brian
clean slate
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
  {
482 by Brian Aker
Remove uint.
920
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
1 by brian
clean slate
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);
51.2.2 by Patrick Galbraith
Removed DBUGs from
931
      return(1);
1 by brian
clean slate
932
    }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
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
    }
1 by brian
clean slate
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
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
964
    /*
965
      We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
1 by brian
clean slate
966
      as auto-update field.
967
    */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
968
    if (field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1 by brian
clean slate
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
    {
482 by Brian Aker
Remove uint.
980
      uint32_t old_int_count=int_count;
1 by brian
clean slate
981
982
      if (field->charset->mbminlen > 1)
983
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
984
        /*
1 by brian
clean slate
985
          Escape UCS2 intervals using HEX notation to avoid
986
          problems with delimiters between enum elements.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
987
          As the original representation is still needed in
1 by brian
clean slate
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));
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
994
        *field->interval= *field->save_interval;
995
        field->interval->type_names=
996
          (const char **) sql_alloc(sizeof(char*) *
1 by brian
clean slate
997
				    (field->interval->count+1));
998
        field->interval->type_names[field->interval->count]= 0;
999
        field->interval->type_lengths=
482 by Brian Aker
Remove uint.
1000
          (uint32_t *) sql_alloc(sizeof(uint) * field->interval->count);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1001
482 by Brian Aker
Remove uint.
1002
        for (uint32_t pos= 0; pos < field->interval->count; pos++)
1 by brian
clean slate
1003
        {
1004
          char *dst;
1005
          const char *src= field->save_interval->type_names[pos];
482 by Brian Aker
Remove uint.
1006
          uint32_t hex_length;
1 by brian
clean slate
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());
51.2.2 by Patrick Galbraith
Removed DBUGs from
1034
    return(1);
1 by brian
clean slate
1035
  }
1036
  /* Hack to avoid bugs with small static rows in MySQL */
398.1.4 by Monty Taylor
Renamed max/min.
1037
  reclength=cmax((ulong)file->min_record_length(table_options),reclength);
1 by brian
clean slate
1038
  if (info_length+(ulong) create_fields.elements*FCOMP+288+
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1039
      n_length+int_length+com_length+vcol_info_length > 65535L ||
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1040
      int_count > 255)
1 by brian
clean slate
1041
  {
1042
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
1043
    return(1);
1 by brian
clean slate
1044
  }
1045
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1046
  memset(forminfo, 0, 288);
1 by brian
clean slate
1047
  length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1048
	  com_length+vcol_info_length);
1 by brian
clean slate
1049
  int2store(forminfo,length);
206 by Brian Aker
Removed final uint dead types.
1050
  forminfo[256] = (uint8_t) screens;
1 by brian
clean slate
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);
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1065
  int2store(forminfo+286,vcol_info_length);
1066
  /* forminfo+288 is free to use for additional information */
51.2.2 by Patrick Galbraith
Removed DBUGs from
1067
  return(0);
1 by brian
clean slate
1068
} /* pack_header */
1069
1070
1071
	/* get each unique interval each own id */
1072
482 by Brian Aker
Remove uint.
1073
static uint32_t get_interval_id(uint32_t *int_count,List<Create_field> &create_fields,
1 by brian
clean slate
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
{
482 by Brian Aker
Remove uint.
1104
  register uint32_t i;
481.3.1 by Monty Taylor
Merged vcol stuff.
1105
  uint32_t int_count, comment_length=0, vcol_info_length=0;
481 by Brian Aker
Remove all of uchar.
1106
  unsigned char buff[MAX_FIELD_WIDTH];
1 by brian
clean slate
1107
  Create_field *field;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1108
1 by brian
clean slate
1109
1110
	/* Write field info */
1111
1112
  List_iterator<Create_field> it(create_fields);
1113
1114
  int_count=0;
1115
  while ((field=it++))
1116
  {
482 by Brian Aker
Remove uint.
1117
    uint32_t recpos;
481.3.1 by Monty Taylor
Merged vcol stuff.
1118
    uint32_t cur_vcol_expr_len= 0;
481 by Brian Aker
Remove all of uchar.
1119
    buff[0]= (unsigned char) field->row;
1120
    buff[1]= (unsigned char) field->col;
1121
    buff[2]= (unsigned char) field->sc_length;
1 by brian
clean slate
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);
481 by Brian Aker
Remove all of uchar.
1128
    buff[12]= (unsigned char) field->interval_id;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1129
    buff[13]= (unsigned char) field->sql_type;
1130
    if (field->charset)
481 by Brian Aker
Remove all of uchar.
1131
      buff[14]= (unsigned char) field->charset->number;
1 by brian
clean slate
1132
    else
1133
      buff[14]= 0;				// Numerical
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1134
    if (field->vcol_info)
1135
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1136
      /*
383.7.1 by Andrey Zhakov
Initial submit of code and tests
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;
481.3.1 by Monty Taylor
Merged vcol stuff.
1143
      buff[13]= (unsigned char) DRIZZLE_TYPE_VIRTUAL;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1144
    }
1 by brian
clean slate
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))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1149
      return(1);
1 by brian
clean slate
1150
  }
1151
1152
	/* Write fieldnames */
481 by Brian Aker
Remove all of uchar.
1153
  buff[0]=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
1154
  if (my_write(file, buff, 1, MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1155
    return(1);
1 by brian
clean slate
1156
  i=0;
1157
  it.rewind();
1158
  while ((field=it++))
1159
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1160
    char *pos= strcpy((char*) buff,field->field_name);
1161
    pos+= strlen(field->field_name);
1 by brian
clean slate
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))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1166
      return(1);
1 by brian
clean slate
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];
482 by Brian Aker
Remove uint.
1183
        uint32_t           i;
1 by brian
clean slate
1184
        unsigned char *val= NULL;
1185
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
1186
        memset(occ, 0, sizeof(occ));
1 by brian
clean slate
1187
1188
        for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
482 by Brian Aker
Remove uint.
1189
          for (uint32_t j = 0; j < field->interval->type_lengths[i]; j++)
1 by brian
clean slate
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
        {
482 by Brian Aker
Remove uint.
1198
          for (uint32_t i=1; i<256; i++)
1 by brian
clean slate
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));
51.2.2 by Patrick Galbraith
Removed DBUGs from
1211
            return(1);
1 by brian
clean slate
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
    }
481 by Brian Aker
Remove all of uchar.
1225
    if (my_write(file,(unsigned char*) tmp.ptr(),tmp.length(),MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1226
      return(1);
1 by brian
clean slate
1227
  }
1228
  if (comment_length)
1229
  {
1230
    it.rewind();
1231
    int_count=0;
1232
    while ((field=it++))
1233
    {
1234
      if (field->comment.length)
481 by Brian Aker
Remove all of uchar.
1235
	if (my_write(file, (unsigned char*) field->comment.str, field->comment.length,
1 by brian
clean slate
1236
		     MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1237
	  return(1);
1 by brian
clean slate
1238
    }
1239
  }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
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
      {
481.3.1 by Monty Taylor
Merged vcol stuff.
1255
        buff[0]= (unsigned char)1;
1256
        buff[1]= (unsigned char) field->sql_type;
1257
        buff[2]= (unsigned char) field->is_stored;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1258
        if (my_write(file, buff, 3, MYF_RW))
1259
          return(1);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1260
        if (my_write(file,
1261
                     (unsigned char*) field->vcol_info->expr_str.str,
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1262
                     field->vcol_info->expr_str.length,
1263
                     MYF_RW))
1264
          return(1);
1265
      }
1266
    }
1267
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1268
  return(0);
1 by brian
clean slate
1269
}
1270
1271
77.1.45 by Monty Taylor
Warning fixes.
1272
/* save an empty record on start of formfile */
1 by brian
clean slate
1273
520.1.22 by Brian Aker
Second pass of thd cleanup
1274
static bool make_empty_rec(Session *session, File file,
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1275
                           enum legacy_db_type table_type __attribute__((unused)),
482 by Brian Aker
Remove uint.
1276
                           uint32_t table_options,
77.1.45 by Monty Taylor
Warning fixes.
1277
                           List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
1278
                           uint32_t reclength,
1 by brian
clean slate
1279
                           ulong data_offset,
1280
                           handler *handler)
1281
{
1282
  int error= 0;
1283
  Field::utype type;
482 by Brian Aker
Remove uint.
1284
  uint32_t null_count;
481 by Brian Aker
Remove all of uchar.
1285
  unsigned char *buff,*null_pos;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1286
  Table table;
1 by brian
clean slate
1287
  TABLE_SHARE share;
1288
  Create_field *field;
520.1.22 by Brian Aker
Second pass of thd cleanup
1289
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1290
1 by brian
clean slate
1291
1292
  /* We need a table to generate columns for default values */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1293
  memset(&table, 0, sizeof(table));
1294
  memset(&share, 0, sizeof(share));
1 by brian
clean slate
1295
  table.s= &share;
1296
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1297
  if (!(buff=(unsigned char*) malloc((size_t) reclength)))
1 by brian
clean slate
1298
  {
51.2.2 by Patrick Galbraith
Removed DBUGs from
1299
    return(1);
1 by brian
clean slate
1300
  }
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1301
  memset(buff, 0, (size_t) reclength);
1 by brian
clean slate
1302
520.1.22 by Brian Aker
Second pass of thd cleanup
1303
  table.in_use= session;
1 by brian
clean slate
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);
520.1.22 by Brian Aker
Second pass of thd cleanup
1316
  session->count_cuted_fields= CHECK_FIELD_WARN;    // To find wrong default values
1 by brian
clean slate
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 :
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1332
                                field->interval,
1 by brian
clean slate
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
    }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1363
    else if (regfield->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
1364
	     (field->flags & NOT_NULL_FLAG))
1365
    {
1366
      regfield->set_notnull();
163 by Brian Aker
Merge Monty's code.
1367
      regfield->store((int64_t) 1, true);
1 by brian
clean slate
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
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1376
  assert(data_offset == ((null_count + 7) / 8));
1 by brian
clean slate
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)
481 by Brian Aker
Remove all of uchar.
1383
    *(null_pos + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1 by brian
clean slate
1384
1385
  error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0;
1386
1387
err:
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
1388
  free(buff);
520.1.22 by Brian Aker
Second pass of thd cleanup
1389
  session->count_cuted_fields= old_count_cuted_fields;
51.2.2 by Patrick Galbraith
Removed DBUGs from
1390
  return(error);
1 by brian
clean slate
1391
} /* make_empty_rec */