Drizzled Public API Documentation

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