~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/parser.cc

  • Committer: Lee Bieber
  • Date: 2010-11-07 19:34:48 UTC
  • mfrom: (1910.1.2 build)
  • Revision ID: kalebral@gmail.com-20101107193448-64kdu912qej354sh
Merge Stewart - including adapting and expanding the "differences from mysql" page from the wiki.
Merge Stewart - fix bug 668143: drizzleslap with --commit runs second iteration data load in a transaction

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2010 Brian Aker
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
#include "config.h"
22
 
 
23
 
#include <drizzled/parser.h>
24
 
 
25
 
namespace drizzled
26
 
{
27
 
namespace parser
28
 
{
29
 
 
30
 
/**
31
 
  Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
32
 
  See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
33
 
  This function returns the proper item for the SQL expression
34
 
  <code>left [NOT] IN ( expr )</code>
35
 
  @param session the current thread
36
 
  @param left the in predicand
37
 
  @param equal true for IN predicates, false for NOT IN predicates
38
 
  @param expr first and only expression of the in value list
39
 
  @return an expression representing the IN predicate.
40
 
*/
41
 
 
42
 
Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
43
 
{
44
 
  /*
45
 
    Relevant references for this issue:
46
 
    - SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
47
 
    - SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
48
 
    - SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
49
 
    - SQL:2003, Part 2, section 7.15 <subquery>, page 370,
50
 
    - SQL:2003 Feature F561, "Full value expressions".
51
 
 
52
 
    The exception in SQL:2003 Note 184 means:
53
 
    Item_singlerow_subselect, which corresponds to a <scalar subquery>,
54
 
    should be re-interpreted as an Item_in_subselect, which corresponds
55
 
    to a <table subquery> when used inside an <in predicate>.
56
 
 
57
 
    Our reading of Note 184 is reccursive, so that all:
58
 
    - IN (( <subquery> ))
59
 
    - IN ((( <subquery> )))
60
 
    - IN '('^N <subquery> ')'^N
61
 
    - etc
62
 
    should be interpreted as a <table subquery>, no matter how deep in the
63
 
    expression the <subquery> is.
64
 
  */
65
 
 
66
 
  Item *result;
67
 
 
68
 
  if (expr->type() == Item::SUBSELECT_ITEM)
69
 
  {
70
 
    Item_subselect *expr2 = (Item_subselect*) expr;
71
 
 
72
 
    if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
73
 
    {
74
 
      Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
75
 
      Select_Lex *subselect;
76
 
 
77
 
      /*
78
 
        Implement the mandated change, by altering the semantic tree:
79
 
          left IN Item_singlerow_subselect(subselect)
80
 
        is modified to
81
 
          left IN (subselect)
82
 
        which is represented as
83
 
          Item_in_subselect(left, subselect)
84
 
      */
85
 
      subselect= expr3->invalidate_and_restore_select_lex();
86
 
      result= new (session->mem_root) Item_in_subselect(left, subselect);
87
 
 
88
 
      if (! equal)
89
 
        result = negate_expression(session, result);
90
 
 
91
 
      return(result);
92
 
    }
93
 
  }
94
 
 
95
 
  if (equal)
96
 
    result= new (session->mem_root) Item_func_eq(left, expr);
97
 
  else
98
 
    result= new (session->mem_root) Item_func_ne(left, expr);
99
 
 
100
 
  return(result);
101
 
}
102
 
 
103
 
/**
104
 
   @brief Creates a new Select_Lex for a UNION branch.
105
 
 
106
 
   Sets up and initializes a Select_Lex structure for a query once the parser
107
 
   discovers a UNION token. The current Select_Lex is pushed on the stack and
108
 
   the new Select_Lex becomes the current one..=
109
 
 
110
 
   @lex The parser state.
111
 
 
112
 
   @is_union_distinct True if the union preceding the new select statement
113
 
   uses UNION DISTINCT.
114
 
 
115
 
   @return <code>false</code> if successful, <code>true</code> if an error was
116
 
   reported. In the latter case parsing should stop.
117
 
 */
118
 
bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
119
 
{
120
 
  if (lex->result)
121
 
  {
122
 
    /* Only the last SELECT can have  INTO...... */
123
 
    my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
124
 
    return true;
125
 
  }
126
 
  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
127
 
  {
128
 
    my_parse_error(session->m_lip);
129
 
    return true;
130
 
  }
131
 
  /* This counter shouldn't be incremented for UNION parts */
132
 
  lex->nest_level--;
133
 
  if (new_select(lex, 0))
134
 
    return true;
135
 
  init_select(lex);
136
 
  lex->current_select->linkage=UNION_TYPE;
137
 
  if (is_union_distinct) /* UNION DISTINCT - remember position */
138
 
    lex->current_select->master_unit()->union_distinct=
139
 
      lex->current_select;
140
 
  return false;
141
 
}
142
 
 
143
 
/**
144
 
   @brief Initializes a Select_Lex for a query within parentheses (aka
145
 
   braces).
146
 
 
147
 
   @return false if successful, true if an error was reported. In the latter
148
 
   case parsing should stop.
149
 
 */
150
 
bool setup_select_in_parentheses(Session *session, LEX *lex)
151
 
{
152
 
  Select_Lex * sel= lex->current_select;
153
 
  if (sel->set_braces(1))
154
 
  {
155
 
    my_parse_error(session->m_lip);
156
 
    return true;
157
 
  }
158
 
  if (sel->linkage == UNION_TYPE &&
159
 
      !sel->master_unit()->first_select()->braces &&
160
 
      sel->master_unit()->first_select()->linkage ==
161
 
      UNION_TYPE)
162
 
  {
163
 
    my_parse_error(session->m_lip);
164
 
    return true;
165
 
  }
166
 
  if (sel->linkage == UNION_TYPE &&
167
 
      sel->olap != UNSPECIFIED_OLAP_TYPE &&
168
 
      sel->master_unit()->fake_select_lex)
169
 
  {
170
 
    my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
171
 
    return true;
172
 
  }
173
 
  /* select in braces, can't contain global parameters */
174
 
  if (sel->master_unit()->fake_select_lex)
175
 
    sel->master_unit()->global_parameters=
176
 
      sel->master_unit()->fake_select_lex;
177
 
  return false;
178
 
}
179
 
 
180
 
Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
181
 
{
182
 
  const plugin::Function *udf= plugin::Function::get(name.c_str(), name.length());
183
 
  Item *item= NULL;
184
 
 
185
 
  if (udf)
186
 
  {
187
 
    item= Create_udf_func::s_singleton.create(session, udf, item_list);
188
 
  } else {
189
 
    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
190
 
  }
191
 
 
192
 
  return item;
193
 
}
194
 
 
195
 
/**
196
 
  @brief Push an error message into MySQL error stack with line
197
 
  and position information.
198
 
 
199
 
  This function provides semantic action implementers with a way
200
 
  to push the famous "You have a syntax error near..." error
201
 
  message into the error stack, which is normally produced only if
202
 
  a parse error is discovered internally by the Bison generated
203
 
  parser.
204
 
*/
205
 
void my_parse_error(Lex_input_stream *lip)
206
 
{
207
 
  assert(lip);
208
 
 
209
 
  const char *yytext= lip->get_tok_start();
210
 
  /* Push an error into the error stack */
211
 
  my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
212
 
                  (yytext ? yytext : ""),
213
 
                  lip->yylineno);
214
 
}
215
 
 
216
 
void my_parse_error(const char *message)
217
 
{
218
 
  my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
219
 
}
220
 
 
221
 
bool check_reserved_words(LEX_STRING *name)
222
 
{
223
 
  if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
224
 
      !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
225
 
      !my_strcasecmp(system_charset_info, name->str, "SESSION"))
226
 
    return true;
227
 
 
228
 
  return false;
229
 
}
230
 
 
231
 
 
232
 
/**
233
 
  @brief Bison callback to report a syntax/OOM error
234
 
 
235
 
  This function is invoked by the bison-generated parser
236
 
  when a syntax error, a parse error or an out-of-memory
237
 
  condition occurs. This function is not invoked when the
238
 
  parser is requested to abort by semantic action code
239
 
  by means of YYABORT or YYACCEPT macros. This is why these
240
 
  macros should not be used (use DRIZZLE_YYABORT/DRIZZLE_YYACCEPT
241
 
  instead).
242
 
 
243
 
  The parser will abort immediately after invoking this callback.
244
 
 
245
 
  This function is not for use in semantic actions and is internal to
246
 
  the parser, as it performs some pre-return cleanup.
247
 
  In semantic actions, please use parser::my_parse_error or my_error to
248
 
  push an error into the error stack and DRIZZLE_YYABORT
249
 
  to abort from the parser.
250
 
*/
251
 
void errorOn(const char *s)
252
 
{
253
 
  Session *session= current_session;
254
 
 
255
 
  /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
256
 
  if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
257
 
  {
258
 
    parser::my_parse_error(session->m_lip);
259
 
  }
260
 
  else
261
 
  {
262
 
    parser::my_parse_error(s);
263
 
  }
264
 
}
265
 
 
266
 
bool buildOrderBy(LEX *lex)
267
 
{
268
 
  Select_Lex *sel= lex->current_select;
269
 
  Select_Lex_Unit *unit= sel-> master_unit();
270
 
 
271
 
  if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
272
 
      sel->olap != UNSPECIFIED_OLAP_TYPE &&
273
 
      (sel->linkage != UNION_TYPE || sel->braces))
274
 
  {
275
 
    my_error(ER_WRONG_USAGE, MYF(0),
276
 
             "CUBE/ROLLUP", "ORDER BY");
277
 
    return false;
278
 
  }
279
 
 
280
 
  if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
281
 
  {
282
 
    /*
283
 
      A query of the of the form (SELECT ...) ORDER BY order_list is
284
 
      executed in the same way as the query
285
 
      SELECT ... ORDER BY order_list
286
 
      unless the SELECT construct contains ORDER BY or LIMIT clauses.
287
 
      Otherwise we create a fake Select_Lex if it has not been created
288
 
      yet.
289
 
    */
290
 
    Select_Lex *first_sl= unit->first_select();
291
 
    if (!unit->is_union() &&
292
 
        (first_sl->order_list.elements ||
293
 
         first_sl->select_limit) &&           
294
 
        unit->add_fake_select_lex(lex->session))
295
 
    {
296
 
      return false;
297
 
    }
298
 
  }
299
 
 
300
 
  return true;
301
 
}
302
 
 
303
 
void buildEngineOption(LEX *lex, const char *key, const LEX_STRING &value)
304
 
{
305
 
  message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
306
 
  opt->set_name(key);
307
 
  opt->set_state(value.str, value.length);
308
 
}
309
 
 
310
 
void buildEngineOption(LEX *lex, const char *key, uint64_t value)
311
 
{
312
 
  drizzled::message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
313
 
  opt->set_name(key);
314
 
  opt->set_state(boost::lexical_cast<std::string>(value));
315
 
}
316
 
 
317
 
void buildSchemaOption(LEX *lex, const char *key, const LEX_STRING &value)
318
 
{
319
 
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
320
 
  message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
321
 
  opt->set_name(key);
322
 
  opt->set_state(value.str, value.length);
323
 
}
324
 
 
325
 
void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
326
 
{
327
 
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
328
 
  message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
329
 
  opt->set_name(key);
330
 
  opt->set_state(boost::lexical_cast<std::string>(value));
331
 
}
332
 
 
333
 
bool checkFieldIdent(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
334
 
{
335
 
  TableList *table= reinterpret_cast<TableList*>(lex->current_select->table_list.first);
336
 
 
337
 
  if (schema_name.length)
338
 
  {
339
 
    if (my_strcasecmp(table_alias_charset, schema_name.str, table->getSchemaName()))
340
 
    {
341
 
      my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.str);
342
 
      return false;
343
 
    }
344
 
  }
345
 
 
346
 
  if (my_strcasecmp(table_alias_charset, table_name.str,
347
 
                    table->getTableName()))
348
 
  {
349
 
    my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
350
 
    return false;
351
 
  }
352
 
 
353
 
  return true;
354
 
}
355
 
 
356
 
Item *buildIdent(LEX *lex,
357
 
                 const LEX_STRING &schema_name,
358
 
                 const LEX_STRING &table_name,
359
 
                 const LEX_STRING &field_name)
360
 
{
361
 
  Select_Lex *sel= lex->current_select;
362
 
 
363
 
  if (table_name.length and sel->no_table_names_allowed)
364
 
  {
365
 
    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
366
 
             MYF(0), table_name.str, lex->session->where());
367
 
  }
368
 
 
369
 
  Item *item= (sel->parsing_place != IN_HAVING or
370
 
               sel->get_in_sum_expr() > 0) ?
371
 
    (Item*) new Item_field(lex->current_context(), schema_name.str, table_name.str, field_name.str) :
372
 
    (Item*) new Item_ref(lex->current_context(), schema_name.str, table_name.str, field_name.str);
373
 
 
374
 
  return item;
375
 
}
376
 
 
377
 
Item *buildTableWild(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
378
 
{
379
 
  Select_Lex *sel= lex->current_select;
380
 
  Item *item= new Item_field(lex->current_context(), schema_name.str, table_name.str, "*");
381
 
  sel->with_wild++;
382
 
 
383
 
  return item;
384
 
}
385
 
 
386
 
void buildCreateFieldIdent(LEX *lex)
387
 
{
388
 
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
389
 
  lex->length= lex->dec=0;
390
 
  lex->type=0;
391
 
  statement->default_value= statement->on_update_value= 0;
392
 
  statement->comment= null_lex_str;
393
 
  lex->charset= NULL;
394
 
  statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
395
 
 
396
 
  message::AlterTable &alter_proto= ((statement::CreateTable *)lex->statement)->alter_info.alter_proto;
397
 
  lex->setField(alter_proto.add_added_field());
398
 
}
399
 
 
400
 
void storeAlterColumnPosition(LEX *lex, const char *position)
401
 
{
402
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
403
 
 
404
 
  lex->last_field->after=const_cast<char*> (position);
405
 
  statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
406
 
}
407
 
 
408
 
bool buildCollation(LEX *lex, const CHARSET_INFO *arg)
409
 
{
410
 
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
411
 
 
412
 
  HA_CREATE_INFO *cinfo= &statement->create_info();
413
 
  if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
414
 
      cinfo->default_table_charset && arg &&
415
 
      !my_charset_same(cinfo->default_table_charset, arg))
416
 
  {
417
 
    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
418
 
             arg->name, cinfo->default_table_charset->csname);
419
 
    return false;
420
 
  }
421
 
  statement->create_info().default_table_charset= arg;
422
 
  statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
423
 
 
424
 
  return true;
425
 
}
426
 
 
427
 
void buildKey(LEX *lex, Key::Keytype type_par, const lex_string_t &name_arg)
428
 
{
429
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
430
 
  Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0,
431
 
                    lex->col_list);
432
 
  statement->alter_info.key_list.push_back(key);
433
 
  lex->col_list.empty(); /* Alloced by memory::sql_alloc */
434
 
}
435
 
 
436
 
void buildForeignKey(LEX *lex, const lex_string_t &name_arg, drizzled::Table_ident *table)
437
 
{
438
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
439
 
  Key *key= new Foreign_key(name_arg, lex->col_list,
440
 
                            table,
441
 
                            lex->ref_list,
442
 
                            statement->fk_delete_opt,
443
 
                            statement->fk_update_opt,
444
 
                            statement->fk_match_option);
445
 
 
446
 
  statement->alter_info.key_list.push_back(key);
447
 
  key= new Key(Key::MULTIPLE, name_arg,
448
 
               &default_key_create_info, 1,
449
 
               lex->col_list);
450
 
  statement->alter_info.key_list.push_back(key);
451
 
  lex->col_list.empty(); /* Alloced by memory::sql_alloc */
452
 
  /* Only used for ALTER TABLE. Ignored otherwise. */
453
 
  statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
454
 
}
455
 
 
456
 
drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
457
 
458
 
  lex->length=(char*) 0; /* use default length */
459
 
 
460
 
  if (is_unsigned)
461
 
  {
462
 
    final_type= DRIZZLE_TYPE_LONGLONG;
463
 
  }
464
 
 
465
 
  if (lex->field())
466
 
  {
467
 
    assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
468
 
    // We update the type for unsigned types
469
 
    if (is_unsigned)
470
 
    {
471
 
      lex->field()->set_type(message::Table::Field::BIGINT);
472
 
      lex->field()->mutable_constraints()->set_is_unsigned(true);
473
 
    }
474
 
    else if (final_type == DRIZZLE_TYPE_LONG)
475
 
    {
476
 
      lex->field()->set_type(message::Table::Field::INTEGER);
477
 
    }
478
 
    else if (final_type == DRIZZLE_TYPE_LONGLONG)
479
 
    {
480
 
      lex->field()->set_type(message::Table::Field::BIGINT);
481
 
    }
482
 
  }
483
 
 
484
 
  return final_type;
485
 
}
486
 
 
487
 
drizzled::enum_field_types buildSerialColumn(LEX *lex)
488
 
{
489
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
490
 
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
491
 
 
492
 
  lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
493
 
 
494
 
  if (lex->field())
495
 
  {
496
 
    lex->field()->mutable_constraints()->set_is_notnull(true);
497
 
    lex->field()->mutable_constraints()->set_is_unsigned(true);
498
 
 
499
 
    lex->field()->set_type(message::Table::Field::BIGINT);
500
 
  }
501
 
 
502
 
  return DRIZZLE_TYPE_LONGLONG;
503
 
}
504
 
 
505
 
drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
506
 
{
507
 
  lex->length= const_cast<char *>(length);
508
 
 
509
 
  if (lex->field())
510
 
  {
511
 
    lex->field()->set_type(message::Table::Field::VARCHAR);
512
 
 
513
 
    message::Table::Field::StringFieldOptions *string_field_options;
514
 
 
515
 
    string_field_options= lex->field()->mutable_string_options();
516
 
 
517
 
    string_field_options->set_length(atoi(length));
518
 
  }
519
 
 
520
 
  return DRIZZLE_TYPE_VARCHAR;
521
 
}
522
 
 
523
 
drizzled::enum_field_types buildDecimalColumn(LEX *lex)
524
 
{
525
 
  if (lex->field())
526
 
    lex->field()->set_type(message::Table::Field::DECIMAL);
527
 
 
528
 
  return DRIZZLE_TYPE_DECIMAL;
529
 
}
530
 
 
531
 
drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
532
 
{
533
 
  lex->length= const_cast<char *>(length);
534
 
  lex->charset= &my_charset_bin;
535
 
 
536
 
  if (lex->field())
537
 
  {
538
 
    lex->field()->set_type(message::Table::Field::VARCHAR);
539
 
 
540
 
    message::Table::Field::StringFieldOptions *string_field_options;
541
 
 
542
 
    string_field_options= lex->field()->mutable_string_options();
543
 
 
544
 
    string_field_options->set_length(atoi(length));
545
 
    string_field_options->set_collation_id(my_charset_bin.number);
546
 
    string_field_options->set_collation(my_charset_bin.name);
547
 
  }
548
 
 
549
 
  return DRIZZLE_TYPE_VARCHAR;
550
 
}
551
 
 
552
 
drizzled::enum_field_types buildBlobColumn(LEX *lex)
553
 
{
554
 
  lex->charset=&my_charset_bin;
555
 
  lex->length=(char*) 0; /* use default length */
556
 
 
557
 
  if (lex->field())
558
 
  {
559
 
    lex->field()->set_type(message::Table::Field::BLOB);
560
 
    message::Table::Field::StringFieldOptions *string_field_options;
561
 
 
562
 
    string_field_options= lex->field()->mutable_string_options();
563
 
    string_field_options->set_collation_id(my_charset_bin.number);
564
 
    string_field_options->set_collation(my_charset_bin.name);
565
 
  }
566
 
 
567
 
  return DRIZZLE_TYPE_BLOB;
568
 
}
569
 
 
570
 
drizzled::enum_field_types buildBooleanColumn(LEX *lex)
571
 
{
572
 
  if (lex->field())
573
 
    lex->field()->set_type(message::Table::Field::BOOLEAN);
574
 
 
575
 
  return DRIZZLE_TYPE_BOOLEAN;
576
 
}
577
 
 
578
 
drizzled::enum_field_types buildUuidColumn(LEX *lex)
579
 
{
580
 
  if (lex->field())
581
 
    lex->field()->set_type(message::Table::Field::UUID);
582
 
 
583
 
  return DRIZZLE_TYPE_UUID;
584
 
}
585
 
 
586
 
drizzled::enum_field_types buildDoubleColumn(LEX *lex)
587
 
{
588
 
  if (lex->field())
589
 
  {
590
 
    lex->field()->set_type(message::Table::Field::DOUBLE);
591
 
  }
592
 
 
593
 
  return DRIZZLE_TYPE_DOUBLE;
594
 
}
595
 
 
596
 
drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
597
 
{
598
 
  if (lex->field())
599
 
  {
600
 
    lex->field()->set_type(message::Table::Field::EPOCH);
601
 
  }
602
 
 
603
 
  if (length)
604
 
  {
605
 
    lex->length= const_cast<char *>(length);
606
 
    return DRIZZLE_TYPE_MICROTIME;
607
 
  }
608
 
 
609
 
  lex->length= NULL;
610
 
 
611
 
  return DRIZZLE_TYPE_TIMESTAMP;
612
 
}
613
 
 
614
 
void buildKeyOnColumn(LEX *lex)
615
 
{
616
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
617
 
 
618
 
  lex->type|= UNIQUE_KEY_FLAG;
619
 
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
620
 
 
621
 
  if (lex->field())
622
 
  {
623
 
    lex->field()->mutable_constraints()->set_is_unique(true);
624
 
  }
625
 
}
626
 
 
627
 
void buildAutoOnColumn(LEX *lex)
628
 
{
629
 
  lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
630
 
 
631
 
  if (lex->field())
632
 
  {
633
 
    lex->field()->mutable_constraints()->set_is_notnull(true);
634
 
  }
635
 
}
636
 
 
637
 
void buildPrimaryOnColumn(LEX *lex)
638
 
{
639
 
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
640
 
 
641
 
  lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
642
 
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
643
 
 
644
 
  if (lex->field())
645
 
  {
646
 
    lex->field()->mutable_constraints()->set_is_notnull(true);
647
 
  }
648
 
}
649
 
 
650
 
} // namespace parser
651
 
} // namespace drizzled