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
22
#include <drizzled/session.h>
23
#include <drizzled/parser.h>
24
#include <drizzled/alter_info.h>
26
#include <drizzled/message/alter_table.pb.h>
27
#include <drizzled/item/subselect.h>
28
#include <drizzled/sql_lex.h>
34
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
35
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
36
This function returns the proper item for the SQL expression
37
<code>left [NOT] IN ( expr )</code>
38
@param session the current thread
39
@param left the in predicand
40
@param equal true for IN predicates, false for NOT IN predicates
41
@param expr first and only expression of the in value list
42
@return an expression representing the IN predicate.
45
Item* handle_sql2003_note184_exception(Session *session, Item* left, bool equal, Item *expr)
48
Relevant references for this issue:
49
- SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
50
- SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
51
- SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
52
- SQL:2003, Part 2, section 7.15 <subquery>, page 370,
53
- SQL:2003 Feature F561, "Full value expressions".
55
The exception in SQL:2003 Note 184 means:
56
Item_singlerow_subselect, which corresponds to a <scalar subquery>,
57
should be re-interpreted as an Item_in_subselect, which corresponds
58
to a <table subquery> when used inside an <in predicate>.
60
Our reading of Note 184 is reccursive, so that all:
62
- IN ((( <subquery> )))
63
- IN '('^N <subquery> ')'^N
65
should be interpreted as a <table subquery>, no matter how deep in the
66
expression the <subquery> is.
71
if (expr->type() == Item::SUBSELECT_ITEM)
73
Item_subselect *expr2 = (Item_subselect*) expr;
75
if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
77
Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
78
Select_Lex *subselect;
81
Implement the mandated change, by altering the semantic tree:
82
left IN Item_singlerow_subselect(subselect)
85
which is represented as
86
Item_in_subselect(left, subselect)
88
subselect= expr3->invalidate_and_restore_select_lex();
89
result= new (session->mem_root) Item_in_subselect(left, subselect);
92
result = negate_expression(session, result);
99
result= new (session->mem_root) Item_func_eq(left, expr);
101
result= new (session->mem_root) Item_func_ne(left, expr);
107
@brief Creates a new Select_Lex for a UNION branch.
109
Sets up and initializes a Select_Lex structure for a query once the parser
110
discovers a UNION token. The current Select_Lex is pushed on the stack and
111
the new Select_Lex becomes the current one..=
113
@lex The parser state.
115
@is_union_distinct True if the union preceding the new select statement
118
@return <code>false</code> if successful, <code>true</code> if an error was
119
reported. In the latter case parsing should stop.
121
bool add_select_to_union_list(Session *session, LEX *lex, bool is_union_distinct)
125
/* Only the last SELECT can have INTO...... */
126
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
129
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
131
my_parse_error(session->m_lip);
134
/* This counter shouldn't be incremented for UNION parts */
136
if (new_select(lex, 0))
139
lex->current_select->linkage=UNION_TYPE;
140
if (is_union_distinct) /* UNION DISTINCT - remember position */
141
lex->current_select->master_unit()->union_distinct=
147
@brief Initializes a Select_Lex for a query within parentheses (aka
150
@return false if successful, true if an error was reported. In the latter
151
case parsing should stop.
153
bool setup_select_in_parentheses(Session *session, LEX *lex)
155
Select_Lex * sel= lex->current_select;
156
if (sel->set_braces(1))
158
my_parse_error(session->m_lip);
161
if (sel->linkage == UNION_TYPE &&
162
!sel->master_unit()->first_select()->braces &&
163
sel->master_unit()->first_select()->linkage ==
166
my_parse_error(session->m_lip);
169
if (sel->linkage == UNION_TYPE &&
170
sel->olap != UNSPECIFIED_OLAP_TYPE &&
171
sel->master_unit()->fake_select_lex)
173
my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
176
/* select in braces, can't contain global parameters */
177
if (sel->master_unit()->fake_select_lex)
178
sel->master_unit()->global_parameters=
179
sel->master_unit()->fake_select_lex;
183
Item* reserved_keyword_function(Session *session, const std::string &name, List<Item> *item_list)
185
const plugin::Function *udf= plugin::Function::get(name);
189
return Create_udf_func::s_singleton.create(session, udf, item_list);
192
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", name.c_str());
198
@brief Push an error message into MySQL error stack with line
199
and position information.
201
This function provides semantic action implementers with a way
202
to push the famous "You have a syntax error near..." error
203
message into the error stack, which is normally produced only if
204
a parse error is discovered internally by the Bison generated
207
void my_parse_error(Lex_input_stream *lip)
211
const char *yytext= lip->get_tok_start();
212
/* Push an error into the error stack */
213
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), ER(ER_SYNTAX_ERROR),
214
(yytext ? yytext : ""),
218
void my_parse_error(const char *message)
220
my_printf_error(ER_PARSE_ERROR_UNKNOWN, ER(ER_PARSE_ERROR_UNKNOWN), MYF(0), message);
223
bool check_reserved_words(LEX_STRING *name)
225
if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
226
!my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
227
!my_strcasecmp(system_charset_info, name->str, "SESSION"))
235
@brief Bison callback to report a syntax/OOM error
237
This function is invoked by the bison-generated parser
238
when a syntax error, a parse error or an out-of-memory
239
condition occurs. This function is not invoked when the
240
parser is requested to abort by semantic action code
241
by means of YYABORT or YYACCEPT macros. This is why these
242
macros should not be used (use DRIZZLE_YYABORT/DRIZZLE_YYACCEPT
245
The parser will abort immediately after invoking this callback.
247
This function is not for use in semantic actions and is internal to
248
the parser, as it performs some pre-return cleanup.
249
In semantic actions, please use parser::my_parse_error or my_error to
250
push an error into the error stack and DRIZZLE_YYABORT
251
to abort from the parser.
253
void errorOn(drizzled::Session *session, const char *s)
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(LEX *lex)
268
Select_Lex *sel= lex->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 (lex->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(lex->session))
303
void buildEngineOption(LEX *lex, const char *key, const LEX_STRING &value)
305
message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
307
opt->set_state(value.str, value.length);
310
void buildEngineOption(LEX *lex, const char *key, uint64_t value)
312
drizzled::message::Engine::Option *opt= lex->table()->mutable_engine()->add_options();
314
opt->set_state(boost::lexical_cast<std::string>(value));
317
void buildSchemaOption(LEX *lex, const char *key, const LEX_STRING &value)
319
statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
320
message::Engine::Option *opt= statement->schema_message.mutable_engine()->add_options();
322
opt->set_state(value.str, value.length);
325
void buildSchemaOption(LEX *lex, const char *key, uint64_t value)
327
statement::CreateSchema *statement= (statement::CreateSchema *)lex->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(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
335
TableList *table= reinterpret_cast<TableList*>(lex->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(LEX *lex,
357
const LEX_STRING &schema_name,
358
const LEX_STRING &table_name,
359
const LEX_STRING &field_name)
361
Select_Lex *sel= lex->current_select;
363
if (table_name.length and sel->no_table_names_allowed)
365
my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
366
MYF(0), table_name.str, lex->session->where());
369
Item *item= (sel->parsing_place != IN_HAVING or
370
sel->get_in_sum_expr() > 0) ?
371
(Item*) new Item_field(lex->current_context(), schema_name.str, table_name.str, field_name.str) :
372
(Item*) new Item_ref(lex->current_context(), schema_name.str, table_name.str, field_name.str);
377
Item *buildTableWild(LEX *lex, const LEX_STRING &schema_name, const LEX_STRING &table_name)
379
Select_Lex *sel= lex->current_select;
380
Item *item= new Item_field(lex->current_context(), schema_name.str, table_name.str, "*");
386
void buildCreateFieldIdent(LEX *lex)
388
statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
389
lex->length= lex->dec=0;
391
statement->default_value= statement->on_update_value= 0;
392
statement->comment= null_lex_str;
394
statement->column_format= COLUMN_FORMAT_TYPE_DEFAULT;
396
message::AddedFields &added_fields_proto= ((statement::CreateTable *)lex->statement)->alter_info.added_fields_proto;
397
lex->setField(added_fields_proto.add_added_field());
400
void storeAlterColumnPosition(LEX *lex, const char *position)
402
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
404
lex->last_field->after=const_cast<char*> (position);
405
statement->alter_info.flags.set(ALTER_COLUMN_ORDER);
408
bool buildCollation(LEX *lex, const charset_info_st *arg)
410
statement::CreateTable *statement= (statement::CreateTable *)lex->statement;
412
HA_CREATE_INFO *cinfo= &statement->create_info();
413
if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
414
cinfo->default_table_charset && arg &&
415
!my_charset_same(cinfo->default_table_charset, arg))
417
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
418
arg->name, cinfo->default_table_charset->csname);
421
statement->create_info().default_table_charset= arg;
422
statement->create_info().used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
427
void buildKey(LEX *lex, Key::Keytype type_par, const lex_string_t &name_arg)
429
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
430
Key *key= new Key(type_par, name_arg, &statement->key_create_info, 0,
432
statement->alter_info.key_list.push_back(key);
433
lex->col_list.clear(); /* Alloced by memory::sql_alloc */
436
void buildForeignKey(LEX *lex, const lex_string_t &name_arg, drizzled::Table_ident *table)
438
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
439
Key *key= new Foreign_key(name_arg, lex->col_list,
442
statement->fk_delete_opt,
443
statement->fk_update_opt,
444
statement->fk_match_option);
446
statement->alter_info.key_list.push_back(key);
447
key= new Key(Key::MULTIPLE, name_arg,
448
&default_key_create_info, 1,
450
statement->alter_info.key_list.push_back(key);
451
lex->col_list.clear(); /* Alloced by memory::sql_alloc */
452
/* Only used for ALTER TABLE. Ignored otherwise. */
453
statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
456
drizzled::enum_field_types buildIntegerColumn(LEX *lex, drizzled::enum_field_types final_type, const bool is_unsigned)
458
lex->length=(char*) 0; /* use default length */
462
final_type= DRIZZLE_TYPE_LONGLONG;
467
assert (final_type == DRIZZLE_TYPE_LONG or final_type == DRIZZLE_TYPE_LONGLONG);
468
// We update the type for unsigned types
471
lex->field()->set_type(message::Table::Field::BIGINT);
472
lex->field()->mutable_constraints()->set_is_unsigned(true);
474
else if (final_type == DRIZZLE_TYPE_LONG)
476
lex->field()->set_type(message::Table::Field::INTEGER);
478
else if (final_type == DRIZZLE_TYPE_LONGLONG)
480
lex->field()->set_type(message::Table::Field::BIGINT);
487
drizzled::enum_field_types buildSerialColumn(LEX *lex)
489
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
490
statement->alter_info.flags.set(ALTER_ADD_INDEX);
492
lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG | UNSIGNED_FLAG);
496
lex->field()->mutable_constraints()->set_is_notnull(true);
497
lex->field()->mutable_constraints()->set_is_unsigned(true);
499
lex->field()->set_type(message::Table::Field::BIGINT);
502
return DRIZZLE_TYPE_LONGLONG;
505
drizzled::enum_field_types buildVarcharColumn(LEX *lex, const char *length)
507
lex->length= const_cast<char *>(length);
511
lex->field()->set_type(message::Table::Field::VARCHAR);
513
message::Table::Field::StringFieldOptions *string_field_options;
515
string_field_options= lex->field()->mutable_string_options();
517
string_field_options->set_length(atoi(length));
520
return DRIZZLE_TYPE_VARCHAR;
523
drizzled::enum_field_types buildDecimalColumn(LEX *lex)
526
lex->field()->set_type(message::Table::Field::DECIMAL);
528
return DRIZZLE_TYPE_DECIMAL;
531
drizzled::enum_field_types buildVarbinaryColumn(LEX *lex, const char *length)
533
lex->length= const_cast<char *>(length);
534
lex->charset= &my_charset_bin;
538
lex->field()->set_type(message::Table::Field::VARCHAR);
540
message::Table::Field::StringFieldOptions *string_field_options;
542
string_field_options= lex->field()->mutable_string_options();
544
string_field_options->set_length(atoi(length));
545
string_field_options->set_collation_id(my_charset_bin.number);
546
string_field_options->set_collation(my_charset_bin.name);
549
return DRIZZLE_TYPE_VARCHAR;
552
drizzled::enum_field_types buildBlobColumn(LEX *lex)
554
lex->charset=&my_charset_bin;
555
lex->length=(char*) 0; /* use default length */
559
lex->field()->set_type(message::Table::Field::BLOB);
560
message::Table::Field::StringFieldOptions *string_field_options;
562
string_field_options= lex->field()->mutable_string_options();
563
string_field_options->set_collation_id(my_charset_bin.number);
564
string_field_options->set_collation(my_charset_bin.name);
567
return DRIZZLE_TYPE_BLOB;
570
drizzled::enum_field_types buildBooleanColumn(LEX *lex)
573
lex->field()->set_type(message::Table::Field::BOOLEAN);
575
return DRIZZLE_TYPE_BOOLEAN;
578
drizzled::enum_field_types buildUuidColumn(LEX *lex)
581
lex->field()->set_type(message::Table::Field::UUID);
583
return DRIZZLE_TYPE_UUID;
586
drizzled::enum_field_types buildDoubleColumn(LEX *lex)
590
lex->field()->set_type(message::Table::Field::DOUBLE);
593
return DRIZZLE_TYPE_DOUBLE;
596
drizzled::enum_field_types buildTimestampColumn(LEX *lex, const char *length)
600
lex->field()->set_type(message::Table::Field::EPOCH);
605
lex->length= const_cast<char *>(length);
606
return DRIZZLE_TYPE_MICROTIME;
611
return DRIZZLE_TYPE_TIMESTAMP;
614
void buildKeyOnColumn(LEX *lex)
616
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
618
lex->type|= UNIQUE_KEY_FLAG;
619
statement->alter_info.flags.set(ALTER_ADD_INDEX);
623
lex->field()->mutable_constraints()->set_is_unique(true);
627
void buildAutoOnColumn(LEX *lex)
629
lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG;
633
lex->field()->mutable_constraints()->set_is_notnull(true);
637
void buildPrimaryOnColumn(LEX *lex)
639
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
641
lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
642
statement->alter_info.flags.set(ALTER_ADD_INDEX);
646
lex->field()->mutable_constraints()->set_is_notnull(true);
650
void buildReplicationOption(LEX *lex, bool arg)
652
statement::CreateSchema *statement= (statement::CreateSchema *)lex->statement;
653
message::set_is_replicated(statement->schema_message, arg);
656
void buildAddAlterDropIndex(LEX *lex, const char *name, bool is_foreign_key)
658
statement::AlterTable *statement= (statement::AlterTable *)lex->statement;
660
message::AlterTable::AlterTableOperation *operation;
661
operation= lex->alter_table()->add_operations();
662
operation->set_drop_name(name);
664
statement->alter_info.flags.set(ALTER_DROP_INDEX);
667
statement->alter_info.flags.set(ALTER_FOREIGN_KEY);
668
operation->set_operation(message::AlterTable::AlterTableOperation::DROP_FOREIGN_KEY);
672
operation->set_operation(message::AlterTable::AlterTableOperation::DROP_KEY);
676
} // namespace parser
677
} // namespace drizzled