1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge 4.1 -> 5.0

BitKeeper/etc/ignore:
  auto-union
BitKeeper/etc/logging_ok:
  auto-union
VC++Files/sql/mysqld.dsp:
  Auto merged
configure.in:
  Auto merged
include/my_global.h:
  Auto merged
include/mysql_com.h:
  Auto merged
libmysql/libmysql.c:
  Auto merged
libmysqld/Makefile.am:
  Auto merged
myisam/myisamchk.c:
  Auto merged
myisam/myisamdef.h:
  Auto merged
mysql-test/install_test_db.sh:
  Auto merged
mysql-test/r/func_time.result:
  Auto merged
mysql-test/r/mysqldump.result:
  Auto merged
mysql-test/r/show_check.result:
  Auto merged
mysql-test/r/subselect.result:
  Auto merged
mysql-test/r/union.result:
  Auto merged
mysql-test/t/func_time.test:
  Auto merged
mysql-test/t/subselect.test:
  Auto merged
scripts/make_binary_distribution.sh:
  Auto merged
scripts/mysql_install_db.sh:
  Auto merged
sql/ha_berkeley.cc:
  Auto merged
mysql-test/t/rpl_error_ignored_table.test:
  Auto merged
sql/ha_berkeley.h:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/ha_innodb.h:
  Auto merged
sql/ha_myisam.cc:
  Auto merged
sql/handler.cc:
  Auto merged
sql/handler.h:
  Auto merged
sql/item.cc:
  Auto merged
sql/item.h:
  Auto merged
sql/item_cmpfunc.cc:
  Auto merged
sql/item_cmpfunc.h:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/item_sum.cc:
  Auto merged
sql/item_sum.h:
  Auto merged
sql/lex.h:
  Auto merged
sql/log.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/protocol.cc:
  Auto merged
sql/records.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_acl.h:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_cache.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_db.cc:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_load.cc:
  Auto merged
sql/sql_prepare.cc:
  Auto merged
sql/sql_select.h:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/sql_string.cc:
  Auto merged
sql/sql_test.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/table.h:
  Auto merged
tests/client_test.c:
  Auto merged
This commit is contained in:
unknown
2004-05-07 18:52:06 +02:00
2201 changed files with 519910 additions and 8438 deletions

View File

@@ -65,13 +65,10 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
#endif
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
static int check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables, bool no_errors);
const char *any_db="*any*"; // Special symbol for check_access
@@ -1109,6 +1106,12 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
while (fgets(buff, thd->net.max_packet, file))
{
uint length=(uint) strlen(buff);
if (buff[length-1]!='\n' && !feof(file))
{
send_error(thd,ER_NET_PACKET_TOO_LARGE, NullS);
thd->is_fatal_error= 1;
break;
}
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
buff[length-1] == ';'))
length--;
@@ -1191,7 +1194,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
DBUG_RETURN(1);
if (check_one_table_access(thd, SELECT_ACL, table_list, 0))
if (check_one_table_access(thd, SELECT_ACL, table_list))
goto err;
thd->free_list = 0;
thd->query_length=(uint) strlen(tbl_name);
@@ -1439,6 +1442,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_EXECUTE:
{
thd->free_list= NULL;
mysql_stmt_execute(thd, packet, packet_length);
break;
}
@@ -1551,7 +1555,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
0, 0))
break;
if (grant_option && check_grant(thd,SELECT_ACL,&table_list,2,0))
if (grant_option &&
check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
break;
mysqld_list_fields(thd,&table_list,fields);
free_items(thd->free_list);
@@ -1894,7 +1899,7 @@ mysql_execute_command(THD *thd)
if (&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables))
DBUG_RETURN(0);
/*
When option readonly is set deny operations which change tables.
Except for the replication thread and the 'super' users.
@@ -1911,6 +1916,13 @@ mysql_execute_command(THD *thd)
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
/* assign global limit variable if limit is not given */
{
SELECT_LEX *param= lex->unit.global_parameters;
if (!param->explicit_limit)
param->select_limit= thd->variables.select_limit;
}
select_result *result=lex->result;
if (tables)
{
@@ -2150,11 +2162,7 @@ mysql_execute_command(THD *thd)
if (grant_option)
{
/* Check that the first table has CREATE privilege */
TABLE_LIST *tmp_table_list=tables->next;
tables->next=0;
bool error=check_grant(thd,CREATE_ACL,tables,0,0);
tables->next=tmp_table_list;
if (error)
if (check_grant(thd, CREATE_ACL, tables, 0, 1, 0))
goto error;
}
if (strlen(tables->real_name) > NAME_LEN)
@@ -2180,30 +2188,13 @@ mysql_execute_command(THD *thd)
case SQLCOM_CREATE_TABLE:
{
/* Skip first table, which is the table we are creating */
TABLE_LIST *create_table= tables;
TABLE_LIST *create_table_local=
(TABLE_LIST*)lex->select_lex.table_list.first;
// exclude from global table list
tables= tables->next;
// and from local list if it is not the same
if (&lex->select_lex != lex->all_selects_list)
lex->select_lex.table_list.first= (gptr)create_table_local->next;
else
lex->select_lex.table_list.first= (gptr)tables;
create_table->next= 0;
TABLE_LIST *create_table, *create_table_local;
tables= lex->unlink_first_table(tables, &create_table,
&create_table_local);
if ((res= create_table_precheck(thd, tables, create_table)))
goto unsent_create_error;
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
lex->create_info.alias= create_table->alias;
if (check_access(thd, want_priv, create_table->db,
&create_table->grant.privilege, 0, 0) ||
check_merge_table_access(thd, create_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
goto create_eror; /* purecov: inspected */
if (grant_option && want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table,0,0))
goto create_eror;
#ifndef HAVE_READLINK
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
#else
@@ -2239,10 +2230,10 @@ mysql_execute_command(THD *thd)
create_table->real_name))
{
net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
goto create_eror;
goto create_error;
}
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto create_eror; // Error message is given
goto create_error; // Error message is given
select_lex->options|= SELECT_NO_UNLOCK;
unit->set_limit(select_lex, select_lex);
@@ -2256,6 +2247,9 @@ mysql_execute_command(THD *thd)
lex->key_list,
select_lex->item_list,lex->duplicates)))
res=handle_select(thd, lex, result);
//reset for PS
lex->create_list.empty();
lex->key_list.empty();
}
}
else // regular create
@@ -2273,39 +2267,22 @@ mysql_execute_command(THD *thd)
if (!res)
send_ok(thd);
}
// put tables back for PS rexecuting
create_table->next= tables;
tables= create_table;
if (&lex->select_lex != lex->all_selects_list)
{
/*
we do not touch local table 'next' field => we need just
put the table in the list
*/
lex->select_lex.table_list.first= (gptr) create_table_local;
}
else
lex->select_lex.table_list.first= (gptr) tables;
tables= lex->link_first_table_back(tables, create_table,
create_table_local);
break;
create_eror:
create_error:
res= 1; //error reported
unsent_create_error:
// put tables back for PS rexecuting
create_table->next= tables;
tables= create_table;
if (&lex->select_lex != lex->all_selects_list)
{
/*
we do not touch local table 'next' field => we need just
put the table in the list
*/
lex->select_lex.table_list.first= (gptr) create_table_local;
}
tables= lex->link_first_table_back(tables, create_table,
create_table_local);
break;
}
case SQLCOM_CREATE_INDEX:
if (check_one_table_access(thd, INDEX_ACL, tables, 0))
if (check_one_table_access(thd, INDEX_ACL, tables))
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
if (end_active_trans(thd))
@@ -2372,7 +2349,7 @@ unsent_create_error:
goto error; /* purecov: inspected */
if (grant_option)
{
if (check_grant(thd,ALTER_ACL,tables,0,0))
if (check_grant(thd, ALTER_ACL, tables, 0, UINT_MAX, 0))
goto error;
if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
{ // Rename of table
@@ -2381,7 +2358,8 @@ unsent_create_error:
tmp_table.real_name=lex->name;
tmp_table.db=select_lex->db;
tmp_table.grant.privilege=priv;
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, 0))
if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
UINT_MAX, 0))
goto error;
}
}
@@ -2399,6 +2377,7 @@ unsent_create_error:
lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->alter_flags,
lex->duplicates,
lex->alter_keys_onoff,
lex->tablespace_op,
@@ -2429,10 +2408,11 @@ unsent_create_error:
old_list=table[0];
new_list=table->next[0];
old_list.next=new_list.next=0;
if (check_grant(thd,ALTER_ACL,&old_list,0,0) ||
if (check_grant(thd, ALTER_ACL, &old_list, 0, UINT_MAX, 0) ||
(!test_all_bits(table->next->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list,0,0)))
check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0,
UINT_MAX, 0)))
goto error;
}
}
@@ -2547,7 +2527,7 @@ unsent_create_error:
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
0, (ORDER *) 0,
0, (ORDER *) 0, 0,
DUP_ERROR);
}
else
@@ -2564,15 +2544,8 @@ unsent_create_error:
break;
}
case SQLCOM_UPDATE:
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
goto error;
}
if (check_db_used(thd,tables))
goto error;
if (check_one_table_access(thd, UPDATE_ACL, tables, 0))
goto error;
if (update_precheck(thd, tables))
break;
res= mysql_update(thd,tables,
select_lex->item_list,
lex->value_list,
@@ -2586,39 +2559,8 @@ unsent_create_error:
break;
case SQLCOM_UPDATE_MULTI:
{
const char *msg= 0;
TABLE_LIST *table;
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
goto error;
}
/*
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
for (table= tables ; table ; table= table->next)
{
TABLE_LIST *save= table->next;
table->next= 0;
if (check_one_table_access(thd, UPDATE_ACL, table, 1) &&
check_one_table_access(thd, SELECT_ACL, table, 0))
goto error;
table->next= save;
}
if (select_lex->order_list.elements)
msg= "ORDER BY";
else if (select_lex->select_limit && select_lex->select_limit !=
HA_POS_ERROR)
msg= "LIMIT";
if (msg)
{
net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg);
res= 1;
if ((res= multi_update_precheck(thd, tables)))
break;
}
res= mysql_multi_update(thd,tables,
&select_lex->item_list,
&lex->value_list,
@@ -2630,17 +2572,9 @@ unsent_create_error:
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
{
my_bool update=(lex->value_list.elements ? UPDATE_ACL : 0);
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
if (check_one_table_access(thd, privilege, tables, 0))
goto error;
if (select_lex->item_list.elements != lex->value_list.elements)
{
send_error(thd,ER_WRONG_VALUE_COUNT);
goto error;
}
my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
if ((res= insert_precheck(thd, tables, update)))
break;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
select_lex->item_list, lex->value_list,
(update ? DUP_UPDATE : lex->duplicates));
@@ -2651,16 +2585,9 @@ unsent_create_error:
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
{
/*
Check that we have modify privileges for the first table and
select privileges for the rest
*/
{
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
if (check_one_table_access(thd, privilege, tables, 0))
goto error;
}
TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first;
if ((res= insert_select_precheck(thd, tables)))
break;
/* Fix lock for first table */
if (tables->lock_type == TL_WRITE_DELAYED)
@@ -2678,16 +2605,18 @@ unsent_create_error:
select_lex->options |= OPTION_BUFFER_RESULT;
}
/* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first=
(byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next);
lex->select_lex.resolve_mode= SELECT_LEX::NOMATTER_MODE;
if (!(res=open_and_lock_tables(thd, tables)))
{
if ((result=new select_insert(tables->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_local_table->next;
lex->select_lex.resolve_mode= SELECT_LEX::NOMATTER_MODE;
res=handle_select(thd,lex,result);
/* revert changes for SP */
lex->select_lex.table_list.first= (byte*) first_local_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
if (thd->net.report_error)
res= -1;
}
@@ -2696,7 +2625,7 @@ unsent_create_error:
break;
}
case SQLCOM_TRUNCATE:
if (check_one_table_access(thd, DELETE_ACL, tables, 0))
if (check_one_table_access(thd, DELETE_ACL, tables))
goto error;
/*
Don't allow this within a transaction because we want to use
@@ -2711,10 +2640,8 @@ unsent_create_error:
break;
case SQLCOM_DELETE:
{
if (check_one_table_access(thd, DELETE_ACL, tables, 0))
goto error;
// Set privilege for the WHERE clause
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
if ((res= delete_precheck(thd, tables)))
break;
res = mysql_delete(thd,tables, select_lex->where,
&select_lex->order_list,
select_lex->select_limit, select_lex->options);
@@ -2724,58 +2651,33 @@ unsent_create_error:
}
case SQLCOM_DELETE_MULTI:
{
TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first;
TABLE_LIST *auxi;
uint table_count=0;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
TABLE_LIST *target_tbl;
uint table_count;
multi_delete *result;
/* sql_yacc guarantees that tables and aux_tables are not zero */
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
check_table_access(thd,SELECT_ACL, tables,0) ||
check_table_access(thd,DELETE_ACL, aux_tables,0))
goto error;
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
goto error;
}
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
{
table_count++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
{
if (!my_strcasecmp(table_alias_charset, auxi->alias, walk->alias) &&
!strcmp(walk->db, auxi->db))
break;
}
if (!walk)
{
net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
goto error;
}
if (walk->derived)
{
net_printf(thd, ER_NON_UPDATABLE_TABLE,
auxi->real_name, "DELETE");
goto error;
}
walk->lock_type= auxi->lock_type;
auxi->table_list= walk; // Remember corresponding table
}
if ((res= multi_delete_precheck(thd, tables, &table_count)))
break;
/* condition will be TRUE on SP re-excuting */
if (select_lex->item_list.elements != 0)
select_lex->item_list.empty();
if (add_item_to_list(thd, new Item_null()))
{
res= -1;
break;
}
thd->proc_info="init";
if ((res=open_and_lock_tables(thd,tables)))
break;
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
for (target_tbl= (TABLE_LIST*) aux_tables;
target_tbl;
target_tbl= target_tbl->next)
{
auxi->table= auxi->table_list->table;
target_tbl->table= target_tbl->table_list->table;
/*
Multi-delete can't be constructed over-union => we always have
single SELECT on top and have to check underlaying SELECTs of it
@@ -2785,10 +2687,11 @@ unsent_create_error:
un= un->next_unit())
{
if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
un->check_updateable(auxi->table_list->db,
auxi->table_list->real_name))
un->check_updateable(target_tbl->table_list->db,
target_tbl->table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name);
my_error(ER_UPDATE_TABLE_USED, MYF(0),
target_tbl->table_list->real_name);
res= -1;
break;
}
@@ -2846,7 +2749,7 @@ unsent_create_error:
}
break;
case SQLCOM_DROP_INDEX:
if (check_one_table_access(thd, INDEX_ACL, tables, 0))
if (check_one_table_access(thd, INDEX_ACL, tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
res= -1;
@@ -2961,7 +2864,7 @@ unsent_create_error:
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
&tables->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
goto error;
res= mysqld_show_fields(thd,tables,
(lex->wild ? lex->wild->ptr() : NullS),
@@ -2981,7 +2884,7 @@ unsent_create_error:
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
&tables->grant.privilege, 0, 0))
goto error; /* purecov: inspected */
if (grant_option && check_grant(thd,SELECT_ACL,tables,2,0))
if (grant_option && check_grant(thd, SELECT_ACL, tables, 2, UINT_MAX, 0))
goto error;
res= mysqld_show_keys(thd,tables);
break;
@@ -3009,7 +2912,7 @@ unsent_create_error:
send_error(thd,ER_NOT_ALLOWED_COMMAND);
goto error;
}
if (check_one_table_access(thd, privilege, tables, 0))
if (check_one_table_access(thd, privilege, tables))
goto error;
}
res=mysql_load(thd, lex->exchange, tables, lex->field_list,
@@ -3273,7 +3176,7 @@ unsent_create_error:
if (grant_option && check_grant(thd,
(lex->grant | lex->grant_tot_col |
GRANT_ACL),
tables,0,0))
tables, 0, UINT_MAX, 0))
goto error;
if (!(res = mysql_table_grant(thd,tables,lex->users_list, lex->columns,
lex->grant,
@@ -3768,33 +3671,26 @@ error:
thd Thread handler
privilege requested privelage
tables table list of command
no_errors Don't send error to client
RETURN
0 - OK
1 - access denied, error is sent to client
*/
static int check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables, bool no_errors)
int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables)
{
if (check_access(thd, privilege, tables->db, &tables->grant.privilege,0,0))
return 1;
// Show only 1 table for check_grant
TABLE_LIST *subselects_tables= tables->next;
tables->next= 0;
if (grant_option && check_grant(thd, privilege, tables, 0, 0))
{
tables->next= subselects_tables;
/* Show only 1 table for check_grant */
if (grant_option && check_grant(thd, privilege, tables, 0, 1, 0))
return 1;
}
// check rights on tables of subselect (if exists)
if (subselects_tables)
/* Check rights on tables of subselect (if exists) */
TABLE_LIST *subselects_tables;
if ((subselects_tables= tables->next))
{
tables->next= subselects_tables;
if ((check_table_access(thd, SELECT_ACL, subselects_tables,0)))
return 1;
}
@@ -3973,12 +3869,12 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
}
if (grant_option)
return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
test(want_access & EXTRA_ACL), no_errors);
test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
return FALSE;
}
static bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list)
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list)
{
int error=0;
if (table_list)
@@ -4135,9 +4031,7 @@ mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
select_lex->select_limit= (&lex->select_lex == select_lex) ?
lex->thd->variables.select_limit : /* Primry UNION */
HA_POS_ERROR; /* subquery */
select_lex->select_limit= HA_POS_ERROR;
if (select_lex == &lex->select_lex)
{
lex->exchange= 0;
@@ -4189,9 +4083,7 @@ mysql_new_select(LEX *lex, bool move_down)
fake->select_number= INT_MAX;
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= (&lex->unit == unit) ?
lex->thd->variables.select_limit : /* Primry UNION */
HA_POS_ERROR; /* subquery */
fake->select_limit= HA_POS_ERROR;
}
}
@@ -4249,6 +4141,7 @@ void mysql_init_multi_delete(LEX *lex)
When you modify mysql_parse(), you may need to mofify
mysql_test_parse_for_slave() in this same file.
*/
void mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_ENTER("mysql_parse");
@@ -4771,7 +4664,6 @@ static void remove_escape(char *name)
bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
{
ORDER *order;
Item **item_ptr;
DBUG_ENTER("add_to_list");
if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
DBUG_RETURN(1);
@@ -5289,3 +5181,353 @@ Item * all_any_subquery_creator(Item *left_expr,
return it; /* ANY/SOME */
}
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
In the future ALTER TABLE will notice that only added indexes
and create these one by one for the existing table without having to do
a full rebuild.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
List<Alter_drop> drop;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR));
}
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
DBUG_ENTER("mysql_drop_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR));
}
/*
Multi update query pre-check
SYNOPSIS
multi_update_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 Error (message is sent to user)
-1 Error (message is not sent to user)
*/
int multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("multi_update_precheck");
const char *msg= 0;
TABLE_LIST *table;
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
TABLE_LIST *update_list= (TABLE_LIST*)select_lex->table_list.first;
if (select_lex->item_list.elements != lex->value_list.elements)
{
my_error(ER_WRONG_VALUE_COUNT, MYF(0));
DBUG_RETURN(-1);
}
/*
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
for (table= update_list; table; table= table->next)
{
if ((check_access(thd, UPDATE_ACL, table->db,
&table->grant.privilege, 0, 1) ||
grant_option && check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
DBUG_RETURN(1);
/*
We assign following flag only to copy of table, because it will
be checked only if query contains subqueries i.e. only if copy exists
*/
if (table->table_list)
table->table_list->table_in_update_from_clause= 1;
}
/*
Is there tables of subqueries?
*/
if (&lex->select_lex != lex->all_selects_list)
{
for (table= tables; table; table= table->next)
{
if (table->table_in_update_from_clause)
{
/*
If we check table by local TABLE_LIST copy then we should copy
grants to global table list, because it will be used for table
opening.
*/
if (table->table_list)
table->grant= table->table_list->grant;
}
else
{
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))
DBUG_RETURN(1);
}
}
}
if (select_lex->order_list.elements)
msg= "ORDER BY";
else if (select_lex->select_limit && select_lex->select_limit !=
HA_POS_ERROR)
msg= "LIMIT";
if (msg)
{
my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*
Multi delete query pre-check
SYNOPSIS
multi_delete_precheck()
thd Thread handler
tables Global table list
table_count Pointer to table counter
RETURN VALUE
0 OK
1 error (message is sent to user)
-1 error (message is not sent to user)
*/
int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
{
DBUG_ENTER("multi_delete_precheck");
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
TABLE_LIST *delete_tables= (TABLE_LIST *)select_lex->table_list.first;
TABLE_LIST *target_tbl;
*table_count= 0;
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
check_table_access(thd,SELECT_ACL, tables,0) ||
check_table_access(thd,DELETE_ACL, aux_tables,0))
DBUG_RETURN(1);
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0));
DBUG_RETURN(-1);
}
for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next)
{
(*table_count)++;
/* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk;
for (walk= delete_tables; walk; walk= walk->next)
{
if (!my_strcasecmp(table_alias_charset,
target_tbl->alias, walk->alias) &&
!strcmp(walk->db, target_tbl->db))
break;
}
if (!walk)
{
my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name,
"MULTI DELETE");
DBUG_RETURN(-1);
}
if (walk->derived)
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), target_tbl->real_name,
"DELETE");
DBUG_RETURN(-1);
}
walk->lock_type= target_tbl->lock_type;
target_tbl->table_list= walk; // Remember corresponding table
}
DBUG_RETURN(0);
}
/*
INSERT ... SELECT query pre-check
SYNOPSIS
multi_delete_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 Error (message is sent to user)
-1 Error (message is not sent to user)
*/
int insert_select_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("insert_select_precheck");
/*
Check that we have modify privileges for the first table and
select privileges for the rest
*/
ulong privilege= (thd->lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
DBUG_RETURN(check_one_table_access(thd, privilege, tables) ? 1 : 0);
}
/*
simple UPDATE query pre-check
SYNOPSIS
update_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 Error (message is sent to user)
-1 Error (message is not sent to user)
*/
int update_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("update_precheck");
if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
{
my_error(ER_WRONG_VALUE_COUNT, MYF(0));
DBUG_RETURN(-1);
}
DBUG_RETURN((check_db_used(thd, tables) ||
check_one_table_access(thd, UPDATE_ACL, tables)) ? 1 : 0);
}
/*
simple DELETE query pre-check
SYNOPSIS
delete_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 error (message is sent to user)
-1 error (message is not sent to user)
*/
int delete_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("delete_precheck");
if (check_one_table_access(thd, DELETE_ACL, tables))
DBUG_RETURN(1);
/* Set privilege for the WHERE clause */
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
DBUG_RETURN(0);
}
/*
simple INSERT query pre-check
SYNOPSIS
insert_precheck()
thd Thread handler
tables Global table list
RETURN VALUE
0 OK
1 error (message is sent to user)
-1 error (message is not sent to user)
*/
int insert_precheck(THD *thd, TABLE_LIST *tables, bool update)
{
LEX *lex= thd->lex;
DBUG_ENTER("insert_precheck");
ulong privilege= (lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL | update);
if (check_one_table_access(thd, privilege, tables))
DBUG_RETURN(1);
if (lex->select_lex.item_list.elements != lex->value_list.elements)
{
my_error(ER_WRONG_VALUE_COUNT, MYF(0));
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*
CREATE TABLE query pre-check
SYNOPSIS
create_table_precheck()
thd Thread handler
tables Global table list
create_table Table which will be created
RETURN VALUE
0 OK
1 Error (message is sent to user)
-1 Error (message is not sent to user)
*/
int create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table)
{
LEX *lex= thd->lex;
DBUG_ENTER("create_table_precheck");
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
CREATE_TMP_ACL : CREATE_ACL);
lex->create_info.alias= create_table->alias;
if (check_access(thd, want_priv, create_table->db,
&create_table->grant.privilege, 0, 0) ||
check_merge_table_access(thd, create_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))
DBUG_RETURN(1);
DBUG_RETURN((grant_option && want_priv != CREATE_TMP_ACL &&
check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0)) ?
1 : 0);
}