diff options
author | unknown <pem@mysql.comhem.se> | 2004-03-19 19:01:54 +0100 |
---|---|---|
committer | unknown <pem@mysql.comhem.se> | 2004-03-19 19:01:54 +0100 |
commit | d2ad3cff192de352961ec01f5370821690d7173f (patch) | |
tree | 8a8b60eab5553d3fb3d8304e77dadd313b4c77e6 /sql/sp.cc | |
parent | edf2003009c7fd44c6a8b4a9306685357dbbb399 (diff) | |
download | mariadb-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.cc | 106 |
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); } |