~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

  • Committer: Stewart Smith
  • Date: 2009-06-16 06:55:11 UTC
  • mto: This revision was merged to the branch mainline in revision 1094.
  • Revision ID: stewart@flamingspork.com-20090616065511-ps3ewfxj7918lwy3
rollback.test for MyISAM temp only.
- rename to myisam_rollback to reflect what it's testing
- just use create temporary table

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "config.h"
 
16
#include <drizzled/server_includes.h>
17
17
#include <drizzled/error.h>
18
18
#include <drizzled/session.h>
19
19
#include <drizzled/unireg.h>
20
 
#include "drizzled/sql_table.h"
21
 
#include "drizzled/global_charset_info.h"
22
 
#include "drizzled/message/statement_transform.h"
23
 
 
24
 
#include "drizzled/internal/my_sys.h"
25
 
 
26
20
 
27
21
/* For proto */
28
22
#include <string>
29
23
#include <fstream>
30
 
#include <fcntl.h>
31
24
#include <drizzled/message/schema.pb.h>
32
25
#include <drizzled/message/table.pb.h>
33
26
#include <google/protobuf/io/zero_copy_stream.h>
34
27
#include <google/protobuf/io/zero_copy_stream_impl.h>
35
 
#include <google/protobuf/message.h>
36
 
 
37
 
#include <drizzled/table_proto.h>
38
 
#include <drizzled/charset.h>
39
 
 
40
 
#include "drizzled/function/time/typecast.h"
41
 
 
42
28
using namespace std;
43
29
 
44
 
namespace drizzled {
45
 
 
46
 
static int fill_table_proto(message::Table &table_proto,
47
 
                            List<CreateField> &create_fields,
48
 
                            HA_CREATE_INFO *create_info,
49
 
                            uint32_t keys,
50
 
                            KeyInfo *key_info)
 
30
int drizzle_read_table_proto(const char* path, drizzled::message::Table* table)
 
31
{
 
32
  int fd= open(path, O_RDONLY);
 
33
 
 
34
  if(fd==-1)
 
35
    return errno;
 
36
 
 
37
  google::protobuf::io::ZeroCopyInputStream* input=
 
38
    new google::protobuf::io::FileInputStream(fd);
 
39
 
 
40
  if (!table->ParseFromZeroCopyStream(input))
 
41
  {
 
42
    delete input;
 
43
    close(fd);
 
44
    return -1;
 
45
  }
 
46
 
 
47
  delete input;
 
48
  close(fd);
 
49
  return 0;
 
50
}
 
51
 
 
52
static int fill_table_proto(drizzled::message::Table *table_proto,
 
53
                            const char *table_name,
 
54
                            List<CreateField> &create_fields,
 
55
                            HA_CREATE_INFO *create_info,
 
56
                            uint32_t keys,
 
57
                            KEY *key_info)
51
58
{
52
59
  CreateField *field_arg;
53
60
  List_iterator<CreateField> it(create_fields);
54
 
  message::Table::TableOptions *table_options= table_proto.mutable_options();
 
61
  drizzled::message::Table::StorageEngine *engine= table_proto->mutable_engine();
 
62
  drizzled::message::Table::TableOptions *table_options= table_proto->mutable_options();
55
63
 
56
64
  if (create_fields.elements > MAX_FIELDS)
57
65
  {
59
67
    return(1);
60
68
  }
61
69
 
62
 
  assert(strcmp(table_proto.engine().name().c_str(),
63
 
                create_info->db_type->getName().c_str())==0);
64
 
 
65
 
  int field_number= 0;
66
 
  bool use_existing_fields= table_proto.field_size() > 0;
 
70
  engine->set_name(create_info->db_type->getName());
 
71
 
 
72
  assert(strcmp(table_proto->name().c_str(),table_name)==0);
 
73
 
67
74
  while ((field_arg= it++))
68
75
  {
69
 
    message::Table::Field *attribute;
70
 
 
71
 
    /* some (one) code path for CREATE TABLE fills the proto
72
 
       out more than the others, so we already have partially
73
 
       filled out Field messages */
74
 
 
75
 
    if (use_existing_fields)
76
 
      attribute= table_proto.mutable_field(field_number++);
77
 
    else
78
 
    {
79
 
      /* Other code paths still have to fill out the proto */
80
 
      attribute= table_proto.add_field();
81
 
 
82
 
      if (field_arg->flags & NOT_NULL_FLAG)
83
 
      {
84
 
        message::Table::Field::FieldConstraints *constraints;
85
 
 
86
 
        constraints= attribute->mutable_constraints();
87
 
        constraints->set_is_nullable(false);
88
 
      }
89
 
 
90
 
      attribute->set_name(field_arg->field_name);
91
 
    }
92
 
 
93
 
    assert((!(field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_nullable());
94
 
    assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
95
 
 
96
 
 
97
 
    message::Table::Field::FieldType parser_type= attribute->type();
98
 
 
99
 
    if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
100
 
    {
101
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
102
 
      return -1;
103
 
    }
104
 
 
105
 
    attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
106
 
 
107
 
    switch (attribute->type()) {
108
 
    default: /* Only deal with types that need extra information */
109
 
      break;
110
 
    case message::Table::Field::DOUBLE:
111
 
      {
112
 
        /*
113
 
         * For DOUBLE, we only add a specific scale and precision iff
114
 
         * the fixed decimal point has been specified...
115
 
         */
116
 
        if (field_arg->decimals != NOT_FIXED_DEC)
117
 
        {
118
 
          message::Table::Field::NumericFieldOptions *numeric_field_options;
119
 
 
120
 
          numeric_field_options= attribute->mutable_numeric_options();
121
 
 
122
 
          numeric_field_options->set_precision(field_arg->length);
123
 
          numeric_field_options->set_scale(field_arg->decimals);
124
 
        }
125
 
      }
126
 
      break;
127
 
    case message::Table::Field::VARCHAR:
128
 
      {
129
 
        message::Table::Field::StringFieldOptions *string_field_options;
 
76
    drizzled::message::Table::Field *attribute;
 
77
 
 
78
    attribute= table_proto->add_field();
 
79
    attribute->set_name(field_arg->field_name);
 
80
 
 
81
    attribute->set_pack_flag(field_arg->pack_flag); /* TODO: MUST DIE */
 
82
 
 
83
    if(f_maybe_null(field_arg->pack_flag))
 
84
    {
 
85
      drizzled::message::Table::Field::FieldConstraints *constraints;
 
86
 
 
87
      constraints= attribute->mutable_constraints();
 
88
      constraints->set_is_nullable(true);
 
89
    }
 
90
 
 
91
    switch (field_arg->sql_type) {
 
92
    case DRIZZLE_TYPE_TINY:
 
93
      attribute->set_type(drizzled::message::Table::Field::TINYINT);
 
94
      break;
 
95
    case DRIZZLE_TYPE_LONG:
 
96
      attribute->set_type(drizzled::message::Table::Field::INTEGER);
 
97
      break;
 
98
    case DRIZZLE_TYPE_DOUBLE:
 
99
      attribute->set_type(drizzled::message::Table::Field::DOUBLE);
 
100
      break;
 
101
    case DRIZZLE_TYPE_NULL  :
 
102
      assert(1); /* Not a user definable type */
 
103
    case DRIZZLE_TYPE_TIMESTAMP:
 
104
      attribute->set_type(drizzled::message::Table::Field::TIMESTAMP);
 
105
      break;
 
106
    case DRIZZLE_TYPE_LONGLONG:
 
107
      attribute->set_type(drizzled::message::Table::Field::BIGINT);
 
108
      break;
 
109
    case DRIZZLE_TYPE_DATETIME:
 
110
      attribute->set_type(drizzled::message::Table::Field::DATETIME);
 
111
      break;
 
112
    case DRIZZLE_TYPE_DATE:
 
113
      attribute->set_type(drizzled::message::Table::Field::DATE);
 
114
      break;
 
115
    case DRIZZLE_TYPE_VARCHAR:
 
116
      {
 
117
        drizzled::message::Table::Field::StringFieldOptions *string_field_options;
130
118
 
131
119
        string_field_options= attribute->mutable_string_options();
132
 
 
133
 
        if (! use_existing_fields || string_field_options->length()==0)
134
 
          string_field_options->set_length(field_arg->length
135
 
                                           / field_arg->charset->mbmaxlen);
136
 
        else
137
 
          assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
138
 
 
139
 
        if (! string_field_options->has_collation())
140
 
        {
141
 
          string_field_options->set_collation_id(field_arg->charset->number);
142
 
          string_field_options->set_collation(field_arg->charset->name);
143
 
        }
 
120
        attribute->set_type(drizzled::message::Table::Field::VARCHAR);
 
121
        string_field_options->set_length(field_arg->length
 
122
                                         / field_arg->charset->mbmaxlen);
 
123
        string_field_options->set_collation_id(field_arg->charset->number);
 
124
        string_field_options->set_collation(field_arg->charset->name);
 
125
 
144
126
        break;
145
127
      }
146
 
    case message::Table::Field::DECIMAL:
 
128
    case DRIZZLE_TYPE_NEWDECIMAL:
147
129
      {
148
 
        message::Table::Field::NumericFieldOptions *numeric_field_options;
 
130
        drizzled::message::Table::Field::NumericFieldOptions *numeric_field_options;
149
131
 
 
132
        attribute->set_type(drizzled::message::Table::Field::DECIMAL);
150
133
        numeric_field_options= attribute->mutable_numeric_options();
151
134
        /* This is magic, I hate magic numbers -Brian */
152
135
        numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
153
136
        numeric_field_options->set_scale(field_arg->decimals);
154
137
        break;
155
138
      }
156
 
    case message::Table::Field::ENUM:
 
139
    case DRIZZLE_TYPE_ENUM:
157
140
      {
158
 
        message::Table::Field::EnumerationValues *enumeration_options;
 
141
        drizzled::message::Table::Field::SetFieldOptions *set_field_options;
159
142
 
160
143
        assert(field_arg->interval);
161
144
 
162
 
        enumeration_options= attribute->mutable_enumeration_values();
 
145
        attribute->set_type(drizzled::message::Table::Field::ENUM);
 
146
        set_field_options= attribute->mutable_set_options();
163
147
 
164
148
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
165
149
        {
166
150
          const char *src= field_arg->interval->type_names[pos];
167
151
 
168
 
          enumeration_options->add_field_value(src);
 
152
          set_field_options->add_field_value(src);
169
153
        }
170
 
        enumeration_options->set_collation_id(field_arg->charset->number);
171
 
        enumeration_options->set_collation(field_arg->charset->name);
 
154
        set_field_options->set_count_elements(set_field_options->field_value_size());
 
155
        set_field_options->set_collation_id(field_arg->charset->number);
 
156
        set_field_options->set_collation(field_arg->charset->name);
172
157
        break;
173
158
      }
174
 
    case message::Table::Field::BLOB:
 
159
    case DRIZZLE_TYPE_BLOB:
175
160
      {
176
 
        message::Table::Field::StringFieldOptions *string_field_options;
 
161
        attribute->set_type(drizzled::message::Table::Field::BLOB);
 
162
 
 
163
        drizzled::message::Table::Field::StringFieldOptions *string_field_options;
177
164
 
178
165
        string_field_options= attribute->mutable_string_options();
179
166
        string_field_options->set_collation_id(field_arg->charset->number);
181
168
      }
182
169
 
183
170
      break;
 
171
    default:
 
172
      assert(0); /* Tell us, since this shouldn't happend */
184
173
    }
185
174
 
186
 
    assert (!use_existing_fields || parser_type == attribute->type());
187
 
 
188
175
#ifdef NOTDONE
189
176
    field_constraints= attribute->mutable_constraints();
190
177
    constraints->set_is_nullable(field_arg->def->null_value);
191
178
#endif
192
179
 
 
180
    switch(field_arg->column_format())
 
181
    {
 
182
    case COLUMN_FORMAT_TYPE_NOT_USED:
 
183
      break;
 
184
    case COLUMN_FORMAT_TYPE_DEFAULT:
 
185
      attribute->set_format(drizzled::message::Table::Field::DefaultFormat);
 
186
      break;
 
187
    case COLUMN_FORMAT_TYPE_FIXED:
 
188
      attribute->set_format(drizzled::message::Table::Field::FixedFormat);
 
189
      break;
 
190
    case COLUMN_FORMAT_TYPE_DYNAMIC:
 
191
      attribute->set_format(drizzled::message::Table::Field::DynamicFormat);
 
192
      break;
 
193
    default:
 
194
      assert(0); /* Tell us, since this shouldn't happend */
 
195
    }
 
196
 
193
197
    if (field_arg->comment.length)
194
198
    {
195
199
      uint32_t tmp_len;
207
211
        return(1);
208
212
      }
209
213
 
210
 
      if (! use_existing_fields)
211
 
        attribute->set_comment(field_arg->comment.str);
212
 
 
213
 
      assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
 
214
      attribute->set_comment(field_arg->comment.str);
214
215
    }
215
216
 
216
 
    if (field_arg->unireg_check == Field::NEXT_NUMBER)
 
217
    if(field_arg->unireg_check == Field::NEXT_NUMBER)
217
218
    {
218
 
      message::Table::Field::NumericFieldOptions *field_options;
 
219
      drizzled::message::Table::Field::NumericFieldOptions *field_options;
219
220
      field_options= attribute->mutable_numeric_options();
220
221
      field_options->set_is_autoincrement(true);
221
222
    }
222
223
 
223
 
    if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
224
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
225
 
    {
226
 
      message::Table::Field::FieldOptions *field_options;
227
 
      field_options= attribute->mutable_options();
228
 
      field_options->set_default_expression("CURRENT_TIMESTAMP");
229
 
    }
230
 
 
231
 
    if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
232
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
233
 
    {
234
 
      message::Table::Field::FieldOptions *field_options;
235
 
      field_options= attribute->mutable_options();
236
 
      field_options->set_update_expression("CURRENT_TIMESTAMP");
237
 
    }
238
 
 
239
 
    if (field_arg->def == NULL  && attribute->constraints().is_nullable())
240
 
    {
241
 
      message::Table::Field::FieldOptions *field_options;
242
 
      field_options= attribute->mutable_options();
243
 
 
244
 
      field_options->set_default_null(true);
245
 
    }
246
 
    if (field_arg->def)
247
 
    {
248
 
      message::Table::Field::FieldOptions *field_options;
249
 
      field_options= attribute->mutable_options();
250
 
 
251
 
      if (field_arg->def->is_null())
 
224
    if(field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
 
225
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
 
226
    {
 
227
      drizzled::message::Table::Field::FieldOptions *field_options;
 
228
      field_options= attribute->mutable_options();
 
229
      field_options->set_default_value("NOW()");
 
230
    }
 
231
 
 
232
    if(field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
 
233
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
 
234
    {
 
235
      drizzled::message::Table::Field::FieldOptions *field_options;
 
236
      field_options= attribute->mutable_options();
 
237
      field_options->set_update_value("NOW()");
 
238
    }
 
239
 
 
240
    if(field_arg->def)
 
241
    {
 
242
      drizzled::message::Table::Field::FieldOptions *field_options;
 
243
      field_options= attribute->mutable_options();
 
244
 
 
245
      if(field_arg->def->is_null())
252
246
      {
253
247
        field_options->set_default_null(true);
254
248
      }
259
253
 
260
254
        assert(default_value);
261
255
 
262
 
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
 
256
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
263
257
           || field_arg->sql_type==DRIZZLE_TYPE_BLOB)
264
258
           && ((field_arg->length / field_arg->charset->mbmaxlen)
265
259
           < default_value->length()))
268
262
          return 1;
269
263
        }
270
264
 
271
 
        if (field_arg->sql_type == DRIZZLE_TYPE_DATE
272
 
            || field_arg->sql_type == DRIZZLE_TYPE_DATETIME
273
 
            || field_arg->sql_type == DRIZZLE_TYPE_TIMESTAMP)
274
 
        {
275
 
          DRIZZLE_TIME ltime;
276
 
 
277
 
          if (field_arg->def->get_date(&ltime, TIME_FUZZY_DATE))
278
 
          {
279
 
            my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
280
 
                     default_value->c_str());
281
 
            return 1;
282
 
          }
283
 
 
284
 
          /* We now do the casting down to the appropriate type.
285
 
 
286
 
             Yes, this implicit casting is balls.
287
 
             It was previously done on reading the proto back in,
288
 
             but we really shouldn't store the bogus things in the proto,
289
 
             and instead do the casting behaviour here.
290
 
 
291
 
             the timestamp errors are taken care of elsewhere.
292
 
          */
293
 
 
294
 
          if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
295
 
          {
296
 
            Item *typecast= new Item_datetime_typecast(field_arg->def);
297
 
            typecast->quick_fix_field();
298
 
            typecast->val_str(default_value);
299
 
          }
300
 
          else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
301
 
          {
302
 
            Item *typecast= new Item_date_typecast(field_arg->def);
303
 
            typecast->quick_fix_field();
304
 
            typecast->val_str(default_value);
305
 
          }
306
 
        }
307
 
 
308
 
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
 
265
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
309
266
            && field_arg->charset==&my_charset_bin)
310
267
           || (field_arg->sql_type==DRIZZLE_TYPE_BLOB
311
268
            && field_arg->charset==&my_charset_bin))
322
279
      }
323
280
    }
324
281
 
 
282
    {
 
283
      drizzled::message::Table::Field::FieldOptions *field_options;
 
284
      field_options= attribute->mutable_options();
 
285
 
 
286
      field_options->set_length(field_arg->length);
 
287
    }
 
288
 
325
289
    assert(field_arg->unireg_check == Field::NONE
326
290
           || field_arg->unireg_check == Field::NEXT_NUMBER
327
291
           || field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
330
294
 
331
295
  }
332
296
 
333
 
  assert(! use_existing_fields || (field_number == table_proto.field_size()));
334
 
 
335
 
  if (create_info->table_options & HA_OPTION_PACK_RECORD)
336
 
    table_options->set_pack_record(true);
337
 
 
338
 
  if (table_options->has_comment() && table_options->comment().length() == 0)
339
 
    table_options->clear_comment();
340
 
 
341
 
  if (table_options->has_comment())
 
297
  if (create_info->used_fields & HA_CREATE_USED_PACK_KEYS)
 
298
  {
 
299
    if(create_info->table_options & HA_OPTION_PACK_KEYS)
 
300
      table_options->set_pack_keys(true);
 
301
    else if(create_info->table_options & HA_OPTION_NO_PACK_KEYS)
 
302
      table_options->set_pack_keys(false);
 
303
  }
 
304
  else
 
305
    if(create_info->table_options & HA_OPTION_PACK_KEYS)
 
306
      table_options->set_pack_keys(true);
 
307
 
 
308
 
 
309
  if (create_info->used_fields & HA_CREATE_USED_CHECKSUM)
 
310
  {
 
311
    assert(create_info->table_options & (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM));
 
312
 
 
313
    if(create_info->table_options & HA_OPTION_CHECKSUM)
 
314
      table_options->set_checksum(true);
 
315
    else
 
316
      table_options->set_checksum(false);
 
317
  }
 
318
  else if(create_info->table_options & HA_OPTION_CHECKSUM)
 
319
    table_options->set_checksum(true);
 
320
 
 
321
 
 
322
  if (create_info->used_fields & HA_CREATE_USED_PAGE_CHECKSUM)
 
323
  {
 
324
    if (create_info->page_checksum == HA_CHOICE_YES)
 
325
      table_options->set_page_checksum(true);
 
326
    else if (create_info->page_checksum == HA_CHOICE_NO)
 
327
      table_options->set_page_checksum(false);
 
328
  }
 
329
  else if (create_info->page_checksum == HA_CHOICE_YES)
 
330
    table_options->set_page_checksum(true);
 
331
 
 
332
 
 
333
  if (create_info->used_fields & HA_CREATE_USED_DELAY_KEY_WRITE)
 
334
  {
 
335
    if(create_info->table_options & HA_OPTION_DELAY_KEY_WRITE)
 
336
      table_options->set_delay_key_write(true);
 
337
    else if(create_info->table_options & HA_OPTION_NO_DELAY_KEY_WRITE)
 
338
      table_options->set_delay_key_write(false);
 
339
  }
 
340
  else if(create_info->table_options & HA_OPTION_DELAY_KEY_WRITE)
 
341
    table_options->set_delay_key_write(true);
 
342
 
 
343
 
 
344
  switch(create_info->row_type)
 
345
  {
 
346
  case ROW_TYPE_DEFAULT:
 
347
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_DEFAULT);
 
348
    break;
 
349
  case ROW_TYPE_FIXED:
 
350
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_FIXED);
 
351
    break;
 
352
  case ROW_TYPE_DYNAMIC:
 
353
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_DYNAMIC);
 
354
    break;
 
355
  case ROW_TYPE_COMPRESSED:
 
356
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_COMPRESSED);
 
357
    break;
 
358
  case ROW_TYPE_REDUNDANT:
 
359
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_REDUNDANT);
 
360
    break;
 
361
  case ROW_TYPE_COMPACT:
 
362
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_COMPACT);
 
363
    break;
 
364
  case ROW_TYPE_PAGE:
 
365
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_PAGE);
 
366
    break;
 
367
  default:
 
368
    abort();
 
369
  }
 
370
 
 
371
  table_options->set_pack_record(create_info->table_options
 
372
                                 & HA_OPTION_PACK_RECORD);
 
373
 
 
374
  if (create_info->comment.length)
342
375
  {
343
376
    uint32_t tmp_len;
344
377
    tmp_len= system_charset_info->cset->charpos(system_charset_info,
345
 
                                                table_options->comment().c_str(),
346
 
                                                table_options->comment().c_str() +
347
 
                                                table_options->comment().length(),
348
 
                                                TABLE_COMMENT_MAXLEN);
 
378
                                                create_info->comment.str,
 
379
                                                create_info->comment.str +
 
380
                                                create_info->comment.length,
 
381
                                                TABLE_COMMENT_MAXLEN);
349
382
 
350
 
    if (tmp_len < table_options->comment().length())
 
383
    if (tmp_len < create_info->comment.length)
351
384
    {
352
385
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
353
 
               table_options->comment().c_str(),"Table COMMENT",
354
 
               (uint32_t) TABLE_COMMENT_MAXLEN);
 
386
               create_info->comment.str,"Table COMMENT",
 
387
               (uint32_t) TABLE_COMMENT_MAXLEN);
355
388
      return(1);
356
389
    }
 
390
 
 
391
    table_options->set_comment(create_info->comment.str);
357
392
  }
358
 
 
359
393
  if (create_info->default_table_charset)
360
394
  {
361
395
    table_options->set_collation_id(
363
397
    table_options->set_collation(create_info->default_table_charset->name);
364
398
  }
365
399
 
366
 
  if (create_info->used_fields & HA_CREATE_USED_AUTO)
367
 
    table_options->set_has_user_set_auto_increment_value(true);
368
 
  else
369
 
    table_options->set_has_user_set_auto_increment_value(false);
 
400
  if (create_info->connect_string.length)
 
401
    table_options->set_connect_string(create_info->connect_string.str);
 
402
 
 
403
  if (create_info->data_file_name)
 
404
    table_options->set_data_file_name(create_info->data_file_name);
 
405
 
 
406
  if (create_info->index_file_name)
 
407
    table_options->set_index_file_name(create_info->index_file_name);
 
408
 
 
409
  if (create_info->max_rows)
 
410
    table_options->set_max_rows(create_info->max_rows);
 
411
 
 
412
  if (create_info->min_rows)
 
413
    table_options->set_min_rows(create_info->min_rows);
370
414
 
371
415
  if (create_info->auto_increment_value)
372
416
    table_options->set_auto_increment_value(create_info->auto_increment_value);
373
417
 
374
 
  for (uint32_t i= 0; i < keys; i++)
 
418
  if (create_info->avg_row_length)
 
419
    table_options->set_avg_row_length(create_info->avg_row_length);
 
420
 
 
421
  if (create_info->key_block_size)
 
422
    table_options->set_key_block_size(create_info->key_block_size);
 
423
 
 
424
  if (create_info->block_size)
 
425
    table_options->set_block_size(create_info->block_size);
 
426
 
 
427
  for (unsigned int i= 0; i < keys; i++)
375
428
  {
376
 
    message::Table::Index *idx;
 
429
    drizzled::message::Table::Index *idx;
377
430
 
378
 
    idx= table_proto.add_indexes();
 
431
    idx= table_proto->add_indexes();
379
432
 
380
433
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
381
434
           (key_info[i].comment.length > 0));
384
437
 
385
438
    idx->set_key_length(key_info[i].key_length);
386
439
 
387
 
    if (is_primary_key_name(key_info[i].name))
 
440
    if(is_primary_key_name(key_info[i].name))
388
441
      idx->set_is_primary(true);
389
442
    else
390
443
      idx->set_is_primary(false);
392
445
    switch(key_info[i].algorithm)
393
446
    {
394
447
    case HA_KEY_ALG_HASH:
395
 
      idx->set_type(message::Table::Index::HASH);
 
448
      idx->set_type(drizzled::message::Table::Index::HASH);
396
449
      break;
397
450
 
398
451
    case HA_KEY_ALG_BTREE:
399
 
      idx->set_type(message::Table::Index::BTREE);
 
452
      idx->set_type(drizzled::message::Table::Index::BTREE);
400
453
      break;
401
454
 
 
455
    case HA_KEY_ALG_RTREE:
 
456
      idx->set_type(drizzled::message::Table::Index::RTREE);
 
457
    case HA_KEY_ALG_FULLTEXT:
 
458
      idx->set_type(drizzled::message::Table::Index::FULLTEXT);
402
459
    case HA_KEY_ALG_UNDEF:
403
 
      idx->set_type(message::Table::Index::UNKNOWN_INDEX);
 
460
      idx->set_type(drizzled::message::Table::Index::UNKNOWN_INDEX);
404
461
      break;
405
462
 
406
463
    default:
412
469
    else
413
470
      idx->set_is_unique(false);
414
471
 
415
 
    message::Table::Index::Options *index_options= idx->mutable_options();
 
472
    drizzled::message::Table::Index::IndexOptions *index_options= idx->mutable_options();
416
473
 
417
 
    if (key_info[i].flags & HA_USES_BLOCK_SIZE)
 
474
    if(key_info[i].flags & HA_USES_BLOCK_SIZE)
418
475
      index_options->set_key_block_size(key_info[i].block_size);
419
476
 
420
 
    if (key_info[i].flags & HA_PACK_KEY)
 
477
    if(key_info[i].flags & HA_PACK_KEY)
421
478
      index_options->set_pack_key(true);
422
479
 
423
 
    if (key_info[i].flags & HA_BINARY_PACK_KEY)
 
480
    if(key_info[i].flags & HA_BINARY_PACK_KEY)
424
481
      index_options->set_binary_pack_key(true);
425
482
 
426
 
    if (key_info[i].flags & HA_VAR_LENGTH_PART)
 
483
    if(key_info[i].flags & HA_VAR_LENGTH_PART)
427
484
      index_options->set_var_length_key(true);
428
485
 
429
 
    if (key_info[i].flags & HA_NULL_PART_KEY)
 
486
    if(key_info[i].flags & HA_NULL_PART_KEY)
430
487
      index_options->set_null_part_key(true);
431
488
 
432
 
    if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
 
489
    if(key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
433
490
      index_options->set_has_partial_segments(true);
434
491
 
435
 
    if (key_info[i].flags & HA_GENERATED_KEY)
 
492
    if(key_info[i].flags & HA_GENERATED_KEY)
436
493
      index_options->set_auto_generated_key(true);
437
494
 
438
495
    if (key_info[i].flags & HA_USES_COMMENT)
454
511
 
455
512
      idx->set_comment(key_info[i].comment.str);
456
513
    }
457
 
    static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
458
 
                                               HA_USES_BLOCK_SIZE | 
459
 
                                               HA_BINARY_PACK_KEY |
460
 
                                               HA_VAR_LENGTH_PART |
461
 
                                               HA_NULL_PART_KEY | 
462
 
                                               HA_KEY_HAS_PART_KEY_SEG |
463
 
                                               HA_GENERATED_KEY |
464
 
                                               HA_USES_COMMENT);
465
 
    if (key_info[i].flags & ~unknown_index_flag)
 
514
    if(key_info[i].flags & ~(HA_NOSAME | HA_PACK_KEY | HA_USES_BLOCK_SIZE | HA_BINARY_PACK_KEY | HA_VAR_LENGTH_PART | HA_NULL_PART_KEY | HA_KEY_HAS_PART_KEY_SEG | HA_GENERATED_KEY | HA_USES_COMMENT))
466
515
      abort(); // Invalid (unknown) index flag.
467
516
 
468
517
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
469
518
    {
470
 
      message::Table::Index::IndexPart *idxpart;
471
 
      const int fieldnr= key_info[i].key_part[j].fieldnr;
472
 
      int mbmaxlen= 1;
 
519
      drizzled::message::Table::Index::IndexPart *idxpart;
473
520
 
474
521
      idxpart= idx->add_index_part();
475
522
 
476
 
      idxpart->set_fieldnr(fieldnr);
477
 
 
478
 
      if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
479
 
          || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
480
 
      {
481
 
        uint32_t collation_id;
482
 
 
483
 
        if (table_proto.field(fieldnr).string_options().has_collation_id())
484
 
          collation_id= table_proto.field(fieldnr).string_options().collation_id();
485
 
        else
486
 
          collation_id= table_proto.options().collation_id();
487
 
 
488
 
        const CHARSET_INFO *cs= get_charset(collation_id);
489
 
 
490
 
        mbmaxlen= cs->mbmaxlen;
491
 
      }
492
 
 
493
 
      idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
494
 
    }
495
 
  }
496
 
 
497
 
  if (not table_proto.IsInitialized())
498
 
  {
499
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), table_proto.InitializationErrorString().c_str());
500
 
    return 1;
501
 
  }
502
 
 
503
 
  /*
504
 
    Here we test to see if we can validate the Table Message before we continue. 
505
 
    We do this by serializing the protobuffer.
506
 
  */
507
 
  {
508
 
    string tmp_string;
509
 
 
510
 
    try {
511
 
      table_proto.SerializeToString(&tmp_string);
512
 
    }
513
 
 
514
 
    catch (...)
515
 
    {
516
 
      my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
517
 
               table_proto.InitializationErrorString().empty() ? "": table_proto.InitializationErrorString().c_str());
518
 
 
519
 
      return 1;
520
 
    }
521
 
  }
522
 
 
 
523
      idxpart->set_fieldnr(key_info[i].key_part[j].fieldnr);
 
524
 
 
525
      idxpart->set_compare_length(key_info[i].key_part[j].length);
 
526
 
 
527
      idxpart->set_key_type(key_info[i].key_part[j].key_type);
 
528
 
 
529
    }
 
530
  }
 
531
 
 
532
  return 0;
 
533
}
 
534
 
 
535
int copy_table_proto_file(const char *from, const char* to)
 
536
{
 
537
  string dfesrc(from);
 
538
  string dfedst(to);
 
539
  string file_ext = ".dfe";
 
540
 
 
541
  dfesrc.append(file_ext);
 
542
  dfedst.append(file_ext);
 
543
 
 
544
  return my_copy(dfesrc.c_str(), dfedst.c_str(),
 
545
                 MYF(MY_DONT_OVERWRITE_FILE));
 
546
}
 
547
 
 
548
int rename_table_proto_file(const char *from, const char* to)
 
549
{
 
550
  string from_path(from);
 
551
  string to_path(to);
 
552
  string file_ext = ".dfe";
 
553
 
 
554
  from_path.append(file_ext);
 
555
  to_path.append(file_ext);
 
556
 
 
557
  return my_rename(from_path.c_str(),to_path.c_str(),MYF(MY_WME));
 
558
}
 
559
 
 
560
int delete_table_proto_file(const char *file_name)
 
561
{
 
562
  string new_path(file_name);
 
563
  string file_ext = ".dfe";
 
564
 
 
565
  new_path.append(file_ext);
 
566
  return my_delete(new_path.c_str(), MYF(0));
 
567
}
 
568
 
 
569
int table_proto_exists(const char *path)
 
570
{
 
571
  string proto_path(path);
 
572
  string file_ext(".dfe");
 
573
  proto_path.append(file_ext);
 
574
 
 
575
  int error= access(proto_path.c_str(), F_OK);
 
576
 
 
577
  if (error == 0)
 
578
    return EEXIST;
 
579
  else
 
580
    return errno;
 
581
}
 
582
 
 
583
static int create_table_proto_file(const char *file_name,
 
584
                                   const char *db,
 
585
                                   const char *table_name,
 
586
                                   drizzled::message::Table *table_proto,
 
587
                                   HA_CREATE_INFO *create_info,
 
588
                                   List<CreateField> &create_fields,
 
589
                                   uint32_t keys,
 
590
                                   KEY *key_info)
 
591
{
 
592
  string new_path(file_name);
 
593
  string file_ext = ".dfe";
 
594
 
 
595
  if(fill_table_proto(table_proto, table_name, create_fields, create_info,
 
596
                      keys, key_info))
 
597
    return -1;
 
598
 
 
599
  new_path.append(file_ext);
 
600
 
 
601
  int fd= open(new_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, my_umask);
 
602
 
 
603
  if(fd==-1)
 
604
  {
 
605
    if(errno==ENOENT)
 
606
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
607
    else
 
608
      my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,errno);
 
609
    return errno;
 
610
  }
 
611
 
 
612
  google::protobuf::io::ZeroCopyOutputStream* output=
 
613
    new google::protobuf::io::FileOutputStream(fd);
 
614
 
 
615
  if (!table_proto->SerializeToZeroCopyStream(output))
 
616
  {
 
617
    delete output;
 
618
    close(fd);
 
619
    return errno;
 
620
  }
 
621
 
 
622
  delete output;
 
623
  close(fd);
523
624
  return 0;
524
625
}
525
626
 
536
637
    create_fields       Fields to create
537
638
    keys                number of keys to create
538
639
    key_info            Keys to create
 
640
    file                Handler to use
 
641
    is_like             is true for mysql_create_like_schema_frm
539
642
 
540
643
  RETURN
541
644
    0  ok
542
645
    1  error
543
646
*/
544
647
 
545
 
bool rea_create_table(Session *session,
546
 
                      const TableIdentifier &identifier,
547
 
                      message::Table &table_proto,
548
 
                      HA_CREATE_INFO *create_info,
549
 
                      List<CreateField> &create_fields,
550
 
                      uint32_t keys, KeyInfo *key_info)
 
648
int rea_create_table(Session *session, const char *path,
 
649
                     const char *db, const char *table_name,
 
650
                     drizzled::message::Table *table_proto,
 
651
                     HA_CREATE_INFO *create_info,
 
652
                     List<CreateField> &create_fields,
 
653
                     uint32_t keys, KEY *key_info,
 
654
                     bool is_like)
551
655
{
552
 
  assert(table_proto.has_name());
553
 
  if (fill_table_proto(table_proto, create_fields, create_info,
554
 
                       keys, key_info))
555
 
    return false;
556
 
 
557
 
  assert(table_proto.name() == identifier.getTableName());
558
 
 
559
 
  if (plugin::StorageEngine::createTable(*session,
560
 
                                         identifier,
561
 
                                         table_proto))
562
 
  {
563
 
    return false;
564
 
  }
565
 
 
566
 
  return true;
567
 
 
 
656
  /* Proto will blow up unless we give a name */
 
657
  assert(table_name);
 
658
 
 
659
  /* For is_like we return once the file has been created */
 
660
  if (is_like)
 
661
  {
 
662
    if (create_table_proto_file(path, db, table_name, table_proto,
 
663
                                create_info,
 
664
                                create_fields, keys, key_info)!=0)
 
665
      return 1;
 
666
 
 
667
    return 0;
 
668
  }
 
669
  /* Here we need to build the full frm from the path */
 
670
  else
 
671
  {
 
672
    if (create_table_proto_file(path, db, table_name, table_proto,
 
673
                                create_info,
 
674
                                create_fields, keys, key_info))
 
675
      return 1;
 
676
  }
 
677
 
 
678
  // Make sure mysql_create_frm din't remove extension
 
679
  if (session->variables.keep_files_on_create)
 
680
    create_info->options|= HA_CREATE_KEEP_FILES;
 
681
 
 
682
  if (ha_create_table(session, path, db, table_name,
 
683
                      create_info,0))
 
684
    goto err_handler;
 
685
  return 0;
 
686
 
 
687
err_handler:
 
688
  delete_table_proto_file(path);
 
689
 
 
690
  return 1;
568
691
} /* rea_create_table */
569
 
 
570
 
} /* namespace drizzled */
571