diff options
-rw-r--r-- | mysql-test/r/sp.result | 24 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 29 | ||||
-rw-r--r-- | scripts/mysql_create_system_tables.sh | 6 | ||||
-rw-r--r-- | scripts/mysql_fix_privilege_tables.sql | 16 | ||||
-rw-r--r-- | sql/lex.h | 4 | ||||
-rw-r--r-- | sql/sp.cc | 55 | ||||
-rw-r--r-- | sql/sp_head.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 19 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 27 |
9 files changed, 146 insertions, 36 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 7544fbe5d60..3a3a72708a4 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -877,10 +877,17 @@ drop table t3| drop procedure cur2| create procedure chistics() language sql +modifies sql data not deterministic sql security definer comment 'Characteristics procedure test' - insert into t1 values ("chistics", 1)| + insert into t1 values ("chistics", 1)| +show create procedure chistics| +Procedure sql_mode Create Procedure +chistics CREATE PROCEDURE `test`.`chistics`() + MODIFIES SQL DATA + COMMENT 'Characteristics procedure test' +insert into t1 values ("chistics", 1) call chistics()| select * from t1| id data @@ -890,6 +897,7 @@ alter procedure chistics sql security invoker name chistics2| show create procedure chistics2| Procedure sql_mode Create Procedure chistics2 CREATE PROCEDURE `test`.`chistics2`() + MODIFIES SQL DATA SQL SECURITY INVOKER COMMENT 'Characteristics procedure test' insert into t1 values ("chistics", 1) @@ -899,14 +907,24 @@ language sql deterministic sql security invoker comment 'Characteristics procedure test' - return 42| + return 42| +show create function chistics| +Function sql_mode Create Function +chistics CREATE FUNCTION `test`.`chistics`() RETURNS int + DETERMINISTIC + SQL SECURITY INVOKER + COMMENT 'Characteristics procedure test' +return 42 select chistics()| chistics() 42 -alter function chistics name chistics2 comment 'Characteristics function test'| +alter function chistics name chistics2 +no sql +comment 'Characteristics function test'| show create function chistics2| Function sql_mode Create Function chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int + NO SQL DETERMINISTIC SQL SECURITY INVOKER COMMENT 'Characteristics function test' diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index a3101ff9488..c3c044a7808 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -978,12 +978,14 @@ drop procedure cur2| # The few characteristics we parse create procedure chistics() - language sql - not deterministic - sql security definer - comment 'Characteristics procedure test' - insert into t1 values ("chistics", 1)| - + language sql + modifies sql data + not deterministic + sql security definer + comment 'Characteristics procedure test' + insert into t1 values ("chistics", 1)| + +show create procedure chistics| # Call it, just to make sure. call chistics()| select * from t1| @@ -993,15 +995,18 @@ show create procedure chistics2| drop procedure chistics2| create function chistics() returns int - language sql - deterministic - sql security invoker - comment 'Characteristics procedure test' - return 42| + language sql + deterministic + sql security invoker + comment 'Characteristics procedure test' + return 42| +show create function chistics| # Call it, just to make sure. select chistics()| -alter function chistics name chistics2 comment 'Characteristics function test'| +alter function chistics name chistics2 + no sql + comment 'Characteristics function test'| show create function chistics2| drop function chistics2| diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index 5a2a45c4b3d..7a4da55f851 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -644,7 +644,11 @@ then c_p="$c_p type enum('FUNCTION','PROCEDURE') NOT NULL," c_p="$c_p specific_name char(64) DEFAULT '' NOT NULL," c_p="$c_p language enum('SQL') DEFAULT 'SQL' NOT NULL," - c_p="$c_p sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL," + c_p="$c_p sql_data_access enum('CONTAINS_SQL'," + c_p="$c_p 'NO_SQL'," + c_p="$c_p 'READS_SQL_DATA'," + c_p="$c_p 'MODIFIES_SQL_DATA'" + c_p="$c_p ) DEFAULT 'CONTAINS_SQL' NOT NULL," c_p="$c_p is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL," c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL," c_p="$c_p param_list blob DEFAULT '' NOT NULL," diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 3c01b69f57e..cae6a1d07b9 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -254,7 +254,11 @@ CREATE TABLE IF NOT EXISTS proc ( type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, - sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL, + sql_data_access enum('CONTAINS_SQL', + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, @@ -289,6 +293,12 @@ CREATE TABLE IF NOT EXISTS proc ( PRIMARY KEY (db,name,type) ) comment='Stored Procedures'; -# Correct the name fields to not binary +# Correct the name fields to not binary, and expand sql_data_access ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, - MODIFY specific_name char(64) DEFAULT '' NOT NULL; + MODIFY specific_name char(64) DEFAULT '' NOT NULL, + MODIFY sql_data_access + enum('CONTAINS_SQL', + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL; diff --git a/sql/lex.h b/sql/lex.h index 4ab557692d1..89daf46218c 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -121,6 +121,7 @@ static SYMBOL symbols[] = { { "CONDITION", SYM(CONDITION_SYM)}, { "CONNECTION", SYM(CONNECTION_SYM)}, { "CONSTRAINT", SYM(CONSTRAINT)}, + { "CONTAINS", SYM(CONTAINS_SYM)}, { "CONTINUE", SYM(CONTINUE_SYM)}, { "CONVERT", SYM(CONVERT_SYM)}, { "CREATE", SYM(CREATE)}, @@ -315,6 +316,7 @@ static SYMBOL symbols[] = { { "MIN_ROWS", SYM(MIN_ROWS)}, { "MOD", SYM(MOD_SYM)}, { "MODE", SYM(MODE_SYM)}, + { "MODIFIES", SYM(MODIFIES_SYM)}, { "MODIFY", SYM(MODIFY_SYM)}, { "MONTH", SYM(MONTH_SYM)}, { "MULTILINESTRING", SYM(MULTILINESTRING)}, @@ -371,6 +373,7 @@ static SYMBOL symbols[] = { { "RAID_CHUNKSIZE", SYM(RAID_CHUNKSIZE)}, { "RAID_TYPE", SYM(RAID_TYPE)}, { "READ", SYM(READ_SYM)}, + { "READS", SYM(READS_SYM)}, { "REAL", SYM(REAL)}, { "REFERENCES", SYM(REFERENCES)}, { "REGEXP", SYM(REGEXP)}, @@ -556,7 +559,6 @@ static SYMBOL sql_functions[] = { { "CONCAT", SYM(CONCAT)}, { "CONCAT_WS", SYM(CONCAT_WS)}, { "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, - { "CONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)}, { "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, { "CONVERT_TZ", SYM(CONVERT_TZ_SYM)}, { "COUNT", SYM(COUNT_SYM)}, diff --git a/sql/sp.cc b/sql/sp.cc index 6475b64eb18..8211d06376c 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -165,13 +165,36 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) goto done; } + bzero((char *)&chistics, sizeof(chistics)); + if ((ptr= get_field(&thd->mem_root, + table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL) + { + ret= SP_GET_FIELD_FAILED; + goto done; + } + switch (ptr[0]) { + case 'N': + chistics.daccess= SP_NO_SQL; + break; + case 'C': + chistics.daccess= SP_CONTAINS_SQL; + break; + case 'R': + chistics.daccess= SP_READS_SQL_DATA; + break; + case 'M': + chistics.daccess= SP_MODIFIES_SQL_DATA; + break; + default: + chistics.daccess= SP_CONTAINS_SQL; + } + if ((ptr= get_field(&thd->mem_root, table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL) { ret= SP_GET_FIELD_FAILED; goto done; } - bzero((char *)&chistics, sizeof(chistics)); chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE); if ((ptr= get_field(&thd->mem_root, @@ -180,7 +203,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ret= SP_GET_FIELD_FAILED; goto done; } - chistics.suid= (ptr[0] == 'I' ? IS_NOT_SUID : IS_SUID); + chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID); if ((params= get_field(&thd->mem_root, table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL) @@ -356,9 +379,12 @@ db_create_routine(THD *thd, int type, sp_head *sp) store((longlong)type); table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]-> store(sp->m_name.str, sp->m_name.length, system_charset_info); + if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS) + table->field[MYSQL_PROC_FIELD_ACCESS]-> + store((longlong)sp->m_chistics->daccess); table->field[MYSQL_PROC_FIELD_DETERMINISTIC]-> store((longlong)(sp->m_chistics->detistic ? 1 : 2)); - if (sp->m_chistics->suid != IS_DEFAULT_SUID) + if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> store((longlong)sp->m_chistics->suid); table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> @@ -433,12 +459,16 @@ db_update_routine(THD *thd, int type, sp_name *name, store_record(table,record[1]); table->timestamp_on_update_now = 0; // Don't update create time now. ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); - if (chistics->suid != IS_DEFAULT_SUID) - table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store((longlong)chistics->suid); + if (chistics->suid != SP_IS_DEFAULT_SUID) + table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> + store((longlong)chistics->suid); if (newname) table->field[MYSQL_PROC_FIELD_NAME]->store(newname, newnamelen, system_charset_info); + if (chistics->daccess != SP_DEFAULT_ACCESS) + table->field[MYSQL_PROC_FIELD_ACCESS]-> + store((longlong)chistics->daccess); if (chistics->comment.str) table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str, chistics->comment.length, @@ -1027,9 +1057,20 @@ create_string(THD *thd, String *buf, buf->append(returns, returnslen); } buf->append('\n'); + switch (chistics->daccess) { + case SP_NO_SQL: + buf->append(" NO SQL\n"); + break; + case SP_READS_SQL_DATA: + buf->append(" READS SQL DATA\n"); + break; + case SP_MODIFIES_SQL_DATA: + buf->append(" MODIFIES SQL DATA\n"); + break; + } if (chistics->detistic) - buf->append( " DETERMINISTIC\n", 18); - if (chistics->suid == IS_NOT_SUID) + buf->append(" DETERMINISTIC\n", 18); + if (chistics->suid == SP_IS_NOT_SUID) buf->append(" SQL SECURITY INVOKER\n", 25); if (chistics->comment.length) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6a17bc189c3..82f8e88d889 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1815,7 +1815,7 @@ sp_instr_error::print(String *str) void sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp) { - ctxp->changed= (sp->m_chistics->suid != IS_NOT_SUID && + ctxp->changed= (sp->m_chistics->suid != SP_IS_NOT_SUID && (strcmp(sp->m_definer_user.str, thd->priv_user) || strcmp(sp->m_definer_host.str, thd->priv_host))); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 72d28aa4526..af5b0896fa5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -94,11 +94,23 @@ enum enum_sql_command { #define DESCRIBE_NORMAL 1 #define DESCRIBE_EXTENDED 2 -enum suid_behaviour +enum enum_sp_suid_behaviour { - IS_DEFAULT_SUID= 0, IS_NOT_SUID, IS_SUID + SP_IS_DEFAULT_SUID= 0, + SP_IS_NOT_SUID, + SP_IS_SUID }; +enum enum_sp_data_access +{ + SP_DEFAULT_ACCESS= 0, + SP_CONTAINS_SQL, + SP_NO_SQL, + SP_READS_SQL_DATA, + SP_MODIFIES_SQL_DATA +}; + + #define DERIVED_SUBQUERY 1 #define DERIVED_VIEW 2 @@ -599,8 +611,9 @@ typedef struct st_alter_info struct st_sp_chistics { LEX_STRING comment; - enum suid_behaviour suid; + enum enum_sp_suid_behaviour suid; bool detistic; + enum enum_sp_data_access daccess; }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 31016b59c6f..d2964df008b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -225,6 +225,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token CONDITION_SYM %token CONNECTION_SYM %token CONSTRAINT +%token CONTAINS_SYM %token CONTINUE_SYM %token CONVERT_SYM %token CURRENT_USER @@ -368,6 +369,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RAID_CHUNKS %token RAID_CHUNKSIZE %token READ_SYM +%token READS_SYM %token REAL_NUM %token REFERENCES %token REGEXP @@ -560,6 +562,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MINUTE_SECOND_SYM %token MINUTE_SYM %token MODE_SYM +%token MODIFIES_SYM %token MODIFY_SYM %token MONTH_SYM %token MLINEFROMTEXT @@ -1378,8 +1381,20 @@ sp_c_chistics: /* Characteristics for both create and alter */ sp_chistic: - COMMENT_SYM TEXT_STRING_sys { Lex->sp_chistics.comment= $2; } - | sp_suid { } + COMMENT_SYM TEXT_STRING_sys + { Lex->sp_chistics.comment= $2; } + | LANGUAGE_SYM SQL_SYM + { /* Just parse it, we only have one language for now. */ } + | NO_SYM SQL_SYM + { Lex->sp_chistics.daccess= SP_NO_SQL; } + | CONTAINS_SYM SQL_SYM + { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; } + | READS_SYM SQL_SYM DATA_SYM + { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; } + | MODIFIES_SYM SQL_SYM DATA_SYM + { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; } + | sp_suid + { } ; /* Alter characteristics */ @@ -1391,7 +1406,6 @@ sp_a_chistic: /* Create characteristics */ sp_c_chistic: sp_chistic { } - | LANGUAGE_SYM SQL_SYM { } | DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; } | NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; } ; @@ -1399,11 +1413,11 @@ sp_c_chistic: sp_suid: SQL_SYM SECURITY_SYM DEFINER_SYM { - Lex->sp_chistics.suid= IS_SUID; + Lex->sp_chistics.suid= SP_IS_SUID; } | SQL_SYM SECURITY_SYM INVOKER_SYM { - Lex->sp_chistics.suid= IS_NOT_SUID; + Lex->sp_chistics.suid= SP_IS_NOT_SUID; } ; @@ -4237,6 +4251,8 @@ simple_expr: { $$= new Item_func_concat(* $3); } | CONCAT_WS '(' expr ',' expr_list ')' { $$= new Item_func_concat_ws($3, *$5); } + | CONTAINS_SYM '(' expr ',' expr ')' + { $$= create_func_contains($3, $5); } | CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')' { Lex->time_zone_tables_used= &fake_time_zone_tables_list; @@ -6780,6 +6796,7 @@ keyword: | COMMIT_SYM {} | COMPRESSED_SYM {} | CONCURRENT {} + | CONTAINS_SYM {} | CUBE_SYM {} | DATA_SYM {} | DATETIME {} |