From 9b823e69967b8bae5b055b7161a8840635e7f0d9 Mon Sep 17 00:00:00 2001 From: Alexander Zhdanov Date: Mon, 16 Oct 2023 14:59:31 +0300 Subject: [PATCH] Add ability to change sql security option in alter function --- doc/sql.extensions/README.ddl.txt | 4 +- src/dsql/DdlNodes.epp | 31 +++++++++++----- src/dsql/DdlNodes.h | 18 ++++----- src/dsql/parse.y | 61 +++++++++++++++++++++++-------- 4 files changed, 79 insertions(+), 35 deletions(-) diff --git a/doc/sql.extensions/README.ddl.txt b/doc/sql.extensions/README.ddl.txt index 15cb880d59..1b324ddba7 100644 --- a/doc/sql.extensions/README.ddl.txt +++ b/doc/sql.extensions/README.ddl.txt @@ -604,7 +604,7 @@ ALTER TABLE ... [ {ENABLE | DISABLE} PUBLICATION ] Defines whether replication is enabled for the specified table. If not specified in the CREATE TABLE statement, the database-level default behaviour is applied. -24) Added the ability to change deterministic option without specifying the entire body of the function. +24) Added the ability to change deterministic and sql security option without specifying the entire body of the function. (Alexander Zhdanov) -ALTER FUNCTION {DETERMINISTIC | NOT DETERMINISTIC} +ALTER FUNCTION [ {DETERMINISTIC | NOT DETERMINISTIC} ] [ SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY ] diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index efc846c8db..8c2ecb77f3 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -1695,7 +1695,7 @@ DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) returnType->type->resolve(dsqlScratch); // check SQL SECURITY is not set if function declared in package - if (package.hasData() && ssDefiner.isAssigned()) + if (package.hasData() && ssDefiner.has_value()) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << Arg::Gds(isc_invalid_clause) << Arg::Str("SQL SECURITY for functions is prohibit in packages")); @@ -1905,13 +1905,13 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* attachment->storeMetaDataBlob(tdbb, transaction, &FUN.RDB$FUNCTION_SOURCE, source); FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE; - FUN.RDB$DETERMINISTIC_FLAG = deterministic ? TRUE : FALSE; + FUN.RDB$DETERMINISTIC_FLAG = deterministic.asBool() ? TRUE : FALSE; FUN.RDB$RETURN_ARGUMENT = 0; - if (ssDefiner.isAssigned()) + if (ssDefiner.has_value()) { FUN.RDB$SQL_SECURITY.NULL = FALSE; - FUN.RDB$SQL_SECURITY = ssDefiner.asBool() ? FB_TRUE : FB_FALSE; + FUN.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE; } else FUN.RDB$SQL_SECURITY.NULL = TRUE; @@ -2101,8 +2101,21 @@ bool CreateAlterFunctionNode::executeAlterIndividualParameters(thread_db* tdbb, } MODIFY FUN - FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE; - FUN.RDB$DETERMINISTIC_FLAG = deterministic ? TRUE : FALSE; + if(deterministic.isAssigned()) + { + FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE; + FUN.RDB$DETERMINISTIC_FLAG = deterministic.asBool() ? TRUE : FALSE; + } + if (ssDefiner.has_value()) + { + if(ssDefiner.value() != SqlSecurity::SS_DROP) + { + FUN.RDB$SQL_SECURITY.NULL = FALSE; + FUN.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE; + } + else + FUN.RDB$SQL_SECURITY.NULL = TRUE; + } modifed = true; END_MODIFY @@ -3516,10 +3529,10 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch if (ssDefiner.has_value()) { - if (ssDefiner.value() != SS_DROP) + if (ssDefiner.value() != SqlSecurity::SS_DROP) { TRG.RDB$SQL_SECURITY.NULL = FALSE; - TRG.RDB$SQL_SECURITY = ssDefiner.value() == SS_DEFINER ? FB_TRUE : FB_FALSE; + TRG.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE; } else TRG.RDB$SQL_SECURITY.NULL = TRUE; @@ -3573,7 +3586,7 @@ DdlNode* CreateAlterTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) } } - if (create && ssDefiner.has_value() && ssDefiner.value() == TriggerDefinition::SS_DROP) + if (create && ssDefiner.has_value() && ssDefiner.value() == SqlSecurity::SS_DROP) status_exception::raise(Arg::Gds(isc_dsql_command_err) << Arg::Gds(isc_dsql_invalid_drop_ss_clause)); return DdlNode::dsqlPass(dsqlScratch); diff --git a/src/dsql/DdlNodes.h b/src/dsql/DdlNodes.h index 2cdc276c25..f33a76d98c 100644 --- a/src/dsql/DdlNodes.h +++ b/src/dsql/DdlNodes.h @@ -40,6 +40,13 @@ namespace Jrd { +enum SqlSecurity +{ + SS_INVOKER, + SS_DEFINER, + SS_DROP +}; + class LocalDeclarationsNode; class RelationSourceNode; class ValueListNode; @@ -414,7 +421,6 @@ public: create(true), alter(false), external(NULL), - deterministic(false), parameters(pool), returnType(NULL), localDeclList(NULL), @@ -469,7 +475,7 @@ public: bool create; bool alter; NestConst external; - bool deterministic; + TriState deterministic; Firebird::Array > parameters; NestConst returnType; NestConst localDeclList; @@ -482,7 +488,7 @@ public: bool privateScope; bool preserveDefaults; SLONG udfReturnPos; - TriState ssDefiner; + std::optional ssDefiner; }; @@ -661,12 +667,6 @@ typedef RecreateNode nullableIntVal; TriState triState; - std::optional nullableSqlSecurityVal; + std::optional nullableSqlSecurityVal; std::optional nullableOverrideClause; struct { bool first; bool second; } boolPair; bool boolVal; @@ -2833,12 +2833,11 @@ function_clause %type change_opt_function_clause change_opt_function_clause - : change_deterministic_opt_function_clause ; %type psql_function_clause psql_function_clause - : function_clause_start sql_security_clause_opt AS local_declarations_opt full_proc_block + : function_clause_start optional_sql_security_full_alter_clause AS local_declarations_opt full_proc_block { $$ = $1; $$->ssDefiner = $2; @@ -2872,17 +2871,27 @@ function_clause_start } ; -%type change_deterministic_opt_function_clause -change_deterministic_opt_function_clause +%type change_opt_function_clause +change_opt_function_clause : symbol_UDF_name { $$ = newNode(*$1); } - deterministic_clause - { - $$ = $2; - $$->deterministic = $3; - } + alter_individual_ops($2) + { $$ = $2; } ; +%type alter_individual_ops() +alter_individual_ops($createAlterFunctionNode) + : alter_individual_op($createAlterFunctionNode) + | alter_individual_ops alter_individual_op($createAlterFunctionNode) + ; + +%type alter_individual_op() +alter_individual_op($createAlterFunctionNode) + : deterministic_clause + { setClause($createAlterFunctionNode->deterministic, "DETERMINISTIC", $1); } + | optional_sql_security_partial_alter_clause + { setClause($createAlterFunctionNode->ssDefiner, "SQL SECURITY", $1); } + ; %type deterministic_clause deterministic_clause @@ -4672,16 +4681,38 @@ trigger_type_opt // we do not allow alter database triggers, hence we do not use { $$ = std::nullopt; } ; +%type optional_sql_security_clause +optional_sql_security_clause + : SQL SECURITY DEFINER + { $$ = SS_DEFINER; } + | SQL SECURITY INVOKER + { $$ = SS_INVOKER; } + ; + +%type optional_sql_security_full_alter_clause +optional_sql_security_full_alter_clause + : optional_sql_security_clause + { $$ = $1; } + | // nothing + { $$ = std::nullopt; } + ; + +%type optional_sql_security_partial_alter_clause +optional_sql_security_partial_alter_clause + : optional_sql_security_clause + { $$ = $1; } + | DROP SQL SECURITY + { $$ = SS_DROP; } + ; + %type trg_sql_security_clause trg_sql_security_clause : // nothing { $$ = std::nullopt; } - | SQL SECURITY DEFINER - { $$ = TriggerDefinition::SS_DEFINER; } - | SQL SECURITY INVOKER - { $$ = TriggerDefinition::SS_INVOKER; } + | optional_sql_security_clause + { $$ = $1; } | DROP SQL SECURITY - { $$ = TriggerDefinition::SS_DROP; } + { $$ = SS_DROP; } ; // DROP metadata operations