~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

Reverted 1103

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