summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
authorunknown <monty@narttu.mysql.fi>2003-05-19 16:35:49 +0300
committerunknown <monty@narttu.mysql.fi>2003-05-19 16:35:49 +0300
commitdaac922bc306847581b9acee4bcf0a31707d72e7 (patch)
tree6025913cf3d482ba0783bf3420f7341c10cd574a /sql/sql_parse.cc
parent7c189b0dcf26ad8e408b8eaa7d69dbbe913ba421 (diff)
parent68aa31f268660db07b634f021716ecb872e19679 (diff)
downloadmariadb-git-daac922bc306847581b9acee4bcf0a31707d72e7.tar.gz
Merge with 4.0.13
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BUILD/SETUP.sh: Auto merged BitKeeper/deleted/.del-libmysql.def~29fc6d70335f1c4c: Auto merged Makefile.am: Auto merged acinclude.m4: Auto merged BitKeeper/triggers/post-commit: Auto merged Build-tools/Do-compile: Auto merged VC++Files/libmysql/libmysql.dsp: Auto merged VC++Files/mysql.dsw: Auto merged client/mysql.cc: Auto merged client/mysqlbinlog.cc: Auto merged client/mysqldump.c: Auto merged include/config-win.h: Auto merged include/my_base.h: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/violite.h: Auto merged innobase/buf/buf0flu.c: Auto merged innobase/buf/buf0lru.c: Auto merged innobase/include/buf0buf.h: Auto merged innobase/include/buf0lru.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/include/srv0srv.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/log/log0log.c: Auto merged innobase/log/log0recv.c: Auto merged innobase/os/os0file.c: Auto merged innobase/row/row0mysql.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/trx/trx0sys.c: Auto merged innobase/trx/trx0trx.c: Auto merged innobase/ut/ut0ut.c: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_key.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_range.c: Auto merged myisam/mi_search.c: Auto merged myisam/sort.c: Auto merged mysql-test/r/delete.result: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/innodb_handler.result: Auto merged mysql-test/r/join.result: Auto merged mysql-test/r/join_outer.result: Auto merged mysql-test/r/key.result: Auto merged mysql-test/r/multi_update.result: Auto merged mysql-test/r/myisam.result: Auto merged mysql-test/r/query_cache.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/alter_table.test: Auto merged mysql-test/t/ctype_latin1_de.test: Auto merged mysql-test/t/delete.test: Auto merged mysql-test/t/fulltext.test: Auto merged mysql-test/t/innodb_handler.test: Auto merged mysql-test/t/join.test: Auto merged mysql-test/t/join_outer.test: Auto merged mysql-test/t/key.test: Auto merged mysql-test/t/multi_update.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/query_cache.test: Auto merged mysql-test/t/repair.test: Auto merged mysql-test/t/select_safe.test: Auto merged mysql-test/t/type_decimal.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/default.c: Auto merged mysys/my_pthread.c: Auto merged scripts/mysql_fix_privilege_tables.sh: Auto merged scripts/mysqld_safe.sh: Auto merged sql/ha_heap.h: 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/init.cc: Auto merged sql/item.cc: Auto merged sql/item_create.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_sum.cc: Auto merged sql/mini_client.cc: Auto merged sql/net_serv.cc: Auto merged sql/opt_range.cc: Auto merged sql/records.cc: Auto merged sql/slave.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_list.h: Auto merged sql/sql_load.cc: Auto merged sql/share/czech/errmsg.txt: Auto merged sql/share/danish/errmsg.txt: Auto merged sql/share/dutch/errmsg.txt: Auto merged sql/share/english/errmsg.txt: Auto merged sql/share/estonian/errmsg.txt: Auto merged sql/share/french/errmsg.txt: Auto merged sql/share/greek/errmsg.txt: Auto merged sql/share/hungarian/errmsg.txt: Auto merged sql/share/italian/errmsg.txt: Auto merged sql/share/japanese/errmsg.txt: Auto merged sql/share/korean/errmsg.txt: Auto merged sql/share/norwegian-ny/errmsg.txt: Auto merged sql/share/norwegian/errmsg.txt: Auto merged sql/share/portuguese/errmsg.txt: Auto merged sql/share/romanian/errmsg.txt: Auto merged sql/share/russian/errmsg.txt: Auto merged sql/share/slovak/errmsg.txt: Auto merged sql/share/spanish/errmsg.txt: Auto merged sql/share/swedish/errmsg.txt: Auto merged sql/share/ukrainian/errmsg.txt: Auto merged sql/unireg.h: Auto merged sql-bench/crash-me.sh: Auto merged sql-bench/test-transactions.sh: Auto merged strings/ctype-tis620.c: Auto merged tests/grant.res: Auto merged sql/log_event.cc: Merge with 4.0.13 Cleaned up comment syntax
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc133
1 files changed, 107 insertions, 26 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1d2449839d8..45c5ea4d520 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -213,7 +213,15 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
+ char tmp_passwd[SCRAMBL41_LENGTH];
DBUG_ENTER("check_user");
+
+ /*
+ Move password to temporary buffer as it may be stored in communication
+ buffer
+ */
+ strmake(tmp_passwd, passwd, sizeof(tmp_passwd));
+ passwd= tmp_passwd; // Use local copy
/* We shall avoid dupplicate user allocations here */
if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
@@ -222,7 +230,8 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(1);
}
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
- passwd, thd->scramble, &thd->priv_user,
+ passwd, thd->scramble,
+ &thd->priv_user, &thd->priv_host,
(protocol_version == 9 ||
!(thd->client_capabilities &
CLIENT_LONG_PASSWORD)),
@@ -230,9 +239,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
cur_priv_version,hint_user);
DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
+ ("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
- thd->host_or_ip, thd->priv_user,
+ thd->host_or_ip, thd->user, thd->priv_user,
had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
@@ -307,6 +316,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(error);
}
send_ok(thd); // Ready to handle questions
+ thd->password= test(passwd[0]); // Remember for error messages
DBUG_RETURN(0); // ok
}
@@ -582,7 +592,6 @@ check_connections(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host;
thd->ip= 0;
- thd->peer_port= 0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
/* Ensure that wrong hostnames doesn't cause buffer overflows */
@@ -751,7 +760,6 @@ check_connections(THD *thd)
}
else if (res)
return -1; // Error sent from check_user()
- thd->password=using_password;
return 0;
}
@@ -1551,7 +1559,8 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
/* We must allocate some extra memory for query cache */
if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
packet_length,
- thd->db_length+2)))
+ thd->db_length+2+
+ sizeof(ha_rows))))
return 1;
thd->query[packet_length]=0;
thd->query_length= packet_length;
@@ -1648,6 +1657,18 @@ mysql_execute_command(THD *thd)
#endif
)
DBUG_VOID_RETURN;
+
+ /*
+ When option readonly is set deny operations which change tables.
+ Except for the replication thread and the 'super' users.
+ */
+ if (opt_readonly &&
+ !(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
+ (uc_update_queries[lex->sql_command] > 0))
+ {
+ send_error(&thd->net,ER_CANT_UPDATE_WITH_READLOCK);
+ DBUG_VOID_RETURN;
+ }
statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
@@ -1832,7 +1853,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_SLAVE_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
LOCK_ACTIVE_MI;
res = show_master_info(thd,active_mi);
@@ -1841,7 +1863,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_MASTER_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_binlog_info(thd);
break;
@@ -3058,12 +3081,21 @@ error:
/****************************************************************************
Get the user (global) and database privileges for all used tables
- Returns true (error) if we can't get the privileges and we don't use
- table/column grants.
- The idea of EXTRA_ACL is that one will be granted access to the table if
- one has the asked privilege on any column combination of the table; For
- example to be able to check a table one needs to have SELECT privilege on
- any column of the table.
+
+ NOTES
+ The idea of EXTRA_ACL is that one will be granted access to the table if
+ one has the asked privilege on any column combination of the table; For
+ example to be able to check a table one needs to have SELECT privilege on
+ any column of the table.
+
+ RETURN
+ 0 ok
+ 1 If we can't get the privileges and we don't use table/column grants.
+
+ save_priv In this we store global and db level grants for the table
+ Note that we don't store db level grants if the global grants
+ is enough to satisfy the request and the global grants contains
+ a SELECT grant.
****************************************************************************/
bool
@@ -3088,7 +3120,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((thd->master_access & want_access) == want_access)
{
- *save_priv=thd->master_access;
+ /*
+ If we don't have a global SELECT privilege, we have to get the database
+ specific access rights to be able to handle queries of type
+ UPDATE t1 SET a=1 WHERE b > 0
+ */
+ db_access= thd->db_access;
+ if (!(thd->master_access & SELECT_ACL) &&
+ (db && (!thd->db || strcmp(db,thd->db))))
+ db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
+ thd->priv_user, db); /* purecov: inspected */
+ *save_priv=thd->master_access | db_access;
DBUG_RETURN(FALSE);
}
if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
@@ -3097,7 +3139,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_ACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -3122,18 +3164,35 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
-/* check for global access and give descriptive error message if it fails */
+/*
+ check for global access and give descriptive error message if it fails
+
+ SYNOPSIS
+ check_global_access()
+ thd Thread handler
+ want_access Use should have any of these global rights
+
+ WARNING
+ One gets access rigth if one has ANY of the rights in want_access
+ This is useful as one in most cases only need one global right,
+ but in some case we want to check if the user has SUPER or
+ REPL_CLIENT_ACL rights.
+
+ RETURN
+ 0 ok
+ 1 Access denied. In this case an error is sent to the client
+*/
bool check_global_access(THD *thd, ulong want_access)
{
char command[128];
- if ((thd->master_access & want_access) == want_access)
+ if ((thd->master_access & want_access))
return 0;
get_privilege_desc(command, sizeof(command), want_access);
net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
@@ -3237,6 +3296,7 @@ static bool check_merge_table_access(THD *thd, char *db,
#define used_stack(A,B) (long) (B - A)
#endif
+#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
{
long stack_used;
@@ -3250,6 +3310,7 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
}
return 0;
}
+#endif /* EMBEDDED_LIBRARY */
#define MY_YACC_INIT 1000 // Start with big alloc
#define MY_YACC_MAX 32000 // Because of 'short'
@@ -3548,9 +3609,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->comment.str= (char*) comment->str_value.ptr();
new_field->comment.length=comment->str_value.length();
}
- if (length)
- if (!(new_field->length= (uint) atoi(length)))
- length=0; /* purecov: inspected */
+ if (length && !(new_field->length= (uint) atoi(length)))
+ length=0; /* purecov: inspected */
uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
if (new_field->length && new_field->decimals &&
@@ -3583,10 +3643,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_DECIMAL:
if (!length)
- new_field->length = 10; // Default length for DECIMAL
- new_field->length+=sign_len;
- if (new_field->decimals)
- new_field->length++;
+ new_field->length= 10; // Default length for DECIMAL
+ if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument
+ {
+ new_field->length+=sign_len;
+ if (new_field->decimals)
+ new_field->length++;
+ }
break;
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
@@ -4011,6 +4074,24 @@ void add_join_on(TABLE_LIST *b,Item *expr)
}
+/*
+ Mark that we have a NATURAL JOIN between two tables
+
+ SYNOPSIS
+ add_join_natural()
+ a Table to do normal join with
+ b Do normal join with this table
+
+ IMPLEMENTATION
+ This function just marks that table b should be joined with a.
+ The function setup_cond() will create in b->on_expr a list
+ of equal condition between all fields of the same name.
+
+ SELECT * FROM t1 NATURAL LEFT JOIN t2
+ <=>
+ SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
+*/
+
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
{
b->natural_join=a;