Drizzled Public API Documentation

parser.cc
00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 Brian Aker
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include <config.h>
00022 #include <drizzled/parser.h>
00023 #include <drizzled/alter_info.h>
00024 #include <drizzled/create_field.h>
00025 #include <drizzled/item/subselect.h>
00026 #include <drizzled/lex_input_stream.h>
00027 #include <drizzled/message/alter_table.pb.h>
00028 #include <drizzled/session.h>
00029 #include <drizzled/sql_lex.h>
00030 
00031 namespace drizzled {
00032 namespace parser {
00033 
00046 Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
00047 {
00048   /*
00049     Relevant references for this issue:
00050     - SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
00051     - SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
00052     - SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
00053     - SQL:2003, Part 2, section 7.15 <subquery>, page 370,
00054     - SQL:2003 Feature F561, "Full value expressions".
00055 
00056     The exception in SQL:2003 Note 184 means:
00057     Item_singlerow_subselect, which corresponds to a <scalar subquery>,
00058     should be re-interpreted as an Item_in_subselect, which corresponds
00059     to a <table subquery> when used inside an <in predicate>.
00060 
00061     Our reading of Note 184 is reccursive, so that all:
00062     - IN (( <subquery> ))
00063     - IN ((( <subquery> )))
00064     - IN '('^N <subquery> ')'^N
00065     - etc
00066     should be interpreted as a <table subquery>, no matter how deep in the
00067     expression the <subquery> is.
00068   */
00069 
00070   if (expr->type() == Item::SUBSELECT_ITEM)
00071   {
00072     Item_subselect *expr2 = (Item_subselect*) expr;
00073 
00074     if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
00075     {
00076       Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
00077 
00078       /*
00079         Implement the mandated change, by altering the semantic tree:
00080           left IN Item_singlerow_subselect(subselect)
00081         is modified to
00082           left IN (subselect)
00083         which is represented as
00084           Item_in_subselect(left, subselect)
00085       */
00086       Select_Lex* subselect= expr3->invalidate_and_restore_select_lex();
00087       Item* result= new (session->mem_root) Item_in_subselect(left, subselect);
00088       return equal ? result : negate_expression(session, result);
00089     }
00090   }
00091   return equal
00092     ? (Item*) new (session->mem_root) Item_func_eq(left, expr)
00093     : (Item*) new (session->mem_root) Item_func_ne(left, expr);
00094 }
00095 
00111 bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
00112 {
00113   if (lex->result)
00114   {
00115     /* Only the last SELECT can have  INTO...... */
00116     my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
00117     return true;
00118   }
00119   if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
00120   {
00121     my_parse_error(session->m_lip);
00122     return true;
00123   }
00124   /* This counter shouldn't be incremented for UNION parts */
00125   lex->nest_level--;
00126   if (new_select(lex, 0))
00127     return true;
00128   init_select(lex);
00129   lex->current_select->linkage=UNION_TYPE;
00130   if (is_union_distinct) /* UNION DISTINCT - remember position */
00131     lex->current_select->master_unit()->union_distinct=
00132       lex->current_select;
00133   return false;
00134 }
00135 
00143 bool setup_select_in_parentheses(Session *session, LEX *lex)
00144 {
00145   Select_Lex * sel= lex->current_select;
00146   if (sel->set_braces(1))
00147   {
00148     my_parse_error(session->m_lip);
00149     return true;
00150   }
00151   if (sel->linkage == UNION_TYPE &&
00152       !sel->master_unit()->first_select()->braces &&
00153       sel->master_unit()->first_select()->linkage ==
00154       UNION_TYPE)
00155   {
00156     my_parse_error(session->m_lip);
00157     return true;
00158   }
00159   if (sel->linkage == UNION_TYPE &&
00160       sel->olap != UNSPECIFIED_OLAP_TYPE &&
00161       sel->master_unit()->fake_select_lex)
00162   {
00163     my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
00164     return true;
00165   }
00166   /* select in braces, can't contain global parameters */
00167   if (sel->master_unit()->fake_select_lex)
00168     sel->master_unit()->global_parameters=
00169       sel->master_unit()->fake_select_lex;
00170   return false;
00171 }
00172 
00173 Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
00174 {
00175   const plugin::Function *udf= plugin::Function::get(name);
00176 
00177   if (udf)
00178   {
00179     return Create_udf_func::s_singleton.create(session, udf, item_list);
00180   }
00181 
00182   my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
00183 
00184   return NULL;
00185 }
00186 
00197 void my_parse_error(Lex_input_stream *lip)
00198 {
00199   assert(lip);
00200 
00201   const char *yytext= lip->get_tok_start();
00202   /* Push an error into the error stack */
00203   my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
00204                   (yytext ? yytext : ""),
00205                   lip->yylineno);
00206 }
00207 
00208 void my_parse_error(const char *message)
00209 {
00210   my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
00211 }
00212 
00213 bool check_reserved_words(str_ref name)
00214 {
00215   return not system_charset_info->strcasecmp(name.data(), "GLOBAL") 
00216     || not system_charset_info->strcasecmp(name.data(), "LOCAL")
00217     || not system_charset_info->strcasecmp(name.data(), "SESSION");
00218 }
00219 
00220 
00240 void errorOn(drizzled::Session *session, const char *s)
00241 {
00242   /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
00243   if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
00244   {
00245     parser::my_parse_error(session->m_lip);
00246   }
00247   else
00248   {
00249     parser::my_parse_error(s);
00250   }
00251 }
00252 
00253 bool buildOrderBy(LEX *lex)
00254 {
00255   Select_Lex *sel= lex->current_select;
00256   Select_Lex_Unit *unit= sel-> master_unit();
00257 
00258   if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
00259       sel->olap != UNSPECIFIED_OLAP_TYPE &&
00260       (sel->linkage != UNION_TYPE || sel->braces))
00261   {
00262     my_error(ER_WRONG_USAGE, MYF(0),
00263              "CUBE/ROLLUP", "ORDER BY");
00264     return false;
00265   }
00266 
00267   if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
00268   {
00269     /*
00270       A query of the of the form (SELECT ...) ORDER BY order_list is
00271       executed in the same way as the query
00272       SELECT ... ORDER BY order_list
00273       unless the SELECT construct contains ORDER BY or LIMIT clauses.
00274       Otherwise we create a fake Select_Lex if it has not been created
00275       yet.
00276     */
00277     Select_Lex *first_sl= unit->first_select();
00278     if (!unit->is_union() &&
00279         (first_sl->order_list.elements ||
00280          first_sl->select_limit) &&           
00281         unit->add_fake_select_lex(lex->session))
00282     {
00283       return false;
00284     }
00285   }
00286 
00287   return true;
00288 }
00289 
00290 void buildEngineOption(LEX *lex, const char *key, str_ref value)
00291 {
00292   message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
00293   opt->set_name(key);
00294   opt->set_state(value.data(), value.size());
00295 }
00296 
00297 void buildEngineOption(LEX *lex, const char *key, uint64_t value)
00298 {
00299   drizzled::message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
00300   opt->set_name(key);
00301   opt->set_state(boost::lexical_cast<std::string>(value));
00302 }
00303 
00304 void buildSchemaOption(LEX *lex, const char *key, str_ref value)
00305 {
00306   statement::CreateSchema *statement= static_cast<statement::CreateSchema*>(lex->statement);
00307   message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
00308   opt->set_name(key);
00309   opt->set_state(value.data(), value.size());
00310 }
00311 
00312 void buildSchemaDefiner(LEX *lex, const identifier::User &user)
00313 {
00314   statement::CreateSchema *statement= static_cast<statement::CreateSchema*>(lex->statement);
00315   message::set_definer(statement->schema_message, user);
00316 }
00317 
00318 void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
00319 {
00320   statement::CreateSchema *statement= static_cast<statement::CreateSchema*>(lex->statement);
00321   message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
00322   opt->set_name(key);
00323   opt->set_state(boost::lexical_cast<std::string>(value));
00324 }
00325 
00326 bool checkFieldIdent(LEX *lex, str_ref schema_name, str_ref table_name)
00327 {
00328   TableList *table= reinterpret_cast<TableList*>(lex->current_select->table_list.first);
00329 
00330   if (schema_name.size() && table_alias_charset->strcasecmp(schema_name.data(), table->getSchemaName()))
00331   {
00332     my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.data());
00333     return false;
00334   }
00335 
00336   if (table_alias_charset->strcasecmp(table_name.data(), table->getTableName()))
00337   {
00338     my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.data());
00339     return false;
00340   }
00341 
00342   return true;
00343 }
00344 
00345 Item *buildIdent(LEX *lex, str_ref schema_name, str_ref table_name, str_ref field_name)
00346 {
00347   Select_Lex *sel= lex->current_select;
00348 
00349   if (table_name.size() and sel->no_table_names_allowed)
00350   {
00351     my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), table_name.data(), lex->session->where());
00352   }
00353 
00354   return sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0
00355     ? (Item*) new Item_field(lex->current_context(), schema_name.data(), table_name.data(), field_name.data()) 
00356     : (Item*) new Item_ref(lex->current_context(), schema_name.data(), table_name.data(), field_name.data());
00357 }
00358 
00359 Item *buildTableWild(LEX *lex, str_ref schema_name, str_ref table_name)
00360 {
00361   Select_Lex *sel= lex->current_select;
00362   Item *item= new Item_field(lex->current_context(), schema_name.data(), table_name.data(), "*");
00363   sel->with_wild++;
00364   return item;
00365 }
00366 
00367 void buildCreateFieldIdent(LEX *lex)
00368 {
00369   statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
00370   lex->length= lex->dec=0;
00371   lex->type=0;
00372   statement->default_value= statement->on_update_value= 0;
00373   statement->comment= null_lex_string();
00374   lex->charset= NULL;
00375   statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
00376 
00377   message::AddedFields &added_fields_proto= ((statement::CreateTable *)lex->statement)->alter_info.added_fields_proto;
00378   lex->setField(added_fields_proto.add_added_field());
00379 }
00380 
00381 void storeAlterColumnPosition(LEX *lex, const char *position)
00382 {
00383   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00384 
00385   lex->last_field->after= position;
00386   statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
00387 }
00388 
00389 bool buildCollation(LEX *lex, const charset_info_st *arg)
00390 {
00391   statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
00392 
00393   HA_CREATE_INFO *cinfo= &statement->create_info();
00394   if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
00395       cinfo->default_table_charset && arg &&
00396       !my_charset_same(cinfo->default_table_charset, arg))
00397   {
00398     my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
00399              arg->name, cinfo->default_table_charset->csname);
00400     return false;
00401   }
00402   statement->create_info().default_table_charset= arg;
00403   statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
00404 
00405   return true;
00406 }
00407 
00408 void buildKey(LEX *lex, Key::Keytype type_par, str_ref name_arg)
00409 {
00410   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00411   Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0, lex->col_list);
00412   statement->alter_info.key_list.push_back(key);
00413   lex->col_list.clear(); /* Alloced by memory::sql_alloc */
00414 }
00415 
00416 void buildForeignKey(LEX *lex, str_ref name_arg, drizzled::Table_ident *table)
00417 {
00418   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00419   statement->alter_info.key_list.push_back(new Foreign_key(name_arg, lex->col_list, table, lex->ref_list, 
00420     statement->fk_delete_opt, statement->fk_update_opt, statement->fk_match_option));
00421 
00422   statement->alter_info.key_list.push_back(new Key(Key::MULTIPLE, name_arg, &default_key_create_info, 1, lex->col_list));
00423   lex->col_list.clear(); /* Alloced by memory::sql_alloc */
00424   /* Only used for ALTER TABLE. Ignored otherwise. */
00425   statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
00426 }
00427 
00428 drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
00429 { 
00430   lex->length= NULL; /* use default length */
00431 
00432   if (is_unsigned)
00433   {
00434     final_type= DRIZZLE_TYPE_LONGLONG;
00435   }
00436 
00437   if (lex->field())
00438   {
00439     assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
00440     // We update the type for unsigned types
00441     if (is_unsigned)
00442     {
00443       lex->field()->set_type(message::Table::Field::BIGINT);
00444       lex->field()->mutable_constraints()->set_is_unsigned(true);
00445     }
00446     else if (final_type == DRIZZLE_TYPE_LONG)
00447     {
00448       lex->field()->set_type(message::Table::Field::INTEGER);
00449     }
00450     else if (final_type == DRIZZLE_TYPE_LONGLONG)
00451     {
00452       lex->field()->set_type(message::Table::Field::BIGINT);
00453     }
00454   }
00455 
00456   return final_type;
00457 }
00458 
00459 drizzled::enum_field_types buildSerialColumn(LEX *lex)
00460 {
00461   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00462   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00463 
00464   lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
00465 
00466   if (lex->field())
00467   {
00468     lex->field()->mutable_constraints()->set_is_notnull(true);
00469     lex->field()->mutable_constraints()->set_is_unsigned(true);
00470 
00471     lex->field()->set_type(message::Table::Field::BIGINT);
00472   }
00473 
00474   return DRIZZLE_TYPE_LONGLONG;
00475 }
00476 
00477 drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
00478 {
00479   lex->length= length;
00480 
00481   if (lex->field())
00482   {
00483     lex->field()->set_type(message::Table::Field::VARCHAR);
00484 
00485     message::Table::Field::StringFieldOptions *string_field_options;
00486 
00487     string_field_options= lex->field()->mutable_string_options();
00488 
00489     string_field_options->set_length(atoi(length));
00490   }
00491 
00492   return DRIZZLE_TYPE_VARCHAR;
00493 }
00494 
00495 drizzled::enum_field_types buildDecimalColumn(LEX *lex)
00496 {
00497   if (lex->field())
00498     lex->field()->set_type(message::Table::Field::DECIMAL);
00499 
00500   return DRIZZLE_TYPE_DECIMAL;
00501 }
00502 
00503 drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
00504 {
00505   lex->length= length;
00506   lex->charset= &my_charset_bin;
00507 
00508   if (lex->field())
00509   {
00510     lex->field()->set_type(message::Table::Field::VARCHAR);
00511 
00512     message::Table::Field::StringFieldOptions *string_field_options;
00513 
00514     string_field_options= lex->field()->mutable_string_options();
00515 
00516     string_field_options->set_length(atoi(length));
00517     string_field_options->set_collation_id(my_charset_bin.number);
00518     string_field_options->set_collation(my_charset_bin.name);
00519   }
00520 
00521   return DRIZZLE_TYPE_VARCHAR;
00522 }
00523 
00524 drizzled::enum_field_types buildBlobColumn(LEX *lex)
00525 {
00526   lex->charset=&my_charset_bin;
00527   lex->length=(char*) 0; /* use default length */
00528 
00529   if (lex->field())
00530   {
00531     lex->field()->set_type(message::Table::Field::BLOB);
00532     message::Table::Field::StringFieldOptions *string_field_options;
00533 
00534     string_field_options= lex->field()->mutable_string_options();
00535     string_field_options->set_collation_id(my_charset_bin.number);
00536     string_field_options->set_collation(my_charset_bin.name);
00537   }
00538 
00539   return DRIZZLE_TYPE_BLOB;
00540 }
00541 
00542 drizzled::enum_field_types buildBooleanColumn(LEX *lex)
00543 {
00544   if (lex->field())
00545     lex->field()->set_type(message::Table::Field::BOOLEAN);
00546 
00547   return DRIZZLE_TYPE_BOOLEAN;
00548 }
00549 
00550 drizzled::enum_field_types buildUuidColumn(LEX *lex)
00551 {
00552   if (lex->field())
00553     lex->field()->set_type(message::Table::Field::UUID);
00554 
00555   return DRIZZLE_TYPE_UUID;
00556 }
00557 
00558 drizzled::enum_field_types buildIPv6Column(LEX *lex)
00559 {
00560   if (lex->field())
00561     lex->field()->set_type(message::Table::Field::IPV6);
00562 
00563   return DRIZZLE_TYPE_IPV6;
00564 }
00565 
00566 drizzled::enum_field_types buildDoubleColumn(LEX *lex)
00567 {
00568   if (lex->field())
00569   {
00570     lex->field()->set_type(message::Table::Field::DOUBLE);
00571   }
00572 
00573   return DRIZZLE_TYPE_DOUBLE;
00574 }
00575 
00576 drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
00577 {
00578   if (lex->field())
00579   {
00580     lex->field()->set_type(message::Table::Field::EPOCH);
00581   }
00582 
00583   if (length)
00584   {
00585     lex->length= length;
00586     return DRIZZLE_TYPE_MICROTIME;
00587   }
00588 
00589   lex->length= NULL;
00590 
00591   return DRIZZLE_TYPE_TIMESTAMP;
00592 }
00593 
00594 void buildKeyOnColumn(LEX *lex)
00595 {
00596   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00597 
00598   lex->type|= UNIQUE_KEY_FLAG;
00599   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00600 
00601   if (lex->field())
00602   {
00603     lex->field()->mutable_constraints()->set_is_unique(true);
00604   }
00605 }
00606 
00607 void buildAutoOnColumn(LEX *lex)
00608 {
00609   lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
00610 
00611   if (lex->field())
00612   {
00613     lex->field()->mutable_constraints()->set_is_notnull(true);
00614   }
00615 }
00616 
00617 void buildPrimaryOnColumn(LEX *lex)
00618 {
00619   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00620 
00621   lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
00622   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00623 
00624   if (lex->field())
00625   {
00626     lex->field()->mutable_constraints()->set_is_notnull(true);
00627   }
00628 }
00629 
00630 void buildReplicationOption(LEX *lex, bool arg)
00631 {
00632   statement::CreateSchema *statement= static_cast<statement::CreateSchema*>(lex->statement);
00633   message::set_is_replicated(statement->schema_message, arg);
00634 }
00635 
00636 void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
00637 {
00638   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00639 
00640   message::AlterTable::AlterTableOperation *operation;
00641   operation= lex->alter_table()->add_operations();
00642   operation->set_drop_name(name);
00643 
00644   statement->alter_info.flags.set(ALTER_DROP_INDEX);
00645   if (is_foreign_key)
00646   {
00647     statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
00648     operation->set_operation(message::AlterTable::AlterTableOperation::DROP_FOREIGN_KEY);
00649   }
00650   else
00651   {
00652     operation->set_operation(message::AlterTable::AlterTableOperation::DROP_KEY);
00653   }
00654 }
00655 
00656 } // namespace parser
00657 } // namespace drizzled