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