Commit d7057356 authored by Alexander Barkov's avatar Alexander Barkov

Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3

parents 5cf0662d 88a9d4ab
......@@ -524,3 +524,105 @@ SPECIFIC_CATALOG SPECIFIC_SCHEMA SPECIFIC_NAME ORDINAL_POSITION PARAMETER_MODE P
def i_s_parameters_test test_func5 0 NULL NULL varchar 30 90 NULL NULL NULL utf8 utf8_general_ci varchar(30) FUNCTION
def i_s_parameters_test test_func5 1 IN s char 20 60 NULL NULL NULL utf8 utf8_general_ci char(20) FUNCTION
DROP DATABASE i_s_parameters_test;
USE test;
#
# Start of 10.3 tests
#
#
# MDEV-15416 Crash when reading I_S.PARAMETERS
#
CREATE PROCEDURE p1(a0 TYPE OF t1.a,
a1 TYPE OF test.t1.a,
b0 ROW TYPE OF t1,
b1 ROW TYPE OF test.t1,
c ROW(a INT,b DOUBLE))
BEGIN
END;
$$
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME p1
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME a0
DATA_TYPE TYPE OF
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER TYPE OF `t1`.`a`
ROUTINE_TYPE PROCEDURE
-------- --------
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME p1
ORDINAL_POSITION 2
PARAMETER_MODE IN
PARAMETER_NAME a1
DATA_TYPE TYPE OF
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER TYPE OF `test`.`t1`.`a`
ROUTINE_TYPE PROCEDURE
-------- --------
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME p1
ORDINAL_POSITION 3
PARAMETER_MODE IN
PARAMETER_NAME b0
DATA_TYPE ROW TYPE OF
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER ROW TYPE OF `t1`
ROUTINE_TYPE PROCEDURE
-------- --------
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME p1
ORDINAL_POSITION 4
PARAMETER_MODE IN
PARAMETER_NAME b1
DATA_TYPE ROW TYPE OF
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER ROW TYPE OF `test`.`t1`
ROUTINE_TYPE PROCEDURE
-------- --------
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME p1
ORDINAL_POSITION 5
PARAMETER_MODE IN
PARAMETER_NAME c
DATA_TYPE ROW
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION NULL
NUMERIC_SCALE NULL
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER ROW
ROUTINE_TYPE PROCEDURE
-------- --------
DROP PROCEDURE p1;
......@@ -171,3 +171,60 @@ create database mysqltest1;
create procedure mysqltest1.foo() select "foo";
update mysql.proc set name='' where db='mysqltest1';
drop database mysqltest1;
#
# MDEV-15444 Querying I_S.PARAMETERS can crash with a corrupted mysql.proc
#
CREATE OR REPLACE FUNCTION f1 (a INT) RETURNS INT RETURN 10;
CREATE OR REPLACE FUNCTION f2 (a INT) RETURNS INT RETURN 10;
SELECT
@type0:=COLUMN_TYPE AS t0,
@type1:=REPLACE(COLUMN_TYPE,')',',''XXX'')') AS t1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema='mysql' AND table_name='proc' AND column_name='type';
t0 enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY')
t1 enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY','XXX')
EXECUTE IMMEDIATE CONCAT('ALTER TABLE mysql.proc MODIFY type ', @type1);
SHOW COLUMNS IN mysql.proc LIKE 'type';
Field Type Null Key Default Extra
type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY','XXX') NO PRI NULL
UPDATE mysql.proc SET type='XXX' WHERE name='f1' AND db='test';
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_SCHEMA='test';
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME f2
ORDINAL_POSITION 0
PARAMETER_MODE NULL
PARAMETER_NAME NULL
DATA_TYPE int
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION 10
NUMERIC_SCALE 0
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER int(11)
ROUTINE_TYPE FUNCTION
SPECIFIC_CATALOG def
SPECIFIC_SCHEMA test
SPECIFIC_NAME f2
ORDINAL_POSITION 1
PARAMETER_MODE IN
PARAMETER_NAME a
DATA_TYPE int
CHARACTER_MAXIMUM_LENGTH NULL
CHARACTER_OCTET_LENGTH NULL
NUMERIC_PRECISION 10
NUMERIC_SCALE 0
DATETIME_PRECISION NULL
CHARACTER_SET_NAME NULL
COLLATION_NAME NULL
DTD_IDENTIFIER int(11)
ROUTINE_TYPE FUNCTION
UPDATE mysql.proc SET type='FUNCTION' WHERE name='f1' AND db='test';
EXECUTE IMMEDIATE CONCAT('ALTER TABLE mysql.proc MODIFY type ', @type0);
SHOW COLUMNS IN mysql.proc LIKE 'type';
Field Type Null Key Default Extra
type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NO PRI NULL
DROP FUNCTION f1;
DROP FUNCTION f2;
--echo #
--echo # MDEV-15416 Crash when reading I_S.PARAMETERS
--echo #
--echo # Create in sql_mode=ORACLE, display in sql_mode=ORACLE and sql_mode=DEFAULT
SET sql_mode=ORACLE;
DELIMITER $$;
CREATE PROCEDURE p1(a0 t1.a%TYPE,
a1 test.t1.a%TYPE,
b0 t1%ROWTYPE,
b1 test.t1%ROWTYPE,
d ROW(a INT,b DOUBLE))
AS
BEGIN
NULL;
END;
$$
DELIMITER ;$$
--vertical_results
SET sql_mode=ORACLE;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='p1';
SET sql_mode=DEFAULT;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='p1';
--horizontal_results
DROP PROCEDURE p1;
SET sql_mode=ORACLE;
DELIMITER $$;
CREATE FUNCTION f1(a0 t1.a%TYPE,
a1 test.t1.a%TYPE,
b0 t1%ROWTYPE,
b1 test.t1%ROWTYPE,
d ROW(a INT,b DOUBLE))
RETURN INT
AS
BEGIN
RETURN 0;
END;
$$
DELIMITER ;$$
--vertical_results
SET sql_mode=ORACLE;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='f1';
SET sql_mode=DEFAULT;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='f1';
--horizontal_results
DROP FUNCTION f1;
--echo # Create in sql_mode=DEFAULT, display in sql_mode=DEFAULT and sql_mode=ORACLE
SET sql_mode=DEFAULT;
DELIMITER $$;
CREATE PROCEDURE p1(a0 TYPE OF t1.a,
a1 TYPE OF test.t1.a,
b0 ROW TYPE OF t1,
b1 ROW TYPE OF test.t1,
d ROW(a INT,b DOUBLE))
BEGIN
END;
$$
DELIMITER ;$$
--vertical_results
SET sql_mode=DEFAULT;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='p1';
SET sql_mode=ORACLE;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='p1';
--horizontal_results
DROP PROCEDURE p1;
SET sql_mode=DEFAULT;
DELIMITER $$;
CREATE FUNCTION f1(a0 TYPE OF t1.a,
a1 TYPE OF test.t1.a,
b0 ROW TYPE OF t1,
b1 ROW TYPE OF test.t1,
d ROW(a INT,b DOUBLE))
RETURNS INT
BEGIN
RETURN 0;
END;
$$
DELIMITER ;$$
--vertical_results
SET sql_mode=DEFAULT;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='f1';
SET sql_mode=ORACLE;
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME='f1';
--horizontal_results
DROP FUNCTION f1;
......@@ -249,3 +249,28 @@ WHERE SPECIFIC_SCHEMA = 'i_s_parameters_test' AND SPECIFIC_NAME = 'test_func5';
# Cleanup
DROP DATABASE i_s_parameters_test;
USE test;
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-15416 Crash when reading I_S.PARAMETERS
--echo #
DELIMITER $$;
CREATE PROCEDURE p1(a0 TYPE OF t1.a,
a1 TYPE OF test.t1.a,
b0 ROW TYPE OF t1,
b1 ROW TYPE OF test.t1,
c ROW(a INT,b DOUBLE))
BEGIN
END;
$$
DELIMITER ;$$
--vertical_results
SELECT *, '--------' FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME = 'p1';
--horizontal_results
DROP PROCEDURE p1;
......@@ -285,3 +285,38 @@ create database mysqltest1;
create procedure mysqltest1.foo() select "foo";
update mysql.proc set name='' where db='mysqltest1';
drop database mysqltest1;
--echo #
--echo # MDEV-15444 Querying I_S.PARAMETERS can crash with a corrupted mysql.proc
--echo #
CREATE OR REPLACE FUNCTION f1 (a INT) RETURNS INT RETURN 10;
CREATE OR REPLACE FUNCTION f2 (a INT) RETURNS INT RETURN 10;
# Get the current data type for mysql.proc.type
--vertical_results
SELECT
@type0:=COLUMN_TYPE AS t0,
@type1:=REPLACE(COLUMN_TYPE,')',',''XXX'')') AS t1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema='mysql' AND table_name='proc' AND column_name='type';
--horizontal_results
# Change mysql.proc.type and update the record for 'f1'
EXECUTE IMMEDIATE CONCAT('ALTER TABLE mysql.proc MODIFY type ', @type1);
SHOW COLUMNS IN mysql.proc LIKE 'type';
UPDATE mysql.proc SET type='XXX' WHERE name='f1' AND db='test';
# Check the I_S query
--vertical_results
SELECT * FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_SCHEMA='test';
--horizontal_results
# Restore the record for 'f1' and restore mysql.proc.type
UPDATE mysql.proc SET type='FUNCTION' WHERE name='f1' AND db='test';
EXECUTE IMMEDIATE CONCAT('ALTER TABLE mysql.proc MODIFY type ', @type0);
SHOW COLUMNS IN mysql.proc LIKE 'type';
DROP FUNCTION f1;
DROP FUNCTION f2;
......@@ -4429,6 +4429,12 @@ class Spvar_definition: public Column_definition
bool is_column_type_ref() const { return m_column_type_ref != 0; }
bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; }
bool is_cursor_rowtype_ref() const { return m_cursor_rowtype_ref; }
bool is_explicit_data_type() const
{
return !is_column_type_ref() &&
!is_table_rowtype_ref() &&
!is_cursor_rowtype_ref();
}
Qualified_column_ident *column_type_ref() const
{
return m_column_type_ref;
......
......@@ -2998,7 +2998,7 @@ Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table,
defstr.set_charset(creation_ctx->get_client_cs());
if (show_create_sp(thd, &defstr,
sp_name_obj.m_db, sp_name_obj.m_name,
params, returns, empty_body_lex_cstring(),
params, returns, empty_body_lex_cstring(sql_mode),
Sp_chistics(), definer, DDL_options(), sql_mode))
return 0;
......@@ -3012,3 +3012,18 @@ Sp_handler::sp_load_for_information_schema(THD *thd, TABLE *proc_table,
return sp;
}
LEX_CSTRING Sp_handler_procedure::empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body_std= {C_STRING_WITH_LEN("BEGIN END")};
static LEX_CSTRING m_empty_body_ora= {C_STRING_WITH_LEN("AS BEGIN NULL; END")};
return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
}
LEX_CSTRING Sp_handler_function::empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body_std= {C_STRING_WITH_LEN("RETURN NULL")};
static LEX_CSTRING m_empty_body_ora= {C_STRING_WITH_LEN("AS BEGIN RETURN NULL; END")};
return mode & MODE_ORACLE ? m_empty_body_ora : m_empty_body_std;
}
......@@ -122,6 +122,16 @@ class Sp_handler
static const Sp_handler *handler(enum enum_sql_command cmd);
static const Sp_handler *handler(stored_procedure_type type);
static const Sp_handler *handler(MDL_key::enum_mdl_namespace ns);
/*
Return a handler only those SP objects that store
definitions in the mysql.proc system table
*/
static const Sp_handler *handler_mysql_proc(stored_procedure_type type)
{
const Sp_handler *sph= handler(type);
return sph ? sph->sp_handler_mysql_proc() : NULL;
}
static bool eq_routine_name(const LEX_CSTRING &name1,
const LEX_CSTRING &name2)
{
......@@ -146,13 +156,14 @@ class Sp_handler
}
virtual stored_procedure_type type() const= 0;
virtual LEX_CSTRING type_lex_cstring() const= 0;
virtual LEX_CSTRING empty_body_lex_cstring() const
virtual LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body= {STRING_WITH_LEN("???")};
DBUG_ASSERT(0);
return m_empty_body;
}
virtual MDL_key::enum_mdl_namespace get_mdl_type() const= 0;
virtual const Sp_handler *sp_handler_mysql_proc() const { return this; }
virtual sp_cache **get_cache(THD *) const { return NULL; }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
virtual HASH *get_priv_hash() const { return NULL; }
......@@ -244,11 +255,7 @@ class Sp_handler_procedure: public Sp_handler
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("PROCEDURE")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring() const
{
static LEX_CSTRING m_empty_body= { STRING_WITH_LEN("BEGIN END")};
return m_empty_body;
}
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const;
const char *show_create_routine_col1_caption() const
{
return "Procedure";
......@@ -298,11 +305,7 @@ class Sp_handler_function: public Sp_handler
static LEX_CSTRING m_type_str= { STRING_WITH_LEN("FUNCTION")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring() const
{
static LEX_CSTRING m_empty_body= { STRING_WITH_LEN("RETURN NULL")};
return m_empty_body;
}
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const;
const char *show_create_routine_col1_caption() const
{
return "Function";
......@@ -371,7 +374,7 @@ class Sp_handler_package_spec: public Sp_handler_package
static LEX_CSTRING m_type_str= {C_STRING_WITH_LEN("PACKAGE")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring() const
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body= {C_STRING_WITH_LEN("BEGIN END")};
return m_empty_body;
......@@ -404,7 +407,7 @@ class Sp_handler_package_body: public Sp_handler_package
static LEX_CSTRING m_type_str= {C_STRING_WITH_LEN("PACKAGE BODY")};
return m_type_str;
}
LEX_CSTRING empty_body_lex_cstring() const
LEX_CSTRING empty_body_lex_cstring(sql_mode_t mode) const
{
static LEX_CSTRING m_empty_body= {C_STRING_WITH_LEN("BEGIN END")};
return m_empty_body;
......@@ -442,6 +445,7 @@ class Sp_handler_trigger: public Sp_handler
DBUG_ASSERT(0);
return MDL_key::TRIGGER;
}
const Sp_handler *sp_handler_mysql_proc() const { return NULL; }
};
......
......@@ -58,6 +58,7 @@
#include "sp_head.h"
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_show.h" // append_identifier
#include "transaction.h"
#include "sql_select.h" /* declares create_tmp_table() */
#include "debug_sync.h"
......@@ -7778,6 +7779,22 @@ void Database_qualified_name::copy(MEM_ROOT *mem_root,
}
bool Table_ident::append_to(THD *thd, String *str) const
{
return (db.length &&
(append_identifier(thd, str, db.str, db.length) ||
str->append('.'))) ||
append_identifier(thd, str, table.str, table.length);
}
bool Qualified_column_ident::append_to(THD *thd, String *str) const
{
return Table_ident::append_to(thd, str) || str->append('.') ||
append_identifier(thd, str, m_column.str, m_column.length);
}
#endif /* !defined(MYSQL_CLIENT) */
......
......@@ -5753,6 +5753,7 @@ class Table_ident :public Sql_alloc
db= *db_name;
}
bool resolve_table_rowtype_ref(THD *thd, Row_definition_list &defs);
bool append_to(THD *thd, String *to) const;
};
......@@ -5777,6 +5778,7 @@ class Qualified_column_ident: public Table_ident
m_column(*column)
{ }
bool resolve_type_ref(THD *thd, Column_definition *def);
bool append_to(THD *thd, String *to) const;
};
......
......@@ -5823,6 +5823,118 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs,
}
/*
Print DATA_TYPE independently from sql_mode.
It's only a brief human-readable description, without attributes,
so it should not be used by client programs to generate SQL scripts.
*/
static bool print_anchor_data_type(const Spvar_definition *def,
String *data_type)
{
if (def->column_type_ref())
return data_type->append(STRING_WITH_LEN("TYPE OF"));
if (def->is_table_rowtype_ref())
return data_type->append(STRING_WITH_LEN("ROW TYPE OF"));
/*
"ROW TYPE OF cursor" is not possible yet.
May become possible when we add package-wide cursors.
*/
DBUG_ASSERT(0);
return false;
}
/*
DTD_IDENTIFIER is the full data type description with attributes.
It can be used by client programs to generate SQL scripts.
Let's print it according to the current sql_mode.
It will make output in line with the value in mysql.proc.param_list,
so both I_S.XXX.DTD_IDENTIFIER and mysql.proc.param_list use the same notation:
default or Oracle, according to the sql_mode at the SP creation time.
The caller must make sure to set thd->variables.sql_mode to the routine sql_mode.
*/
static bool print_anchor_dtd_identifier(THD *thd, const Spvar_definition *def,
String *dtd_identifier)
{
if (def->column_type_ref())
return (thd->variables.sql_mode & MODE_ORACLE) ?
def->column_type_ref()->append_to(thd, dtd_identifier) ||
dtd_identifier->append(STRING_WITH_LEN("%TYPE")) :
dtd_identifier->append(STRING_WITH_LEN("TYPE OF ")) ||
def->column_type_ref()->append_to(thd, dtd_identifier);
if (def->is_table_rowtype_ref())
return (thd->variables.sql_mode & MODE_ORACLE) ?
def->table_rowtype_ref()->append_to(thd, dtd_identifier) ||
dtd_identifier->append(STRING_WITH_LEN("%ROWTYPE")) :
dtd_identifier->append(STRING_WITH_LEN("ROW TYPE OF ")) ||
def->table_rowtype_ref()->append_to(thd, dtd_identifier);
DBUG_ASSERT(0); // See comments in print_anchor_data_type()
return false;
}
/*
Set columns DATA_TYPE and DTD_IDENTIFIER from an SP variable definition
*/
static void store_variable_type(THD *thd, const sp_variable *spvar,
TABLE *tmptbl,
TABLE_SHARE *tmpshare,
CHARSET_INFO *cs,
TABLE *table, uint offset)
{
if (spvar->field_def.is_explicit_data_type())
{
if (spvar->field_def.is_row())
{
// Explicit ROW
table->field[offset]->store(STRING_WITH_LEN("ROW"), cs);
table->field[offset]->set_notnull();
// Perhaps eventually we need to print all ROW elements in DTD_IDENTIFIER
table->field[offset + 8]->store(STRING_WITH_LEN("ROW"), cs);
table->field[offset + 8]->set_notnull();
}
else
{
// Explicit scalar data type
Field *field= spvar->field_def.make_field(tmpshare, thd->mem_root,
&spvar->name);
field->table= tmptbl;
tmptbl->in_use= thd;
store_column_type(table, field, cs, offset);
}
}
else
{
StringBuffer<128> data_type(cs), dtd_identifier(cs);
if (print_anchor_data_type(&spvar->field_def, &data_type))
{
table->field[offset]->store(STRING_WITH_LEN("ERROR"), cs); // EOM?
table->field[offset]->set_notnull();
}
else
{
DBUG_ASSERT(data_type.length());
table->field[offset]->store(data_type.ptr(), data_type.length(), cs);
table->field[offset]->set_notnull();
}
if (print_anchor_dtd_identifier(thd, &spvar->field_def, &dtd_identifier))
{
table->field[offset + 8]->store(STRING_WITH_LEN("ERROR"), cs); // EOM?
table->field[offset + 8]->set_notnull();
}
else
{
DBUG_ASSERT(dtd_identifier.length());
table->field[offset + 8]->store(dtd_identifier.ptr(),
dtd_identifier.length(), cs);
table->field[offset + 8]->set_notnull();
}
}
}
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
const LEX_CSTRING *db_name,
......@@ -6196,6 +6308,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
const Sp_handler *sph;
bool free_sp_head;
bool error= 0;
sql_mode_t sql_mode;
DBUG_ENTER("store_schema_params");
bzero((char*) &tbl, sizeof(TABLE));
......@@ -6205,9 +6318,12 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db);
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
sph= Sp_handler::handler((stored_procedure_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int());
sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
if (!sph)
sph= &sp_handler_procedure;
DBUG_RETURN(0);
if (!full_access)
full_access= !strcmp(sp_user, definer.str);
......@@ -6221,15 +6337,15 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root,
&returns);
sp= sph->sp_load_for_information_schema(thd, proc_table, db, name,
params, returns,
(ulong) proc_table->
field[MYSQL_PROC_FIELD_SQL_MODE]->
val_int(),
params, returns, sql_mode,
&free_sp_head);
if (sp)
{
Field *field;
LEX_CSTRING tmp_string;
Sql_mode_save sql_mode_backup(thd);
thd->variables.sql_mode= sql_mode;
if (sph->type() == TYPE_ENUM_FUNCTION)
{
restore_record(table, s->default_values);
......@@ -6288,11 +6404,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table,
&tmp_string);
table->field[15]->store(tmp_string, cs);
field= spvar->field_def.make_field(&share, thd->mem_root,
&spvar->name);
field->table= &tbl;
tbl.in_use= thd;
store_column_type(table, field, cs, 6);
store_variable_type(thd, spvar, &tbl, &share, cs, table, 6);
if (schema_table_store_record(thd, table))
{
error= 1;
......@@ -6319,10 +6431,11 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db);
proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name);
proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer);
sph= Sp_handler::handler((stored_procedure_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int());
sph= Sp_handler::handler_mysql_proc((stored_procedure_type)
proc_table->field[MYSQL_PROC_MYSQL_TYPE]->
val_int());
if (!sph)
sph= &sp_handler_procedure;
return 0;
if (!full_access)
full_access= !strcmp(sp_user, definer.str);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment