1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Brian Aker
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.
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.
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
23
#include <drizzled/parser.h>
31
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
32
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
33
This function returns the proper item for the SQL expression
34
<code>left [NOT] IN ( expr )</code>
35
@param session the current thread
36
@param left the in predicand
37
@param equal true for IN predicates, false for NOT IN predicates
38
@param expr first and only expression of the in value list
39
@return an expression representing the IN predicate.
42
Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
45
Relevant references for this issue:
46
- SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
47
- SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
48
- SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
49
- SQL:2003, Part 2, section 7.15 <subquery>, page 370,
50
- SQL:2003 Feature F561, "Full value expressions".
52
The exception in SQL:2003 Note 184 means:
53
Item_singlerow_subselect, which corresponds to a <scalar subquery>,
54
should be re-interpreted as an Item_in_subselect, which corresponds
55
to a <table subquery> when used inside an <in predicate>.
57
Our reading of Note 184 is reccursive, so that all:
59
- IN ((( <subquery> )))
60
- IN '('^N <subquery> ')'^N
62
should be interpreted as a <table subquery>, no matter how deep in the
63
expression the <subquery> is.
68
if (expr->type() == Item::SUBSELECT_ITEM)
70
Item_subselect *expr2 = (Item_subselect*) expr;
72
if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
74
Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
75
Select_Lex *subselect;
78
Implement the mandated change, by altering the semantic tree:
79
left IN Item_singlerow_subselect(subselect)
82
which is represented as
83
Item_in_subselect(left, subselect)
85
subselect= expr3->invalidate_and_restore_select_lex();
86
result= new (session->mem_root) Item_in_subselect(left, subselect);
89
result = negate_expression(session, result);
96
result= new (session->mem_root) Item_func_eq(left, expr);
98
result= new (session->mem_root) Item_func_ne(left, expr);
104
@brief Creates a new Select_Lex for a UNION branch.
106
Sets up and initializes a Select_Lex structure for a query once the parser
107
discovers a UNION token. The current Select_Lex is pushed on the stack and
108
the new Select_Lex becomes the current one..=
110
@lex The parser state.
112
@is_union_distinct True if the union preceding the new select statement
115
@return <code>false</code> if successful, <code>true</code> if an error was
116
reported. In the latter case parsing should stop.
118
bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
122
/* Only the last SELECT can have INTO...... */
123
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
126
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
128
my_parse_error(session->m_lip);
131
/* This counter shouldn't be incremented for UNION parts */
133
if (new_select(lex, 0))
136
lex->current_select->linkage=UNION_TYPE;
137
if (is_union_distinct) /* UNION DISTINCT - remember position */
138
lex->current_select->master_unit()->union_distinct=
144
@brief Initializes a Select_Lex for a query within parentheses (aka
147
@return false if successful, true if an error was reported. In the latter
148
case parsing should stop.
150
bool setup_select_in_parentheses(Session *session, LEX *lex)
152
Select_Lex * sel= lex->current_select;
153
if (sel->set_braces(1))
155
my_parse_error(session->m_lip);
158
if (sel->linkage == UNION_TYPE &&
159
!sel->master_unit()->first_select()->braces &&
160
sel->master_unit()->first_select()->linkage ==
163
my_parse_error(session->m_lip);
166
if (sel->linkage == UNION_TYPE &&
167
sel->olap != UNSPECIFIED_OLAP_TYPE &&
168
sel->master_unit()->fake_select_lex)
170
my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
173
/* select in braces, can't contain global parameters */
174
if (sel->master_unit()->fake_select_lex)
175
sel->master_unit()->global_parameters=
176
sel->master_unit()->fake_select_lex;
180
Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
182
const plugin::Function *udf= plugin::Function::get(name.c_str(), name.length());
187
item= Create_udf_func::s_singleton.create(session, udf, item_list);
189
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
196
@brief Push an error message into MySQL error stack with line
197
and position information.
199
This function provides semantic action implementers with a way
200
to push the famous "You have a syntax error near..." error
201
message into the error stack, which is normally produced only if
202
a parse error is discovered internally by the Bison generated
205
void my_parse_error(Lex_input_stream *lip)
209
const char *yytext= lip->get_tok_start();
210
/* Push an error into the error stack */
211
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
212
(yytext ? yytext : ""),
216
void my_parse_error(const char *message)
218
my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
221
bool check_reserved_words(LEX_STRING *name)
223
if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
224
!my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
225
!my_strcasecmp(system_charset_info, name->str, "SESSION"))
233
@brief Bison callback to report a syntax/OOM error
235
This function is invoked by the bison-generated parser
236
when a syntax error, a parse error or an out-of-memory
237
condition occurs. This function is not invoked when the
238
parser is requested to abort by semantic action code
239
by means of YYABORT or YYACCEPT macros. This is why these
240
macros should not be used (use DRIZZLE_YYABORT/DRIZZLE_YYACCEPT
243
The parser will abort immediately after invoking this callback.
245
This function is not for use in semantic actions and is internal to
246
the parser, as it performs some pre-return cleanup.
247
In semantic actions, please use parser::my_parse_error or my_error to
248
push an error into the error stack and DRIZZLE_YYABORT
249
to abort from the parser.
251
void errorOn(const char *s)
253
Session *session= current_session;
255
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
256
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
258
parser::my_parse_error(session->m_lip);
262
parser::my_parse_error(s);
266
bool buildOrderBy(Session *session)
268
Select_Lex *sel= session->getLex()->current_select;
269
Select_Lex_Unit *unit= sel-> master_unit();
271
if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
272
sel->olap != UNSPECIFIED_OLAP_TYPE &&
273
(sel->linkage != UNION_TYPE || sel->braces))
275
my_error(ER_WRONG_USAGE, MYF(0),
276
"CUBE/ROLLUP", "ORDER BY");
280
if (session->getLex()->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
283
A query of the of the form (SELECT ...) ORDER BY order_list is
284
executed in the same way as the query
285
SELECT ... ORDER BY order_list
286
unless the SELECT construct contains ORDER BY or LIMIT clauses.
287
Otherwise we create a fake Select_Lex if it has not been created
290
Select_Lex *first_sl= unit->first_select();
291
if (!unit->is_union() &&
292
(first_sl->order_list.elements ||
293
first_sl->select_limit) &&
294
unit->add_fake_select_lex(session->getLex()->session))
303
void buildEngineOption(Session *session, const char *key, const LEX_STRING &value)
305
message::Engine::Option *opt= session->getLex()->table()->mutable_engine()->add_options();
307
opt->set_state(value.str, value.length);
310
void buildEngineOption(Session *session, const char *key, uint64_t value)
312
drizzled::message::Engine::Option *opt= session->getLex()->table()->mutable_engine()->add_options();
314
opt->set_state(boost::lexical_cast<std::string>(value));
317
void buildSchemaOption(Session *session, const char *key, const LEX_STRING &value)
319
statement::CreateSchema *statement= (statement::CreateSchema *)session->getLex()->statement;
320
message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
322
opt->set_state(value.str, value.length);
325
void buildSchemaOption(Session *session, const char *key, uint64_t value)
327
statement::CreateSchema *statement= (statement::CreateSchema *)session->getLex()->statement;
328
message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
330
opt->set_state(boost::lexical_cast<std::string>(value));
333
bool checkFieldIdent(Session *session, const LEX_STRING &schema_name, const LEX_STRING &table_name)
335
TableList *table= reinterpret_cast<TableList*>(session->getLex()->current_select->table_list.first);
337
if (schema_name.length)
339
if (my_strcasecmp(table_alias_charset, schema_name.str, table->getSchemaName()))
341
my_error(ER_WRONG_DB_NAME, MYF(0), schema_name.str);
346
if (my_strcasecmp(table_alias_charset, table_name.str,
347
table->getTableName()))
349
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
356
Item *buildIdent(Session *session,
357
const LEX_STRING &schema_name,
358
const LEX_STRING &table_name,
359
const LEX_STRING &field_name)
361
Select_Lex *sel= session->getLex()->current_select;
363
if (sel->no_table_names_allowed)
365
my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
366
MYF(0), table_name.str, session->where);
369
Item *item= (sel->parsing_place != IN_HAVING or
370
sel->get_in_sum_expr() > 0) ?
371
(Item*) new Item_field(session->getLex()->current_context(), schema_name.str, table_name.str, field_name.str) :
372
(Item*) new Item_ref(session->getLex()->current_context(), schema_name.str, table_name.str, field_name.str);
377
} // namespace parser
378
} // namespace drizzled