~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

Merge Nathan

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/plugin/storage_engine.h>
25
 
 
26
 
#include "drizzled/internal/my_sys.h"
27
 
 
28
20
 
29
21
/* For proto */
30
22
#include <string>
31
23
#include <fstream>
32
 
#include <fcntl.h>
33
24
#include <drizzled/message/schema.pb.h>
34
25
#include <drizzled/message/table.pb.h>
35
26
#include <google/protobuf/io/zero_copy_stream.h>
36
27
#include <google/protobuf/io/zero_copy_stream_impl.h>
37
 
#include <google/protobuf/message.h>
38
 
 
39
 
#include <drizzled/table_proto.h>
40
 
#include <drizzled/charset.h>
41
 
 
42
 
#include "drizzled/function/time/typecast.h"
43
 
 
44
28
using namespace std;
45
29
 
46
 
namespace drizzled {
47
 
 
48
 
bool fill_table_proto(message::Table &table_proto,
49
 
                      List<CreateField> &create_fields,
50
 
                      HA_CREATE_INFO *create_info,
51
 
                      uint32_t keys,
52
 
                      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)
53
58
{
54
59
  CreateField *field_arg;
55
60
  List_iterator<CreateField> it(create_fields);
56
 
  message::Table::TableOptions *table_options= table_proto.mutable_options();
 
61
  drizzled::message::Table::TableOptions *table_options= table_proto->mutable_options();
57
62
 
58
63
  if (create_fields.elements > MAX_FIELDS)
59
64
  {
60
65
    my_error(ER_TOO_MANY_FIELDS, MYF(0), ER(ER_TOO_MANY_FIELDS));
61
 
    return true;
 
66
    return(1);
62
67
  }
63
68
 
64
 
  assert(strcmp(table_proto.engine().name().c_str(),
 
69
  assert(strcmp(table_proto->engine().name().c_str(),
65
70
                create_info->db_type->getName().c_str())==0);
66
71
 
67
 
  int field_number= 0;
68
 
  bool use_existing_fields= table_proto.field_size() > 0;
 
72
  assert(strcmp(table_proto->name().c_str(),table_name)==0);
 
73
 
69
74
  while ((field_arg= it++))
70
75
  {
71
 
    message::Table::Field *attribute;
72
 
 
73
 
    /* some (one) code path for CREATE TABLE fills the proto
74
 
       out more than the others, so we already have partially
75
 
       filled out Field messages */
76
 
 
77
 
    if (use_existing_fields)
78
 
    {
79
 
      attribute= table_proto.mutable_field(field_number++);
80
 
    }
81
 
    else
82
 
    {
83
 
      /* Other code paths still have to fill out the proto */
84
 
      attribute= table_proto.add_field();
85
 
 
86
 
      if (field_arg->flags & NOT_NULL_FLAG)
87
 
      {
88
 
        attribute->mutable_constraints()->set_is_notnull(true);
89
 
      }
90
 
 
91
 
      if (field_arg->flags & UNSIGNED_FLAG and 
92
 
          (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
93
 
      {
94
 
        field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
95
 
        attribute->mutable_constraints()->set_is_unsigned(true);
96
 
      }
97
 
 
98
 
      attribute->set_name(field_arg->field_name);
99
 
    }
100
 
 
101
 
    assert(((field_arg->flags & NOT_NULL_FLAG)) == attribute->constraints().is_notnull());
102
 
    assert(strcmp(attribute->name().c_str(), field_arg->field_name)==0);
103
 
 
104
 
 
105
 
    message::Table::Field::FieldType parser_type= attribute->type();
106
 
 
107
 
    if (field_arg->sql_type == DRIZZLE_TYPE_NULL)
108
 
    {
109
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), table_proto.name().c_str(), -1);
110
 
      return true;
111
 
    }
112
 
 
113
 
    if (field_arg->flags & UNSIGNED_FLAG and 
114
 
       (field_arg->sql_type == DRIZZLE_TYPE_LONGLONG or field_arg->sql_type == DRIZZLE_TYPE_LONG))
115
 
    {
116
 
      message::Table::Field::FieldConstraints *constraints= attribute->mutable_constraints();
117
 
 
118
 
      field_arg->sql_type= DRIZZLE_TYPE_LONGLONG;
119
 
      constraints->set_is_unsigned(true);
120
 
    }
121
 
 
122
 
    attribute->set_type(message::internalFieldTypeToFieldProtoType(field_arg->sql_type));
123
 
 
124
 
    switch (attribute->type()) {
125
 
    case message::Table::Field::BIGINT:
126
 
    case message::Table::Field::INTEGER:
127
 
    case message::Table::Field::DATE:
128
 
    case message::Table::Field::DATETIME:
129
 
    case message::Table::Field::UUID:
130
 
    case message::Table::Field::TIME:
131
 
    case message::Table::Field::BOOLEAN:
132
 
      break;
133
 
    case message::Table::Field::DOUBLE:
134
 
      {
135
 
        /*
136
 
         * For DOUBLE, we only add a specific scale and precision iff
137
 
         * the fixed decimal point has been specified...
138
 
         */
139
 
        if (field_arg->decimals != NOT_FIXED_DEC)
140
 
        {
141
 
          message::Table::Field::NumericFieldOptions *numeric_field_options;
142
 
 
143
 
          numeric_field_options= attribute->mutable_numeric_options();
144
 
 
145
 
          numeric_field_options->set_precision(field_arg->length);
146
 
          numeric_field_options->set_scale(field_arg->decimals);
147
 
        }
148
 
      }
149
 
      break;
150
 
    case message::Table::Field::VARCHAR:
151
 
      {
152
 
        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;
153
118
 
154
119
        string_field_options= attribute->mutable_string_options();
155
 
 
156
 
        if (! use_existing_fields || string_field_options->length()==0)
157
 
          string_field_options->set_length(field_arg->length
158
 
                                           / field_arg->charset->mbmaxlen);
159
 
        else
160
 
          assert((uint32_t)string_field_options->length() == (uint32_t)(field_arg->length / field_arg->charset->mbmaxlen));
161
 
 
162
 
        if (! string_field_options->has_collation())
163
 
        {
164
 
          string_field_options->set_collation_id(field_arg->charset->number);
165
 
          string_field_options->set_collation(field_arg->charset->name);
166
 
        }
 
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
 
167
126
        break;
168
127
      }
169
 
    case message::Table::Field::DECIMAL:
 
128
    case DRIZZLE_TYPE_NEWDECIMAL:
170
129
      {
171
 
        message::Table::Field::NumericFieldOptions *numeric_field_options;
 
130
        drizzled::message::Table::Field::NumericFieldOptions *numeric_field_options;
172
131
 
 
132
        attribute->set_type(drizzled::message::Table::Field::DECIMAL);
173
133
        numeric_field_options= attribute->mutable_numeric_options();
174
134
        /* This is magic, I hate magic numbers -Brian */
175
135
        numeric_field_options->set_precision(field_arg->length + ( field_arg->decimals ? -2 : -1));
176
136
        numeric_field_options->set_scale(field_arg->decimals);
177
137
        break;
178
138
      }
179
 
    case message::Table::Field::ENUM:
 
139
    case DRIZZLE_TYPE_ENUM:
180
140
      {
181
 
        message::Table::Field::EnumerationValues *enumeration_options;
 
141
        drizzled::message::Table::Field::SetFieldOptions *set_field_options;
182
142
 
183
143
        assert(field_arg->interval);
184
144
 
185
 
        enumeration_options= attribute->mutable_enumeration_values();
 
145
        attribute->set_type(drizzled::message::Table::Field::ENUM);
 
146
        set_field_options= attribute->mutable_set_options();
186
147
 
187
148
        for (uint32_t pos= 0; pos < field_arg->interval->count; pos++)
188
149
        {
189
150
          const char *src= field_arg->interval->type_names[pos];
190
151
 
191
 
          enumeration_options->add_field_value(src);
 
152
          set_field_options->add_field_value(src);
192
153
        }
193
 
        enumeration_options->set_collation_id(field_arg->charset->number);
194
 
        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);
195
157
        break;
196
158
      }
197
 
 
198
 
    case message::Table::Field::BLOB:
 
159
    case DRIZZLE_TYPE_BLOB:
199
160
      {
200
 
        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;
201
164
 
202
165
        string_field_options= attribute->mutable_string_options();
203
166
        string_field_options->set_collation_id(field_arg->charset->number);
205
168
      }
206
169
 
207
170
      break;
208
 
 
209
 
    case message::Table::Field::EPOCH:
210
 
      {
211
 
        if (field_arg->sql_type == DRIZZLE_TYPE_MICROTIME)
212
 
          attribute->mutable_time_options()->set_microseconds(true);
213
 
      }
214
 
 
215
 
      break;
 
171
    default:
 
172
      assert(0); /* Tell us, since this shouldn't happend */
216
173
    }
217
174
 
218
 
    assert (!use_existing_fields || parser_type == attribute->type());
219
 
 
220
175
#ifdef NOTDONE
221
176
    field_constraints= attribute->mutable_constraints();
222
177
    constraints->set_is_nullable(field_arg->def->null_value);
223
178
#endif
224
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
 
225
197
    if (field_arg->comment.length)
226
198
    {
227
199
      uint32_t tmp_len;
236
208
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
237
209
                 field_arg->comment.str,"COLUMN COMMENT",
238
210
                 (uint32_t) COLUMN_COMMENT_MAXLEN);
239
 
        return true;
 
211
        return(1);
240
212
      }
241
213
 
242
 
      if (! use_existing_fields)
243
 
        attribute->set_comment(field_arg->comment.str);
244
 
 
245
 
      assert(strcmp(attribute->comment().c_str(), field_arg->comment.str)==0);
 
214
      attribute->set_comment(field_arg->comment.str);
246
215
    }
247
216
 
248
 
    if (field_arg->unireg_check == Field::NEXT_NUMBER)
 
217
    if(field_arg->unireg_check == Field::NEXT_NUMBER)
249
218
    {
250
 
      message::Table::Field::NumericFieldOptions *field_options;
 
219
      drizzled::message::Table::Field::NumericFieldOptions *field_options;
251
220
      field_options= attribute->mutable_numeric_options();
252
221
      field_options->set_is_autoincrement(true);
253
222
    }
254
223
 
255
 
    if (field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
256
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
257
 
    {
258
 
      message::Table::Field::FieldOptions *field_options;
259
 
      field_options= attribute->mutable_options();
260
 
      field_options->set_default_expression("CURRENT_TIMESTAMP");
261
 
    }
262
 
 
263
 
    if (field_arg->unireg_check == Field::TIMESTAMP_UN_FIELD
264
 
       || field_arg->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
265
 
    {
266
 
      message::Table::Field::FieldOptions *field_options;
267
 
      field_options= attribute->mutable_options();
268
 
      field_options->set_update_expression("CURRENT_TIMESTAMP");
269
 
    }
270
 
 
271
 
    if (field_arg->def == NULL  && not attribute->constraints().is_notnull())
272
 
    {
273
 
      message::Table::Field::FieldOptions *field_options;
274
 
      field_options= attribute->mutable_options();
275
 
 
276
 
      field_options->set_default_null(true);
277
 
    }
278
 
    if (field_arg->def)
279
 
    {
280
 
      message::Table::Field::FieldOptions *field_options;
281
 
      field_options= attribute->mutable_options();
282
 
 
283
 
      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())
284
246
      {
285
247
        field_options->set_default_null(true);
286
248
      }
291
253
 
292
254
        assert(default_value);
293
255
 
294
 
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
 
256
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
295
257
           || field_arg->sql_type==DRIZZLE_TYPE_BLOB)
296
258
           && ((field_arg->length / field_arg->charset->mbmaxlen)
297
259
           < default_value->length()))
298
260
        {
299
261
          my_error(ER_INVALID_DEFAULT, MYF(0), field_arg->field_name);
300
 
          return true;
 
262
          return 1;
301
263
        }
302
264
 
303
 
        if (field_arg->sql_type == DRIZZLE_TYPE_DATE
304
 
            || field_arg->sql_type == DRIZZLE_TYPE_TIME
305
 
            || field_arg->sql_type == DRIZZLE_TYPE_DATETIME
306
 
            || field_arg->sql_type == DRIZZLE_TYPE_MICROTIME
307
 
            || field_arg->sql_type == DRIZZLE_TYPE_TIMESTAMP)
308
 
        {
309
 
          type::Time ltime;
310
 
 
311
 
          if (field_arg->def->get_date(ltime, TIME_FUZZY_DATE))
312
 
          {
313
 
            my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR),
314
 
                     default_value->c_str());
315
 
            return true;
316
 
          }
317
 
 
318
 
          /* We now do the casting down to the appropriate type.
319
 
 
320
 
             Yes, this implicit casting is balls.
321
 
             It was previously done on reading the proto back in,
322
 
             but we really shouldn't store the bogus things in the proto,
323
 
             and instead do the casting behaviour here.
324
 
 
325
 
             the timestamp errors are taken care of elsewhere.
326
 
          */
327
 
 
328
 
          if (field_arg->sql_type == DRIZZLE_TYPE_DATETIME)
329
 
          {
330
 
            Item *typecast= new Item_datetime_typecast(field_arg->def);
331
 
            typecast->quick_fix_field();
332
 
            typecast->val_str(default_value);
333
 
          }
334
 
          else if (field_arg->sql_type == DRIZZLE_TYPE_DATE)
335
 
          {
336
 
            Item *typecast= new Item_date_typecast(field_arg->def);
337
 
            typecast->quick_fix_field();
338
 
            typecast->val_str(default_value);
339
 
          }
340
 
        }
341
 
 
342
 
        if ((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
 
265
        if((field_arg->sql_type==DRIZZLE_TYPE_VARCHAR
343
266
            && field_arg->charset==&my_charset_bin)
344
267
           || (field_arg->sql_type==DRIZZLE_TYPE_BLOB
345
268
            && field_arg->charset==&my_charset_bin))
356
279
      }
357
280
    }
358
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
 
359
289
    assert(field_arg->unireg_check == Field::NONE
360
290
           || field_arg->unireg_check == Field::NEXT_NUMBER
361
291
           || field_arg->unireg_check == Field::TIMESTAMP_DN_FIELD
364
294
 
365
295
  }
366
296
 
367
 
  assert(! use_existing_fields || (field_number == table_proto.field_size()));
368
 
 
369
 
  if (create_info->table_options & HA_OPTION_PACK_RECORD)
370
 
    table_options->set_pack_record(true);
371
 
 
372
 
  if (table_options->has_comment() && table_options->comment().length() == 0)
373
 
    table_options->clear_comment();
374
 
 
375
 
  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)
376
375
  {
377
376
    uint32_t tmp_len;
378
377
    tmp_len= system_charset_info->cset->charpos(system_charset_info,
379
 
                                                table_options->comment().c_str(),
380
 
                                                table_options->comment().c_str() +
381
 
                                                table_options->comment().length(),
382
 
                                                TABLE_COMMENT_MAXLEN);
 
378
                                                create_info->comment.str,
 
379
                                                create_info->comment.str +
 
380
                                                create_info->comment.length,
 
381
                                                TABLE_COMMENT_MAXLEN);
383
382
 
384
 
    if (tmp_len < table_options->comment().length())
 
383
    if (tmp_len < create_info->comment.length)
385
384
    {
386
385
      my_error(ER_WRONG_STRING_LENGTH, MYF(0),
387
 
               table_options->comment().c_str(),"Table COMMENT",
388
 
               (uint32_t) TABLE_COMMENT_MAXLEN);
389
 
      return true;
 
386
               create_info->comment.str,"Table COMMENT",
 
387
               (uint32_t) TABLE_COMMENT_MAXLEN);
 
388
      return(1);
390
389
    }
 
390
 
 
391
    table_options->set_comment(create_info->comment.str);
391
392
  }
392
 
 
393
393
  if (create_info->default_table_charset)
394
394
  {
395
 
    table_options->set_collation_id(create_info->default_table_charset->number);
 
395
    table_options->set_collation_id(
 
396
                               create_info->default_table_charset->number);
396
397
    table_options->set_collation(create_info->default_table_charset->name);
397
398
  }
398
399
 
399
 
  if (create_info->used_fields & HA_CREATE_USED_AUTO)
400
 
    table_options->set_has_user_set_auto_increment_value(true);
401
 
  else
402
 
    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);
403
414
 
404
415
  if (create_info->auto_increment_value)
405
416
    table_options->set_auto_increment_value(create_info->auto_increment_value);
406
417
 
407
 
  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++)
408
428
  {
409
 
    message::Table::Index *idx;
 
429
    drizzled::message::Table::Index *idx;
410
430
 
411
 
    idx= table_proto.add_indexes();
 
431
    idx= table_proto->add_indexes();
412
432
 
413
433
    assert(test(key_info[i].flags & HA_USES_COMMENT) ==
414
434
           (key_info[i].comment.length > 0));
417
437
 
418
438
    idx->set_key_length(key_info[i].key_length);
419
439
 
420
 
    if (is_primary_key_name(key_info[i].name))
 
440
    if(is_primary_key_name(key_info[i].name))
421
441
      idx->set_is_primary(true);
422
442
    else
423
443
      idx->set_is_primary(false);
425
445
    switch(key_info[i].algorithm)
426
446
    {
427
447
    case HA_KEY_ALG_HASH:
428
 
      idx->set_type(message::Table::Index::HASH);
 
448
      idx->set_type(drizzled::message::Table::Index::HASH);
429
449
      break;
430
450
 
431
451
    case HA_KEY_ALG_BTREE:
432
 
      idx->set_type(message::Table::Index::BTREE);
 
452
      idx->set_type(drizzled::message::Table::Index::BTREE);
433
453
      break;
434
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);
435
459
    case HA_KEY_ALG_UNDEF:
436
 
      idx->set_type(message::Table::Index::UNKNOWN_INDEX);
 
460
      idx->set_type(drizzled::message::Table::Index::UNKNOWN_INDEX);
437
461
      break;
438
462
 
439
463
    default:
445
469
    else
446
470
      idx->set_is_unique(false);
447
471
 
448
 
    message::Table::Index::Options *index_options= idx->mutable_options();
 
472
    drizzled::message::Table::Index::IndexOptions *index_options= idx->mutable_options();
449
473
 
450
 
    if (key_info[i].flags & HA_USES_BLOCK_SIZE)
 
474
    if(key_info[i].flags & HA_USES_BLOCK_SIZE)
451
475
      index_options->set_key_block_size(key_info[i].block_size);
452
476
 
453
 
    if (key_info[i].flags & HA_PACK_KEY)
 
477
    if(key_info[i].flags & HA_PACK_KEY)
454
478
      index_options->set_pack_key(true);
455
479
 
456
 
    if (key_info[i].flags & HA_BINARY_PACK_KEY)
 
480
    if(key_info[i].flags & HA_BINARY_PACK_KEY)
457
481
      index_options->set_binary_pack_key(true);
458
482
 
459
 
    if (key_info[i].flags & HA_VAR_LENGTH_PART)
 
483
    if(key_info[i].flags & HA_VAR_LENGTH_PART)
460
484
      index_options->set_var_length_key(true);
461
485
 
462
 
    if (key_info[i].flags & HA_NULL_PART_KEY)
 
486
    if(key_info[i].flags & HA_NULL_PART_KEY)
463
487
      index_options->set_null_part_key(true);
464
488
 
465
 
    if (key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
 
489
    if(key_info[i].flags & HA_KEY_HAS_PART_KEY_SEG)
466
490
      index_options->set_has_partial_segments(true);
467
491
 
468
 
    if (key_info[i].flags & HA_GENERATED_KEY)
 
492
    if(key_info[i].flags & HA_GENERATED_KEY)
469
493
      index_options->set_auto_generated_key(true);
470
494
 
471
495
    if (key_info[i].flags & HA_USES_COMMENT)
482
506
        my_error(ER_WRONG_STRING_LENGTH, MYF(0),
483
507
                 key_info[i].comment.str,"Index COMMENT",
484
508
                 (uint32_t) TABLE_COMMENT_MAXLEN);
485
 
        return true;
 
509
        return(1);
486
510
      }
487
511
 
488
512
      idx->set_comment(key_info[i].comment.str);
489
513
    }
490
 
    static const uint64_t unknown_index_flag= (HA_NOSAME | HA_PACK_KEY |
491
 
                                               HA_USES_BLOCK_SIZE | 
492
 
                                               HA_BINARY_PACK_KEY |
493
 
                                               HA_VAR_LENGTH_PART |
494
 
                                               HA_NULL_PART_KEY | 
495
 
                                               HA_KEY_HAS_PART_KEY_SEG |
496
 
                                               HA_GENERATED_KEY |
497
 
                                               HA_USES_COMMENT);
498
 
    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))
499
515
      abort(); // Invalid (unknown) index flag.
500
516
 
501
517
    for(unsigned int j=0; j< key_info[i].key_parts; j++)
502
518
    {
503
 
      message::Table::Index::IndexPart *idxpart;
504
 
      const int fieldnr= key_info[i].key_part[j].fieldnr;
505
 
      int mbmaxlen= 1;
 
519
      drizzled::message::Table::Index::IndexPart *idxpart;
506
520
 
507
521
      idxpart= idx->add_index_part();
508
522
 
509
 
      idxpart->set_fieldnr(fieldnr);
510
 
 
511
 
      if (table_proto.field(fieldnr).type() == message::Table::Field::VARCHAR
512
 
          || table_proto.field(fieldnr).type() == message::Table::Field::BLOB)
513
 
      {
514
 
        uint32_t collation_id;
515
 
 
516
 
        if (table_proto.field(fieldnr).string_options().has_collation_id())
517
 
          collation_id= table_proto.field(fieldnr).string_options().collation_id();
518
 
        else
519
 
          collation_id= table_proto.options().collation_id();
520
 
 
521
 
        const CHARSET_INFO *cs= get_charset(collation_id);
522
 
 
523
 
        mbmaxlen= cs->mbmaxlen;
524
 
      }
525
 
 
526
 
      idxpart->set_compare_length(key_info[i].key_part[j].length / mbmaxlen);
527
 
    }
528
 
  }
529
 
 
530
 
  if (not table_proto.IsInitialized())
531
 
  {
532
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
533
 
             table_proto.name().c_str(),
534
 
             table_proto.InitializationErrorString().c_str());
535
 
 
536
 
    return true;
537
 
  }
538
 
 
539
 
  /*
540
 
    Here we test to see if we can validate the Table Message before we continue. 
541
 
    We do this by serializing the protobuffer.
542
 
  */
543
 
  {
544
 
    string tmp_string;
545
 
 
546
 
    try {
547
 
      table_proto.SerializeToString(&tmp_string);
548
 
    }
549
 
 
550
 
    catch (...)
551
 
    {
552
 
      my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
553
 
               table_proto.name().c_str(),
554
 
               table_proto.InitializationErrorString().c_str());
555
 
 
556
 
      return true;
557
 
    }
558
 
  }
559
 
 
560
 
  return false;
 
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);
 
624
  return 0;
561
625
}
562
626
 
563
627
/*
573
637
    create_fields       Fields to create
574
638
    keys                number of keys to create
575
639
    key_info            Keys to create
 
640
    file                Handler to use
 
641
    is_like             is true for mysql_create_like_schema_frm
576
642
 
577
643
  RETURN
578
644
    0  ok
579
645
    1  error
580
646
*/
581
647
 
582
 
bool rea_create_table(Session *session,
583
 
                      const identifier::Table &identifier,
584
 
                      message::Table &table_proto,
585
 
                      HA_CREATE_INFO *create_info,
586
 
                      List<CreateField> &create_fields,
587
 
                      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)
588
655
{
589
 
  assert(table_proto.has_name());
590
 
  if (fill_table_proto(table_proto, create_fields, create_info,
591
 
                       keys, key_info))
592
 
  {
593
 
    return false;
594
 
  }
595
 
 
596
 
  assert(table_proto.name() == identifier.getTableName());
597
 
 
598
 
  if (not plugin::StorageEngine::createTable(*session,
599
 
                                             identifier,
600
 
                                             table_proto))
601
 
  {
602
 
    return false;
603
 
  }
604
 
 
605
 
  return true;
606
 
 
 
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
  if (ha_create_table(session, path, db, table_name,
 
679
                      create_info,0))
 
680
    goto err_handler;
 
681
  return 0;
 
682
 
 
683
err_handler:
 
684
  delete_table_proto_file(path);
 
685
 
 
686
  return 1;
607
687
} /* rea_create_table */
608
 
 
609
 
} /* namespace drizzled */
610