~drizzle-trunk/drizzle/development

2096.1.14 by Brian Aker
Pull in more C code from parser.
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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
128
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
155
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
163
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
*/
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
205
void my_parse_error(Lex_input_stream *lip)
2096.1.14 by Brian Aker
Pull in more C code from parser.
206
{
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
207
  assert(lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
208
209
  const char *yytext= lip->get_tok_start();
210
  /* Push an error into the error stack */
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
211
  my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
2096.1.14 by Brian Aker
Pull in more C code from parser.
212
                  (yytext ? yytext : ""),
213
                  lip->yylineno);
214
}
215
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
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
2096.1.15 by Brian Aker
Additional parser cleanup.
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
2104.3.1 by Brian Aker
Merge in ulong typedef used.
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)
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
257
  {
258
    parser::my_parse_error(session->m_lip);
259
  }
260
  else
261
  {
262
    parser::my_parse_error(s);
263
  }
2104.3.1 by Brian Aker
Merge in ulong typedef used.
264
}
265
2114.4.9 by Brian Aker
Try not to pass session quite as often
266
bool buildOrderBy(LEX *lex)
2104.3.4 by Brian Aker
Encapsulate from parser buildOrderBy()
267
{
2114.4.9 by Brian Aker
Try not to pass session quite as often
268
  Select_Lex *sel= lex->current_select;
2104.3.4 by Brian Aker
Encapsulate from parser buildOrderBy()
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
2114.4.9 by Brian Aker
Try not to pass session quite as often
280
  if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
2104.3.4 by Brian Aker
Encapsulate from parser buildOrderBy()
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) &&           
2114.4.9 by Brian Aker
Try not to pass session quite as often
294
        unit->add_fake_select_lex(lex->session))
2104.3.4 by Brian Aker
Encapsulate from parser buildOrderBy()
295
    {
296
      return false;
297
    }
298
  }
299
300
  return true;
301
}
2096.1.14 by Brian Aker
Pull in more C code from parser.
302
2114.4.9 by Brian Aker
Try not to pass session quite as often
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);
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
336
2114.4.6 by Brian Aker
Remove duplicate call by using null
337
  if (schema_name.length)
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
338
  {
2114.4.6 by Brian Aker
Remove duplicate call by using null
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
    }
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
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
2114.4.9 by Brian Aker
Try not to pass session quite as often
356
Item *buildIdent(LEX *lex,
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
357
                 const LEX_STRING &schema_name,
358
                 const LEX_STRING &table_name,
359
                 const LEX_STRING &field_name)
360
{
2114.4.9 by Brian Aker
Try not to pass session quite as often
361
  Select_Lex *sel= lex->current_select;
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
362
2114.4.7 by Brian Aker
Pull simple_ident into method.
363
  if (table_name.length and sel->no_table_names_allowed)
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
364
  {
365
    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
2114.4.10 by Brian Aker
Remove current_session from a couple of locations, encapsulate where in
366
             MYF(0), table_name.str, lex->session->where());
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
367
  }
368
369
  Item *item= (sel->parsing_place != IN_HAVING or
370
               sel->get_in_sum_expr() > 0) ?
2114.4.9 by Brian Aker
Try not to pass session quite as often
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);
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
373
374
  return item;
375
}
376
2114.4.9 by Brian Aker
Try not to pass session quite as often
377
Item *buildTableWild(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
2114.4.8 by Brian Aker
Merge in additional parser encapsulation.
378
{
2114.4.9 by Brian Aker
Try not to pass session quite as often
379
  Select_Lex *sel= lex->current_select;
380
  Item *item= new Item_field(lex->current_context(), schema_name.str, table_name.str, "*");
2114.4.8 by Brian Aker
Merge in additional parser encapsulation.
381
  sel->with_wild++;
382
383
  return item;
384
}
385
2114.4.9 by Brian Aker
Try not to pass session quite as often
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
2137.1.13 by Brian Aker
Fix bad error in warnings/errors.
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
2148.5.4 by Brian Aker
Move over the collation test to a function outside of the parser.
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
2148.5.5 by Brian Aker
buildKey for parser.
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
2148.5.6 by Brian Aker
Additional encapsulation.
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
2148.5.8 by Brian Aker
Move integer building into parser code file.
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
2148.5.9 by Brian Aker
Merge in column varchar build.
487
drizzled::enum_field_types buildSerialColumn(LEX *lex)
488
{
2148.5.15 by Brian Aker
Fix serial to be the same in the parser.
489
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
490
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
491
2148.5.9 by Brian Aker
Merge in column varchar build.
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
2148.5.14 by Brian Aker
function for decimal to be pulled out of the parser.
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
2148.5.10 by Brian Aker
Merge in timestamp build parser function.
531
drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
532
{
533
  lex->length= const_cast<char *>(length);
2148.5.11 by Brian Aker
Merge in varbinary build method.
534
  lex->charset= &my_charset_bin;
2148.5.10 by Brian Aker
Merge in timestamp build parser function.
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
2148.5.16 by Brian Aker
Adding build for unique column
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
2148.5.17 by Brian Aker
Merge up parser work for additional column builds.
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
2096.1.14 by Brian Aker
Pull in more C code from parser.
650
} // namespace parser
651
} // namespace drizzled