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/session.h>
00023 #include <drizzled/parser.h>
00024 #include <drizzled/alter_info.h>
00025 #include <drizzled/alter_drop.h>
00026 #include <drizzled/item/subselect.h>
00027 #include <drizzled/sql_lex.h>
00028 
00029 namespace drizzled {
00030 namespace parser {
00031 
00044 Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
00045 {
00046   /*
00047     Relevant references for this issue:
00048     - SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
00049     - SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
00050     - SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
00051     - SQL:2003, Part 2, section 7.15 <subquery>, page 370,
00052     - SQL:2003 Feature F561, "Full value expressions".
00053 
00054     The exception in SQL:2003 Note 184 means:
00055     Item_singlerow_subselect, which corresponds to a <scalar subquery>,
00056     should be re-interpreted as an Item_in_subselect, which corresponds
00057     to a <table subquery> when used inside an <in predicate>.
00058 
00059     Our reading of Note 184 is reccursive, so that all:
00060     - IN (( <subquery> ))
00061     - IN ((( <subquery> )))
00062     - IN '('^N <subquery> ')'^N
00063     - etc
00064     should be interpreted as a <table subquery>, no matter how deep in the
00065     expression the <subquery> is.
00066   */
00067 
00068   Item *result;
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       Select_Lex *subselect;
00078 
00079       /*
00080         Implement the mandated change, by altering the semantic tree:
00081           left IN Item_singlerow_subselect(subselect)
00082         is modified to
00083           left IN (subselect)
00084         which is represented as
00085           Item_in_subselect(left, subselect)
00086       */
00087       subselect= expr3->invalidate_and_restore_select_lex();
00088       result= new (session->mem_root) Item_in_subselect(left, subselect);
00089 
00090       if (! equal)
00091         result = negate_expression(session, result);
00092 
00093       return(result);
00094     }
00095   }
00096 
00097   if (equal)
00098     result= new (session->mem_root) Item_func_eq(left, expr);
00099   else
00100     result= new (session->mem_root) Item_func_ne(left, expr);
00101 
00102   return(result);
00103 }
00104 
00120 bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
00121 {
00122   if (lex->result)
00123   {
00124     /* Only the last SELECT can have  INTO...... */
00125     my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
00126     return true;
00127   }
00128   if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
00129   {
00130     my_parse_error(session->m_lip);
00131     return true;
00132   }
00133   /* This counter shouldn't be incremented for UNION parts */
00134   lex->nest_level--;
00135   if (new_select(lex, 0))
00136     return true;
00137   init_select(lex);
00138   lex->current_select->linkage=UNION_TYPE;
00139   if (is_union_distinct) /* UNION DISTINCT - remember position */
00140     lex->current_select->master_unit()->union_distinct=
00141       lex->current_select;
00142   return false;
00143 }
00144 
00152 bool setup_select_in_parentheses(Session *session, LEX *lex)
00153 {
00154   Select_Lex * sel= lex->current_select;
00155   if (sel->set_braces(1))
00156   {
00157     my_parse_error(session->m_lip);
00158     return true;
00159   }
00160   if (sel->linkage == UNION_TYPE &&
00161       !sel->master_unit()->first_select()->braces &&
00162       sel->master_unit()->first_select()->linkage ==
00163       UNION_TYPE)
00164   {
00165     my_parse_error(session->m_lip);
00166     return true;
00167   }
00168   if (sel->linkage == UNION_TYPE &&
00169       sel->olap != UNSPECIFIED_OLAP_TYPE &&
00170       sel->master_unit()->fake_select_lex)
00171   {
00172     my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
00173     return true;
00174   }
00175   /* select in braces, can't contain global parameters */
00176   if (sel->master_unit()->fake_select_lex)
00177     sel->master_unit()->global_parameters=
00178       sel->master_unit()->fake_select_lex;
00179   return false;
00180 }
00181 
00182 Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
00183 {
00184   const plugin::Function *udf= plugin::Function::get(name);
00185 
00186   if (udf)
00187   {
00188     return Create_udf_func::s_singleton.create(session, udf, item_list);
00189   }
00190 
00191   my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
00192 
00193   return NULL;
00194 }
00195 
00206 void my_parse_error(Lex_input_stream *lip)
00207 {
00208   assert(lip);
00209 
00210   const char *yytext= lip->get_tok_start();
00211   /* Push an error into the error stack */
00212   my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
00213                   (yytext ? yytext : ""),
00214                   lip->yylineno);
00215 }
00216 
00217 void my_parse_error(const char *message)
00218 {
00219   my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
00220 }
00221 
00222 bool check_reserved_words(LEX_STRING *name)
00223 {
00224   if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
00225       !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
00226       !my_strcasecmp(system_charset_info, name->str, "SESSION"))
00227     return true;
00228 
00229   return false;
00230 }
00231 
00232 
00252 void errorOn(drizzled::Session *session, const char *s)
00253 {
00254   /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
00255   if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
00256   {
00257     parser::my_parse_error(session->m_lip);
00258   }
00259   else
00260   {
00261     parser::my_parse_error(s);
00262   }
00263 }
00264 
00265 bool buildOrderBy(LEX *lex)
00266 {
00267   Select_Lex *sel= lex->current_select;
00268   Select_Lex_Unit *unit= sel-> master_unit();
00269 
00270   if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
00271       sel->olap != UNSPECIFIED_OLAP_TYPE &&
00272       (sel->linkage != UNION_TYPE || sel->braces))
00273   {
00274     my_error(ER_WRONG_USAGE, MYF(0),
00275              "CUBE/ROLLUP", "ORDER BY");
00276     return false;
00277   }
00278 
00279   if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
00280   {
00281     /*
00282       A query of the of the form (SELECT ...) ORDER BY order_list is
00283       executed in the same way as the query
00284       SELECT ... ORDER BY order_list
00285       unless the SELECT construct contains ORDER BY or LIMIT clauses.
00286       Otherwise we create a fake Select_Lex if it has not been created
00287       yet.
00288     */
00289     Select_Lex *first_sl= unit->first_select();
00290     if (!unit->is_union() &&
00291         (first_sl->order_list.elements ||
00292          first_sl->select_limit) &&           
00293         unit->add_fake_select_lex(lex->session))
00294     {
00295       return false;
00296     }
00297   }
00298 
00299   return true;
00300 }
00301 
00302 void buildEngineOption(LEX *lex, const char *key, const LEX_STRING &value)
00303 {
00304   message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
00305   opt->set_name(key);
00306   opt->set_state(value.str, value.length);
00307 }
00308 
00309 void buildEngineOption(LEX *lex, const char *key, uint64_t value)
00310 {
00311   drizzled::message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
00312   opt->set_name(key);
00313   opt->set_state(boost::lexical_cast<std::string>(value));
00314 }
00315 
00316 void buildSchemaOption(LEX *lex, const char *key, const LEX_STRING &value)
00317 {
00318   statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
00319   message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
00320   opt->set_name(key);
00321   opt->set_state(value.str, value.length);
00322 }
00323 
00324 void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
00325 {
00326   statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
00327   message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
00328   opt->set_name(key);
00329   opt->set_state(boost::lexical_cast<std::string>(value));
00330 }
00331 
00332 bool checkFieldIdent(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
00333 {
00334   TableList *table= reinterpret_cast<TableList*>(lex->current_select->table_list.first);
00335 
00336   if (schema_name.length)
00337   {
00338     if (my_strcasecmp(table_alias_charset, schema_name.str, table->getSchemaName()))
00339     {
00340       my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.str);
00341       return false;
00342     }
00343   }
00344 
00345   if (my_strcasecmp(table_alias_charset, table_name.str,
00346                     table->getTableName()))
00347   {
00348     my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
00349     return false;
00350   }
00351 
00352   return true;
00353 }
00354 
00355 Item *buildIdent(LEX *lex,
00356                  const LEX_STRING &schema_name,
00357                  const LEX_STRING &table_name,
00358                  const LEX_STRING &field_name)
00359 {
00360   Select_Lex *sel= lex->current_select;
00361 
00362   if (table_name.length and sel->no_table_names_allowed)
00363   {
00364     my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
00365              MYF(0), table_name.str, lex->session->where());
00366   }
00367 
00368   Item *item= (sel->parsing_place != IN_HAVING or
00369                sel->get_in_sum_expr() > 0) ?
00370     (Item*) new Item_field(lex->current_context(), schema_name.str, table_name.str, field_name.str) :
00371     (Item*) new Item_ref(lex->current_context(), schema_name.str, table_name.str, field_name.str);
00372 
00373   return item;
00374 }
00375 
00376 Item *buildTableWild(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
00377 {
00378   Select_Lex *sel= lex->current_select;
00379   Item *item= new Item_field(lex->current_context(), schema_name.str, table_name.str, "*");
00380   sel->with_wild++;
00381 
00382   return item;
00383 }
00384 
00385 void buildCreateFieldIdent(LEX *lex)
00386 {
00387   statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
00388   lex->length= lex->dec=0;
00389   lex->type=0;
00390   statement->default_value= statement->on_update_value= 0;
00391   statement->comment= null_lex_str;
00392   lex->charset= NULL;
00393   statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
00394 
00395   message::AlterTable &alter_proto= ((statement::CreateTable *)lex->statement)->alter_info.alter_proto;
00396   lex->setField(alter_proto.add_added_field());
00397 }
00398 
00399 void storeAlterColumnPosition(LEX *lex, const char *position)
00400 {
00401   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00402 
00403   lex->last_field->after=const_cast<char*> (position);
00404   statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
00405 }
00406 
00407 bool buildCollation(LEX *lex, const CHARSET_INFO *arg)
00408 {
00409   statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
00410 
00411   HA_CREATE_INFO *cinfo= &statement->create_info();
00412   if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
00413       cinfo->default_table_charset && arg &&
00414       !my_charset_same(cinfo->default_table_charset, arg))
00415   {
00416     my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
00417              arg->name, cinfo->default_table_charset->csname);
00418     return false;
00419   }
00420   statement->create_info().default_table_charset= arg;
00421   statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
00422 
00423   return true;
00424 }
00425 
00426 void buildKey(LEX *lex, Key::Keytype type_par, const lex_string_t &name_arg)
00427 {
00428   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00429   Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0,
00430                     lex->col_list);
00431   statement->alter_info.key_list.push_back(key);
00432   lex->col_list.clear(); /* Alloced by memory::sql_alloc */
00433 }
00434 
00435 void buildForeignKey(LEX *lex, const lex_string_t &name_arg, drizzled::Table_ident *table)
00436 {
00437   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00438   Key *key= new Foreign_key(name_arg, lex->col_list,
00439                             table,
00440                             lex->ref_list,
00441                             statement->fk_delete_opt,
00442                             statement->fk_update_opt,
00443                             statement->fk_match_option);
00444 
00445   statement->alter_info.key_list.push_back(key);
00446   key= new Key(Key::MULTIPLE, name_arg,
00447                &default_key_create_info, 1,
00448                lex->col_list);
00449   statement->alter_info.key_list.push_back(key);
00450   lex->col_list.clear(); /* Alloced by memory::sql_alloc */
00451   /* Only used for ALTER TABLE. Ignored otherwise. */
00452   statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
00453 }
00454 
00455 drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
00456 { 
00457   lex->length=(char*) 0; /* use default length */
00458 
00459   if (is_unsigned)
00460   {
00461     final_type= DRIZZLE_TYPE_LONGLONG;
00462   }
00463 
00464   if (lex->field())
00465   {
00466     assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
00467     // We update the type for unsigned types
00468     if (is_unsigned)
00469     {
00470       lex->field()->set_type(message::Table::Field::BIGINT);
00471       lex->field()->mutable_constraints()->set_is_unsigned(true);
00472     }
00473     else if (final_type == DRIZZLE_TYPE_LONG)
00474     {
00475       lex->field()->set_type(message::Table::Field::INTEGER);
00476     }
00477     else if (final_type == DRIZZLE_TYPE_LONGLONG)
00478     {
00479       lex->field()->set_type(message::Table::Field::BIGINT);
00480     }
00481   }
00482 
00483   return final_type;
00484 }
00485 
00486 drizzled::enum_field_types buildSerialColumn(LEX *lex)
00487 {
00488   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00489   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00490 
00491   lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
00492 
00493   if (lex->field())
00494   {
00495     lex->field()->mutable_constraints()->set_is_notnull(true);
00496     lex->field()->mutable_constraints()->set_is_unsigned(true);
00497 
00498     lex->field()->set_type(message::Table::Field::BIGINT);
00499   }
00500 
00501   return DRIZZLE_TYPE_LONGLONG;
00502 }
00503 
00504 drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
00505 {
00506   lex->length= const_cast<char *>(length);
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   }
00518 
00519   return DRIZZLE_TYPE_VARCHAR;
00520 }
00521 
00522 drizzled::enum_field_types buildDecimalColumn(LEX *lex)
00523 {
00524   if (lex->field())
00525     lex->field()->set_type(message::Table::Field::DECIMAL);
00526 
00527   return DRIZZLE_TYPE_DECIMAL;
00528 }
00529 
00530 drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
00531 {
00532   lex->length= const_cast<char *>(length);
00533   lex->charset= &my_charset_bin;
00534 
00535   if (lex->field())
00536   {
00537     lex->field()->set_type(message::Table::Field::VARCHAR);
00538 
00539     message::Table::Field::StringFieldOptions *string_field_options;
00540 
00541     string_field_options= lex->field()->mutable_string_options();
00542 
00543     string_field_options->set_length(atoi(length));
00544     string_field_options->set_collation_id(my_charset_bin.number);
00545     string_field_options->set_collation(my_charset_bin.name);
00546   }
00547 
00548   return DRIZZLE_TYPE_VARCHAR;
00549 }
00550 
00551 drizzled::enum_field_types buildBlobColumn(LEX *lex)
00552 {
00553   lex->charset=&my_charset_bin;
00554   lex->length=(char*) 0; /* use default length */
00555 
00556   if (lex->field())
00557   {
00558     lex->field()->set_type(message::Table::Field::BLOB);
00559     message::Table::Field::StringFieldOptions *string_field_options;
00560 
00561     string_field_options= lex->field()->mutable_string_options();
00562     string_field_options->set_collation_id(my_charset_bin.number);
00563     string_field_options->set_collation(my_charset_bin.name);
00564   }
00565 
00566   return DRIZZLE_TYPE_BLOB;
00567 }
00568 
00569 drizzled::enum_field_types buildBooleanColumn(LEX *lex)
00570 {
00571   if (lex->field())
00572     lex->field()->set_type(message::Table::Field::BOOLEAN);
00573 
00574   return DRIZZLE_TYPE_BOOLEAN;
00575 }
00576 
00577 drizzled::enum_field_types buildUuidColumn(LEX *lex)
00578 {
00579   if (lex->field())
00580     lex->field()->set_type(message::Table::Field::UUID);
00581 
00582   return DRIZZLE_TYPE_UUID;
00583 }
00584 
00585 drizzled::enum_field_types buildDoubleColumn(LEX *lex)
00586 {
00587   if (lex->field())
00588   {
00589     lex->field()->set_type(message::Table::Field::DOUBLE);
00590   }
00591 
00592   return DRIZZLE_TYPE_DOUBLE;
00593 }
00594 
00595 drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
00596 {
00597   if (lex->field())
00598   {
00599     lex->field()->set_type(message::Table::Field::EPOCH);
00600   }
00601 
00602   if (length)
00603   {
00604     lex->length= const_cast<char *>(length);
00605     return DRIZZLE_TYPE_MICROTIME;
00606   }
00607 
00608   lex->length= NULL;
00609 
00610   return DRIZZLE_TYPE_TIMESTAMP;
00611 }
00612 
00613 void buildKeyOnColumn(LEX *lex)
00614 {
00615   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00616 
00617   lex->type|= UNIQUE_KEY_FLAG;
00618   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00619 
00620   if (lex->field())
00621   {
00622     lex->field()->mutable_constraints()->set_is_unique(true);
00623   }
00624 }
00625 
00626 void buildAutoOnColumn(LEX *lex)
00627 {
00628   lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
00629 
00630   if (lex->field())
00631   {
00632     lex->field()->mutable_constraints()->set_is_notnull(true);
00633   }
00634 }
00635 
00636 void buildPrimaryOnColumn(LEX *lex)
00637 {
00638   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00639 
00640   lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
00641   statement->alter_info.flags.set(ALTER_ADD_INDEX);
00642 
00643   if (lex->field())
00644   {
00645     lex->field()->mutable_constraints()->set_is_notnull(true);
00646   }
00647 }
00648 
00649 void buildReplicationOption(LEX *lex, bool arg)
00650 {
00651   statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
00652   message::set_is_replicated(statement->schema_message, arg);
00653 }
00654 
00655 void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
00656 {
00657   statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
00658 
00659   statement->alter_info.flags.set(ALTER_DROP_INDEX);
00660   if (is_foreign_key)
00661   {
00662     statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
00663     statement->alter_info.drop_list.push_back(AlterDrop(AlterDrop::FOREIGN_KEY, name));
00664   }
00665   else
00666   {
00667     statement->alter_info.drop_list.push_back(AlterDrop(AlterDrop::KEY, name));
00668   }
00669 }
00670 
00671 } // namespace parser
00672 } // namespace drizzled