~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
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
625
int create_table_proto_file(char *file_name,
626
                            const char *table_name,
627
                            HA_CREATE_INFO *create_info,
628
                            List<Create_field> &create_fields,
590.1.2 by Stewart Smith
store indexes in table definition protobuf
629
                            uint32_t keys,
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
630
                            KEY *key_info)
631
{
632
  (void)key_info;
633
634
  drizzle::Table table_proto;
635
  string new_path(file_name);
636
  string file_ext = ".tabledefinition";
637
590.1.2 by Stewart Smith
store indexes in table definition protobuf
638
  fill_table_proto(&table_proto, table_name, create_fields, create_info,
639
                   keys, key_info);
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
640
641
  new_path.replace(new_path.find(".frm"), file_ext.length(), file_ext );
642
643
  fstream output(new_path.c_str(), ios::out | ios::trunc | ios::binary);
644
  if (!table_proto.SerializeToOstream(&output))
645
  {
646
    printf("Failed to write schema.\n");
647
    fprintf(stderr, "Failed to write schema.\n");
648
    return -1;
649
  }
650
651
  return 0;
652
}
1 by brian
clean slate
653
654
/*
655
  Create a frm (table definition) file and the tables
656
657
  SYNOPSIS
658
    rea_create_table()
520.1.22 by Brian Aker
Second pass of thd cleanup
659
    session			Thread handler
1 by brian
clean slate
660
    path		Name of file (including database, without .frm)
661
    db			Data base name
662
    table_name		Table name
663
    create_info		create info parameters
664
    create_fields	Fields to create
665
    keys		number of keys to create
666
    key_info		Keys to create
667
    file		Handler to use
668
669
  RETURN
670
    0  ok
671
    1  error
672
*/
673
520.1.22 by Brian Aker
Second pass of thd cleanup
674
int rea_create_table(Session *session, const char *path,
1 by brian
clean slate
675
                     const char *db, const char *table_name,
676
                     HA_CREATE_INFO *create_info,
677
                     List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
678
                     uint32_t keys, KEY *key_info, handler *file)
1 by brian
clean slate
679
{
680
  char frm_name[FN_REFLEN];
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
681
  sprintf(frm_name,"%s%s",path,reg_ext);
520.1.22 by Brian Aker
Second pass of thd cleanup
682
  if (mysql_create_frm(session, frm_name, db, table_name, create_info,
1 by brian
clean slate
683
                       create_fields, keys, key_info, file))
684
51.2.2 by Patrick Galbraith
Removed DBUGs from
685
    return(1);
1 by brian
clean slate
686
584.2.5 by Stewart Smith
store a protobuf tabledefinition along with FRM
687
  if (create_table_proto_file(frm_name, table_name, create_info,
688
                              create_fields, keys, key_info) != 0)
689
    return 1;
690
1 by brian
clean slate
691
  // Make sure mysql_create_frm din't remove extension
51.2.2 by Patrick Galbraith
Removed DBUGs from
692
  assert(*fn_rext(frm_name));
520.1.22 by Brian Aker
Second pass of thd cleanup
693
  if (session->variables.keep_files_on_create)
1 by brian
clean slate
694
    create_info->options|= HA_CREATE_KEEP_FILES;
695
  if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
696
    goto err_handler;
590.1.3 by Stewart Smith
remove frm_only create_info option
697
  if ( ha_create_table(session, path, db, table_name,
1 by brian
clean slate
698
                                                create_info,0))
699
    goto err_handler;
51.2.2 by Patrick Galbraith
Removed DBUGs from
700
  return(0);
1 by brian
clean slate
701
702
err_handler:
398.1.10 by Monty Taylor
Actually removed VOID() this time.
703
  file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
1 by brian
clean slate
704
  my_delete(frm_name, MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
705
  return(1);
1 by brian
clean slate
706
} /* rea_create_table */
707
708
709
	/* Pack screens to a screen for save in a form-file */
710
481 by Brian Aker
Remove all of uchar.
711
static unsigned char *pack_screens(List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
712
                           uint32_t *info_length, uint32_t *screens,
1 by brian
clean slate
713
                           bool small_file)
714
{
482 by Brian Aker
Remove uint.
715
  register uint32_t i;
716
  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
717
  uint32_t length,cols, cols_half_len;
481 by Brian Aker
Remove all of uchar.
718
  unsigned char *info,*pos,*start_screen;
482 by Brian Aker
Remove uint.
719
  uint32_t fields=create_fields.elements;
1 by brian
clean slate
720
  List_iterator<Create_field> it(create_fields);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
721
1 by brian
clean slate
722
  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
723
  cols_half_len= (uint32_t)(cols >> 1);
1 by brian
clean slate
724
725
  *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
726
  length= (*screens) * (SC_INFO_LENGTH+cols_half_len+4);
1 by brian
clean slate
727
728
  Create_field *field;
729
  while ((field=it++))
730
    length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
731
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
732
  if (!(info=(unsigned char*) malloc(length)))
51.2.2 by Patrick Galbraith
Removed DBUGs from
733
    return(0);
1 by brian
clean slate
734
735
  start_screen=0;
736
  row=end_row;
737
  pos=info;
738
  it.rewind();
739
  for (i=0 ; i < fields ; i++)
740
  {
741
    Create_field *cfield=it++;
742
    if (row++ == end_row)
743
    {
744
      if (i)
745
      {
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
746
        length=(uint) (pos-start_screen);
747
        int2store(start_screen,length);
748
        start_screen[2]=(unsigned char) (fields_on_screen+1);
749
        start_screen[3]=(unsigned char) (fields_on_screen);
1 by brian
clean slate
750
      }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
751
      row= start_row;
1 by brian
clean slate
752
      start_screen=pos;
753
      pos+=4;
481 by Brian Aker
Remove all of uchar.
754
      pos[0]= (unsigned char) start_row-2;	/* Header string */
755
      pos[1]= (unsigned char) (cols >> 2);
756
      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
757
      memset((char*)pos+3,' ',cols_half_len);
758
      pos[cols_half_len+3]= '\0';
759
      pos+= cols_half_len+4;
1 by brian
clean slate
760
    }
667.1.1 by Toru Maesaka
Threw out MySQL's strfill and replaced it with libc's memset
761
    length= (uint32_t) strlen(cfield->field_name);
1 by brian
clean slate
762
    if (length > cols-3)
763
      length=cols-3;
764
765
    if (!small_file)
766
    {
481 by Brian Aker
Remove all of uchar.
767
      pos[0]=(unsigned char) row;
1 by brian
clean slate
768
      pos[1]=0;
481 by Brian Aker
Remove all of uchar.
769
      pos[2]=(unsigned char) (length+1);
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
770
      strncpy((char*)pos+3,cfield->field_name, length);
771
      pos[length + 3]= '\0';
772
      pos+= length + 3 + 1;
1 by brian
clean slate
773
    }
206 by Brian Aker
Removed final uint dead types.
774
    cfield->row=(uint8_t) row;
775
    cfield->col=(uint8_t) (length+1);
398.1.4 by Monty Taylor
Renamed max/min.
776
    cfield->sc_length=(uint8_t) cmin(cfield->length,(uint32_t)cols-(length+2));
1 by brian
clean slate
777
  }
778
  length=(uint) (pos-start_screen);
779
  int2store(start_screen,length);
481 by Brian Aker
Remove all of uchar.
780
  start_screen[2]=(unsigned char) (row-start_row+2);
781
  start_screen[3]=(unsigned char) (row-start_row+1);
1 by brian
clean slate
782
783
  *info_length=(uint) (pos-info);
51.2.2 by Patrick Galbraith
Removed DBUGs from
784
  return(info);
1 by brian
clean slate
785
} /* pack_screens */
786
787
788
	/* Pack keyinfo and keynames to keybuff for save in form-file. */
789
482 by Brian Aker
Remove uint.
790
static uint32_t pack_keys(unsigned char *keybuff, uint32_t key_count, KEY *keyinfo,
1 by brian
clean slate
791
                      ulong data_offset)
792
{
482 by Brian Aker
Remove uint.
793
  uint32_t key_parts,length;
481 by Brian Aker
Remove all of uchar.
794
  unsigned char *pos, *keyname_pos;
1 by brian
clean slate
795
  KEY *key,*end;
796
  KEY_PART_INFO *key_part,*key_part_end;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
797
1 by brian
clean slate
798
799
  pos=keybuff+6;
800
  key_parts=0;
801
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
802
  {
803
    int2store(pos, (key->flags ^ HA_NOSAME));
804
    int2store(pos+2,key->key_length);
481 by Brian Aker
Remove all of uchar.
805
    pos[4]= (unsigned char) key->key_parts;
806
    pos[5]= (unsigned char) key->algorithm;
1 by brian
clean slate
807
    int2store(pos+6, key->block_size);
808
    pos+=8;
809
    key_parts+=key->key_parts;
810
    for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
811
	 key_part != key_part_end ;
812
	 key_part++)
813
814
    {
482 by Brian Aker
Remove uint.
815
      uint32_t offset;
1 by brian
clean slate
816
      int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
817
      offset= (uint) (key_part->offset+data_offset+1);
818
      int2store(pos+2, offset);
819
      pos[4]=0;					// Sort order
820
      int2store(pos+5,key_part->key_type);
821
      int2store(pos+7,key_part->length);
822
      pos+=9;
823
    }
824
  }
825
	/* Save keynames */
826
  keyname_pos=pos;
481 by Brian Aker
Remove all of uchar.
827
  *pos++=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
828
  for (key=keyinfo ; key != end ; key++)
829
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
830
    unsigned char *tmp=(unsigned char*) strcpy((char*) pos,key->name);
831
    tmp+= strlen(key->name);
481 by Brian Aker
Remove all of uchar.
832
    *tmp++= (unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
833
    *tmp=0;
834
    pos=tmp;
835
  }
836
  *(pos++)=0;
837
838
  for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
839
  {
840
    if (key->flags & HA_USES_COMMENT)
841
    {
842
      int2store(pos, key->comment.length);
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
843
      unsigned char *tmp= (unsigned char*)strncpy((char*) pos+2,key->comment.str,key->comment.length);
844
      tmp+= key->comment.length;
1 by brian
clean slate
845
      pos= tmp;
846
    }
847
  }
848
849
  if (key_count > 127 || key_parts > 127)
850
  {
851
    keybuff[0]= (key_count & 0x7f) | 0x80;
852
    keybuff[1]= key_count >> 7;
853
    int2store(keybuff+2,key_parts);
854
  }
855
  else
856
  {
481 by Brian Aker
Remove all of uchar.
857
    keybuff[0]=(unsigned char) key_count;
858
    keybuff[1]=(unsigned char) key_parts;
1 by brian
clean slate
859
    keybuff[2]= keybuff[3]= 0;
860
  }
861
  length=(uint) (pos-keyname_pos);
862
  int2store(keybuff+4,length);
51.2.2 by Patrick Galbraith
Removed DBUGs from
863
  return((uint) (pos-keybuff));
1 by brian
clean slate
864
} /* pack_keys */
865
866
77.1.45 by Monty Taylor
Warning fixes.
867
/* Make formheader */
1 by brian
clean slate
868
481 by Brian Aker
Remove all of uchar.
869
static bool pack_header(unsigned char *forminfo,
77.1.45 by Monty Taylor
Warning fixes.
870
                        List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
871
                        uint32_t info_length, uint32_t screens, uint32_t table_options,
1 by brian
clean slate
872
                        ulong data_offset, handler *file)
873
{
482 by Brian Aker
Remove uint.
874
  uint32_t length,int_count,int_length,no_empty, int_parts;
875
  uint32_t time_stamp_pos,null_fields;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
876
  ulong reclength, totlength, n_length, com_length, vcol_info_length;
77.1.45 by Monty Taylor
Warning fixes.
877
1 by brian
clean slate
878
879
  if (create_fields.elements > MAX_FIELDS)
880
  {
881
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
882
    return(1);
1 by brian
clean slate
883
  }
884
885
  totlength= 0L;
886
  reclength= data_offset;
887
  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
888
    com_length=vcol_info_length=0;
1 by brian
clean slate
889
  n_length=2L;
890
891
	/* Check fields */
892
893
  List_iterator<Create_field> it(create_fields);
894
  Create_field *field;
895
  while ((field=it++))
896
  {
482 by Brian Aker
Remove uint.
897
    uint32_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
1 by brian
clean slate
898
                                                     field->comment.str,
899
                                                     field->comment.str +
900
                                                     field->comment.length,
901
                                                     COLUMN_COMMENT_MAXLEN);
902
903
    if (tmp_len < field->comment.length)
904
    {
905
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
906
               field->comment.str,"COLUMN COMMENT",
907
               (uint) COLUMN_COMMENT_MAXLEN);
51.2.2 by Patrick Galbraith
Removed DBUGs from
908
      return(1);
1 by brian
clean slate
909
    }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
910
    if (field->vcol_info)
911
    {
912
      tmp_len= system_charset_info->cset->charpos(system_charset_info,
913
                                                  field->vcol_info->expr_str.str,
914
                                                  field->vcol_info->expr_str.str +
915
                                                  field->vcol_info->expr_str.length,
916
                                                  VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
917
918
      if (tmp_len < field->vcol_info->expr_str.length)
919
      {
920
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
921
                 field->vcol_info->expr_str.str,"VIRTUAL COLUMN EXPRESSION",
922
                 (uint) VIRTUAL_COLUMN_EXPRESSION_MAXLEN);
923
        return(1);
924
      }
925
      /*
926
        Sum up the length of the expression string and mandatory header bytes
927
        to the total length.
928
      */
929
      vcol_info_length+= field->vcol_info->expr_str.length+(uint)FRM_VCOL_HEADER_SIZE;
930
    }
1 by brian
clean slate
931
932
    totlength+= field->length;
933
    com_length+= field->comment.length;
934
    if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY ||
935
	field->unireg_check & MTYP_NOEMPTY_BIT)
936
    {
937
      field->unireg_check= (Field::utype) ((uint) field->unireg_check |
938
					   MTYP_NOEMPTY_BIT);
939
      no_empty++;
940
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
941
    /*
942
      We mark first TIMESTAMP field with NOW() in DEFAULT or ON UPDATE
1 by brian
clean slate
943
      as auto-update field.
944
    */
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
945
    if (field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1 by brian
clean slate
946
        MTYP_TYPENR(field->unireg_check) != Field::NONE &&
947
	!time_stamp_pos)
948
      time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1;
949
    length=field->pack_length;
950
    if ((uint) field->offset+ (uint) data_offset+ length > reclength)
951
      reclength=(uint) (field->offset+ data_offset + length);
952
    n_length+= (ulong) strlen(field->field_name)+1;
953
    field->interval_id=0;
954
    field->save_interval= 0;
955
    if (field->interval)
956
    {
482 by Brian Aker
Remove uint.
957
      uint32_t old_int_count=int_count;
1 by brian
clean slate
958
959
      if (field->charset->mbminlen > 1)
960
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
961
        /*
1 by brian
clean slate
962
          Escape UCS2 intervals using HEX notation to avoid
963
          problems with delimiters between enum elements.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
964
          As the original representation is still needed in
1 by brian
clean slate
965
          the function make_empty_rec to create a record of
966
          filled with default values it is saved in save_interval
967
          The HEX representation is created from this copy.
968
        */
969
        field->save_interval= field->interval;
970
        field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
971
        *field->interval= *field->save_interval;
972
        field->interval->type_names=
973
          (const char **) sql_alloc(sizeof(char*) *
1 by brian
clean slate
974
				    (field->interval->count+1));
975
        field->interval->type_names[field->interval->count]= 0;
976
        field->interval->type_lengths=
482 by Brian Aker
Remove uint.
977
          (uint32_t *) sql_alloc(sizeof(uint) * field->interval->count);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
978
482 by Brian Aker
Remove uint.
979
        for (uint32_t pos= 0; pos < field->interval->count; pos++)
1 by brian
clean slate
980
        {
981
          char *dst;
982
          const char *src= field->save_interval->type_names[pos];
482 by Brian Aker
Remove uint.
983
          uint32_t hex_length;
1 by brian
clean slate
984
          length= field->save_interval->type_lengths[pos];
985
          hex_length= length * 2;
986
          field->interval->type_lengths[pos]= hex_length;
987
          field->interval->type_names[pos]= dst= (char*) sql_alloc(hex_length +
988
                                                                   1);
989
          octet2hex(dst, src, length);
990
        }
991
      }
992
993
      field->interval_id=get_interval_id(&int_count,create_fields,field);
994
      if (old_int_count != int_count)
995
      {
996
	for (const char **pos=field->interval->type_names ; *pos ; pos++)
997
	  int_length+=(uint) strlen(*pos)+1;	// field + suffix prefix
998
	int_parts+=field->interval->count+1;
999
      }
1000
    }
1001
    if (f_maybe_null(field->pack_flag))
1002
      null_fields++;
1003
  }
1004
  int_length+=int_count*2;			// 255 prefix + 0 suffix
1005
1006
	/* Save values in forminfo */
1007
1008
  if (reclength > (ulong) file->max_record_length())
1009
  {
1010
    my_error(ER_TOO_BIG_ROWSIZE, MYF(0), (uint) file->max_record_length());
51.2.2 by Patrick Galbraith
Removed DBUGs from
1011
    return(1);
1 by brian
clean slate
1012
  }
1013
  /* Hack to avoid bugs with small static rows in MySQL */
398.1.4 by Monty Taylor
Renamed max/min.
1014
  reclength=cmax((ulong)file->min_record_length(table_options),reclength);
1 by brian
clean slate
1015
  if (info_length+(ulong) create_fields.elements*FCOMP+288+
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1016
      n_length+int_length+com_length+vcol_info_length > 65535L ||
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1017
      int_count > 255)
1 by brian
clean slate
1018
  {
1019
    my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
1020
    return(1);
1 by brian
clean slate
1021
  }
1022
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1023
  memset(forminfo, 0, 288);
1 by brian
clean slate
1024
  length=(info_length+create_fields.elements*FCOMP+288+n_length+int_length+
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1025
	  com_length+vcol_info_length);
1 by brian
clean slate
1026
  int2store(forminfo,length);
206 by Brian Aker
Removed final uint dead types.
1027
  forminfo[256] = (uint8_t) screens;
1 by brian
clean slate
1028
  int2store(forminfo+258,create_fields.elements);
1029
  int2store(forminfo+260,info_length);
1030
  int2store(forminfo+262,totlength);
1031
  int2store(forminfo+264,no_empty);
1032
  int2store(forminfo+266,reclength);
1033
  int2store(forminfo+268,n_length);
1034
  int2store(forminfo+270,int_count);
1035
  int2store(forminfo+272,int_parts);
1036
  int2store(forminfo+274,int_length);
1037
  int2store(forminfo+276,time_stamp_pos);
1038
  int2store(forminfo+278,80);			/* Columns needed */
1039
  int2store(forminfo+280,22);			/* Rows needed */
1040
  int2store(forminfo+282,null_fields);
1041
  int2store(forminfo+284,com_length);
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1042
  int2store(forminfo+286,vcol_info_length);
1043
  /* forminfo+288 is free to use for additional information */
51.2.2 by Patrick Galbraith
Removed DBUGs from
1044
  return(0);
1 by brian
clean slate
1045
} /* pack_header */
1046
1047
1048
	/* get each unique interval each own id */
1049
482 by Brian Aker
Remove uint.
1050
static uint32_t get_interval_id(uint32_t *int_count,List<Create_field> &create_fields,
1 by brian
clean slate
1051
			    Create_field *last_field)
1052
{
1053
  List_iterator<Create_field> it(create_fields);
1054
  Create_field *field;
1055
  TYPELIB *interval=last_field->interval;
1056
1057
  while ((field=it++) != last_field)
1058
  {
1059
    if (field->interval_id && field->interval->count == interval->count)
1060
    {
1061
      const char **a,**b;
1062
      for (a=field->interval->type_names, b=interval->type_names ;
1063
	   *a && !strcmp(*a,*b);
1064
	   a++,b++) ;
1065
1066
      if (! *a)
1067
      {
1068
	return field->interval_id;		// Re-use last interval
1069
      }
1070
    }
1071
  }
1072
  return ++*int_count;				// New unique interval
1073
}
1074
1075
1076
	/* Save fields, fieldnames and intervals */
1077
1078
static bool pack_fields(File file, List<Create_field> &create_fields,
1079
                        ulong data_offset)
1080
{
482 by Brian Aker
Remove uint.
1081
  register uint32_t i;
481.3.1 by Monty Taylor
Merged vcol stuff.
1082
  uint32_t int_count, comment_length=0, vcol_info_length=0;
481 by Brian Aker
Remove all of uchar.
1083
  unsigned char buff[MAX_FIELD_WIDTH];
1 by brian
clean slate
1084
  Create_field *field;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1085
1 by brian
clean slate
1086
1087
	/* Write field info */
1088
1089
  List_iterator<Create_field> it(create_fields);
1090
1091
  int_count=0;
1092
  while ((field=it++))
1093
  {
482 by Brian Aker
Remove uint.
1094
    uint32_t recpos;
481.3.1 by Monty Taylor
Merged vcol stuff.
1095
    uint32_t cur_vcol_expr_len= 0;
481 by Brian Aker
Remove all of uchar.
1096
    buff[0]= (unsigned char) field->row;
1097
    buff[1]= (unsigned char) field->col;
1098
    buff[2]= (unsigned char) field->sc_length;
1 by brian
clean slate
1099
    int2store(buff+3, field->length);
1100
    /* The +1 is here becasue the col offset in .frm file have offset 1 */
1101
    recpos= field->offset+1 + (uint) data_offset;
1102
    int3store(buff+5,recpos);
1103
    int2store(buff+8,field->pack_flag);
1104
    int2store(buff+10,field->unireg_check);
481 by Brian Aker
Remove all of uchar.
1105
    buff[12]= (unsigned char) field->interval_id;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1106
    buff[13]= (unsigned char) field->sql_type;
1107
    if (field->charset)
481 by Brian Aker
Remove all of uchar.
1108
      buff[14]= (unsigned char) field->charset->number;
1 by brian
clean slate
1109
    else
1110
      buff[14]= 0;				// Numerical
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1111
    if (field->vcol_info)
1112
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1113
      /*
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1114
        Use the interval_id place in the .frm file to store the length of
1115
        virtual field's data.
1116
      */
1117
      buff[12]= cur_vcol_expr_len= field->vcol_info->expr_str.length +
1118
                (uint)FRM_VCOL_HEADER_SIZE;
1119
      vcol_info_length+= cur_vcol_expr_len+(uint)FRM_VCOL_HEADER_SIZE;
481.3.1 by Monty Taylor
Merged vcol stuff.
1120
      buff[13]= (unsigned char) DRIZZLE_TYPE_VIRTUAL;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1121
    }
1 by brian
clean slate
1122
    int2store(buff+15, field->comment.length);
1123
    comment_length+= field->comment.length;
1124
    set_if_bigger(int_count,field->interval_id);
1125
    if (my_write(file, buff, FCOMP, MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1126
      return(1);
1 by brian
clean slate
1127
  }
1128
1129
	/* Write fieldnames */
481 by Brian Aker
Remove all of uchar.
1130
  buff[0]=(unsigned char) NAMES_SEP_CHAR;
1 by brian
clean slate
1131
  if (my_write(file, buff, 1, MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1132
    return(1);
1 by brian
clean slate
1133
  i=0;
1134
  it.rewind();
1135
  while ((field=it++))
1136
  {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
1137
    char *pos= strcpy((char*) buff,field->field_name);
1138
    pos+= strlen(field->field_name);
1 by brian
clean slate
1139
    *pos++=NAMES_SEP_CHAR;
1140
    if (i == create_fields.elements-1)
1141
      *pos++=0;
1142
    if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1143
      return(1);
1 by brian
clean slate
1144
    i++;
1145
  }
1146
1147
	/* Write intervals */
1148
  if (int_count)
1149
  {
1150
    String tmp((char*) buff,sizeof(buff), &my_charset_bin);
1151
    tmp.length(0);
1152
    it.rewind();
1153
    int_count=0;
1154
    while ((field=it++))
1155
    {
1156
      if (field->interval_id > int_count)
1157
      {
1158
        unsigned char  sep= 0;
1159
        unsigned char  occ[256];
482 by Brian Aker
Remove uint.
1160
        uint32_t           i;
1 by brian
clean slate
1161
        unsigned char *val= NULL;
1162
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
1163
        memset(occ, 0, sizeof(occ));
1 by brian
clean slate
1164
1165
        for (i=0; (val= (unsigned char*) field->interval->type_names[i]); i++)
482 by Brian Aker
Remove uint.
1166
          for (uint32_t j = 0; j < field->interval->type_lengths[i]; j++)
1 by brian
clean slate
1167
            occ[(unsigned int) (val[j])]= 1;
1168
1169
        if (!occ[(unsigned char)NAMES_SEP_CHAR])
1170
          sep= (unsigned char) NAMES_SEP_CHAR;
1171
        else if (!occ[(unsigned int)','])
1172
          sep= ',';
1173
        else
1174
        {
482 by Brian Aker
Remove uint.
1175
          for (uint32_t i=1; i<256; i++)
1 by brian
clean slate
1176
          {
1177
            if(!occ[i])
1178
            {
1179
              sep= i;
1180
              break;
1181
            }
1182
          }
1183
1184
          if(!sep)    /* disaster, enum uses all characters, none left as separator */
1185
          {
1186
            my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
1187
                       MYF(0));
51.2.2 by Patrick Galbraith
Removed DBUGs from
1188
            return(1);
1 by brian
clean slate
1189
          }
1190
        }
1191
1192
        int_count= field->interval_id;
1193
        tmp.append(sep);
1194
        for (const char **pos=field->interval->type_names ; *pos ; pos++)
1195
        {
1196
          tmp.append(*pos);
1197
          tmp.append(sep);
1198
        }
1199
        tmp.append('\0');                      // End of intervall
1200
      }
1201
    }
481 by Brian Aker
Remove all of uchar.
1202
    if (my_write(file,(unsigned char*) tmp.ptr(),tmp.length(),MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1203
      return(1);
1 by brian
clean slate
1204
  }
1205
  if (comment_length)
1206
  {
1207
    it.rewind();
1208
    int_count=0;
1209
    while ((field=it++))
1210
    {
1211
      if (field->comment.length)
481 by Brian Aker
Remove all of uchar.
1212
	if (my_write(file, (unsigned char*) field->comment.str, field->comment.length,
1 by brian
clean slate
1213
		     MYF_RW))
51.2.2 by Patrick Galbraith
Removed DBUGs from
1214
	  return(1);
1 by brian
clean slate
1215
    }
1216
  }
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1217
  if (vcol_info_length)
1218
  {
1219
    it.rewind();
1220
    int_count=0;
1221
    while ((field=it++))
1222
    {
1223
      /*
1224
        Pack each virtual field as follows:
1225
        byte 1      = 1 (always 1 to allow for future extensions)
1226
        byte 2      = sql_type
1227
        byte 3      = flags (as of now, 0 - no flags, 1 - field is physically stored)
1228
        byte 4-...  = virtual column expression (text data)
1229
      */
1230
      if (field->vcol_info && field->vcol_info->expr_str.length)
1231
      {
481.3.1 by Monty Taylor
Merged vcol stuff.
1232
        buff[0]= (unsigned char)1;
1233
        buff[1]= (unsigned char) field->sql_type;
1234
        buff[2]= (unsigned char) field->is_stored;
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1235
        if (my_write(file, buff, 3, MYF_RW))
1236
          return(1);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1237
        if (my_write(file,
1238
                     (unsigned char*) field->vcol_info->expr_str.str,
383.7.1 by Andrey Zhakov
Initial submit of code and tests
1239
                     field->vcol_info->expr_str.length,
1240
                     MYF_RW))
1241
          return(1);
1242
      }
1243
    }
1244
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1245
  return(0);
1 by brian
clean slate
1246
}
1247
1248
77.1.45 by Monty Taylor
Warning fixes.
1249
/* save an empty record on start of formfile */
1 by brian
clean slate
1250
520.1.22 by Brian Aker
Second pass of thd cleanup
1251
static bool make_empty_rec(Session *session, File file,
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
1252
                           enum legacy_db_type table_type __attribute__((unused)),
482 by Brian Aker
Remove uint.
1253
                           uint32_t table_options,
77.1.45 by Monty Taylor
Warning fixes.
1254
                           List<Create_field> &create_fields,
482 by Brian Aker
Remove uint.
1255
                           uint32_t reclength,
1 by brian
clean slate
1256
                           ulong data_offset,
1257
                           handler *handler)
1258
{
1259
  int error= 0;
1260
  Field::utype type;
482 by Brian Aker
Remove uint.
1261
  uint32_t null_count;
481 by Brian Aker
Remove all of uchar.
1262
  unsigned char *buff,*null_pos;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
1263
  Table table;
1 by brian
clean slate
1264
  TABLE_SHARE share;
1265
  Create_field *field;
520.1.22 by Brian Aker
Second pass of thd cleanup
1266
  enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1267
1 by brian
clean slate
1268
1269
  /* 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().
1270
  memset(&table, 0, sizeof(table));
1271
  memset(&share, 0, sizeof(share));
1 by brian
clean slate
1272
  table.s= &share;
1273
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1274
  if (!(buff=(unsigned char*) malloc((size_t) reclength)))
1 by brian
clean slate
1275
  {
51.2.2 by Patrick Galbraith
Removed DBUGs from
1276
    return(1);
1 by brian
clean slate
1277
  }
641.3.8 by Monty Taylor
Removed my_malloc from drizzled.
1278
  memset(buff, 0, (size_t) reclength);
1 by brian
clean slate
1279
520.1.22 by Brian Aker
Second pass of thd cleanup
1280
  table.in_use= session;
1 by brian
clean slate
1281
  table.s->db_low_byte_first= handler->low_byte_first();
1282
  table.s->blob_ptr_size= portable_sizeof_char_ptr;
1283
1284
  null_count=0;
1285
  if (!(table_options & HA_OPTION_PACK_RECORD))
1286
  {
1287
    null_count++;			// Need one bit for delete mark
1288
    *buff|= 1;
1289
  }
1290
  null_pos= buff;
1291
1292
  List_iterator<Create_field> it(create_fields);
520.1.22 by Brian Aker
Second pass of thd cleanup
1293
  session->count_cuted_fields= CHECK_FIELD_WARN;    // To find wrong default values
1 by brian
clean slate
1294
  while ((field=it++))
1295
  {
1296
    /*
1297
      regfield don't have to be deleted as it's allocated with sql_alloc()
1298
    */
1299
    Field *regfield= make_field(&share,
1300
                                buff+field->offset + data_offset,
1301
                                field->length,
1302
                                null_pos + null_count / 8,
1303
                                null_count & 7,
1304
                                field->pack_flag,
1305
                                field->sql_type,
1306
                                field->charset,
1307
                                field->unireg_check,
1308
                                field->save_interval ? field->save_interval :
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1309
                                field->interval,
1 by brian
clean slate
1310
                                field->field_name);
1311
    if (!regfield)
1312
    {
1313
      error= 1;
1314
      goto err;                                 // End of memory
1315
    }
1316
1317
    /* save_in_field() will access regfield->table->in_use */
1318
    regfield->init(&table);
1319
1320
    if (!(field->flags & NOT_NULL_FLAG))
1321
    {
1322
      *regfield->null_ptr|= regfield->null_bit;
1323
      null_count++;
1324
    }
1325
1326
    type= (Field::utype) MTYP_TYPENR(field->unireg_check);
1327
1328
    if (field->def)
1329
    {
1330
      int res= field->def->save_in_field(regfield, 1);
1331
      /* If not ok or warning of level 'note' */
1332
      if (res != 0 && res != 3)
1333
      {
1334
        my_error(ER_INVALID_DEFAULT, MYF(0), regfield->field_name);
1335
        error= 1;
1336
        delete regfield; //To avoid memory leak
1337
        goto err;
1338
      }
1339
    }
212.2.2 by Patrick Galbraith
Renamed FIELD_TYPE to DRIZZLE_TYPE
1340
    else if (regfield->real_type() == DRIZZLE_TYPE_ENUM &&
1 by brian
clean slate
1341
	     (field->flags & NOT_NULL_FLAG))
1342
    {
1343
      regfield->set_notnull();
163 by Brian Aker
Merge Monty's code.
1344
      regfield->store((int64_t) 1, true);
1 by brian
clean slate
1345
    }
1346
    else if (type == Field::YES)		// Old unireg type
1347
      regfield->store(ER(ER_YES),(uint) strlen(ER(ER_YES)),system_charset_info);
1348
    else if (type == Field::NO)			// Old unireg type
1349
      regfield->store(ER(ER_NO), (uint) strlen(ER(ER_NO)),system_charset_info);
1350
    else
1351
      regfield->reset();
1352
  }
51.2.2 by Patrick Galbraith
Removed DBUGs from
1353
  assert(data_offset == ((null_count + 7) / 8));
1 by brian
clean slate
1354
1355
  /*
1356
    We need to set the unused bits to 1. If the number of bits is a multiple
1357
    of 8 there are no unused bits.
1358
  */
1359
  if (null_count & 7)
481 by Brian Aker
Remove all of uchar.
1360
    *(null_pos + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1 by brian
clean slate
1361
1362
  error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0;
1363
1364
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.
1365
  free(buff);
520.1.22 by Brian Aker
Second pass of thd cleanup
1366
  session->count_cuted_fields= old_count_cuted_fields;
51.2.2 by Patrick Galbraith
Removed DBUGs from
1367
  return(error);
1 by brian
clean slate
1368
} /* make_empty_rec */