Commit ed305c0f authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12461 TYPE OF and ROW TYPE OF anchored data types

parent 113a980f
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
#
#
# Initiation:
# - creating database db1
# - creating user user1 with access rights to db1
#
CREATE DATABASE db1;
CREATE TABLE db1.t1 (a INT, b VARCHAR(10));
CREATE USER user1;
GRANT ALL PRIVILEGES ON test.* TO user1;
connect conn1,localhost,user1,,test;
SELECT database();
database()
test
SELECT user();
user()
user1@localhost
#
# Making sure that user1 does not have privileges to db1.t1
#
SHOW CREATE TABLE db1.t1;
ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
SHOW FIELDS IN db1.t1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
#
# Trigger: using TYPE OF with a table we don't have access to
#
CREATE TABLE test.t1 (a INT, b INT);
INSERT INTO test.t1 (a,b) VALUES (10,20);
SELECT * FROM t1;
a b
10 20
CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
BEGIN
DECLARE b TYPE OF db1.t1.b DEFAULT 20;
SET NEW.b = 10;
END
$$
INSERT INTO t1 (a) VALUES (10);
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
SELECT * FROM t1;
a b
10 20
DROP TRIGGER tr1;
DROP TABLE t1;
#
# Stored procedure: Using TYPE OF for with a table that we don't have access to
# DEFINER user1, SQL SECURITY DEFAULT
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 10;
SELECT a;
END;
$$
CALL p1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
DROP PROCEDURE p1;
#
# Stored procedure: Using TYPE OF for with a table that we don't have access to
# DEFINER root, SQL SECURITY INVOKER
#
connection default;
CREATE PROCEDURE p1()
SQL SECURITY INVOKER
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 10;
SELECT a;
END;
$$
connection conn1;
CALL p1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
DROP PROCEDURE p1;
connection default;
CREATE PROCEDURE p1()
SQL SECURITY INVOKER
BEGIN
DECLARE a ROW TYPE OF db1.t1;
SELECT a.a;
END;
$$
connection conn1;
CALL p1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
DROP PROCEDURE p1;
#
# Stored procedure: Using TYPE OF for with a table that we don't have access to
# DEFINER root, SQL SECURITY DEFINER
#
connection default;
CREATE PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 10;
SELECT a;
END;
$$
connection conn1;
CALL p1;
a
10
DROP PROCEDURE p1;
connection default;
CREATE PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
DECLARE a ROW TYPE OF db1.t1;
SET a.a= 10;
SELECT a.a;
END;
$$
connection conn1;
CALL p1;
a.a
10
DROP PROCEDURE p1;
#
# Stored function: Using TYPE OF for with a table that we don't have access to
# DEFINER user1, SQL SECURITY DEFAULT
#
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1() RETURNS INT
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 0;
RETURN OCTET_LENGTH(a);
END;
$$
SELECT f1();
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
DROP FUNCTION f1;
DROP TABLE t1;
#
# Stored function: Using TYPE OF for with a table that we don't have access to
# DEFINER root, SQL SECURITY INVOKER
#
connection default;
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1() RETURNS INT
SQL SECURITY INVOKER
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 0;
RETURN OCTET_LENGTH(a);
END;
$$
connection conn1;
SELECT f1();
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for table 't1'
DROP FUNCTION f1;
DROP TABLE t1;
#
# Stored function: Using TYPE OF for with a table that we don't have access to
# DEFINER root, SQL SECURITY DEFINER
#
connection default;
CREATE TABLE t1 (a INT);
CREATE FUNCTION f1() RETURNS INT
SQL SECURITY DEFINER
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 0;
RETURN OCTET_LENGTH(a);
END;
$$
connection conn1;
SELECT f1();
f1()
1
DROP FUNCTION f1;
DROP TABLE t1;
connection default;
GRANT SELECT (a) ON db1.t1 TO user1;
connection conn1;
#
# Making sure that user1 has access to db1.t1.a, but not to db1.t1.b
#
SHOW CREATE TABLE db1.t1;
ERROR 42000: SHOW command denied to user 'user1'@'localhost' for table 't1'
SHOW FIELDS IN db1.t1;
Field Type Null Key Default Extra
a int(11) YES NULL
#
# Trigger: Per-column privileges
#
CREATE TABLE test.t1 (a INT, b INT);
INSERT INTO test.t1 (a,b) VALUES (10,20);
SELECT * FROM t1;
a b
10 20
CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 20;
BEGIN
SET NEW.b := 10;
END;
END
$$
INSERT INTO t1 (a) VALUES (10);
SELECT * FROM t1;
a b
10 20
10 10
DROP TRIGGER tr1;
CREATE TRIGGER test.tr1 BEFORE INSERT ON test.t1 FOR EACH ROW
BEGIN
DECLARE b TYPE OF db1.t1.b DEFAULT 20;
BEGIN
SET NEW.b = 10;
END;
END
$$
INSERT INTO t1 (a) VALUES (10);
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
SELECT * FROM t1;
a b
10 20
10 10
DROP TRIGGER tr1;
DROP TABLE t1;
#
# Stored procedure: Per-column privileges
# DEFINER user1, SQL SECURITY DEFAULT
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a TYPE OF db1.t1.a DEFAULT 10;
SELECT a;
END;
$$
CALL p1;
a
10
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
BEGIN
DECLARE b TYPE OF db1.t1.b DEFAULT 10;
SELECT b;
END;
$$
CALL p1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
BEGIN
DECLARE b ROW TYPE OF db1.t1;
SET b.b=10;
SELECT b.b;
END;
$$
CALL p1;
ERROR 42000: SELECT command denied to user 'user1'@'localhost' for column 'b' in table 't1'
DROP PROCEDURE p1;
#
# Clean up
#
disconnect conn1;
connection default;
DROP USER user1;
DROP DATABASE db1;
#
# End of MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
#
......@@ -2368,3 +2368,23 @@ tr1 1 2016-01-01 10:10:10.33
tr2 2 2016-01-01 10:10:10.99
drop table t1;
set time_zone= @@global.time_zone;
#
# Start of 10.3 tests
#
#
# MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
#
CREATE TABLE t1 (a INT, b INT, total INT);
CREATE TRIGGER tr1 BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
DECLARE va TYPE OF t1.a DEFAULT NEW.a;
DECLARE vb TYPE OF t1.b DEFAULT NEW.b;
SET NEW.total:= va + vb;
END;
$$
INSERT INTO t1 (a,b) VALUES (10, 20);
SELECT * FROM t1;
a b total
10 20 30
DROP TABLE t1;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2676,3 +2676,26 @@ select trigger_name, action_order, created from information_schema.triggers
where event_object_table = 't1' and trigger_schema='test';
drop table t1;
set time_zone= @@global.time_zone;
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-12461 TYPE OF and ROW TYPE OF anchored data types
--echo #
CREATE TABLE t1 (a INT, b INT, total INT);
DELIMITER $$;
CREATE TRIGGER tr1 BEFORE INSERT ON t1
FOR EACH ROW
BEGIN
DECLARE va TYPE OF t1.a DEFAULT NEW.a;
DECLARE vb TYPE OF t1.b DEFAULT NEW.b;
SET NEW.total:= va + vb;
END;
$$
DELIMITER ;$$
INSERT INTO t1 (a,b) VALUES (10, 20);
SELECT * FROM t1;
DROP TABLE t1;
......@@ -423,6 +423,7 @@ static SYMBOL symbols[] = {
{ "NUMBER", SYM(NUMBER_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
{ "NVARCHAR", SYM(NVARCHAR_SYM)},
{ "OF", SYM(OF_SYM)},
{ "OFFSET", SYM(OFFSET_SYM)},
{ "OLD_PASSWORD", SYM(OLD_PASSWORD_SYM)},
{ "ON", SYM(ON)},
......
......@@ -799,6 +799,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
String *string;
TABLE_LIST *table_list;
Table_ident *table;
Qualified_column_ident *qualified_column_ident;
char *simple_string;
const char *const_simple_string;
chooser_compare_func_creator boolfunc2creator;
......@@ -1274,6 +1275,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NUMERIC_SYM /* SQL-2003-R */
%token NTH_VALUE_SYM /* SQL-2011 */
%token NVARCHAR_SYM
%token OF_SYM /* SQL-1992-R, Oracle-R */
%token OFFSET_SYM
%token OLD_PASSWORD_SYM
%token ON /* SQL-2003-R */
......@@ -1592,6 +1594,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
opt_constraint constraint opt_ident
sp_decl_ident
sp_block_label
%type <lex_string_with_metadata>
......@@ -1608,6 +1611,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_ident table_ident_nodb references xid
table_ident_opt_wild create_like
%type <qualified_column_ident>
qualified_column_ident
optionally_qualified_column_ident
%type <simple_string>
remember_name remember_end opt_db remember_tok_start
wild_and_where
......@@ -1883,9 +1890,10 @@ END_OF_INPUT
%type <NONE> case_stmt_specification
%type <NONE> loop_body while_body repeat_body
%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <num> sp_decl_idents sp_decl_idents_init_vars
%type <num> sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl sp_decl_body
%type <spblock> sp_decls sp_decl sp_decl_body sp_decl_variable_list
%type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type
%type <spvar_mode> sp_opt_inout
......@@ -1909,7 +1917,7 @@ END_OF_INPUT
%type <cond_info_list> condition_information;
%type <spvar_definition> row_field_name row_field_definition
%type <spvar_definition_list> row_field_definition_list field_type_row
%type <spvar_definition_list> row_field_definition_list row_type_body
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
......@@ -2864,13 +2872,17 @@ sp_param_name_and_type:
if (Lex->sp_param_fill_definition($$= $1))
MYSQL_YYABORT;
}
| sp_param_name field_type_row
| sp_param_name TYPE_SYM OF_SYM qualified_column_ident
{
Lex->sphead->fill_spvar_using_type_reference($$= $1, $4);
}
| sp_param_name ROW_SYM row_type_body
{
$$= $1;
$$->field_def.field_name= $$->name.str;
Lex->sphead->fill_spvar_definition(thd, &$$->field_def);
Lex->sphead->row_fill_field_definitions(thd, $2);
$$->field_def.set_row_field_definitions($2);
Lex->sphead->row_fill_field_definitions(thd, $3);
$$->field_def.set_row_field_definitions($3);
}
;
......@@ -2950,6 +2962,40 @@ sp_decl:
DECLARE_SYM sp_decl_body { $$= $2; }
;
qualified_column_ident:
sp_decl_ident '.' ident
{
if (!($$= new (thd->mem_root) Qualified_column_ident($1, $3)))
MYSQL_YYABORT;
}
| sp_decl_ident '.' ident '.' ident
{
if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
$1, $3, $5)))
MYSQL_YYABORT;
}
;
optionally_qualified_column_ident:
sp_decl_ident
{
if (!($$= new (thd->mem_root) Qualified_column_ident($1)))
MYSQL_YYABORT;
}
| sp_decl_ident '.' ident
{
if (!($$= new (thd->mem_root) Qualified_column_ident($1, $3)))
MYSQL_YYABORT;
}
| sp_decl_ident '.' ident '.' ident
{
if (!($$= new (thd->mem_root) Qualified_column_ident(thd,
$1, $3, $5)))
MYSQL_YYABORT;
}
;
row_field_name:
ident
{
......@@ -2983,36 +3029,56 @@ row_field_definition_list:
}
;
field_type_row:
ROW_SYM '(' row_field_definition_list ')' { $$= $3; }
row_type_body:
'(' row_field_definition_list ')' { $$= $2; }
;
sp_decl_body:
sp_decl_idents_init_vars:
sp_decl_idents
{
Lex->sp_variable_declarations_init(thd, $1);
}
;
sp_decl_variable_list:
sp_decl_idents_init_vars
type_with_opt_collate
sp_opt_default
{
if (Lex->sp_variable_declarations_finalize(thd, $1,
&Lex->last_field[0], $4))
&Lex->last_field[0], $3))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
| sp_decl_idents
| sp_decl_idents_init_vars
TYPE_SYM OF_SYM optionally_qualified_column_ident
sp_opt_default
{
Lex->sp_variable_declarations_init(thd, $1);
if (Lex->sp_variable_declarations_with_ref_finalize(thd, $1, $4, $5))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
field_type_row
| sp_decl_idents_init_vars
ROW_SYM TYPE_SYM OF_SYM optionally_qualified_column_ident
sp_opt_default
{
if (Lex->sp_variable_declarations_rowtype_finalize(thd, $1, $5, $6))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
| sp_decl_idents_init_vars
ROW_SYM row_type_body
sp_opt_default
{
if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
MYSQL_YYABORT;
$$.init_using_vars($1);
}
| ident CONDITION_SYM FOR_SYM sp_cond
;
sp_decl_body:
sp_decl_variable_list
| sp_decl_ident CONDITION_SYM FOR_SYM sp_cond
{
if (Lex->spcont->declare_condition(thd, $1, $4))
MYSQL_YYABORT;
......@@ -3031,7 +3097,7 @@ sp_decl_body:
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1;
}
| ident CURSOR_SYM
| sp_decl_ident CURSOR_SYM
{
Lex->sp_block_init(thd);
}
......@@ -3448,8 +3514,12 @@ condition_information_item_name:
{ $$= Condition_information_item::RETURNED_SQLSTATE; }
;
sp_decl_ident:
ident { $$= $1; }
;
sp_decl_idents:
ident
sp_decl_ident
{
/* NOTE: field definition is filled in sp_decl section. */
......@@ -14445,6 +14515,7 @@ keyword_sp:
| NOTFOUND_SYM {}
| NUMBER_SYM {}
| NVARCHAR_SYM {}
| OF_SYM {} /* SQL-1999-R, Oracle-R */
| OFFSET_SYM {}
| OLD_PASSWORD_SYM {}
| ONE_SYM {}
......
This diff is collapsed.
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