~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_proto_write.cc

  • Committer: Monty Taylor
  • Date: 2009-03-18 18:45:23 UTC
  • mto: (950.1.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 943.
  • Revision ID: mordred@inaugust.com-20090318184523-mfbjyj5wkipv4n3b
Moved big tests to big suite. Added make target "make test-big" to allow for easy running of the big tests.

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