~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
91
/*
92
  Create a frm (table definition) file
93
94
  SYNOPSIS
95
    mysql_create_frm()
520.1.22 by Brian Aker
Second pass of thd cleanup
96
    session			Thread handler
1 by brian
clean slate
97
    file_name		Path for file (including database and .frm)
98
    db                  Name of database
99
    table               Name of table
100
    create_info		create info parameters
101
    create_fields	Fields to create
102
    keys		number of keys to create
103
    key_info		Keys to create
104
    db_file		Handler to use. May be zero, in which case we use
105
			create_info->db_type
106
  RETURN
107
    0  ok
108
    1  error
109
*/
110
520.1.22 by Brian Aker
Second pass of thd cleanup
111
bool mysql_create_frm(Session *session, const char *file_name,
1 by brian
clean slate
112
                      const char *db, const char *table,
113
		      HA_CREATE_INFO *create_info,
114
		      List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
115
		      uint32_t keys, KEY *key_info,
1 by brian
clean slate
116
		      handler *db_file)
117
{
118
  LEX_STRING str_db_type;
482 by Brian Aker
Remove uint.
119
  uint32_t reclength, info_length, screens, key_info_length, maxlength, tmp_len;
1 by brian
clean slate
120
  ulong key_buff_length;
121
  File file;
122
  ulong filepos, data_offset;
481 by Brian Aker
Remove all of uchar.
123
  unsigned char fileinfo[64],forminfo[288],*keybuff;
1 by brian
clean slate
124
  TYPELIB formnames;
481 by Brian Aker
Remove all of uchar.
125
  unsigned char *screen_buff;
1 by brian
clean slate
126
  char buff[128];
482 by Brian Aker
Remove uint.
127
  const uint32_t format_section_header_size= 8;
128
  uint32_t format_section_len;
1 by brian
clean slate
129
  Pack_header_error_handler pack_header_error_handler;
130
  int error;
131
51.2.2 by Patrick Galbraith
Removed DBUGs from
132
  assert(*fn_rext((char*)file_name)); // Check .frm extension
1 by brian
clean slate
133
  formnames.type_names=0;
134
  if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
135
    return(1);
136
  assert(db_file != NULL);
1 by brian
clean slate
137
138
 /* If fixed row records, we need one bit to check for deleted rows */
139
  if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
140
    create_info->null_bits++;
141
  data_offset= (create_info->null_bits + 7) / 8;
142
520.1.22 by Brian Aker
Second pass of thd cleanup
143
  session->push_internal_handler(&pack_header_error_handler);
1 by brian
clean slate
144
411 by Brian Aker
Removed legacy bits around enum.
145
  error= pack_header(forminfo,
1 by brian
clean slate
146
                     create_fields,info_length,
147
                     screens, create_info->table_options,
148
                     data_offset, db_file);
149
520.1.22 by Brian Aker
Second pass of thd cleanup
150
  session->pop_internal_handler();
1 by brian
clean slate
151
152
  if (error)
153
  {
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.
154
    free(screen_buff);
1 by brian
clean slate
155
    if (! pack_header_error_handler.is_handled)
51.2.2 by Patrick Galbraith
Removed DBUGs from
156
      return(1);
1 by brian
clean slate
157
158
    // Try again without UNIREG screens (to get more columns)
159
    if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
160
      return(1);
411 by Brian Aker
Removed legacy bits around enum.
161
    if (pack_header(forminfo,
1 by brian
clean slate
162
                    create_fields,info_length,
163
		    screens, create_info->table_options, data_offset, db_file))
164
    {
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.
165
      free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
166
      return(1);
1 by brian
clean slate
167
    }
168
  }
169
  reclength=uint2korr(forminfo+266);
170
171
  /* Calculate extra data segment length */
172
  str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type);
173
  str_db_type.length= strlen(str_db_type.str);
174
  /* str_db_type */
175
  create_info->extra_size= (2 + str_db_type.length +
176
                            2 + create_info->connect_string.length);
177
  /*
178
    Partition:
179
      Length of partition info = 4 byte
180
      Potential NULL byte at end of partition info string = 1 byte
181
      Indicator if auto-partitioned table = 1 byte
182
      => Total 6 byte
183
  */
184
  create_info->extra_size+= 6;
185
186
  /* Add space for storage type and field format array of fields */
187
  format_section_len=
106 by Brian Aker
Tablespace removal.
188
    format_section_header_size + 1 + create_fields.elements;
1 by brian
clean slate
189
  create_info->extra_size+= format_section_len;
190
191
  tmp_len= system_charset_info->cset->charpos(system_charset_info,
192
                                              create_info->comment.str,
193
                                              create_info->comment.str +
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
194
                                              create_info->comment.length,
1 by brian
clean slate
195
                                              TABLE_COMMENT_MAXLEN);
196
197
  if (tmp_len < create_info->comment.length)
198
  {
199
    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
200
             create_info->comment.str,"Table COMMENT",
1 by brian
clean slate
201
             (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.
202
    free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
203
    return(1);
1 by brian
clean slate
204
  }
205
206
  //if table comment is larger than 180 bytes, store into extra segment.
207
  if (create_info->comment.length > 180)
208
  {
209
    forminfo[46]=255;
210
    create_info->extra_size+= 2 + create_info->comment.length;
211
  }
212
  else{
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
213
    strncpy((char*) forminfo+47, create_info->comment.str ?
1 by brian
clean slate
214
            create_info->comment.str : "", create_info->comment.length);
481 by Brian Aker
Remove all of uchar.
215
    forminfo[46]=(unsigned char) create_info->comment.length;
1 by brian
clean slate
216
#ifdef EXTRA_DEBUG
217
    /*
218
      EXTRA_DEBUG causes strmake() to initialize its buffer behind the
219
      payload with a magic value to detect wrong buffer-sizes. We
220
      explicitly zero that segment again.
221
    */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
222
    memset(forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
1 by brian
clean slate
223
#endif
224
  }
225
520.1.22 by Brian Aker
Second pass of thd cleanup
226
  if ((file=create_frm(session, file_name, db, table, reclength, fileinfo,
1 by brian
clean slate
227
		       create_info, keys, key_info)) < 0)
228
  {
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.
229
    free(screen_buff);
51.2.2 by Patrick Galbraith
Removed DBUGs from
230
    return(1);
1 by brian
clean slate
231
  }
232
233
  key_buff_length= uint4korr(fileinfo+47);
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
234
  keybuff=(unsigned char*) malloc(key_buff_length);
1 by brian
clean slate
235
  key_info_length= pack_keys(keybuff, keys, key_info, data_offset);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
236
  get_form_pos(file,fileinfo,&formnames);
1 by brian
clean slate
237
  if (!(filepos=make_new_entry(file,fileinfo,&formnames,"")))
238
    goto err;
239
  maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000));
240
  int2store(forminfo+2,maxlength);
241
  int4store(fileinfo+10,(ulong) (filepos+maxlength));
481 by Brian Aker
Remove all of uchar.
242
  fileinfo[26]= (unsigned char) test((create_info->max_rows == 1) &&
1 by brian
clean slate
243
			     (create_info->min_rows == 1) && (keys == 0));
244
  int2store(fileinfo+28,key_info_length);
245
246
247
  int2store(fileinfo+59,db_file->extra_rec_buf_length());
248
31 by Brian Aker
Removed my versions of pread/pwrite from the Kernel
249
  if (pwrite(file, fileinfo, 64, 0L) == 0 ||
250
      pwrite(file, keybuff, key_info_length, (ulong) uint2korr(fileinfo+6)) == 0)
1 by brian
clean slate
251
    goto err;
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
252
  lseek(file, (off_t)(uint2korr(fileinfo+6) + key_buff_length), SEEK_SET);
520.1.22 by Brian Aker
Second pass of thd cleanup
253
  if (make_empty_rec(session,file,ha_legacy_type(create_info->db_type),
1 by brian
clean slate
254
                     create_info->table_options,
255
		     create_fields,reclength, data_offset, db_file))
256
    goto err;
257
258
  int2store(buff, create_info->connect_string.length);
481 by Brian Aker
Remove all of uchar.
259
  if (my_write(file, (const unsigned char*)buff, 2, MYF(MY_NABP)) ||
260
      my_write(file, (const unsigned char*)create_info->connect_string.str,
1 by brian
clean slate
261
               create_info->connect_string.length, MYF(MY_NABP)))
262
      goto err;
263
264
  int2store(buff, str_db_type.length);
481 by Brian Aker
Remove all of uchar.
265
  if (my_write(file, (const unsigned char*)buff, 2, MYF(MY_NABP)) ||
266
      my_write(file, (const unsigned char*)str_db_type.str,
1 by brian
clean slate
267
               str_db_type.length, MYF(MY_NABP)))
268
    goto err;
269
270
  {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
271
    memset(buff, 0, 6);
481 by Brian Aker
Remove all of uchar.
272
    if (my_write(file, (unsigned char*) buff, 6, MYF_RW))
1 by brian
clean slate
273
      goto err;
274
  }
275
481 by Brian Aker
Remove all of uchar.
276
  if (forminfo[46] == (unsigned char)255)
1 by brian
clean slate
277
  {
481 by Brian Aker
Remove all of uchar.
278
    unsigned char comment_length_buff[2];
1 by brian
clean slate
279
    int2store(comment_length_buff,create_info->comment.length);
280
    if (my_write(file, comment_length_buff, 2, MYF(MY_NABP)) ||
481 by Brian Aker
Remove all of uchar.
281
        my_write(file, (unsigned char*)create_info->comment.str,
1 by brian
clean slate
282
                  create_info->comment.length, MYF(MY_NABP)))
283
      goto err;
284
  }
285
286
  /* Store storage type and field format array of fields */
287
  {
288
    /* prepare header */
289
    {
482 by Brian Aker
Remove uint.
290
      uint32_t flags= 0;
1 by brian
clean slate
291
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
292
      memset(buff, 0, format_section_header_size);
1 by brian
clean slate
293
      /* length of section 2 bytes*/
294
      int2store(buff+0, format_section_len);
295
      /* flags of section 4 bytes*/
296
      int4store(buff+2, flags);
297
      /* 2 bytes left for future use */
298
    }
299
    /* write header */
481 by Brian Aker
Remove all of uchar.
300
    if (my_write(file, (const unsigned char*)buff, format_section_header_size, MYF_RW))
1 by brian
clean slate
301
      goto err;
302
    buff[0]= 0;
481 by Brian Aker
Remove all of uchar.
303
    if (my_write(file, (const unsigned char*)buff, 1, MYF_RW))
1 by brian
clean slate
304
      goto err;
305
    /* write column info, 1 byte per column */
306
    {
307
      List_iterator<Create_field> it(create_fields);
308
      Create_field *field;
481 by Brian Aker
Remove all of uchar.
309
      unsigned char column_format, write_byte;
1 by brian
clean slate
310
      while ((field=it++))
311
      {
481 by Brian Aker
Remove all of uchar.
312
        column_format= (unsigned char)field->column_format();
101 by Brian Aker
Second pass on storage_type.
313
        write_byte= (column_format << COLUMN_FORMAT_SHIFT);
1 by brian
clean slate
314
        if (my_write(file, &write_byte, 1, MYF_RW))
315
          goto err;
316
      }
317
    }
318
  }
656.1.39 by Monty Taylor
Removed my_seek, my_tell, my_fwrite, my_fseek.
319
  lseek(file,filepos,SEEK_SET);
1 by brian
clean slate
320
  if (my_write(file, forminfo, 288, MYF_RW) ||
321
      my_write(file, screen_buff, info_length, MYF_RW) ||
322
      pack_fields(file, create_fields, data_offset))
323
    goto err;
324
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.
325
  free(screen_buff);
326
  free(keybuff);
1 by brian
clean slate
327
377.1.2 by Brian Aker
Remove random dead variables.
328
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1 by brian
clean slate
329
      (my_sync(file, MYF(MY_WME)) ||
330
       my_sync_dir_by_file(file_name, MYF(MY_WME))))
331
      goto err2;
332
333
  if (my_close(file,MYF(MY_WME)))
334
    goto err3;
335
336
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
337
    /*
1 by brian
clean slate
338
      Restore all UCS2 intervals.
339
      HEX representation of them is not needed anymore.
340
    */
341
    List_iterator<Create_field> it(create_fields);
342
    Create_field *field;
343
    while ((field=it++))
344
    {
345
      if (field->save_interval)
346
      {
347
        field->interval= field->save_interval;
348
        field->save_interval= 0;
349
      }
350
    }
351
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
352
  return(0);
1 by brian
clean slate
353
354
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.
355
  free(screen_buff);
356
  free(keybuff);
1 by brian
clean slate
357
err2:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
358
  my_close(file,MYF(MY_WME));
1 by brian
clean slate
359
err3:
360
  my_delete(file_name,MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
361
  return(1);
1 by brian
clean slate
362
} /* mysql_create_frm */
363
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
364
static void fill_table_proto(drizzle::Table *table_proto,
365
                             const char *table_name,
366
                             List<Create_field> &create_fields,
590.1.2 by Stewart Smith
store indexes in table definition protobuf
367
                             HA_CREATE_INFO *create_info,
368
                             uint32_t keys,
369
                             KEY *key_info)
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
370
{
371
  Create_field *field_arg;
372
  List_iterator<Create_field> it(create_fields);
373
  drizzle::Table::StorageEngine *engine= table_proto->mutable_engine();
374
  drizzle::Table::TableOptions *table_options= table_proto->mutable_options();
375
376
  engine->set_name(create_info->db_type->name);
377
378
  table_proto->set_name(table_name);
379
  table_proto->set_type(drizzle::Table::STANDARD);
380
381
  while ((field_arg= it++))
382
  {
383
    drizzle::Table::Field *attribute;
384
    //drizzle::Table::Field::FieldConstraints *constraints;
385
386
    attribute= table_proto->add_field();
387
    attribute->set_name(field_arg->field_name);
388
    switch (field_arg->sql_type) {
389
    case DRIZZLE_TYPE_TINY:
390
      attribute->set_type(drizzle::Table::Field::TINYINT);
391
      break;
392
    case DRIZZLE_TYPE_LONG:
393
      attribute->set_type(drizzle::Table::Field::INTEGER);
394
      break;
395
    case DRIZZLE_TYPE_DOUBLE:
396
      attribute->set_type(drizzle::Table::Field::DOUBLE);
397
      break;
398
    case DRIZZLE_TYPE_NULL  :
399
      assert(1); /* Not a user definable type */
400
    case DRIZZLE_TYPE_TIMESTAMP:
401
      attribute->set_type(drizzle::Table::Field::TIMESTAMP);
402
      break;
403
    case DRIZZLE_TYPE_LONGLONG:
404
      attribute->set_type(drizzle::Table::Field::BIGINT);
405
      break;
406
    case DRIZZLE_TYPE_TIME:
407
      attribute->set_type(drizzle::Table::Field::TIME);
408
      break;
409
    case DRIZZLE_TYPE_DATETIME:
410
      attribute->set_type(drizzle::Table::Field::DATETIME);
411
      break;
587 by Brian Aker
Merge stewert
412
    case DRIZZLE_TYPE_DATE:
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
413
      attribute->set_type(drizzle::Table::Field::DATE);
414
      break;
415
    case DRIZZLE_TYPE_VARCHAR:
416
      {
417
        drizzle::Table::Field::StringFieldOptions *string_field_options;
418
419
        string_field_options= attribute->mutable_string_options();
420
        attribute->set_type(drizzle::Table::Field::VARCHAR);
421
        string_field_options->set_length(field_arg->char_length);
422
        string_field_options->set_collation_id(field_arg->charset->number);
423
        string_field_options->set_collation(field_arg->charset->name);
424
425
        break;
426
      }
427
    case DRIZZLE_TYPE_NEWDECIMAL:
428
      {
429
        drizzle::Table::Field::NumericFieldOptions *numeric_field_options;
430
431
        attribute->set_type(drizzle::Table::Field::DECIMAL);
432
        numeric_field_options= attribute->mutable_numeric_options();
433
        /* This is magic, I hate magic numbers -Brian */
434
        numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
435
        numeric_field_options->set_scale(field_arg->decimals);
436
        break;
437
      }
438
    case DRIZZLE_TYPE_ENUM:
439
      {
440
        drizzle::Table::Field::SetFieldOptions *set_field_options;
441
442
        assert(field_arg->interval);
443
444
        attribute->set_type(drizzle::Table::Field::ENUM);
445
        set_field_options= attribute->mutable_set_options();
446
447
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
448
        {
449
          const char *src= field_arg->interval->type_names[pos];
450
451
          set_field_options->add_value(src);
452
        }
453
        set_field_options->set_count_elements(set_field_options->value_size());
454
        break;
455
      }
456
    case DRIZZLE_TYPE_BLOB:
457
      attribute->set_type(drizzle::Table::Field::BLOB);
458
      break;
459
    default:
460
      assert(1);
461
    }
462
463
#ifdef NOTDONE
464
    field_constraints= attribute->mutable_constraints();
465
    constraints->set_is_nullable(field_arg->def->null_value);
466
#endif
467
468
    /* Set the comment */
469
    if (field_arg->comment.length)
470
      attribute->set_comment(field_arg->comment.str);
471
  }
472
473
  if (create_info->comment.length)
474
    table_options->set_comment(create_info->comment.str);
475
476
  if (create_info->table_charset)
477
  {
478
    table_options->set_collation_id(field_arg->charset->number);
479
    table_options->set_collation(field_arg->charset->name);
480
  }
481
482
  if (create_info->connect_string.length)
483
    table_options->set_connect_string(create_info->connect_string.str);
484
485
  if (create_info->data_file_name)
486
    table_options->set_data_file_name(create_info->data_file_name);
487
488
  if (create_info->index_file_name)
489
    table_options->set_index_file_name(create_info->index_file_name);
490
491
  if (create_info->max_rows)
492
    table_options->set_max_rows(create_info->max_rows);
493
494
  if (create_info->min_rows)
495
    table_options->set_min_rows(create_info->min_rows);
496
497
  if (create_info->auto_increment_value)
498
    table_options->set_auto_increment_value(create_info->auto_increment_value);
499
500
  if (create_info->avg_row_length)
501
    table_options->set_avg_row_length(create_info->avg_row_length);
502
503
  if (create_info->key_block_size)
504
    table_options->set_key_block_size(create_info->key_block_size);
505
506
  if (create_info->block_size)
507
    table_options->set_block_size(create_info->block_size);
590.1.2 by Stewart Smith
store indexes in table definition protobuf
508
509
  for (unsigned int i= 0; i < keys; i++)
510
  {
511
    drizzle::Table::Index *idx;
512
513
    idx= table_proto->add_index();
514
515
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
516
           (key_info[i].comment.length > 0));
517
518
    idx->set_name(key_info[i].name);
519
520
    if(is_primary_key_name(key_info[i].name))
521
      idx->set_is_primary(true);
522
    else
523
      idx->set_is_primary(false);
524
525
    switch(key_info[i].algorithm)
526
    {
527
    case HA_KEY_ALG_HASH:
528
      idx->set_type(drizzle::Table::Index::HASH);
529
      break;
530
531
    case HA_KEY_ALG_BTREE:
532
      idx->set_type(drizzle::Table::Index::BTREE);
533
      break;
534
535
    case HA_KEY_ALG_RTREE:
536
    case HA_KEY_ALG_FULLTEXT:
537
    case HA_KEY_ALG_UNDEF:
538
      idx->set_type(drizzle::Table::Index::UNKNOWN_INDEX);
539
      break;
540
541
    default:
542
      abort(); /* Somebody's brain broke. haven't added index type to proto */
543
      break;
544
    }
545
546
    if (key_info[i].flags & HA_NOSAME)
547
      idx->set_is_unique(true);
548
    else
549
      idx->set_is_unique(false);
550
551
    /* FIXME: block_size ? */
552
553
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
554
    {
555
      drizzle::Table::Index::IndexPart *idxpart;
556
      drizzle::Table::Field *field;
557
558
      idxpart= idx->add_index_part();
559
560
      field= idxpart->mutable_field();
561
      *field= table_proto->field(key_info[i].key_part[j].fieldnr);
562
563
      idxpart->set_compare_length(key_info[i].key_part[j].length);
564
    }
565
566
    if (key_info[i].flags & HA_USES_COMMENT)
567
      idx->set_comment(key_info[i].comment.str);
568
  }
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
569
}
570
584.2.7 by Stewart Smith
rename and delete tabledefinition protobuf file
571
int rename_table_proto_file(const char *from, const char* to)
572
{
573
  string from_path(from);
574
  string to_path(to);
575
  string file_ext = ".tabledefinition";
576
577
  from_path.append(file_ext);
578
  to_path.append(file_ext);
579
580
  return my_rename(from_path.c_str(),to_path.c_str(),MYF(MY_WME));
581
}
582
583
int delete_table_proto_file(char *file_name)
584
{
585
  string new_path(file_name);
586
  string file_ext = ".tabledefinition";
587
588
  new_path.append(file_ext);
589
  return my_delete(new_path.c_str(), MYF(0));
590
}
591
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
592
int create_table_proto_file(char *file_name,
593
                            const char *table_name,
594
                            HA_CREATE_INFO *create_info,
595
                            List<Create_field> &create_fields,
590.1.2 by Stewart Smith
store indexes in table definition protobuf
596
                            uint32_t keys,
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
597
                            KEY *key_info)
598
{
599
  (void)key_info;
600
601
  drizzle::Table table_proto;
602
  string new_path(file_name);
603
  string file_ext = ".tabledefinition";
604
590.1.2 by Stewart Smith
store indexes in table definition protobuf
605
  fill_table_proto(&table_proto, table_name, create_fields, create_info,
606
                   keys, key_info);
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
607
608
  new_path.replace(new_path.find(".frm"), file_ext.length(), file_ext );
609
610
  fstream output(new_path.c_str(), ios::out | ios::trunc | ios::binary);
611
  if (!table_proto.SerializeToOstream(&output))
612
  {
613
    printf("Failed to write schema.\n");
614
    fprintf(stderr, "Failed to write schema.\n");
615
    return -1;
616
  }
617
618
  return 0;
619
}
1 by brian
clean slate
620
621
/*
622
  Create a frm (table definition) file and the tables
623
624
  SYNOPSIS
625
    rea_create_table()
520.1.22 by Brian Aker
Second pass of thd cleanup
626
    session			Thread handler
1 by brian
clean slate
627
    path		Name of file (including database, without .frm)
628
    db			Data base name
629
    table_name		Table name
630
    create_info		create info parameters
631
    create_fields	Fields to create
632
    keys		number of keys to create
633
    key_info		Keys to create
634
    file		Handler to use
635
636
  RETURN
637
    0  ok
638
    1  error
639
*/
640
520.1.22 by Brian Aker
Second pass of thd cleanup
641
int rea_create_table(Session *session, const char *path,
1 by brian
clean slate
642
                     const char *db, const char *table_name,
643
                     HA_CREATE_INFO *create_info,
644
                     List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
645
                     uint32_t keys, KEY *key_info, handler *file)
1 by brian
clean slate
646
{
647
  char frm_name[FN_REFLEN];
461 by Monty Taylor
Removed NullS. bu-bye.
648
  strxmov(frm_name, path, reg_ext, NULL);
520.1.22 by Brian Aker
Second pass of thd cleanup
649
  if (mysql_create_frm(session, frm_name, db, table_name, create_info,
1 by brian
clean slate
650
                       create_fields, keys, key_info, file))
651
51.2.2 by Patrick Galbraith
Removed DBUGs from
652
    return(1);
1 by brian
clean slate
653
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
654
  if (create_table_proto_file(frm_name, table_name, create_info,
655
                              create_fields, keys, key_info) != 0)
656
    return 1;
657
1 by brian
clean slate
658
  // Make sure mysql_create_frm din't remove extension
51.2.2 by Patrick Galbraith
Removed DBUGs from
659
  assert(*fn_rext(frm_name));
520.1.22 by Brian Aker
Second pass of thd cleanup
660
  if (session->variables.keep_files_on_create)
1 by brian
clean slate
661
    create_info->options|= HA_CREATE_KEEP_FILES;
662
  if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
663
    goto err_handler;
590.1.3 by Stewart Smith
remove frm_only create_info option
664
  if ( ha_create_table(session, path, db, table_name,
1 by brian
clean slate
665
                                                create_info,0))
666
    goto err_handler;
51.2.2 by Patrick Galbraith
Removed DBUGs from
667
  return(0);
1 by brian
clean slate
668
669
err_handler:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
670
  file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
1 by brian
clean slate
671
  my_delete(frm_name, MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
672
  return(1);
1 by brian
clean slate
673
} /* rea_create_table */
674
675
676
	/* Pack screens to a screen for save in a form-file */
677
481 by Brian Aker
Remove all of uchar.
678
static unsigned char *pack_screens(List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
679
                           uint32_t *info_length, uint32_t *screens,
1 by brian
clean slate
680
                           bool small_file)
681
{
482 by Brian Aker
Remove uint.
682
  register uint32_t i;
683
  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
684
  uint32_t length,cols, cols_half_len;
481 by Brian Aker
Remove all of uchar.
685
  unsigned char *info,*pos,*start_screen;
482 by Brian Aker
Remove uint.
686
  uint32_t fields=create_fields.elements;
1 by brian
clean slate
687
  List_iterator<Create_field> it(create_fields);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
688
1 by brian
clean slate
689
  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
690
  cols_half_len= (uint32_t)(cols >> 1);
1 by brian
clean slate
691
692
  *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
693
  length= (*screens) * (SC_INFO_LENGTH+cols_half_len+4);
1 by brian
clean slate
694
695
  Create_field *field;
696
  while ((field=it++))
697
    length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
698
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
699
  if (!(info=(unsigned char*) malloc(length)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
700
    return(0);
1 by brian
clean slate
701
702
  start_screen=0;
703
  row=end_row;
704
  pos=info;
705
  it.rewind();
706
  for (i=0 ; i < fields ; i++)
707
  {
708
    Create_field *cfield=it++;
709
    if (row++ == end_row)
710
    {
711
      if (i)
712
      {
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
713
        length=(uint) (pos-start_screen);
714
        int2store(start_screen,length);
715
        start_screen[2]=(unsigned char) (fields_on_screen+1);
716
        start_screen[3]=(unsigned char) (fields_on_screen);
1 by brian
clean slate
717
      }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
718
      row= start_row;
1 by brian
clean slate
719
      start_screen=pos;
720
      pos+=4;
481 by Brian Aker
Remove all of uchar.
721
      pos[0]= (unsigned char) start_row-2;	/* Header string */
722
      pos[1]= (unsigned char) (cols >> 2);
723
      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
724
      memset((char*)pos+3,' ',cols_half_len);
725
      pos[cols_half_len+3]= '\0';
726
      pos+= cols_half_len+4;
1 by brian
clean slate
727
    }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
728
    length= (uint32_t) strlen(cfield->field_name);
1 by brian
clean slate
729
    if (length > cols-3)
730
      length=cols-3;
731
732
    if (!small_file)
733
    {
481 by Brian Aker
Remove all of uchar.
734
      pos[0]=(unsigned char) row;
1 by brian
clean slate
735
      pos[1]=0;
481 by Brian Aker
Remove all of uchar.
736
      pos[2]=(unsigned char) (length+1);
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
737
      strncpy((char*)pos+3,cfield->field_name, length);
738
      pos[length + 3]= '\0';
739
      pos+= length + 3 + 1;
1 by brian
clean slate
740
    }
206 by Brian Aker
Removed final uint dead types.
741
    cfield->row=(uint8_t) row;
742
    cfield->col=(uint8_t) (length+1);
398.1.4 by Monty Taylor
Renamed max/min.
743
    cfield->sc_length=(uint8_t) cmin(cfield->length,(uint32_t)cols-(length+2));
1 by brian
clean slate
744
  }
745
  length=(uint) (pos-start_screen);
746
  int2store(start_screen,length);
481 by Brian Aker
Remove all of uchar.
747
  start_screen[2]=(unsigned char) (row-start_row+2);
748
  start_screen[3]=(unsigned char) (row-start_row+1);
1 by brian
clean slate
749
750
  *info_length=(uint) (pos-info);
51.2.2 by Patrick Galbraith
Removed DBUGs from
751
  return(info);
1 by brian
clean slate
752
} /* pack_screens */
753
754
755
	/* Pack keyinfo and keynames to keybuff for save in form-file. */
756
482 by Brian Aker
Remove uint.
757
static uint32_t pack_keys(unsigned char *keybuff, uint32_t key_count, KEY *keyinfo,
1 by brian
clean slate
758
                      ulong data_offset)
759
{
482 by Brian Aker
Remove uint.
760
  uint32_t key_parts,length;
481 by Brian Aker
Remove all of uchar.
761
  unsigned char *pos, *keyname_pos;
1 by brian
clean slate
762
  KEY *key,*end;
763
  KEY_PART_INFO *key_part,*key_part_end;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
764
1 by brian
clean slate
765
766
  pos=keybuff+6;
767
  key_parts=0;
768
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
769
  {
770
    int2store(pos, (key->flags ^ HA_NOSAME));
771
    int2store(pos+2,key->key_length);
481 by Brian Aker
Remove all of uchar.
772
    pos[4]= (unsigned char) key->key_parts;
773
    pos[5]= (unsigned char) key->algorithm;
1 by brian
clean slate
774
    int2store(pos+6, key->block_size);
775
    pos+=8;
776
    key_parts+=key->key_parts;
777
    for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
778
	 key_part != key_part_end ;
779
	 key_part++)
780
781
    {
482 by Brian Aker
Remove uint.
782
      uint32_t offset;
1 by brian
clean slate
783
      int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
784
      offset= (uint) (key_part->offset+data_offset+1);
785
      int2store(pos+2, offset);
786
      pos[4]=0;					// Sort order
787
      int2store(pos+5,key_part->key_type);
788
      int2store(pos+7,key_part->length);
789
      pos+=9;
790
    }
791
  }
792
	/* Save keynames */
793
  keyname_pos=pos;
481 by Brian Aker
Remove all of uchar.
794
  *pos++=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
795
  for (key=keyinfo ; key != end ; key++)
796
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
797
    unsigned char *tmp=(unsigned char*) strcpy((char*) pos,key->name);
798
    tmp+= strlen(key->name);
481 by Brian Aker
Remove all of uchar.
799
    *tmp++= (unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
800
    *tmp=0;
801
    pos=tmp;
802
  }
803
  *(pos++)=0;
804
805
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
806
  {
807
    if (key->flags & HA_USES_COMMENT)
808
    {
809
      int2store(pos, key->comment.length);
481 by Brian Aker
Remove all of uchar.
810
      unsigned char *tmp= (unsigned char*)my_stpncpy((char*) pos+2,key->comment.str,key->comment.length);
1 by brian
clean slate
811
      pos= tmp;
812
    }
813
  }
814
815
  if (key_count > 127 || key_parts > 127)
816
  {
817
    keybuff[0]= (key_count & 0x7f) | 0x80;
818
    keybuff[1]= key_count >> 7;
819
    int2store(keybuff+2,key_parts);
820
  }
821
  else
822
  {
481 by Brian Aker
Remove all of uchar.
823
    keybuff[0]=(unsigned char) key_count;
824
    keybuff[1]=(unsigned char) key_parts;
1 by brian
clean slate
825
    keybuff[2]= keybuff[3]= 0;
826
  }
827
  length=(uint) (pos-keyname_pos);
828
  int2store(keybuff+4,length);
51.2.2 by Patrick Galbraith
Removed DBUGs from
829
  return((uint) (pos-keybuff));
1 by brian
clean slate
830
} /* pack_keys */
831
832
77.1.45 by Monty Taylor
Warning fixes.
833
/* Make formheader */
1 by brian
clean slate
834
481 by Brian Aker
Remove all of uchar.
835
static bool pack_header(unsigned char *forminfo,
77.1.45 by Monty Taylor
Warning fixes.
836
                        List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
837
                        uint32_t info_length, uint32_t screens, uint32_t table_options,
1 by brian
clean slate
838
                        ulong data_offset, handler *file)
839
{
482 by Brian Aker
Remove uint.
840
  uint32_t length,int_count,int_length,no_empty, int_parts;
841
  uint32_t time_stamp_pos,null_fields;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
842
  ulong reclength, totlength, n_length, com_length, vcol_info_length;
77.1.45 by Monty Taylor
Warning fixes.
843
1 by brian
clean slate
844
845
  if (create_fields.elements > MAX_FIELDS)
846
  {
847
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
848
    return(1);
1 by brian
clean slate
849
  }
850
851
  totlength= 0L;
852
  reclength= data_offset;
853
  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
854
    com_length=vcol_info_length=0;
1 by brian
clean slate
855
  n_length=2L;
856
857
	/* Check fields */
858
859
  List_iterator<Create_field> it(create_fields);
860
  Create_field *field;
861
  while ((field=it++))
862
  {
482 by Brian Aker
Remove uint.
863
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
1 by brian
clean slate
864
                                                     field->comment.str,
865
                                                     field->comment.str +
866
                                                     field->comment.length,
867
                                                     COLUMN_COMMENT_MAXLEN);
868
869
    if (tmp_len < field->comment.length)
870
    {
871
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
872
               field->comment.str,"COLUMN COMMENT",
873
               (uint) COLUMN_COMMENT_MAXLEN);
51.2.2 by Patrick Galbraith
Removed DBUGs from
874
      return(1);
1 by brian
clean slate
875
    }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
876
    if (field->vcol_info)
877
    {
878
      tmp_len= system_charset_info->cset->charpos(system_charset_info,
879
                                                  field->vcol_info->expr_str.str,
880
                                                  field->vcol_info->expr_str.str +
881
                                                  field->vcol_info->expr_str.length,
882
                                                  VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
883
884
      if (tmp_len < field->vcol_info->expr_str.length)
885
      {
886
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
887
                 field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
888
                 (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
889
        return(1);
890
      }
891
      /*
892
        Sum up the length of the expression string and mandatory header bytes
893
        to the total length.
894
      */
895
      vcol_info_length+= field->vcol_info->expr_str.length+(uint)FRM_VCOL_HEADER_SIZE;
896
    }
1 by brian
clean slate
897
898
    totlength+= field->length;
899
    com_length+= field->comment.length;
900
    if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
901
	field->unireg_check & MTYP_NOEMPTY_BIT)
902
    {
903
      field->unireg_check= (Field::utype) ((uint) field->unireg_check |
904
					   MTYP_NOEMPTY_BIT);
905
      no_empty++;
906
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
907
    /*
908
      We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
1 by brian
clean slate
909
      as auto-update field.
910
    */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
911
    if (field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1 by brian
clean slate
912
        MTYP_TYPENR(field->unireg_check) != Field::NONE &&
913
	!time_stamp_pos)
914
      time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
915
    length=field->pack_length;
916
    if ((uint) field->offset+ (uint) data_offset+ length > reclength)
917
      reclength=(uint) (field->offset+ data_offset + length);
918
    n_length+= (ulong) strlen(field->field_name)+1;
919
    field->interval_id=0;
920
    field->save_interval= 0;
921
    if (field->interval)
922
    {
482 by Brian Aker
Remove uint.
923
      uint32_t old_int_count=int_count;
1 by brian
clean slate
924
925
      if (field->charset->mbminlen > 1)
926
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
927
        /*
1 by brian
clean slate
928
          Escape UCS2 intervals using HEX notation to avoid
929
          problems with delimiters between enum elements.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
930
          As the original representation is still needed in
1 by brian
clean slate
931
          the function make_empty_rec to create a record of
932
          filled with default values it is saved in save_interval
933
          The HEX representation is created from this copy.
934
        */
935
        field->save_interval= field->interval;
936
        field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
937
        *field->interval= *field->save_interval;
938
        field->interval->type_names=
939
          (const char **) sql_alloc(sizeof(char*) *
1 by brian
clean slate
940
				    (field->interval->count+1));
941
        field->interval->type_names[field->interval->count]= 0;
942
        field->interval->type_lengths=
482 by Brian Aker
Remove uint.
943
          (uint32_t *) sql_alloc(sizeof(uint) * field->interval->count);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
944
482 by Brian Aker
Remove uint.
945
        for (uint32_t pos= 0; pos < field->interval->count; pos++)
1 by brian
clean slate
946
        {
947
          char *dst;
948
          const char *src= field->save_interval->type_names[pos];
482 by Brian Aker
Remove uint.
949
          uint32_t hex_length;
1 by brian
clean slate
950
          length= field->save_interval->type_lengths[pos];
951
          hex_length= length * 2;
952
          field->interval->type_lengths[pos]= hex_length;
953
          field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length +
954
                                                                   1);
955
          octet2hex(dst, src, length);
956
        }
957
      }
958
959
      field->interval_id=get_interval_id(&int_count,create_fields,field);
960
      if (old_int_count != int_count)
961
      {
962
	for (const char **pos=field->interval->type_names ; *pos ; pos++)
963
	  int_length+=(uint) strlen(*pos)+1;	// field + suffix prefix
964
	int_parts+=field->interval->count+1;
965
      }
966
    }
967
    if (f_maybe_null(field->pack_flag))
968
      null_fields++;
969
  }
970
  int_length+=int_count*2;			// 255 prefix + 0 suffix
971
972
	/* Save values in forminfo */
973
974
  if (reclength > (ulong) file->max_record_length())
975
  {
976
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0), (uint) file->max_record_length());
51.2.2 by Patrick Galbraith
Removed DBUGs from
977
    return(1);
1 by brian
clean slate
978
  }
979
  /* Hack to avoid bugs with small static rows in MySQL */
398.1.4 by Monty Taylor
Renamed max/min.
980
  reclength=cmax((ulong)file->min_record_length(table_options),reclength);
1 by brian
clean slate
981
  if (info_length+(ulong) create_fields.elements*FCOMP+288+
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
982
      n_length+int_length+com_length+vcol_info_length > 65535L ||
383.7.1 by Andrey Zhakov
Initial submit of code and tests
983
      int_count > 255)
1 by brian
clean slate
984
  {
985
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
986
    return(1);
1 by brian
clean slate
987
  }
988
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
989
  memset(forminfo, 0, 288);
1 by brian
clean slate
990
  length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
383.7.1 by Andrey Zhakov
Initial submit of code and tests
991
	  com_length+vcol_info_length);
1 by brian
clean slate
992
  int2store(forminfo,length);
206 by Brian Aker
Removed final uint dead types.
993
  forminfo[256] = (uint8_t) screens;
1 by brian
clean slate
994
  int2store(forminfo+258,create_fields.elements);
995
  int2store(forminfo+260,info_length);
996
  int2store(forminfo+262,totlength);
997
  int2store(forminfo+264,no_empty);
998
  int2store(forminfo+266,reclength);
999
  int2store(forminfo+268,n_length);
1000
  int2store(forminfo+270,int_count);
1001
  int2store(forminfo+272,int_parts);
1002
  int2store(forminfo+274,int_length);
1003
  int2store(forminfo+276,time_stamp_pos);
1004
  int2store(forminfo+278,80);			/* Columns needed */
1005
  int2store(forminfo+280,22);			/* Rows needed */
1006
  int2store(forminfo+282,null_fields);
1007
  int2store(forminfo+284,com_length);
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1008
  int2store(forminfo+286,vcol_info_length);
1009
  /* forminfo+288 is free to use for additional information */
51.2.2 by Patrick Galbraith
Removed DBUGs from
1010
  return(0);
1 by brian
clean slate
1011
} /* pack_header */
1012
1013
1014
	/* get each unique interval each own id */
1015
482 by Brian Aker
Remove uint.
1016
static uint32_t get_interval_id(uint32_t *int_count,List<Create_field> &create_fields,
1 by brian
clean slate
1017
			    Create_field *last_field)
1018
{
1019
  List_iterator<Create_field> it(create_fields);
1020
  Create_field *field;
1021
  TYPELIB *interval=last_field->interval;
1022
1023
  while ((field=it++) != last_field)
1024
  {
1025
    if (field->interval_id && field->interval->count == interval->count)
1026
    {
1027
      const char **a,**b;
1028
      for (a=field->interval->type_names, b=interval->type_names ;
1029
	   *a && !strcmp(*a,*b);
1030
	   a++,b++) ;
1031
1032
      if (! *a)
1033
      {
1034
	return field->interval_id;		// Re-use last interval
1035
      }
1036
    }
1037
  }
1038
  return ++*int_count;				// New unique interval
1039
}
1040
1041
1042
	/* Save fields, fieldnames and intervals */
1043
1044
static bool pack_fields(File file, List<Create_field> &create_fields,
1045
                        ulong data_offset)
1046
{
482 by Brian Aker
Remove uint.
1047
  register uint32_t i;
481.3.1 by Monty Taylor
Merged vcol stuff.
1048
  uint32_t int_count, comment_length=0, vcol_info_length=0;
481 by Brian Aker
Remove all of uchar.
1049
  unsigned char buff[MAX_FIELD_WIDTH];
1 by brian
clean slate
1050
  Create_field *field;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1051
1 by brian
clean slate
1052
1053
	/* Write field info */
1054
1055
  List_iterator<Create_field> it(create_fields);
1056
1057
  int_count=0;
1058
  while ((field=it++))
1059
  {
482 by Brian Aker
Remove uint.
1060
    uint32_t recpos;
481.3.1 by Monty Taylor
Merged vcol stuff.
1061
    uint32_t cur_vcol_expr_len= 0;
481 by Brian Aker
Remove all of uchar.
1062
    buff[0]= (unsigned char) field->row;
1063
    buff[1]= (unsigned char) field->col;
1064
    buff[2]= (unsigned char) field->sc_length;
1 by brian
clean slate
1065
    int2store(buff+3, field->length);
1066
    /* The +1 is here becasue the col offset in .frm file have offset 1 */
1067
    recpos= field->offset+1 + (uint) data_offset;
1068
    int3store(buff+5,recpos);
1069
    int2store(buff+8,field->pack_flag);
1070
    int2store(buff+10,field->unireg_check);
481 by Brian Aker
Remove all of uchar.
1071
    buff[12]= (unsigned char) field->interval_id;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1072
    buff[13]= (unsigned char) field->sql_type;
1073
    if (field->charset)
481 by Brian Aker
Remove all of uchar.
1074
      buff[14]= (unsigned char) field->charset->number;
1 by brian
clean slate
1075
    else
1076
      buff[14]= 0;				// Numerical
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1077
    if (field->vcol_info)
1078
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1079
      /*
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1080
        Use the interval_id place in the .frm file to store the length of
1081
        virtual field's data.
1082
      */
1083
      buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
1084
                (uint)FRM_VCOL_HEADER_SIZE;
1085
      vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE;
481.3.1 by Monty Taylor
Merged vcol stuff.
1086
      buff[13]= (unsigned char) DRIZZLE_TYPE_VIRTUAL;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1087
    }
1 by brian
clean slate
1088
    int2store(buff+15, field->comment.length);
1089
    comment_length+= field->comment.length;
1090
    set_if_bigger(int_count,field->interval_id);
1091
    if (my_write(file, buff, FCOMP, MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1092
      return(1);
1 by brian
clean slate
1093
  }
1094
1095
	/* Write fieldnames */
481 by Brian Aker
Remove all of uchar.
1096
  buff[0]=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
1097
  if (my_write(file, buff, 1, MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1098
    return(1);
1 by brian
clean slate
1099
  i=0;
1100
  it.rewind();
1101
  while ((field=it++))
1102
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1103
    char *pos= strcpy((char*) buff,field->field_name);
1104
    pos+= strlen(field->field_name);
1 by brian
clean slate
1105
    *pos++=NAMES_SEP_CHAR;
1106
    if (i == create_fields.elements-1)
1107
      *pos++=0;
1108
    if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1109
      return(1);
1 by brian
clean slate
1110
    i++;
1111
  }
1112
1113
	/* Write intervals */
1114
  if (int_count)
1115
  {
1116
    String tmp((char*) buff,sizeof(buff), &my_charset_bin);
1117
    tmp.length(0);
1118
    it.rewind();
1119
    int_count=0;
1120
    while ((field=it++))
1121
    {
1122
      if (field->interval_id > int_count)
1123
      {
1124
        unsigned char  sep= 0;
1125
        unsigned char  occ[256];
482 by Brian Aker
Remove uint.
1126
        uint32_t           i;
1 by brian
clean slate
1127
        unsigned char *val= NULL;
1128
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
1129
        memset(occ, 0, sizeof(occ));
1 by brian
clean slate
1130
1131
        for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
482 by Brian Aker
Remove uint.
1132
          for (uint32_t j = 0; j < field->interval->type_lengths[i]; j++)
1 by brian
clean slate
1133
            occ[(unsigned int) (val[j])]= 1;
1134
1135
        if (!occ[(unsigned char)NAMES_SEP_CHAR])
1136
          sep= (unsigned char) NAMES_SEP_CHAR;
1137
        else if (!occ[(unsigned int)','])
1138
          sep= ',';
1139
        else
1140
        {
482 by Brian Aker
Remove uint.
1141
          for (uint32_t i=1; i<256; i++)
1 by brian
clean slate
1142
          {
1143
            if(!occ[i])
1144
            {
1145
              sep= i;
1146
              break;
1147
            }
1148
          }
1149
1150
          if(!sep)    /* disaster, enum uses all characters, none left as separator */
1151
          {
1152
            my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
1153
                       MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
1154
            return(1);
1 by brian
clean slate
1155
          }
1156
        }
1157
1158
        int_count= field->interval_id;
1159
        tmp.append(sep);
1160
        for (const char **pos=field->interval->type_names ; *pos ; pos++)
1161
        {
1162
          tmp.append(*pos);
1163
          tmp.append(sep);
1164
        }
1165
        tmp.append('\0');                      // End of intervall
1166
      }
1167
    }
481 by Brian Aker
Remove all of uchar.
1168
    if (my_write(file,(unsigned char*) tmp.ptr(),tmp.length(),MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1169
      return(1);
1 by brian
clean slate
1170
  }
1171
  if (comment_length)
1172
  {
1173
    it.rewind();
1174
    int_count=0;
1175
    while ((field=it++))
1176
    {
1177
      if (field->comment.length)
481 by Brian Aker
Remove all of uchar.
1178
	if (my_write(file, (unsigned char*) field->comment.str, field->comment.length,
1 by brian
clean slate
1179
		     MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1180
	  return(1);
1 by brian
clean slate
1181
    }
1182
  }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1183
  if (vcol_info_length)
1184
  {
1185
    it.rewind();
1186
    int_count=0;
1187
    while ((field=it++))
1188
    {
1189
      /*
1190
        Pack each virtual field as follows:
1191
        byte 1      = 1 (always 1 to allow for future extensions)
1192
        byte 2      = sql_type
1193
        byte 3      = flags (as of now, 0 - no flags, 1 - field is physically stored)
1194
        byte 4-...  = virtual column expression (text data)
1195
      */
1196
      if (field->vcol_info && field->vcol_info->expr_str.length)
1197
      {
481.3.1 by Monty Taylor
Merged vcol stuff.
1198
        buff[0]= (unsigned char)1;
1199
        buff[1]= (unsigned char) field->sql_type;
1200
        buff[2]= (unsigned char) field->is_stored;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1201
        if (my_write(file, buff, 3, MYF_RW))
1202
          return(1);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1203
        if (my_write(file,
1204
                     (unsigned char*) field->vcol_info->expr_str.str,
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1205
                     field->vcol_info->expr_str.length,
1206
                     MYF_RW))
1207
          return(1);
1208
      }
1209
    }
1210
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1211
  return(0);
1 by brian
clean slate
1212
}
1213
1214
77.1.45 by Monty Taylor
Warning fixes.
1215
/* save an empty record on start of formfile */
1 by brian
clean slate
1216
520.1.22 by Brian Aker
Second pass of thd cleanup
1217
static bool make_empty_rec(Session *session, File file,
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1218
                           enum legacy_db_type table_type __attribute__((unused)),
482 by Brian Aker
Remove uint.
1219
                           uint32_t table_options,
77.1.45 by Monty Taylor
Warning fixes.
1220
                           List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
1221
                           uint32_t reclength,
1 by brian
clean slate
1222
                           ulong data_offset,
1223
                           handler *handler)
1224
{
1225
  int error= 0;
1226
  Field::utype type;
482 by Brian Aker
Remove uint.
1227
  uint32_t null_count;
481 by Brian Aker
Remove all of uchar.
1228
  unsigned char *buff,*null_pos;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1229
  Table table;
1 by brian
clean slate
1230
  TABLE_SHARE share;
1231
  Create_field *field;
520.1.22 by Brian Aker
Second pass of thd cleanup
1232
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1233
1 by brian
clean slate
1234
1235
  /* 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().
1236
  memset(&table, 0, sizeof(table));
1237
  memset(&share, 0, sizeof(share));
1 by brian
clean slate
1238
  table.s= &share;
1239
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1240
  if (!(buff=(unsigned char*) malloc((size_t) reclength)))
1 by brian
clean slate
1241
  {
51.2.2 by Patrick Galbraith
Removed DBUGs from
1242
    return(1);
1 by brian
clean slate
1243
  }
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1244
  memset(buff, 0, (size_t) reclength);
1 by brian
clean slate
1245
520.1.22 by Brian Aker
Second pass of thd cleanup
1246
  table.in_use= session;
1 by brian
clean slate
1247
  table.s->db_low_byte_first= handler->low_byte_first();
1248
  table.s->blob_ptr_size= portable_sizeof_char_ptr;
1249
1250
  null_count=0;
1251
  if (!(table_options & HA_OPTION_PACK_RECORD))
1252
  {
1253
    null_count++;			// Need one bit for delete mark
1254
    *buff|= 1;
1255
  }
1256
  null_pos= buff;
1257
1258
  List_iterator<Create_field> it(create_fields);
520.1.22 by Brian Aker
Second pass of thd cleanup
1259
  session->count_cuted_fields= CHECK_FIELD_WARN;    // To find wrong default values
1 by brian
clean slate
1260
  while ((field=it++))
1261
  {
1262
    /*
1263
      regfield don't have to be deleted as it's allocated with sql_alloc()
1264
    */
1265
    Field *regfield= make_field(&share,
1266
                                buff+field->offset + data_offset,
1267
                                field->length,
1268
                                null_pos + null_count / 8,
1269
                                null_count & 7,
1270
                                field->pack_flag,
1271
                                field->sql_type,
1272
                                field->charset,
1273
                                field->unireg_check,
1274
                                field->save_interval ? field->save_interval :
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1275
                                field->interval,
1 by brian
clean slate
1276
                                field->field_name);
1277
    if (!regfield)
1278
    {
1279
      error= 1;
1280
      goto err;                                 // End of memory
1281
    }
1282
1283
    /* save_in_field() will access regfield->table->in_use */
1284
    regfield->init(&table);
1285
1286
    if (!(field->flags & NOT_NULL_FLAG))
1287
    {
1288
      *regfield->null_ptr|= regfield->null_bit;
1289
      null_count++;
1290
    }
1291
1292
    type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1293
1294
    if (field->def)
1295
    {
1296
      int res= field->def->save_in_field(regfield, 1);
1297
      /* If not ok or warning of level 'note' */
1298
      if (res != 0 && res != 3)
1299
      {
1300
        my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1301
        error= 1;
1302
        delete regfield; //To avoid memory leak
1303
        goto err;
1304
      }
1305
    }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1306
    else if (regfield->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
1307
	     (field->flags & NOT_NULL_FLAG))
1308
    {
1309
      regfield->set_notnull();
163 by Brian Aker
Merge Monty's code.
1310
      regfield->store((int64_t) 1, true);
1 by brian
clean slate
1311
    }
1312
    else if (type == Field::YES)		// Old unireg type
1313
      regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),system_charset_info);
1314
    else if (type == Field::NO)			// Old unireg type
1315
      regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
1316
    else
1317
      regfield->reset();
1318
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1319
  assert(data_offset == ((null_count + 7) / 8));
1 by brian
clean slate
1320
1321
  /*
1322
    We need to set the unused bits to 1. If the number of bits is a multiple
1323
    of 8 there are no unused bits.
1324
  */
1325
  if (null_count & 7)
481 by Brian Aker
Remove all of uchar.
1326
    *(null_pos + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1 by brian
clean slate
1327
1328
  error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0;
1329
1330
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.
1331
  free(buff);
520.1.22 by Brian Aker
Second pass of thd cleanup
1332
  session->count_cuted_fields= old_count_cuted_fields;
51.2.2 by Patrick Galbraith
Removed DBUGs from
1333
  return(error);
1 by brian
clean slate
1334
} /* make_empty_rec */