~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

  • Committer: Brian Aker
  • Date: 2009-05-20 23:51:08 UTC
  • mfrom: (1022.2.18 mordred)
  • Revision ID: brian@gaz-20090520235108-nb5he1em112798pb
Merge Monty

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)
51
 
{
52
 
  CreateField *field_arg;
53
 
  List_iterator<CreateField> it(create_fields);
54
 
  message::Table::TableOptions *table_options= table_proto.mutable_options();
 
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<Create_field> &create_fields,
 
55
                            HA_CREATE_INFO *create_info,
 
56
                            uint32_t keys,
 
57
                            KEY *key_info)
 
58
{
 
59
  Create_field *field_arg;
 
60
  List_iterator<Create_field> it(create_fields);
 
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
  table_proto->set_name(table_name);
 
73
  table_proto->set_type(drizzled::message::Table::STANDARD);
 
74
 
67
75
  while ((field_arg= it++))
68
76
  {
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;
 
77
    drizzled::message::Table::Field *attribute;
 
78
 
 
79
    attribute= table_proto->add_field();
 
80
    attribute->set_name(field_arg->field_name);
 
81
 
 
82
    attribute->set_pack_flag(field_arg->pack_flag); /* TODO: MUST DIE */
 
83
 
 
84
    if(f_maybe_null(field_arg->pack_flag))
 
85
    {
 
86
      drizzled::message::Table::Field::FieldConstraints *constraints;
 
87
 
 
88
      constraints= attribute->mutable_constraints();
 
89
      constraints->set_is_nullable(true);
 
90
    }
 
91
 
 
92
    switch (field_arg->sql_type) {
 
93
    case DRIZZLE_TYPE_TINY:
 
94
      attribute->set_type(drizzled::message::Table::Field::TINYINT);
 
95
      break;
 
96
    case DRIZZLE_TYPE_LONG:
 
97
      attribute->set_type(drizzled::message::Table::Field::INTEGER);
 
98
      break;
 
99
    case DRIZZLE_TYPE_DOUBLE:
 
100
      attribute->set_type(drizzled::message::Table::Field::DOUBLE);
 
101
      break;
 
102
    case DRIZZLE_TYPE_NULL  :
 
103
      assert(1); /* Not a user definable type */
 
104
    case DRIZZLE_TYPE_TIMESTAMP:
 
105
      attribute->set_type(drizzled::message::Table::Field::TIMESTAMP);
 
106
      break;
 
107
    case DRIZZLE_TYPE_LONGLONG:
 
108
      attribute->set_type(drizzled::message::Table::Field::BIGINT);
 
109
      break;
 
110
    case DRIZZLE_TYPE_DATETIME:
 
111
      attribute->set_type(drizzled::message::Table::Field::DATETIME);
 
112
      break;
 
113
    case DRIZZLE_TYPE_DATE:
 
114
      attribute->set_type(drizzled::message::Table::Field::DATE);
 
115
      break;
 
116
    case DRIZZLE_TYPE_VARCHAR:
 
117
      {
 
118
        drizzled::message::Table::Field::StringFieldOptions *string_field_options;
130
119
 
131
120
        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
 
        }
 
121
        attribute->set_type(drizzled::message::Table::Field::VARCHAR);
 
122
        string_field_options->set_length(field_arg->length
 
123
                                         / field_arg->charset->mbmaxlen);
 
124
        string_field_options->set_collation_id(field_arg->charset->number);
 
125
        string_field_options->set_collation(field_arg->charset->name);
 
126
 
144
127
        break;
145
128
      }
146
 
    case message::Table::Field::DECIMAL:
 
129
    case DRIZZLE_TYPE_NEWDECIMAL:
147
130
      {
148
 
        message::Table::Field::NumericFieldOptions *numeric_field_options;
 
131
        drizzled::message::Table::Field::NumericFieldOptions *numeric_field_options;
149
132
 
 
133
        attribute->set_type(drizzled::message::Table::Field::DECIMAL);
150
134
        numeric_field_options= attribute->mutable_numeric_options();
151
135
        /* This is magic, I hate magic numbers -Brian */
152
136
        numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
153
137
        numeric_field_options->set_scale(field_arg->decimals);
154
138
        break;
155
139
      }
156
 
    case message::Table::Field::ENUM:
 
140
    case DRIZZLE_TYPE_ENUM:
157
141
      {
158
 
        message::Table::Field::EnumerationValues *enumeration_options;
 
142
        drizzled::message::Table::Field::SetFieldOptions *set_field_options;
159
143
 
160
144
        assert(field_arg->interval);
161
145
 
162
 
        enumeration_options= attribute->mutable_enumeration_values();
 
146
        attribute->set_type(drizzled::message::Table::Field::ENUM);
 
147
        set_field_options= attribute->mutable_set_options();
163
148
 
164
149
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
165
150
        {
166
151
          const char *src= field_arg->interval->type_names[pos];
167
152
 
168
 
          enumeration_options->add_field_value(src);
 
153
          set_field_options->add_field_value(src);
169
154
        }
170
 
        enumeration_options->set_collation_id(field_arg->charset->number);
171
 
        enumeration_options->set_collation(field_arg->charset->name);
 
155
        set_field_options->set_count_elements(set_field_options->field_value_size());
 
156
        set_field_options->set_collation_id(field_arg->charset->number);
 
157
        set_field_options->set_collation(field_arg->charset->name);
172
158
        break;
173
159
      }
174
 
    case message::Table::Field::BLOB:
 
160
    case DRIZZLE_TYPE_BLOB:
175
161
      {
176
 
        message::Table::Field::StringFieldOptions *string_field_options;
 
162
        attribute->set_type(drizzled::message::Table::Field::BLOB);
 
163
 
 
164
        drizzled::message::Table::Field::StringFieldOptions *string_field_options;
177
165
 
178
166
        string_field_options= attribute->mutable_string_options();
179
167
        string_field_options->set_collation_id(field_arg->charset->number);
181
169
      }
182
170
 
183
171
      break;
 
172
    default:
 
173
      assert(0); /* Tell us, since this shouldn't happend */
184
174
    }
185
175
 
186
 
    assert (!use_existing_fields || parser_type == attribute->type());
187
 
 
188
176
#ifdef NOTDONE
189
177
    field_constraints= attribute->mutable_constraints();
190
178
    constraints->set_is_nullable(field_arg->def->null_value);
191
179
#endif
192
180
 
 
181
    switch(field_arg->column_format())
 
182
    {
 
183
    case COLUMN_FORMAT_TYPE_NOT_USED:
 
184
      break;
 
185
    case COLUMN_FORMAT_TYPE_DEFAULT:
 
186
      attribute->set_format(drizzled::message::Table::Field::DefaultFormat);
 
187
      break;
 
188
    case COLUMN_FORMAT_TYPE_FIXED:
 
189
      attribute->set_format(drizzled::message::Table::Field::FixedFormat);
 
190
      break;
 
191
    case COLUMN_FORMAT_TYPE_DYNAMIC:
 
192
      attribute->set_format(drizzled::message::Table::Field::DynamicFormat);
 
193
      break;
 
194
    default:
 
195
      assert(0); /* Tell us, since this shouldn't happend */
 
196
    }
 
197
 
193
198
    if (field_arg->comment.length)
194
199
    {
195
200
      uint32_t tmp_len;
207
212
        return(1);
208
213
      }
209
214
 
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);
 
215
      attribute->set_comment(field_arg->comment.str);
214
216
    }
215
217
 
216
 
    if (field_arg->unireg_check == Field::NEXT_NUMBER)
 
218
    if(field_arg->unireg_check == Field::NEXT_NUMBER)
217
219
    {
218
 
      message::Table::Field::NumericFieldOptions *field_options;
 
220
      drizzled::message::Table::Field::NumericFieldOptions *field_options;
219
221
      field_options= attribute->mutable_numeric_options();
220
222
      field_options->set_is_autoincrement(true);
221
223
    }
222
224
 
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())
 
225
    if(field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
 
226
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
 
227
    {
 
228
      drizzled::message::Table::Field::FieldOptions *field_options;
 
229
      field_options= attribute->mutable_options();
 
230
      field_options->set_default_value("NOW()");
 
231
    }
 
232
 
 
233
    if(field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
 
234
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
 
235
    {
 
236
      drizzled::message::Table::Field::FieldOptions *field_options;
 
237
      field_options= attribute->mutable_options();
 
238
      field_options->set_update_value("NOW()");
 
239
    }
 
240
 
 
241
    if(field_arg->def)
 
242
    {
 
243
      drizzled::message::Table::Field::FieldOptions *field_options;
 
244
      field_options= attribute->mutable_options();
 
245
 
 
246
      if(field_arg->def->is_null())
252
247
      {
253
248
        field_options->set_default_null(true);
254
249
      }
259
254
 
260
255
        assert(default_value);
261
256
 
262
 
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
 
257
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
263
258
           || field_arg->sql_type==DRIZZLE_TYPE_BLOB)
264
259
           && ((field_arg->length / field_arg->charset->mbmaxlen)
265
260
           < default_value->length()))
268
263
          return 1;
269
264
        }
270
265
 
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
 
266
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
309
267
            && field_arg->charset==&my_charset_bin)
310
268
           || (field_arg->sql_type==DRIZZLE_TYPE_BLOB
311
269
            && field_arg->charset==&my_charset_bin))
322
280
      }
323
281
    }
324
282
 
 
283
    {
 
284
      drizzled::message::Table::Field::FieldOptions *field_options;
 
285
      field_options= attribute->mutable_options();
 
286
 
 
287
      field_options->set_length(field_arg->length);
 
288
    }
 
289
 
325
290
    assert(field_arg->unireg_check == Field::NONE
326
291
           || field_arg->unireg_check == Field::NEXT_NUMBER
327
292
           || field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
330
295
 
331
296
  }
332
297
 
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())
 
298
  if (create_info->used_fields & HA_CREATE_USED_PACK_KEYS)
 
299
  {
 
300
    if(create_info->table_options & HA_OPTION_PACK_KEYS)
 
301
      table_options->set_pack_keys(true);
 
302
    else if(create_info->table_options & HA_OPTION_NO_PACK_KEYS)
 
303
      table_options->set_pack_keys(false);
 
304
  }
 
305
  else
 
306
    if(create_info->table_options & HA_OPTION_PACK_KEYS)
 
307
      table_options->set_pack_keys(true);
 
308
 
 
309
 
 
310
  if (create_info->used_fields & HA_CREATE_USED_CHECKSUM)
 
311
  {
 
312
    assert(create_info->table_options & (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM));
 
313
 
 
314
    if(create_info->table_options & HA_OPTION_CHECKSUM)
 
315
      table_options->set_checksum(true);
 
316
    else
 
317
      table_options->set_checksum(false);
 
318
  }
 
319
  else if(create_info->table_options & HA_OPTION_CHECKSUM)
 
320
    table_options->set_checksum(true);
 
321
 
 
322
 
 
323
  if (create_info->used_fields & HA_CREATE_USED_PAGE_CHECKSUM)
 
324
  {
 
325
    if (create_info->page_checksum == HA_CHOICE_YES)
 
326
      table_options->set_page_checksum(true);
 
327
    else if (create_info->page_checksum == HA_CHOICE_NO)
 
328
      table_options->set_page_checksum(false);
 
329
  }
 
330
  else if (create_info->page_checksum == HA_CHOICE_YES)
 
331
    table_options->set_page_checksum(true);
 
332
 
 
333
 
 
334
  if (create_info->used_fields & HA_CREATE_USED_DELAY_KEY_WRITE)
 
335
  {
 
336
    if(create_info->table_options & HA_OPTION_DELAY_KEY_WRITE)
 
337
      table_options->set_delay_key_write(true);
 
338
    else if(create_info->table_options & HA_OPTION_NO_DELAY_KEY_WRITE)
 
339
      table_options->set_delay_key_write(false);
 
340
  }
 
341
  else if(create_info->table_options & HA_OPTION_DELAY_KEY_WRITE)
 
342
    table_options->set_delay_key_write(true);
 
343
 
 
344
 
 
345
  switch(create_info->row_type)
 
346
  {
 
347
  case ROW_TYPE_DEFAULT:
 
348
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_DEFAULT);
 
349
    break;
 
350
  case ROW_TYPE_FIXED:
 
351
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_FIXED);
 
352
    break;
 
353
  case ROW_TYPE_DYNAMIC:
 
354
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_DYNAMIC);
 
355
    break;
 
356
  case ROW_TYPE_COMPRESSED:
 
357
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_COMPRESSED);
 
358
    break;
 
359
  case ROW_TYPE_REDUNDANT:
 
360
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_REDUNDANT);
 
361
    break;
 
362
  case ROW_TYPE_COMPACT:
 
363
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_COMPACT);
 
364
    break;
 
365
  case ROW_TYPE_PAGE:
 
366
    table_options->set_row_type(drizzled::message::Table::TableOptions::ROW_TYPE_PAGE);
 
367
    break;
 
368
  default:
 
369
    abort();
 
370
  }
 
371
 
 
372
  table_options->set_pack_record(create_info->table_options
 
373
                                 & HA_OPTION_PACK_RECORD);
 
374
 
 
375
  if (create_info->comment.length)
342
376
  {
343
377
    uint32_t tmp_len;
344
378
    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);
 
379
                                                create_info->comment.str,
 
380
                                                create_info->comment.str +
 
381
                                                create_info->comment.length,
 
382
                                                TABLE_COMMENT_MAXLEN);
349
383
 
350
 
    if (tmp_len < table_options->comment().length())
 
384
    if (tmp_len < create_info->comment.length)
351
385
    {
352
386
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
353
 
               table_options->comment().c_str(),"Table COMMENT",
354
 
               (uint32_t) TABLE_COMMENT_MAXLEN);
 
387
               create_info->comment.str,"Table COMMENT",
 
388
               (uint32_t) TABLE_COMMENT_MAXLEN);
355
389
      return(1);
356
390
    }
 
391
 
 
392
    table_options->set_comment(create_info->comment.str);
357
393
  }
358
 
 
359
394
  if (create_info->default_table_charset)
360
395
  {
361
396
    table_options->set_collation_id(
363
398
    table_options->set_collation(create_info->default_table_charset->name);
364
399
  }
365
400
 
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);
 
401
  if (create_info->connect_string.length)
 
402
    table_options->set_connect_string(create_info->connect_string.str);
 
403
 
 
404
  if (create_info->data_file_name)
 
405
    table_options->set_data_file_name(create_info->data_file_name);
 
406
 
 
407
  if (create_info->index_file_name)
 
408
    table_options->set_index_file_name(create_info->index_file_name);
 
409
 
 
410
  if (create_info->max_rows)
 
411
    table_options->set_max_rows(create_info->max_rows);
 
412
 
 
413
  if (create_info->min_rows)
 
414
    table_options->set_min_rows(create_info->min_rows);
370
415
 
371
416
  if (create_info->auto_increment_value)
372
417
    table_options->set_auto_increment_value(create_info->auto_increment_value);
373
418
 
374
 
  for (uint32_t i= 0; i < keys; i++)
 
419
  if (create_info->avg_row_length)
 
420
    table_options->set_avg_row_length(create_info->avg_row_length);
 
421
 
 
422
  if (create_info->key_block_size)
 
423
    table_options->set_key_block_size(create_info->key_block_size);
 
424
 
 
425
  if (create_info->block_size)
 
426
    table_options->set_block_size(create_info->block_size);
 
427
 
 
428
  for (unsigned int i= 0; i < keys; i++)
375
429
  {
376
 
    message::Table::Index *idx;
 
430
    drizzled::message::Table::Index *idx;
377
431
 
378
 
    idx= table_proto.add_indexes();
 
432
    idx= table_proto->add_indexes();
379
433
 
380
434
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
381
435
           (key_info[i].comment.length > 0));
384
438
 
385
439
    idx->set_key_length(key_info[i].key_length);
386
440
 
387
 
    if (is_primary_key_name(key_info[i].name))
 
441
    if(is_primary_key_name(key_info[i].name))
388
442
      idx->set_is_primary(true);
389
443
    else
390
444
      idx->set_is_primary(false);
392
446
    switch(key_info[i].algorithm)
393
447
    {
394
448
    case HA_KEY_ALG_HASH:
395
 
      idx->set_type(message::Table::Index::HASH);
 
449
      idx->set_type(drizzled::message::Table::Index::HASH);
396
450
      break;
397
451
 
398
452
    case HA_KEY_ALG_BTREE:
399
 
      idx->set_type(message::Table::Index::BTREE);
 
453
      idx->set_type(drizzled::message::Table::Index::BTREE);
400
454
      break;
401
455
 
 
456
    case HA_KEY_ALG_RTREE:
 
457
      idx->set_type(drizzled::message::Table::Index::RTREE);
 
458
    case HA_KEY_ALG_FULLTEXT:
 
459
      idx->set_type(drizzled::message::Table::Index::FULLTEXT);
402
460
    case HA_KEY_ALG_UNDEF:
403
 
      idx->set_type(message::Table::Index::UNKNOWN_INDEX);
 
461
      idx->set_type(drizzled::message::Table::Index::UNKNOWN_INDEX);
404
462
      break;
405
463
 
406
464
    default:
412
470
    else
413
471
      idx->set_is_unique(false);
414
472
 
415
 
    message::Table::Index::Options *index_options= idx->mutable_options();
 
473
    drizzled::message::Table::Index::IndexOptions *index_options= idx->mutable_options();
416
474
 
417
 
    if (key_info[i].flags & HA_USES_BLOCK_SIZE)
 
475
    if(key_info[i].flags & HA_USES_BLOCK_SIZE)
418
476
      index_options->set_key_block_size(key_info[i].block_size);
419
477
 
420
 
    if (key_info[i].flags & HA_PACK_KEY)
 
478
    if(key_info[i].flags & HA_PACK_KEY)
421
479
      index_options->set_pack_key(true);
422
480
 
423
 
    if (key_info[i].flags & HA_BINARY_PACK_KEY)
 
481
    if(key_info[i].flags & HA_BINARY_PACK_KEY)
424
482
      index_options->set_binary_pack_key(true);
425
483
 
426
 
    if (key_info[i].flags & HA_VAR_LENGTH_PART)
 
484
    if(key_info[i].flags & HA_VAR_LENGTH_PART)
427
485
      index_options->set_var_length_key(true);
428
486
 
429
 
    if (key_info[i].flags & HA_NULL_PART_KEY)
 
487
    if(key_info[i].flags & HA_NULL_PART_KEY)
430
488
      index_options->set_null_part_key(true);
431
489
 
432
 
    if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
 
490
    if(key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
433
491
      index_options->set_has_partial_segments(true);
434
492
 
435
 
    if (key_info[i].flags & HA_GENERATED_KEY)
 
493
    if(key_info[i].flags & HA_GENERATED_KEY)
436
494
      index_options->set_auto_generated_key(true);
437
495
 
438
496
    if (key_info[i].flags & HA_USES_COMMENT)
454
512
 
455
513
      idx->set_comment(key_info[i].comment.str);
456
514
    }
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)
 
515
    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
516
      abort(); // Invalid (unknown) index flag.
467
517
 
468
518
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
469
519
    {
470
 
      message::Table::Index::IndexPart *idxpart;
471
 
      const int fieldnr= key_info[i].key_part[j].fieldnr;
472
 
      int mbmaxlen= 1;
 
520
      drizzled::message::Table::Index::IndexPart *idxpart;
473
521
 
474
522
      idxpart= idx->add_index_part();
475
523
 
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
 
 
 
524
      idxpart->set_fieldnr(key_info[i].key_part[j].fieldnr);
 
525
 
 
526
      idxpart->set_compare_length(key_info[i].key_part[j].length);
 
527
 
 
528
      idxpart->set_key_type(key_info[i].key_part[j].key_type);
 
529
 
 
530
    }
 
531
  }
 
532
 
 
533
  return 0;
 
534
}
 
535
 
 
536
int copy_table_proto_file(const char *from, const char* to)
 
537
{
 
538
  string dfesrc(from);
 
539
  string dfedst(to);
 
540
  string file_ext = ".dfe";
 
541
 
 
542
  dfesrc.append(file_ext);
 
543
  dfedst.append(file_ext);
 
544
 
 
545
  return my_copy(dfesrc.c_str(), dfedst.c_str(),
 
546
                 MYF(MY_DONT_OVERWRITE_FILE));
 
547
}
 
548
 
 
549
int rename_table_proto_file(const char *from, const char* to)
 
550
{
 
551
  string from_path(from);
 
552
  string to_path(to);
 
553
  string file_ext = ".dfe";
 
554
 
 
555
  from_path.append(file_ext);
 
556
  to_path.append(file_ext);
 
557
 
 
558
  return my_rename(from_path.c_str(),to_path.c_str(),MYF(MY_WME));
 
559
}
 
560
 
 
561
int delete_table_proto_file(const char *file_name)
 
562
{
 
563
  string new_path(file_name);
 
564
  string file_ext = ".dfe";
 
565
 
 
566
  new_path.append(file_ext);
 
567
  return my_delete(new_path.c_str(), MYF(0));
 
568
}
 
569
 
 
570
int table_proto_exists(const char *path)
 
571
{
 
572
  string proto_path(path);
 
573
  string file_ext(".dfe");
 
574
  proto_path.append(file_ext);
 
575
 
 
576
  int error= access(proto_path.c_str(), F_OK);
 
577
 
 
578
  if(error==0)
 
579
    return EEXIST;
 
580
  else
 
581
    return errno;
 
582
}
 
583
 
 
584
static int create_table_proto_file(const char *file_name,
 
585
                                   const char *db,
 
586
                                   const char *table_name,
 
587
                                   HA_CREATE_INFO *create_info,
 
588
                                   List<Create_field> &create_fields,
 
589
                                   uint32_t keys,
 
590
                                   KEY *key_info)
 
591
{
 
592
  drizzled::message::Table table_proto;
 
593
  string new_path(file_name);
 
594
  string file_ext = ".dfe";
 
595
 
 
596
  if(fill_table_proto(&table_proto, table_name, create_fields, create_info,
 
597
                      keys, key_info))
 
598
    return -1;
 
599
 
 
600
  new_path.append(file_ext);
 
601
 
 
602
  int fd= open(new_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, my_umask);
 
603
 
 
604
  if(fd==-1)
 
605
  {
 
606
    if(errno==ENOENT)
 
607
      my_error(ER_BAD_DB_ERROR,MYF(0),db);
 
608
    else
 
609
      my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,errno);
 
610
    return errno;
 
611
  }
 
612
 
 
613
  google::protobuf::io::ZeroCopyOutputStream* output=
 
614
    new google::protobuf::io::FileOutputStream(fd);
 
615
 
 
616
  if (!table_proto.SerializeToZeroCopyStream(output))
 
617
  {
 
618
    delete output;
 
619
    close(fd);
 
620
    return errno;
 
621
  }
 
622
 
 
623
  delete output;
 
624
  close(fd);
523
625
  return 0;
524
626
}
525
627
 
536
638
    create_fields       Fields to create
537
639
    keys                number of keys to create
538
640
    key_info            Keys to create
 
641
    file                Handler to use
 
642
    is_like             is true for mysql_create_like_schema_frm
539
643
 
540
644
  RETURN
541
645
    0  ok
542
646
    1  error
543
647
*/
544
648
 
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)
 
649
int rea_create_table(Session *session, const char *path,
 
650
                     const char *db, const char *table_name,
 
651
                     HA_CREATE_INFO *create_info,
 
652
                     List<Create_field> &create_fields,
 
653
                     uint32_t keys, KEY *key_info, handler *file,
 
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, create_info,
 
663
                                create_fields, keys, key_info)!=0)
 
664
      return 1;
 
665
 
 
666
    return 0;
 
667
  }
 
668
  /* Here we need to build the full frm from the path */
 
669
  else
 
670
  {
 
671
    if (create_table_proto_file(path, db, table_name, create_info,
 
672
                                create_fields, keys, key_info))
 
673
      return 1;
 
674
  }
 
675
 
 
676
  // Make sure mysql_create_frm din't remove extension
 
677
  if (session->variables.keep_files_on_create)
 
678
    create_info->options|= HA_CREATE_KEEP_FILES;
 
679
  if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
 
680
    goto err_handler;
 
681
  if (ha_create_table(session, path, db, table_name,
 
682
                      create_info,0))
 
683
    goto err_handler;
 
684
  return 0;
 
685
 
 
686
err_handler:
 
687
  file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
 
688
 
 
689
  delete_table_proto_file(path);
 
690
 
 
691
  return 1;
568
692
} /* rea_create_table */
569
 
 
570
 
} /* namespace drizzled */
571