~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/parser.cc

  • Committer: Lee Bieber
  • Date: 2011-03-29 22:31:41 UTC
  • mfrom: (2257.1.3 build)
  • Revision ID: kalebral@gmail.com-20110329223141-yxc22h3l2he58sk0
Merge Andrew - 743842: Build failure using GCC 4.6
Merge Stewart - 738022: CachedDirectory silently fails to add entries if stat() fails
Merge Olaf - Common fwd: add copyright, add more declaration

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
#include <drizzled/session.h>
 
23
#include <drizzled/parser.h>
 
24
#include <drizzled/alter_info.h>
 
25
 
 
26
#include <drizzled/message/alter_table.pb.h>
 
27
#include <drizzled/item/subselect.h>
 
28
#include <drizzled/sql_lex.h>
 
29
 
 
30
namespace drizzled {
 
31
namespace parser {
 
32
 
 
33
/**
 
34
  Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
 
35
  See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
 
36
  This function returns the proper item for the SQL expression
 
37
  <code>left [NOT] IN ( expr )</code>
 
38
  @param session the current thread
 
39
  @param left the in predicand
 
40
  @param equal true for IN predicates, false for NOT IN predicates
 
41
  @param expr first and only expression of the in value list
 
42
  @return an expression representing the IN predicate.
 
43
*/
 
44
 
 
45
Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
 
46
{
 
47
  /*
 
48
    Relevant references for this issue:
 
49
    - SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
 
50
    - SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
 
51
    - SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
 
52
    - SQL:2003, Part 2, section 7.15 <subquery>, page 370,
 
53
    - SQL:2003 Feature F561, "Full value expressions".
 
54
 
 
55
    The exception in SQL:2003 Note 184 means:
 
56
    Item_singlerow_subselect, which corresponds to a <scalar subquery>,
 
57
    should be re-interpreted as an Item_in_subselect, which corresponds
 
58
    to a <table subquery> when used inside an <in predicate>.
 
59
 
 
60
    Our reading of Note 184 is reccursive, so that all:
 
61
    - IN (( <subquery> ))
 
62
    - IN ((( <subquery> )))
 
63
    - IN '('^N <subquery> ')'^N
 
64
    - etc
 
65
    should be interpreted as a <table subquery>, no matter how deep in the
 
66
    expression the <subquery> is.
 
67
  */
 
68
 
 
69
  Item *result;
 
70
 
 
71
  if (expr->type() == Item::SUBSELECT_ITEM)
 
72
  {
 
73
    Item_subselect *expr2 = (Item_subselect*) expr;
 
74
 
 
75
    if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
 
76
    {
 
77
      Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
 
78
      Select_Lex *subselect;
 
79
 
 
80
      /*
 
81
        Implement the mandated change, by altering the semantic tree:
 
82
          left IN Item_singlerow_subselect(subselect)
 
83
        is modified to
 
84
          left IN (subselect)
 
85
        which is represented as
 
86
          Item_in_subselect(left, subselect)
 
87
      */
 
88
      subselect= expr3->invalidate_and_restore_select_lex();
 
89
      result= new (session->mem_root) Item_in_subselect(left, subselect);
 
90
 
 
91
      if (! equal)
 
92
        result = negate_expression(session, result);
 
93
 
 
94
      return(result);
 
95
    }
 
96
  }
 
97
 
 
98
  if (equal)
 
99
    result= new (session->mem_root) Item_func_eq(left, expr);
 
100
  else
 
101
    result= new (session->mem_root) Item_func_ne(left, expr);
 
102
 
 
103
  return(result);
 
104
}
 
105
 
 
106
/**
 
107
   @brief Creates a new Select_Lex for a UNION branch.
 
108
 
 
109
   Sets up and initializes a Select_Lex structure for a query once the parser
 
110
   discovers a UNION token. The current Select_Lex is pushed on the stack and
 
111
   the new Select_Lex becomes the current one..=
 
112
 
 
113
   @lex The parser state.
 
114
 
 
115
   @is_union_distinct True if the union preceding the new select statement
 
116
   uses UNION DISTINCT.
 
117
 
 
118
   @return <code>false</code> if successful, <code>true</code> if an error was
 
119
   reported. In the latter case parsing should stop.
 
120
 */
 
121
bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
 
122
{
 
123
  if (lex->result)
 
124
  {
 
125
    /* Only the last SELECT can have  INTO...... */
 
126
    my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
 
127
    return true;
 
128
  }
 
129
  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
 
130
  {
 
131
    my_parse_error(session->m_lip);
 
132
    return true;
 
133
  }
 
134
  /* This counter shouldn't be incremented for UNION parts */
 
135
  lex->nest_level--;
 
136
  if (new_select(lex, 0))
 
137
    return true;
 
138
  init_select(lex);
 
139
  lex->current_select->linkage=UNION_TYPE;
 
140
  if (is_union_distinct) /* UNION DISTINCT - remember position */
 
141
    lex->current_select->master_unit()->union_distinct=
 
142
      lex->current_select;
 
143
  return false;
 
144
}
 
145
 
 
146
/**
 
147
   @brief Initializes a Select_Lex for a query within parentheses (aka
 
148
   braces).
 
149
 
 
150
   @return false if successful, true if an error was reported. In the latter
 
151
   case parsing should stop.
 
152
 */
 
153
bool setup_select_in_parentheses(Session *session, LEX *lex)
 
154
{
 
155
  Select_Lex * sel= lex->current_select;
 
156
  if (sel->set_braces(1))
 
157
  {
 
158
    my_parse_error(session->m_lip);
 
159
    return true;
 
160
  }
 
161
  if (sel->linkage == UNION_TYPE &&
 
162
      !sel->master_unit()->first_select()->braces &&
 
163
      sel->master_unit()->first_select()->linkage ==
 
164
      UNION_TYPE)
 
165
  {
 
166
    my_parse_error(session->m_lip);
 
167
    return true;
 
168
  }
 
169
  if (sel->linkage == UNION_TYPE &&
 
170
      sel->olap != UNSPECIFIED_OLAP_TYPE &&
 
171
      sel->master_unit()->fake_select_lex)
 
172
  {
 
173
    my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
 
174
    return true;
 
175
  }
 
176
  /* select in braces, can't contain global parameters */
 
177
  if (sel->master_unit()->fake_select_lex)
 
178
    sel->master_unit()->global_parameters=
 
179
      sel->master_unit()->fake_select_lex;
 
180
  return false;
 
181
}
 
182
 
 
183
Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
 
184
{
 
185
  const plugin::Function *udf= plugin::Function::get(name);
 
186
 
 
187
  if (udf)
 
188
  {
 
189
    return Create_udf_func::s_singleton.create(session, udf, item_list);
 
190
  }
 
191
 
 
192
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
 
193
 
 
194
  return NULL;
 
195
}
 
196
 
 
197
/**
 
198
  @brief Push an error message into MySQL error stack with line
 
199
  and position information.
 
200
 
 
201
  This function provides semantic action implementers with a way
 
202
  to push the famous "You have a syntax error near..." error
 
203
  message into the error stack, which is normally produced only if
 
204
  a parse error is discovered internally by the Bison generated
 
205
  parser.
 
206
*/
 
207
void my_parse_error(Lex_input_stream *lip)
 
208
{
 
209
  assert(lip);
 
210
 
 
211
  const char *yytext= lip->get_tok_start();
 
212
  /* Push an error into the error stack */
 
213
  my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
 
214
                  (yytext ? yytext : ""),
 
215
                  lip->yylineno);
 
216
}
 
217
 
 
218
void my_parse_error(const char *message)
 
219
{
 
220
  my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
 
221
}
 
222
 
 
223
bool check_reserved_words(LEX_STRING *name)
 
224
{
 
225
  if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
 
226
      !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
 
227
      !my_strcasecmp(system_charset_info, name->str, "SESSION"))
 
228
    return true;
 
229
 
 
230
  return false;
 
231
}
 
232
 
 
233
 
 
234
/**
 
235
  @brief Bison callback to report a syntax/OOM error
 
236
 
 
237
  This function is invoked by the bison-generated parser
 
238
  when a syntax error, a parse error or an out-of-memory
 
239
  condition occurs. This function is not invoked when the
 
240
  parser is requested to abort by semantic action code
 
241
  by means of YYABORT or YYACCEPT macros. This is why these
 
242
  macros should not be used (use DRIZZLE_YYABORT/DRIZZLE_YYACCEPT
 
243
  instead).
 
244
 
 
245
  The parser will abort immediately after invoking this callback.
 
246
 
 
247
  This function is not for use in semantic actions and is internal to
 
248
  the parser, as it performs some pre-return cleanup.
 
249
  In semantic actions, please use parser::my_parse_error or my_error to
 
250
  push an error into the error stack and DRIZZLE_YYABORT
 
251
  to abort from the parser.
 
252
*/
 
253
void errorOn(drizzled::Session *session, const char *s)
 
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::AddedFields &added_fields_proto= ((statement::CreateTable *)lex->statement)->alter_info.added_fields_proto;
 
397
  lex->setField(added_fields_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_st *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.clear(); /* 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.clear(); /* 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
void buildReplicationOption(LEX *lex, bool arg)
 
651
{
 
652
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
 
653
  message::set_is_replicated(statement->schema_message, arg);
 
654
}
 
655
 
 
656
void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
 
657
{
 
658
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
 
659
 
 
660
  message::AlterTable::AlterTableOperation *operation;
 
661
  operation= lex->alter_table()->add_operations();
 
662
  operation->set_drop_name(name);
 
663
 
 
664
  statement->alter_info.flags.set(ALTER_DROP_INDEX);
 
665
  if (is_foreign_key)
 
666
  {
 
667
    statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
 
668
    operation->set_operation(message::AlterTable::AlterTableOperation::DROP_FOREIGN_KEY);
 
669
  }
 
670
  else
 
671
  {
 
672
    operation->set_operation(message::AlterTable::AlterTableOperation::DROP_KEY);
 
673
  }
 
674
}
 
675
 
 
676
} // namespace parser
 
677
} // namespace drizzled