mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 07:05:33 +02:00
Fix for BUG#16211: Stored function return type for strings is ignored.
Fix for BUG#16676: Database CHARSET not used for stored procedures
The problem in BUG#16211 is that CHARSET-clause of the return type for
stored functions is just ignored.
The problem in BUG#16676 is that if character set is not explicitly
specified for sp-variable, the server character set is used instead
of the database one.
The fix has two parts:
- always store CHARSET-clause of the return type along with the
type definition in mysql.proc.returns column. "Always" means that
CHARSET-clause is appended even if it has not been explicitly
specified in CREATE FUNCTION statement (this affects BUG#16211 only).
Storing CHARSET-clause if it is not specified is essential to avoid
changing character set if the database character set is altered in
the future.
NOTE: this change is not backward compatible with the previous releases.
- use database default character set if CHARSET-clause is not explicitly
specified (this affects both BUG#16211 and BUG#16676).
NOTE: this also breaks backward compatibility.
mysql-test/r/mysqldump.result:
Updated result file.
mysql-test/r/sp.result:
Updated result file.
mysql-test/t/sp.test:
Provided test cases for BUG#16211, BUG#16676.
sql/mysql_priv.h:
Added two convenient functions for work with databases.
sql/sp.cc:
1. Add CHARSET-clause to CREATE-statement if it has been explicitly specified.
2. Polishing -- provided some comments.
sql/sp_head.cc:
Use database charset as default charset of sp-variable.
sql/sp_head.h:
Move init_sp_name() out of init_strings().
sql/sql_db.cc:
Two new functions created:
- load_db_opt_by_name();
- check_db_dir_existence();
sql/sql_show.cc:
Eliminate duplicated code by using
check_db_dir_existence() and load_db_opt_by_name()
sql/sql_table.cc:
Eliminate duplicated code by using
check_db_dir_existence() and load_db_opt_by_name()
sql/sql_yacc.yy:
Call sp_head::init_sp_name() to initialize stored routine name.
This commit is contained in:
parent
49d721d7cf
commit
3c10858474
11 changed files with 472 additions and 69 deletions
|
|
@ -295,7 +295,6 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
|
|||
create Where to store the read options
|
||||
|
||||
DESCRIPTION
|
||||
For now, only default-character-set is read.
|
||||
|
||||
RETURN VALUES
|
||||
0 File found
|
||||
|
|
@ -383,6 +382,50 @@ err1:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Retrieve database options by name. Load database options file or fetch from
|
||||
cache.
|
||||
|
||||
SYNOPSIS
|
||||
load_db_opt_by_name()
|
||||
db_name Database name
|
||||
db_create_info Where to store the database options
|
||||
|
||||
DESCRIPTION
|
||||
load_db_opt_by_name() is a shortcut for load_db_opt().
|
||||
|
||||
NOTE
|
||||
Although load_db_opt_by_name() (and load_db_opt()) returns status of
|
||||
the operation, it is useless usually and should be ignored. The problem
|
||||
is that there are 1) system databases ("mysql") and 2) virtual
|
||||
databases ("information_schema"), which do not contain options file.
|
||||
So, load_db_opt[_by_name]() returns FALSE for these databases, but this
|
||||
is not an error.
|
||||
|
||||
load_db_opt[_by_name]() clears db_create_info structure in any case, so
|
||||
even on failure it contains valid data. So, common use case is just
|
||||
call load_db_opt[_by_name]() without checking return value and use
|
||||
db_create_info right after that.
|
||||
|
||||
RETURN VALUES (read NOTE!)
|
||||
FALSE Success
|
||||
TRUE Failed to retrieve options
|
||||
*/
|
||||
|
||||
bool load_db_opt_by_name(THD *thd, const char *db_name,
|
||||
HA_CREATE_INFO *db_create_info)
|
||||
{
|
||||
char db_opt_path[FN_REFLEN];
|
||||
|
||||
strxnmov(db_opt_path, sizeof (db_opt_path) - 1, mysql_data_home, "/",
|
||||
db_name, "/", MY_DB_OPT_FILE, NullS);
|
||||
|
||||
unpack_filename(db_opt_path, db_opt_path);
|
||||
|
||||
return load_db_opt(thd, db_opt_path, db_create_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a database
|
||||
|
||||
|
|
@ -1126,8 +1169,6 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
|
|||
{
|
||||
int path_length, db_length;
|
||||
char *db_name;
|
||||
char path[FN_REFLEN];
|
||||
HA_CREATE_INFO create;
|
||||
bool system_db= 0;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
ulong db_access;
|
||||
|
|
@ -1196,16 +1237,14 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
(void) sprintf(path,"%s/%s", mysql_data_home, db_name);
|
||||
path_length= unpack_dirname(path, path); // Convert if not UNIX
|
||||
if (path_length && path[path_length-1] == FN_LIBCHAR)
|
||||
path[path_length-1]= '\0'; // remove ending '\'
|
||||
if (my_access(path,F_OK))
|
||||
|
||||
if (check_db_dir_existence(db_name))
|
||||
{
|
||||
my_error(ER_BAD_DB_ERROR, MYF(0), db_name);
|
||||
my_free(db_name, MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
end:
|
||||
x_free(thd->db);
|
||||
DBUG_ASSERT(db_name == NULL || db_name[0] != '\0');
|
||||
|
|
@ -1221,8 +1260,10 @@ end:
|
|||
}
|
||||
else
|
||||
{
|
||||
strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE);
|
||||
load_db_opt(thd, path, &create);
|
||||
HA_CREATE_INFO create;
|
||||
|
||||
load_db_opt_by_name(thd, db_name, &create);
|
||||
|
||||
thd->db_charset= create.default_table_charset ?
|
||||
create.default_table_charset :
|
||||
thd->variables.collation_server;
|
||||
|
|
@ -1230,3 +1271,36 @@ end:
|
|||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check if there is directory for the database name.
|
||||
|
||||
SYNOPSIS
|
||||
check_db_dir_existence()
|
||||
db_name database name
|
||||
|
||||
RETURN VALUES
|
||||
FALSE There is directory for the specified database name.
|
||||
TRUE The directory does not exist.
|
||||
*/
|
||||
|
||||
bool check_db_dir_existence(const char *db_name)
|
||||
{
|
||||
char db_dir_path[FN_REFLEN];
|
||||
uint db_dir_path_len;
|
||||
|
||||
strxnmov(db_dir_path, sizeof (db_dir_path) - 1, mysql_data_home, "/",
|
||||
db_name, NullS);
|
||||
|
||||
db_dir_path_len= unpack_dirname(db_dir_path, db_dir_path);
|
||||
|
||||
/* Remove trailing '/' or '\' if exists. */
|
||||
|
||||
if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
|
||||
db_dir_path[db_dir_path_len - 1]= 0;
|
||||
|
||||
/* Check access. */
|
||||
|
||||
return my_access(db_dir_path, F_OK);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue