summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-09-09 07:26:28 +0300
committerunknown <monty@mysql.com>2004-09-09 07:26:28 +0300
commite18b7ea95942cb8ab0b31d453929dde50dcf3756 (patch)
treee2b882265e31ada44f3adec357920530f0c0ac31 /sql/sql_parse.cc
parentc92b5349701ba68fa7ab97abf14933de8d6352fe (diff)
parent33efc9677d6f6a68d3dba69f4c036856ac4af5fe (diff)
downloadmariadb-git-e18b7ea95942cb8ab0b31d453929dde50dcf3756.tar.gz
Merge on pull
BitKeeper/etc/logging_ok: auto-union include/my_sys.h: Auto merged mysql-test/r/func_in.result: Auto merged
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc166
1 files changed, 118 insertions, 48 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 546183563c9..9a76fa2da84 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1572,7 +1572,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
mysqld_list_fields(thd,&table_list,fields);
free_items(thd->free_list);
- thd->free_list=0; /* free_list should never point to garbage */
+ thd->free_list= 0; /* free_list should never point to garbage */
break;
}
#endif
@@ -1673,8 +1673,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
packet[0].
*/
- enum enum_shutdown_level level=
- (enum enum_shutdown_level) (uchar) packet[0];
+ enum mysql_enum_shutdown_level level=
+ (enum mysql_enum_shutdown_level) (uchar) packet[0];
DBUG_PRINT("quit",("Got shutdown command for level %u", level));
if (level == SHUTDOWN_DEFAULT)
level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
@@ -1958,6 +1958,20 @@ mysql_execute_command(THD *thd)
}
#endif /* !HAVE_REPLICATION */
+ if (lex->time_zone_tables_used)
+ {
+ TABLE_LIST *tmp;
+ if ((tmp= my_tz_get_table_list(thd, &lex->query_tables_last)) ==
+ &fake_time_zone_tables_list)
+ {
+ send_error(thd, 0);
+ DBUG_RETURN(-1);
+ }
+ lex->time_zone_tables_used= tmp;
+ if (!all_tables)
+ all_tables= tmp;
+ }
+
/*
When option readonly is set deny operations which change tables.
Except for the replication thread and the 'super' users.
@@ -2011,8 +2025,6 @@ mysql_execute_command(THD *thd)
else
thd->send_explain_fields(result);
res= mysql_explain_union(thd, &thd->lex->unit, result);
- MYSQL_LOCK *save_lock= thd->lock;
- thd->lock= (MYSQL_LOCK *)0;
if (lex->describe & DESCRIBE_EXTENDED)
{
char buff[1024];
@@ -2024,20 +2036,19 @@ mysql_execute_command(THD *thd)
ER_YES, str.ptr());
}
result->send_eof();
- thd->lock= save_lock;
+ delete result;
}
else
{
- if (!result)
+ if (!result && !(result= new select_send()))
{
- if (!(result=new select_send()))
- {
- res= -1;
- break;
- }
+ res= -1;
+ break;
}
query_cache_store_query(thd, all_tables);
- res=handle_select(thd, lex, result);
+ res= handle_select(thd, lex, result);
+ if (result != lex->result)
+ delete result;
}
}
break;
@@ -2393,6 +2404,21 @@ mysql_execute_command(THD *thd)
net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name);
goto create_error;
}
+ if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
+ {
+ TABLE_LIST *tab;
+ for (tab= select_tables; tab; tab= tab->next_local)
+ {
+ if (find_table_in_local_list((TABLE_LIST*) lex->create_info.
+ merge_list.first,
+ select_tables->db, tab->real_name))
+ {
+ net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
+ goto create_error;
+ }
+ }
+ }
+
if (select_tables &&
check_table_access(thd, SELECT_ACL, select_tables, 0))
goto create_error; // Error message is given
@@ -2432,7 +2458,7 @@ mysql_execute_command(THD *thd)
res= mysql_create_table(thd, create_table->db,
create_table->real_name, &lex->create_info,
lex->create_list,
- lex->key_list, 0, 0, 0); // do logging
+ lex->key_list, 0, 0);
}
if (!res)
send_ok(thd);
@@ -2758,31 +2784,30 @@ unsent_create_error:
// is table which we are changing used somewhere in other parts of query
if (find_table_in_global_list(all_tables->next_global,
- first_table->db, first_table->real_name))
+ first_table->db, first_table->real_name))
{
/* Using same table for INSERT and SELECT */
select_lex->options |= OPTION_BUFFER_RESULT;
}
- if (!(res= open_and_lock_tables(thd, all_tables)))
+ if (!(res= open_and_lock_tables(thd, all_tables)) &&
+ !(res= mysql_insert_select_prepare(thd)) &&
+ (result= new select_insert(first_table, first_table->table,
+ &lex->field_list, lex->duplicates)))
{
- if ((res= mysql_insert_select_prepare(thd)))
- break;
- if ((result= new select_insert(first_table, first_table->table,
- &lex->field_list, lex->duplicates)))
- /* Skip first table, which is the table we are inserting in */
- lex->select_lex.table_list.first= (byte*) first_table->next_local;
- /*
- insert/replace from SELECT give its SELECT_LEX for SELECT,
- and item_list belong to SELECT
- */
- lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
- res= handle_select(thd, lex, result);
- /* revert changes for SP */
- lex->select_lex.table_list.first= (byte*) first_table;
- lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
+ /* Skip first table, which is the table we are inserting in */
+ lex->select_lex.table_list.first= (byte*) first_table->next_local;
+ /*
+ insert/replace from SELECT give its SELECT_LEX for SELECT,
+ and item_list belong to SELECT
+ */
+ lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
+ res= handle_select(thd, lex, result);
+ lex->select_lex.table_list.first= (byte*) first_table;
+ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
+ delete result;
if (thd->net.report_error)
- res= -1;
+ res= -1;
}
else
res= -1;
@@ -2806,7 +2831,7 @@ unsent_create_error:
goto error;
}
- res= mysql_truncate(thd, first_table);
+ res= mysql_truncate(thd, first_table, 0);
break;
case SQLCOM_DELETE:
{
@@ -3755,7 +3780,7 @@ purposes internal to the MySQL server", MYF(0));
case SP_KEY_NOT_FOUND:
if (lex->drop_if_exists)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
SP_COM_STRING(lex), lex->spname->m_name.str);
res= 0;
@@ -4289,6 +4314,7 @@ mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly)
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
+ lex->time_zone_tables_used= 0;
lex->proc_table= lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
lex->variables_used= 0;
@@ -4323,8 +4349,8 @@ mysql_init_select(LEX *lex)
select_lex->select_limit= HA_POS_ERROR;
if (select_lex == &lex->select_lex)
{
+ DBUG_ASSERT(lex->result == 0);
lex->exchange= 0;
- lex->result= 0;
lex->proc_list.first= 0;
}
}
@@ -4493,9 +4519,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
}
}
thd->proc_info="freeing items";
- free_items(thd->free_list); /* Free strings used by items */
- thd->free_list= 0; /* free_list should never point to garbage */
- lex_end(lex);
+ thd->end_statement();
}
DBUG_VOID_RETURN;
}
@@ -4521,10 +4545,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
if (!yyparse((void*) thd) && ! thd->is_fatal_error &&
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
error= 1; /* Ignore question */
- free_items(thd->free_list); /* Free strings used by items */
- thd->free_list= 0; /* free_list should never point to garbage */
- lex_end(lex);
-
+ thd->end_statement();
DBUG_RETURN(error);
}
#endif
@@ -4691,7 +4712,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->sql_type= FIELD_TYPE_BLOB;
sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
(cs == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_AUTO_CONVERT,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
warn_buff);
/* fall through */
case FIELD_TYPE_BLOB:
@@ -4769,8 +4790,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
case FIELD_TYPE_TIMESTAMP:
if (!length)
new_field->length= 14; // Full date YYYYMMDDHHMMSS
- else
+ else if (new_field->length != 19)
{
+ /*
+ We support only even TIMESTAMP lengths less or equal than 14
+ and 19 as length of 4.1 compatible representation.
+ */
new_field->length=((new_field->length+1)/2)*2; /* purecov: inspected */
new_field->length= min(new_field->length,14); /* purecov: inspected */
}
@@ -4831,7 +4856,10 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length=0;
for (const char **pos=interval->type_names; *pos ; pos++)
{
- new_field->length+=(uint) strip_sp((char*) *pos)+1;
+ uint length= (uint) strip_sp((char*) *pos)+1;
+ CHARSET_INFO *cs= thd->variables.character_set_client;
+ length= cs->cset->numchars(cs, *pos, *pos+length);
+ new_field->length+= length;
}
new_field->length--;
set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
@@ -4861,8 +4889,10 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length=(uint) strip_sp((char*) interval->type_names[0]);
for (const char **pos=interval->type_names+1; *pos ; pos++)
{
- uint length=(uint) strip_sp((char*) *pos);
- set_if_bigger(new_field->length,length);
+ uint length=(uint) strip_sp((char*) *pos);
+ CHARSET_INFO *cs= thd->variables.character_set_client;
+ length= cs->cset->numchars(cs, *pos, *pos+length);
+ set_if_bigger(new_field->length,length);
}
set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
if (default_value)
@@ -5493,9 +5523,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0;
if (lock_global_read_lock(thd))
return 1;
+ result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
+ tables);
+ make_global_read_lock_block_commit(thd);
}
+ else
+ result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
my_dbopt_cleanup();
- result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
}
if (options & REFRESH_HOSTS)
hostname_cache_refresh();
@@ -6056,3 +6090,39 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0)) ?
1 : 0);
}
+
+
+/*
+ negate given expression
+
+ SYNOPSIS
+ negate_expression()
+ thd therad handler
+ expr expression for negation
+
+ RETURN
+ negated expression
+*/
+
+Item *negate_expression(THD *thd, Item *expr)
+{
+ Item *negated;
+ if (expr->type() == Item::FUNC_ITEM &&
+ ((Item_func *) expr)->functype() == Item_func::NOT_FUNC)
+ {
+ /* it is NOT(NOT( ... )) */
+ Item *arg= ((Item_func *) expr)->arguments()[0];
+ enum_parsing_place place= thd->lex->current_select->parsing_place;
+ if (arg->is_bool_func() || place == IN_WHERE || place == IN_HAVING)
+ return arg;
+ /*
+ if it is not boolean function then we have to emulate value of
+ not(not(a)), it will be a != 0
+ */
+ return new Item_func_ne(arg, new Item_int((char*) "0", 0, 1));
+ }
+
+ if ((negated= expr->neg_transformer(thd)) != 0)
+ return negated;
+ return new Item_func_not(expr);
+}