summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc124
1 files changed, 80 insertions, 44 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 788d12cb898..33db36ff255 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2293,6 +2293,10 @@ mysql_execute_command(THD *thd)
lex->first_lists_tables_same();
/* should be assigned after making first tables same */
all_tables= lex->query_tables;
+ /* set context for commands which do not use setup_tables */
+ select_lex->
+ context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
+ table_list.first);
/*
Reset warning count for each query that uses tables
@@ -2302,8 +2306,7 @@ mysql_execute_command(THD *thd)
Don't reset warnings when executing a stored routine.
*/
if ((all_tables || &lex->select_lex != lex->all_selects_list ||
- lex->spfuns.records || lex->spprocs.records) &&
- !thd->spcont)
+ lex->sroutines.records) && !thd->spcont)
mysql_reset_errors(thd, 0);
#ifdef HAVE_REPLICATION
@@ -2355,10 +2358,6 @@ mysql_execute_command(THD *thd)
}
#endif /* !HAVE_REPLICATION */
-
-
-
-
/*
When option readonly is set deny operations which change tables.
Except for the replication thread and the 'super' users.
@@ -2576,7 +2575,7 @@ mysql_execute_command(THD *thd)
goto error;
/* PURGE MASTER LOGS BEFORE 'data' */
it= (Item *)lex->value_list.head();
- if ((!it->fixed &&it->fix_fields(lex->thd, 0, &it)) ||
+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
it->check_cols(1))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
@@ -2885,9 +2884,7 @@ mysql_execute_command(THD *thd)
CREATE from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
- select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
res= handle_select(thd, lex, result, 0);
- select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
delete result;
}
/* reset for PS */
@@ -3226,6 +3223,8 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= insert_precheck(thd, all_tables)))
break;
+ /* Skip first table, which is the table we are inserting in */
+ select_lex->context.table_list= first_table->next_local;
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
@@ -3236,6 +3235,7 @@ end_with_restore_list:
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
+ select_result *result;
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= insert_precheck(thd, all_tables)))
break;
@@ -3247,27 +3247,24 @@ end_with_restore_list:
/* Don't unlock tables until command is written to binary log */
select_lex->options|= SELECT_NO_UNLOCK;
- select_result *result;
unit->set_limit(select_lex);
-
if (!(res= open_and_lock_tables(thd, all_tables)))
{
/* Skip first table, which is the table we are inserting in */
select_lex->table_list.first= (byte*)first_table->next_local;
res= mysql_insert_select_prepare(thd);
+ lex->select_lex.context.table_list= first_table->next_local;
if (!res && (result= new select_insert(first_table, first_table->table,
&lex->field_list,
- &lex->update_list, &lex->value_list,
+ &lex->update_list,
+ &lex->value_list,
lex->duplicates, lex->ignore)))
{
- /*
- insert/replace from SELECT give its SELECT_LEX for SELECT,
- and item_list belong to SELECT
- */
- select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
+ /* Skip first table, which is the table we are inserting in */
+ select_lex->context.table_list= first_table->next_local;
+
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
- select_lex->resolve_mode= SELECT_LEX::INSERT_MODE;
delete result;
}
/* revert changes for SP */
@@ -3276,7 +3273,6 @@ end_with_restore_list:
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
-
break;
}
case SQLCOM_TRUNCATE:
@@ -3868,7 +3864,7 @@ end_with_restore_list:
{
Item *it= (Item *)lex->value_list.head();
- if ((!it->fixed && it->fix_fields(lex->thd, 0, &it)) || it->check_cols(1))
+ if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
{
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
MYF(0));
@@ -5235,16 +5231,27 @@ mysql_new_select(LEX *lex, bool move_down)
unit->link_prev= 0;
unit->return_to= lex->current_select;
select_lex->include_down(unit);
- /* TODO: assign resolve_mode for fake subquery after merging with new tree */
+ /*
+ By default we assume that it is usual subselect and we have outer name
+ resolution context, if no we will assign it to 0 later
+ */
+ select_lex->context.outer_context= &select_lex->outer_select()->context;
}
else
{
+ Name_resolution_context *outer_context;
if (lex->current_select->order_list.first && !lex->current_select->braces)
{
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
DBUG_RETURN(1);
}
select_lex->include_neighbour(lex->current_select);
+ /*
+ we are not sure that we have one level of SELECTs above, so we take
+ outer_context address from first select of unit
+ */
+ outer_context=
+ select_lex->master_unit()->first_select()->context.outer_context;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
SELECT_LEX *fake= unit->fake_select_lex;
if (!fake)
@@ -5261,13 +5268,23 @@ mysql_new_select(LEX *lex, bool move_down)
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= 0;
+
+ fake->context.outer_context= outer_context;
+ /* allow item list resolving in fake select for ORDER BY */
+ fake->context.resolve_in_select_list= TRUE;
+ fake->context.select_lex= fake;
}
+ select_lex->context.outer_context= outer_context;
}
select_lex->master_unit()->global_parameters= select_lex;
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
lex->current_select= select_lex;
- select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
+ /*
+ in subquery is SELECT query and we allow resolution of names in SELECT
+ list
+ */
+ select_lex->context.resolve_in_select_list= TRUE;
DBUG_RETURN(0);
}
@@ -5498,6 +5515,21 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
DBUG_RETURN(1);
}
+ if (type == FIELD_TYPE_TIMESTAMP && length)
+ {
+ /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
+ In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
+ and so on, the display width is ignored.
+ */
+ char buf[32];
+ my_snprintf(buf, sizeof(buf),
+ "TIMESTAMP(%s)", length, system_charset_info);
+ push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DEPRECATED_SYNTAX,
+ ER(ER_WARN_DEPRECATED_SYNTAX),
+ buf, "TIMESTAMP");
+ }
+
if (!(new_field= new_create_field(thd, field_name, type, length, decimals,
type_modifier, default_value, on_update_value,
comment, change, interval_list, cs, uint_geom_type)))
@@ -5535,8 +5567,14 @@ new_create_field(THD *thd, char *field_name, enum_field_types type,
new_field->flags= type_modifier;
new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
- new_field->decimals= decimals ? (uint) set_zone(atoi(decimals),0,
- NOT_FIXED_DEC-1) : 0;
+ new_field->decimals= decimals ? (uint)atoi(decimals) : 0;
+ if (new_field->decimals >= NOT_FIXED_DEC)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name,
+ NOT_FIXED_DEC-1);
+ DBUG_RETURN(NULL);
+ }
+
new_field->sql_type=type;
new_field->length=0;
new_field->change=change;
@@ -5557,11 +5595,6 @@ new_create_field(THD *thd, char *field_name, enum_field_types type,
length=0; /* purecov: inspected */
sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
- if (new_field->length && new_field->decimals &&
- new_field->length < new_field->decimals+1 &&
- new_field->decimals != NOT_FIXED_DEC)
- new_field->length=new_field->decimals+1; /* purecov: inspected */
-
switch (type) {
case FIELD_TYPE_TINY:
if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len;
@@ -5587,22 +5620,24 @@ new_create_field(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_NEWDECIMAL:
if (!length)
+ new_field->length= 10;
+ if (new_field->length > DECIMAL_MAX_PRECISION)
{
- if (!(new_field->length= new_field->decimals))
- new_field->length= 10; // Default length for DECIMAL
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name,
+ DECIMAL_MAX_PRECISION);
+ DBUG_RETURN(NULL);
}
- new_field->pack_length=
- my_decimal_get_binary_size(new_field->length, new_field->decimals);
- if (new_field->length <= DECIMAL_MAX_PRECISION &&
- new_field->length >= new_field->decimals)
+ if (new_field->length < new_field->decimals)
{
- new_field->length=
- my_decimal_precision_to_length(new_field->length, new_field->decimals,
- type_modifier & UNSIGNED_FLAG);
- break;
+ my_error(ER_SCALE_BIGGER_THAN_PRECISION, MYF(0), field_name);
+ DBUG_RETURN(NULL);
}
- my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
- DBUG_RETURN(NULL);
+ new_field->length=
+ my_decimal_precision_to_length(new_field->length, new_field->decimals,
+ type_modifier & UNSIGNED_FLAG);
+ new_field->pack_length=
+ my_decimal_get_binary_size(new_field->length, new_field->decimals);
+ break;
case MYSQL_TYPE_VARCHAR:
/*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
@@ -6371,9 +6406,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
*/
/*
- Writing this command to the binlog may result in infinite loops when doing
- mysqlbinlog|mysql, and anyway it does not really make sense to log it
- automatically (would cause more trouble to users than it would help them)
+ Writing this command to the binlog may result in infinite loops
+ when doing mysqlbinlog|mysql, and anyway it does not really make
+ sense to log it automatically (would cause more trouble to users
+ than it would help them)
*/
tmp_write_to_binlog= 0;
mysql_log.new_file(1);