~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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
2207.8.4 by Olaf van der Spek
Refactor includes
22
#include <drizzled/session.h>
2096.1.14 by Brian Aker
Pull in more C code from parser.
23
#include <drizzled/parser.h>
2198.1.1 by Olaf van der Spek
Remove unnecessary alter* includes
24
#include <drizzled/alter_info.h>
2200.2.22 by Stewart Smith
merge trunk
25
2200.2.18 by Stewart Smith
add fields, indexes and foreign keys to drop in ALTER TABLE DROP and DROP INDEX to the AlterTable protobuf message in parser
26
#include <drizzled/message/alter_table.pb.h>
2198.1.2 by Olaf van der Spek
Refactor includes
27
#include <drizzled/item/subselect.h>
2234.1.4 by Olaf van der Spek
Refactor includes
28
#include <drizzled/sql_lex.h>
2096.1.14 by Brian Aker
Pull in more C code from parser.
29
2198.1.1 by Olaf van der Spek
Remove unnecessary alter* includes
30
namespace drizzled {
31
namespace parser {
2096.1.14 by Brian Aker
Pull in more C code from 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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
131
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
158
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
  {
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
166
    my_parse_error(session->m_lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
{
2198.6.15 by Brian Aker
Remove caller convert to std::string (ie we were going back and forth in
185
  const plugin::Function *udf= plugin::Function::get(name);
2096.1.14 by Brian Aker
Pull in more C code from parser.
186
187
  if (udf)
188
  {
2198.6.15 by Brian Aker
Remove caller convert to std::string (ie we were going back and forth in
189
    return Create_udf_func::s_singleton.create(session, udf, item_list);
2096.1.14 by Brian Aker
Pull in more C code from parser.
190
  }
191
2198.6.15 by Brian Aker
Remove caller convert to std::string (ie we were going back and forth in
192
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
193
194
  return NULL;
2096.1.14 by Brian Aker
Pull in more C code from parser.
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
*/
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
207
void my_parse_error(Lex_input_stream *lip)
2096.1.14 by Brian Aker
Pull in more C code from parser.
208
{
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
209
  assert(lip);
2096.1.14 by Brian Aker
Pull in more C code from parser.
210
211
  const char *yytext= lip->get_tok_start();
212
  /* Push an error into the error stack */
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
213
  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.
214
                  (yytext ? yytext : ""),
215
                  lip->yylineno);
216
}
217
2104.3.5 by Brian Aker
Fixed case where parser error message might be null.
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
2096.1.15 by Brian Aker
Additional parser cleanup.
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
2104.3.1 by Brian Aker
Merge in ulong typedef used.
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
*/
2172.3.8 by Brian Aker
Modernize our call to the parser, no more casting required.
253
void errorOn(drizzled::Session *session, const char *s)
2104.3.1 by Brian Aker
Merge in ulong typedef used.
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
2241.6.2 by Brian Aker
This adds the concept of a definer to a table definition.
325
void buildSchemaDefiner(LEX *lex, const LEX_STRING &value)
326
{
327
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
328
  identifier::User user(value.str);
329
  message::set_definer(statement->schema_message, user);
330
}
331
332
void buildSchemaDefiner(LEX *lex, const identifier::User &user)
333
{
334
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
335
  message::set_definer(statement->schema_message, user);
336
}
337
2114.4.9 by Brian Aker
Try not to pass session quite as often
338
void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
339
{
340
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
341
  message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
342
  opt->set_name(key);
343
  opt->set_state(boost::lexical_cast<std::string>(value));
344
}
345
346
bool checkFieldIdent(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
347
{
348
  TableList *table= reinterpret_cast<TableList*>(lex->current_select->table_list.first);
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
349
2114.4.6 by Brian Aker
Remove duplicate call by using null
350
  if (schema_name.length)
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
351
  {
2114.4.6 by Brian Aker
Remove duplicate call by using null
352
    if (my_strcasecmp(table_alias_charset, schema_name.str, table->getSchemaName()))
353
    {
354
      my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.str);
355
      return false;
356
    }
2114.4.4 by Brian Aker
Merge in field ident wrap from parser.
357
  }
358
359
  if (my_strcasecmp(table_alias_charset, table_name.str,
360
                    table->getTableName()))
361
  {
362
    my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
363
    return false;
364
  }
365
366
  return true;
367
}
368
2114.4.9 by Brian Aker
Try not to pass session quite as often
369
Item *buildIdent(LEX *lex,
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
370
                 const LEX_STRING &schema_name,
371
                 const LEX_STRING &table_name,
372
                 const LEX_STRING &field_name)
373
{
2114.4.9 by Brian Aker
Try not to pass session quite as often
374
  Select_Lex *sel= lex->current_select;
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
375
2114.4.7 by Brian Aker
Pull simple_ident into method.
376
  if (table_name.length and sel->no_table_names_allowed)
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
377
  {
378
    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
2114.4.10 by Brian Aker
Remove current_session from a couple of locations, encapsulate where in
379
             MYF(0), table_name.str, lex->session->where());
2114.4.5 by Brian Aker
Remove duplicate code around ident check.
380
  }
381
382
  Item *item= (sel->parsing_place != IN_HAVING or
383
               sel->get_in_sum_expr() > 0) ?
2114.4.9 by Brian Aker
Try not to pass session quite as often
384
    (Item*) new Item_field(lex->current_context(), schema_name.str, table_name.str, field_name.str) :
385
    (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.
386
387
  return item;
388
}
389
2114.4.9 by Brian Aker
Try not to pass session quite as often
390
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.
391
{
2114.4.9 by Brian Aker
Try not to pass session quite as often
392
  Select_Lex *sel= lex->current_select;
393
  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.
394
  sel->with_wild++;
395
396
  return item;
397
}
398
2114.4.9 by Brian Aker
Try not to pass session quite as often
399
void buildCreateFieldIdent(LEX *lex)
400
{
401
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
402
  lex->length= lex->dec=0;
403
  lex->type=0;
404
  statement->default_value= statement->on_update_value= 0;
405
  statement->comment= null_lex_str;
406
  lex->charset= NULL;
407
  statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
408
2200.2.1 by Stewart Smith
rename old alter table proto to AddedFields as it really has a dual purpose and isn't how we should structure Alter Table.
409
  message::AddedFields &added_fields_proto= ((statement::CreateTable *)lex->statement)->alter_info.added_fields_proto;
410
  lex->setField(added_fields_proto.add_added_field());
2114.4.9 by Brian Aker
Try not to pass session quite as often
411
}
412
2137.1.13 by Brian Aker
Fix bad error in warnings/errors.
413
void storeAlterColumnPosition(LEX *lex, const char *position)
414
{
415
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
416
417
  lex->last_field->after=const_cast<char*> (position);
418
  statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
419
}
420
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
421
bool buildCollation(LEX *lex, const charset_info_st *arg)
2148.5.4 by Brian Aker
Move over the collation test to a function outside of the parser.
422
{
423
  statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
424
425
  HA_CREATE_INFO *cinfo= &statement->create_info();
426
  if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
427
      cinfo->default_table_charset && arg &&
428
      !my_charset_same(cinfo->default_table_charset, arg))
429
  {
430
    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
431
             arg->name, cinfo->default_table_charset->csname);
432
    return false;
433
  }
434
  statement->create_info().default_table_charset= arg;
435
  statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
436
437
  return true;
438
}
439
2148.5.5 by Brian Aker
buildKey for parser.
440
void buildKey(LEX *lex, Key::Keytype type_par, const lex_string_t &name_arg)
441
{
442
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
443
  Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0,
444
                    lex->col_list);
445
  statement->alter_info.key_list.push_back(key);
2179.2.1 by Olaf van der Spek
Rename List::empty to clear (std::list uses clear)
446
  lex->col_list.clear(); /* Alloced by memory::sql_alloc */
2148.5.5 by Brian Aker
buildKey for parser.
447
}
448
2148.5.6 by Brian Aker
Additional encapsulation.
449
void buildForeignKey(LEX *lex, const lex_string_t &name_arg, drizzled::Table_ident *table)
450
{
451
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
452
  Key *key= new Foreign_key(name_arg, lex->col_list,
453
                            table,
454
                            lex->ref_list,
455
                            statement->fk_delete_opt,
456
                            statement->fk_update_opt,
457
                            statement->fk_match_option);
458
459
  statement->alter_info.key_list.push_back(key);
460
  key= new Key(Key::MULTIPLE, name_arg,
461
               &default_key_create_info, 1,
462
               lex->col_list);
463
  statement->alter_info.key_list.push_back(key);
2179.2.1 by Olaf van der Spek
Rename List::empty to clear (std::list uses clear)
464
  lex->col_list.clear(); /* Alloced by memory::sql_alloc */
2148.5.6 by Brian Aker
Additional encapsulation.
465
  /* Only used for ALTER TABLE. Ignored otherwise. */
466
  statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
467
}
468
2148.5.8 by Brian Aker
Move integer building into parser code file.
469
drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
470
{ 
471
  lex->length=(char*) 0; /* use default length */
472
473
  if (is_unsigned)
474
  {
475
    final_type= DRIZZLE_TYPE_LONGLONG;
476
  }
477
478
  if (lex->field())
479
  {
480
    assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
481
    // We update the type for unsigned types
482
    if (is_unsigned)
483
    {
484
      lex->field()->set_type(message::Table::Field::BIGINT);
485
      lex->field()->mutable_constraints()->set_is_unsigned(true);
486
    }
487
    else if (final_type == DRIZZLE_TYPE_LONG)
488
    {
489
      lex->field()->set_type(message::Table::Field::INTEGER);
490
    }
491
    else if (final_type == DRIZZLE_TYPE_LONGLONG)
492
    {
493
      lex->field()->set_type(message::Table::Field::BIGINT);
494
    }
495
  }
496
497
  return final_type;
498
}
499
2148.5.9 by Brian Aker
Merge in column varchar build.
500
drizzled::enum_field_types buildSerialColumn(LEX *lex)
501
{
2148.5.15 by Brian Aker
Fix serial to be the same in the parser.
502
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
503
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
504
2148.5.9 by Brian Aker
Merge in column varchar build.
505
  lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
506
507
  if (lex->field())
508
  {
509
    lex->field()->mutable_constraints()->set_is_notnull(true);
510
    lex->field()->mutable_constraints()->set_is_unsigned(true);
511
512
    lex->field()->set_type(message::Table::Field::BIGINT);
513
  }
514
515
  return DRIZZLE_TYPE_LONGLONG;
516
}
517
518
drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
519
{
520
  lex->length= const_cast<char *>(length);
521
522
  if (lex->field())
523
  {
524
    lex->field()->set_type(message::Table::Field::VARCHAR);
525
526
    message::Table::Field::StringFieldOptions *string_field_options;
527
528
    string_field_options= lex->field()->mutable_string_options();
529
530
    string_field_options->set_length(atoi(length));
531
  }
532
533
  return DRIZZLE_TYPE_VARCHAR;
534
}
535
2148.5.14 by Brian Aker
function for decimal to be pulled out of the parser.
536
drizzled::enum_field_types buildDecimalColumn(LEX *lex)
537
{
538
  if (lex->field())
539
    lex->field()->set_type(message::Table::Field::DECIMAL);
540
541
  return DRIZZLE_TYPE_DECIMAL;
542
}
543
2148.5.10 by Brian Aker
Merge in timestamp build parser function.
544
drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
545
{
546
  lex->length= const_cast<char *>(length);
2148.5.11 by Brian Aker
Merge in varbinary build method.
547
  lex->charset= &my_charset_bin;
2148.5.10 by Brian Aker
Merge in timestamp build parser function.
548
549
  if (lex->field())
550
  {
551
    lex->field()->set_type(message::Table::Field::VARCHAR);
552
553
    message::Table::Field::StringFieldOptions *string_field_options;
554
555
    string_field_options= lex->field()->mutable_string_options();
556
557
    string_field_options->set_length(atoi(length));
558
    string_field_options->set_collation_id(my_charset_bin.number);
559
    string_field_options->set_collation(my_charset_bin.name);
560
  }
561
562
  return DRIZZLE_TYPE_VARCHAR;
563
}
564
565
drizzled::enum_field_types buildBlobColumn(LEX *lex)
566
{
567
  lex->charset=&my_charset_bin;
568
  lex->length=(char*) 0; /* use default length */
569
570
  if (lex->field())
571
  {
572
    lex->field()->set_type(message::Table::Field::BLOB);
573
    message::Table::Field::StringFieldOptions *string_field_options;
574
575
    string_field_options= lex->field()->mutable_string_options();
576
    string_field_options->set_collation_id(my_charset_bin.number);
577
    string_field_options->set_collation(my_charset_bin.name);
578
  }
579
580
  return DRIZZLE_TYPE_BLOB;
581
}
582
583
drizzled::enum_field_types buildBooleanColumn(LEX *lex)
584
{
585
  if (lex->field())
586
    lex->field()->set_type(message::Table::Field::BOOLEAN);
587
588
  return DRIZZLE_TYPE_BOOLEAN;
589
}
590
591
drizzled::enum_field_types buildUuidColumn(LEX *lex)
592
{
593
  if (lex->field())
594
    lex->field()->set_type(message::Table::Field::UUID);
595
596
  return DRIZZLE_TYPE_UUID;
597
}
598
599
drizzled::enum_field_types buildDoubleColumn(LEX *lex)
600
{
601
  if (lex->field())
602
  {
603
    lex->field()->set_type(message::Table::Field::DOUBLE);
604
  }
605
606
  return DRIZZLE_TYPE_DOUBLE;
607
}
608
609
drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
610
{
611
  if (lex->field())
612
  {
613
    lex->field()->set_type(message::Table::Field::EPOCH);
614
  }
615
616
  if (length)
617
  {
618
    lex->length= const_cast<char *>(length);
619
    return DRIZZLE_TYPE_MICROTIME;
620
  }
621
622
  lex->length= NULL;
623
624
  return DRIZZLE_TYPE_TIMESTAMP;
625
}
626
2148.5.16 by Brian Aker
Adding build for unique column
627
void buildKeyOnColumn(LEX *lex)
628
{
629
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
630
631
  lex->type|= UNIQUE_KEY_FLAG;
632
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
633
634
  if (lex->field())
635
  {
636
    lex->field()->mutable_constraints()->set_is_unique(true);
637
  }
638
}
639
2148.5.17 by Brian Aker
Merge up parser work for additional column builds.
640
void buildAutoOnColumn(LEX *lex)
641
{
642
  lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
643
644
  if (lex->field())
645
  {
646
    lex->field()->mutable_constraints()->set_is_notnull(true);
647
  }
648
}
649
650
void buildPrimaryOnColumn(LEX *lex)
651
{
652
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
653
654
  lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
655
  statement->alter_info.flags.set(ALTER_ADD_INDEX);
656
657
  if (lex->field())
658
  {
659
    lex->field()->mutable_constraints()->set_is_notnull(true);
660
  }
661
}
662
2172.3.3 by Brian Aker
Abstract out the replication set.
663
void buildReplicationOption(LEX *lex, bool arg)
664
{
665
  statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
2187.7.6 by Brian Aker
This fixes the message such that the table inherits the no replication
666
  message::set_is_replicated(statement->schema_message, arg);
2172.3.3 by Brian Aker
Abstract out the replication set.
667
}
668
2172.3.4 by Brian Aker
Move out drop keys to parser method file.
669
void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
670
{
671
  statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
672
2200.2.18 by Stewart Smith
add fields, indexes and foreign keys to drop in ALTER TABLE DROP and DROP INDEX to the AlterTable protobuf message in parser
673
  message::AlterTable::AlterTableOperation *operation;
674
  operation= lex->alter_table()->add_operations();
675
  operation->set_drop_name(name);
676
2172.3.4 by Brian Aker
Move out drop keys to parser method file.
677
  statement->alter_info.flags.set(ALTER_DROP_INDEX);
678
  if (is_foreign_key)
679
  {
680
    statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
2200.2.18 by Stewart Smith
add fields, indexes and foreign keys to drop in ALTER TABLE DROP and DROP INDEX to the AlterTable protobuf message in parser
681
    operation->set_operation(message::AlterTable::AlterTableOperation::DROP_FOREIGN_KEY);
2172.3.4 by Brian Aker
Move out drop keys to parser method file.
682
  }
683
  else
684
  {
2200.2.18 by Stewart Smith
add fields, indexes and foreign keys to drop in ALTER TABLE DROP and DROP INDEX to the AlterTable protobuf message in parser
685
    operation->set_operation(message::AlterTable::AlterTableOperation::DROP_KEY);
2172.3.4 by Brian Aker
Move out drop keys to parser method file.
686
  }
687
}
688
2096.1.14 by Brian Aker
Pull in more C code from parser.
689
} // namespace parser
690
} // namespace drizzled