summaryrefslogtreecommitdiff
path: root/sql/sp.cc
diff options
context:
space:
mode:
authorunknown <pem@mysql.comhem.se>2004-03-19 19:01:54 +0100
committerunknown <pem@mysql.comhem.se>2004-03-19 19:01:54 +0100
commitd2ad3cff192de352961ec01f5370821690d7173f (patch)
tree8a8b60eab5553d3fb3d8304e77dadd313b4c77e6 /sql/sp.cc
parentedf2003009c7fd44c6a8b4a9306685357dbbb399 (diff)
downloadmariadb-git-d2ad3cff192de352961ec01f5370821690d7173f.tar.gz
WL#1366: Use the schema (db) associated with an SP.
Phase 3: Made qualified names work for functions as well. mysql-test/r/sp-security.result: New testcases for functions with qualified names. mysql-test/t/sp-security.test: New testcases for functions with qualified names. sql/item_func.cc: Added error handling for stored function, if it doesn't exist. sql/item_func.h: Set null_value if execution of a stored function fails. sql/mysql_priv.h: Reverted previous change: No optional args for mysql_change_db(). (SPs use a specially tailored function instead.) sql/sp.cc: Copied mysql_change_db() from sql_db.cc and modified specially for SPs. sql/sp_head.cc: Fixed error handling for errors in functions during query/statement execution. sql/sql_db.cc: Reverted previous change: No optional args for mysql_change_db(). (SPs use a specially tailored function instead.) sql/sql_yacc.yy: Reworked the stored function/UDF invokation parsing and added qualified names for stored functions. UDFs now have precedence over stored functions (whith unqualified name). When using an unqualified name, only IDENT_sys is allowed (i.e. no unreserved keywords), since we get unresolvable reduce/reduce conflicts otherwise.
Diffstat (limited to 'sql/sp.cc')
-rw-r--r--sql/sp.cc106
1 files changed, 96 insertions, 10 deletions
diff --git a/sql/sp.cc b/sql/sp.cc
index 1b58c709e4e..389c627f5f3 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -16,6 +16,7 @@
#include "mysql_priv.h"
+#include "sql_acl.h"
#include "sp.h"
#include "sp_head.h"
#include "sp_cache.h"
@@ -960,19 +961,104 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
}
}
+/*
+ Change database.
+
+ SYNOPSIS
+ sp_change_db()
+ thd Thread handler
+ name Database name
+ empty_is_ok True= it's ok with "" as name
+ no_access_check True= don't do access check
+
+ DESCRIPTION
+ This is the same as mysql_change_db(), but with some extra
+ arguments for Stored Procedure usage; doing implicit "use"
+ when executing an SP in a different database.
+ We also use different error routines, since this might be
+ invoked from a function when executing a query or statement.
+ Note: We would have prefered to reuse mysql_change_db(), but
+ the error handling in particular made that too awkward, so
+ we (reluctantly) have a "copy" here.
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
int
-sp_change_db(THD *thd, char *db, bool no_access_check)
+sp_change_db(THD *thd, char *name, bool no_access_check)
{
- int ret;
- ulong dbaccess= thd->db_access; /* mysql_change_db() changes this */
- my_bool nsok= thd->net.no_send_ok; /* mysql_change_db() does send_ok() */
- thd->net.no_send_ok= TRUE;
+ int length, db_length;
+ char *dbname=my_strdup((char*) name,MYF(MY_WME));
+ char path[FN_REFLEN];
+ ulong db_access;
+ HA_CREATE_INFO create;
DBUG_ENTER("sp_change_db");
- DBUG_PRINT("enter", ("db: %s, no_access_check: %d", db, no_access_check));
+ DBUG_PRINT("enter", ("db: %s, no_access_check: %d", name, no_access_check));
- ret= mysql_change_db(thd, db, 1, no_access_check);
+ db_length= (!dbname ? 0 : strip_sp(dbname));
+ if (dbname && db_length)
+ {
+ if ((db_length > NAME_LEN) || check_db_name(dbname))
+ {
+ my_printf_error(ER_WRONG_DB_NAME, ER(ER_WRONG_DB_NAME), MYF(0), dbname);
+ x_free(dbname);
+ DBUG_RETURN(1);
+ }
+ }
- thd->net.no_send_ok= nsok;
- thd->db_access= dbaccess;
- DBUG_RETURN(ret);
+ if (dbname && db_length)
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (! no_access_check)
+ {
+ if (test_all_bits(thd->master_access,DB_ACLS))
+ db_access=DB_ACLS;
+ else
+ db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) |
+ thd->master_access);
+ if (!(db_access & DB_ACLS) &&
+ (!grant_option || check_grant_db(thd,dbname)))
+ {
+ my_printf_error(ER_DBACCESS_DENIED_ERROR, ER(ER_DBACCESS_DENIED_ERROR),
+ MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
+ my_free(dbname,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+#endif
+ (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
+ length=unpack_dirname(path,path); // Convert if not unix
+ if (length && path[length-1] == FN_LIBCHAR)
+ path[length-1]=0; // remove ending '\'
+ if (access(path,F_OK))
+ {
+ my_printf_error(ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR), MYF(0), dbname);
+ my_free(dbname,MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
+ x_free(thd->db);
+ thd->db=dbname; // THD::~THD will free this
+ thd->db_length=db_length;
+
+ if (dbname && db_length)
+ {
+ strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
+ thd->db_charset= create.default_table_charset ?
+ create.default_table_charset :
+ thd->variables.collation_server;
+ thd->variables.collation_database= thd->db_charset;
+ }
+ DBUG_RETURN(0);
}