~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/parser.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

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(drizzled::Session *session, const char *s)
 
252
{
 
253
  /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
 
254
  if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
 
255
  {
 
256
    parser::my_parse_error(session->m_lip);
 
257
  }
 
258
  else
 
259
  {
 
260
    parser::my_parse_error(s);
 
261
  }
 
262
}
 
263
 
 
264
bool buildOrderBy(LEX *lex)
 
265
{
 
266
  Select_Lex *sel= lex->current_select;
 
267
  Select_Lex_Unit *unit= sel-> master_unit();
 
268
 
 
269
  if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
 
270
      sel->olap != UNSPECIFIED_OLAP_TYPE &&
 
271
      (sel->linkage != UNION_TYPE || sel->braces))
 
272
  {
 
273
    my_error(ER_WRONG_USAGE, MYF(0),
 
274
             "CUBE/ROLLUP", "ORDER BY");
 
275
    return false;
 
276
  }
 
277
 
 
278
  if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
 
279
  {
 
280
    /*
 
281
      A query of the of the form (SELECT ...) ORDER BY order_list is
 
282
      executed in the same way as the query
 
283
      SELECT ... ORDER BY order_list
 
284
      unless the SELECT construct contains ORDER BY or LIMIT clauses.
 
285
      Otherwise we create a fake Select_Lex if it has not been created
 
286
      yet.
 
287
    */
 
288
    Select_Lex *first_sl= unit->first_select();
 
289
    if (!unit->is_union() &&
 
290
        (first_sl->order_list.elements ||
 
291
         first_sl->select_limit) &&           
 
292
        unit->add_fake_select_lex(lex->session))
 
293
    {
 
294
      return false;
 
295
    }
 
296
  }
 
297
 
 
298
  return true;
 
299
}
 
300
 
 
301
void buildEngineOption(LEX *lex, const char *key, const LEX_STRING &value)
 
302
{
 
303
  message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
 
304
  opt->set_name(key);
 
305
  opt->set_state(value.str, value.length);
 
306
}
 
307
 
 
308
void buildEngineOption(LEX *lex, const char *key, uint64_t value)
 
309
{
 
310
  drizzled::message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
 
311
  opt->set_name(key);
 
312
  opt->set_state(boost::lexical_cast<std::string>(value));
 
313
}
 
314
 
 
315
void buildSchemaOption(LEX *lex, const char *key, const LEX_STRING &value)
 
316
{
 
317
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
 
318
  message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
 
319
  opt->set_name(key);
 
320
  opt->set_state(value.str, value.length);
 
321
}
 
322
 
 
323
void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
 
324
{
 
325
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
 
326
  message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
 
327
  opt->set_name(key);
 
328
  opt->set_state(boost::lexical_cast<std::string>(value));
 
329
}
 
330
 
 
331
bool checkFieldIdent(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
 
332
{
 
333
  TableList *table= reinterpret_cast<TableList*>(lex->current_select->table_list.first);
 
334
 
 
335
  if (schema_name.length)
 
336
  {
 
337
    if (my_strcasecmp(table_alias_charset, schema_name.str, table->getSchemaName()))
 
338
    {
 
339
      my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.str);
 
340
      return false;
 
341
    }
 
342
  }
 
343
 
 
344
  if (my_strcasecmp(table_alias_charset, table_name.str,
 
345
                    table->getTableName()))
 
346
  {
 
347
    my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
 
348
    return false;
 
349
  }
 
350
 
 
351
  return true;
 
352
}
 
353
 
 
354
Item *buildIdent(LEX *lex,
 
355
                 const LEX_STRING &schema_name,
 
356
                 const LEX_STRING &table_name,
 
357
                 const LEX_STRING &field_name)
 
358
{
 
359
  Select_Lex *sel= lex->current_select;
 
360
 
 
361
  if (table_name.length and sel->no_table_names_allowed)
 
362
  {
 
363
    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
 
364
             MYF(0), table_name.str, lex->session->where());
 
365
  }
 
366
 
 
367
  Item *item= (sel->parsing_place != IN_HAVING or
 
368
               sel->get_in_sum_expr() > 0) ?
 
369
    (Item*) new Item_field(lex->current_context(), schema_name.str, table_name.str, field_name.str) :
 
370
    (Item*) new Item_ref(lex->current_context(), schema_name.str, table_name.str, field_name.str);
 
371
 
 
372
  return item;
 
373
}
 
374
 
 
375
Item *buildTableWild(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
 
376
{
 
377
  Select_Lex *sel= lex->current_select;
 
378
  Item *item= new Item_field(lex->current_context(), schema_name.str, table_name.str, "*");
 
379
  sel->with_wild++;
 
380
 
 
381
  return item;
 
382
}
 
383
 
 
384
void buildCreateFieldIdent(LEX *lex)
 
385
{
 
386
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
 
387
  lex->length= lex->dec=0;
 
388
  lex->type=0;
 
389
  statement->default_value= statement->on_update_value= 0;
 
390
  statement->comment= null_lex_str;
 
391
  lex->charset= NULL;
 
392
  statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
 
393
 
 
394
  message::AlterTable &alter_proto= ((statement::CreateTable *)lex->statement)->alter_info.alter_proto;
 
395
  lex->setField(alter_proto.add_added_field());
 
396
}
 
397
 
 
398
void storeAlterColumnPosition(LEX *lex, const char *position)
 
399
{
 
400
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
401
 
 
402
  lex->last_field->after=const_cast<char*> (position);
 
403
  statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
 
404
}
 
405
 
 
406
bool buildCollation(LEX *lex, const CHARSET_INFO *arg)
 
407
{
 
408
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
 
409
 
 
410
  HA_CREATE_INFO *cinfo= &statement->create_info();
 
411
  if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
 
412
      cinfo->default_table_charset && arg &&
 
413
      !my_charset_same(cinfo->default_table_charset, arg))
 
414
  {
 
415
    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
 
416
             arg->name, cinfo->default_table_charset->csname);
 
417
    return false;
 
418
  }
 
419
  statement->create_info().default_table_charset= arg;
 
420
  statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
 
421
 
 
422
  return true;
 
423
}
 
424
 
 
425
void buildKey(LEX *lex, Key::Keytype type_par, const lex_string_t &name_arg)
 
426
{
 
427
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
428
  Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0,
 
429
                    lex->col_list);
 
430
  statement->alter_info.key_list.push_back(key);
 
431
  lex->col_list.clear(); /* Alloced by memory::sql_alloc */
 
432
}
 
433
 
 
434
void buildForeignKey(LEX *lex, const lex_string_t &name_arg, drizzled::Table_ident *table)
 
435
{
 
436
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
437
  Key *key= new Foreign_key(name_arg, lex->col_list,
 
438
                            table,
 
439
                            lex->ref_list,
 
440
                            statement->fk_delete_opt,
 
441
                            statement->fk_update_opt,
 
442
                            statement->fk_match_option);
 
443
 
 
444
  statement->alter_info.key_list.push_back(key);
 
445
  key= new Key(Key::MULTIPLE, name_arg,
 
446
               &default_key_create_info, 1,
 
447
               lex->col_list);
 
448
  statement->alter_info.key_list.push_back(key);
 
449
  lex->col_list.clear(); /* Alloced by memory::sql_alloc */
 
450
  /* Only used for ALTER TABLE. Ignored otherwise. */
 
451
  statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
 
452
}
 
453
 
 
454
drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
 
455
 
456
  lex->length=(char*) 0; /* use default length */
 
457
 
 
458
  if (is_unsigned)
 
459
  {
 
460
    final_type= DRIZZLE_TYPE_LONGLONG;
 
461
  }
 
462
 
 
463
  if (lex->field())
 
464
  {
 
465
    assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
 
466
    // We update the type for unsigned types
 
467
    if (is_unsigned)
 
468
    {
 
469
      lex->field()->set_type(message::Table::Field::BIGINT);
 
470
      lex->field()->mutable_constraints()->set_is_unsigned(true);
 
471
    }
 
472
    else if (final_type == DRIZZLE_TYPE_LONG)
 
473
    {
 
474
      lex->field()->set_type(message::Table::Field::INTEGER);
 
475
    }
 
476
    else if (final_type == DRIZZLE_TYPE_LONGLONG)
 
477
    {
 
478
      lex->field()->set_type(message::Table::Field::BIGINT);
 
479
    }
 
480
  }
 
481
 
 
482
  return final_type;
 
483
}
 
484
 
 
485
drizzled::enum_field_types buildSerialColumn(LEX *lex)
 
486
{
 
487
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
488
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
 
489
 
 
490
  lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
 
491
 
 
492
  if (lex->field())
 
493
  {
 
494
    lex->field()->mutable_constraints()->set_is_notnull(true);
 
495
    lex->field()->mutable_constraints()->set_is_unsigned(true);
 
496
 
 
497
    lex->field()->set_type(message::Table::Field::BIGINT);
 
498
  }
 
499
 
 
500
  return DRIZZLE_TYPE_LONGLONG;
 
501
}
 
502
 
 
503
drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
 
504
{
 
505
  lex->length= const_cast<char *>(length);
 
506
 
 
507
  if (lex->field())
 
508
  {
 
509
    lex->field()->set_type(message::Table::Field::VARCHAR);
 
510
 
 
511
    message::Table::Field::StringFieldOptions *string_field_options;
 
512
 
 
513
    string_field_options= lex->field()->mutable_string_options();
 
514
 
 
515
    string_field_options->set_length(atoi(length));
 
516
  }
 
517
 
 
518
  return DRIZZLE_TYPE_VARCHAR;
 
519
}
 
520
 
 
521
drizzled::enum_field_types buildDecimalColumn(LEX *lex)
 
522
{
 
523
  if (lex->field())
 
524
    lex->field()->set_type(message::Table::Field::DECIMAL);
 
525
 
 
526
  return DRIZZLE_TYPE_DECIMAL;
 
527
}
 
528
 
 
529
drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
 
530
{
 
531
  lex->length= const_cast<char *>(length);
 
532
  lex->charset= &my_charset_bin;
 
533
 
 
534
  if (lex->field())
 
535
  {
 
536
    lex->field()->set_type(message::Table::Field::VARCHAR);
 
537
 
 
538
    message::Table::Field::StringFieldOptions *string_field_options;
 
539
 
 
540
    string_field_options= lex->field()->mutable_string_options();
 
541
 
 
542
    string_field_options->set_length(atoi(length));
 
543
    string_field_options->set_collation_id(my_charset_bin.number);
 
544
    string_field_options->set_collation(my_charset_bin.name);
 
545
  }
 
546
 
 
547
  return DRIZZLE_TYPE_VARCHAR;
 
548
}
 
549
 
 
550
drizzled::enum_field_types buildBlobColumn(LEX *lex)
 
551
{
 
552
  lex->charset=&my_charset_bin;
 
553
  lex->length=(char*) 0; /* use default length */
 
554
 
 
555
  if (lex->field())
 
556
  {
 
557
    lex->field()->set_type(message::Table::Field::BLOB);
 
558
    message::Table::Field::StringFieldOptions *string_field_options;
 
559
 
 
560
    string_field_options= lex->field()->mutable_string_options();
 
561
    string_field_options->set_collation_id(my_charset_bin.number);
 
562
    string_field_options->set_collation(my_charset_bin.name);
 
563
  }
 
564
 
 
565
  return DRIZZLE_TYPE_BLOB;
 
566
}
 
567
 
 
568
drizzled::enum_field_types buildBooleanColumn(LEX *lex)
 
569
{
 
570
  if (lex->field())
 
571
    lex->field()->set_type(message::Table::Field::BOOLEAN);
 
572
 
 
573
  return DRIZZLE_TYPE_BOOLEAN;
 
574
}
 
575
 
 
576
drizzled::enum_field_types buildUuidColumn(LEX *lex)
 
577
{
 
578
  if (lex->field())
 
579
    lex->field()->set_type(message::Table::Field::UUID);
 
580
 
 
581
  return DRIZZLE_TYPE_UUID;
 
582
}
 
583
 
 
584
drizzled::enum_field_types buildDoubleColumn(LEX *lex)
 
585
{
 
586
  if (lex->field())
 
587
  {
 
588
    lex->field()->set_type(message::Table::Field::DOUBLE);
 
589
  }
 
590
 
 
591
  return DRIZZLE_TYPE_DOUBLE;
 
592
}
 
593
 
 
594
drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
 
595
{
 
596
  if (lex->field())
 
597
  {
 
598
    lex->field()->set_type(message::Table::Field::EPOCH);
 
599
  }
 
600
 
 
601
  if (length)
 
602
  {
 
603
    lex->length= const_cast<char *>(length);
 
604
    return DRIZZLE_TYPE_MICROTIME;
 
605
  }
 
606
 
 
607
  lex->length= NULL;
 
608
 
 
609
  return DRIZZLE_TYPE_TIMESTAMP;
 
610
}
 
611
 
 
612
void buildKeyOnColumn(LEX *lex)
 
613
{
 
614
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
615
 
 
616
  lex->type|= UNIQUE_KEY_FLAG;
 
617
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
 
618
 
 
619
  if (lex->field())
 
620
  {
 
621
    lex->field()->mutable_constraints()->set_is_unique(true);
 
622
  }
 
623
}
 
624
 
 
625
void buildAutoOnColumn(LEX *lex)
 
626
{
 
627
  lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
 
628
 
 
629
  if (lex->field())
 
630
  {
 
631
    lex->field()->mutable_constraints()->set_is_notnull(true);
 
632
  }
 
633
}
 
634
 
 
635
void buildPrimaryOnColumn(LEX *lex)
 
636
{
 
637
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
638
 
 
639
  lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
 
640
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
 
641
 
 
642
  if (lex->field())
 
643
  {
 
644
    lex->field()->mutable_constraints()->set_is_notnull(true);
 
645
  }
 
646
}
 
647
 
 
648
void buildReplicationOption(LEX *lex, bool arg)
 
649
{
 
650
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
 
651
  message::ReplicationOptions *options= statement->schema_message.mutable_replication_options();
 
652
  options->set_dont_replicate(arg);
 
653
}
 
654
 
 
655
void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
 
656
{
 
657
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
658
 
 
659
  statement->alter_info.flags.set(ALTER_DROP_INDEX);
 
660
  if (is_foreign_key)
 
661
  {
 
662
    statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
 
663
    statement->alter_info.drop_list.push_back(new AlterDrop(AlterDrop::FOREIGN_KEY, name));
 
664
  }
 
665
  else
 
666
  {
 
667
    statement->alter_info.drop_list.push_back(new AlterDrop(AlterDrop::KEY, name));
 
668
  }
 
669
}
 
670
 
 
671
} // namespace parser
 
672
} // namespace drizzled