8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 10:40:38 +01:00

Merge pull request #7807 from Zhdanov0/master

Added the ability to change sql security option without specifying the entire body of the function/procedure/package
This commit is contained in:
Dmitry Yemanov 2023-11-11 00:14:40 +03:00 committed by GitHub
commit 26a78fa18c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 252 additions and 53 deletions

View File

@ -604,7 +604,17 @@ ALTER TABLE <name> ... [ {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 <name> {DETERMINISTIC | NOT DETERMINISTIC}
ALTER FUNCTION <name> [ {DETERMINISTIC | NOT DETERMINISTIC} ] [ SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY ]
25) Added the ability to change sql security option without specifying the entire body of the procedure
(Alexander Zhdanov)
ALTER PROCEDURE <name> SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY
26) Added the ability to change sql security option without specifying the entire body of the package
(Alexander Zhdanov)
ALTER PACKAGE <name> SQL SECURITY {DEFINER | INVOKER} | DROP SQL SECURITY

View File

@ -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
@ -2698,7 +2711,7 @@ DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
returns[i]->type->resolve(dsqlScratch);
// check SQL SECURITY is not set if procedure 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 procedures is prohibit in packages"));
@ -2729,8 +2742,17 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
AutoSavePoint savePoint(tdbb, transaction);
bool altered = false;
const bool alterIndividualParameters = (alter && !(body || external));
// first pass
if (alter)
if (alterIndividualParameters)
{
if (executeAlterIndividualParameters(tdbb, dsqlScratch, transaction, false, true))
altered = true;
else
status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << Arg::Str(name));
}
else if (alter)
{
if (executeAlter(tdbb, dsqlScratch, transaction, false, true))
altered = true;
@ -2747,7 +2769,11 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
compile(tdbb, dsqlScratch);
executeAlter(tdbb, dsqlScratch, transaction, true, false); // second pass
// second pass
if (alterIndividualParameters)
executeAlterIndividualParameters(tdbb, dsqlScratch, transaction, true, false);
else
executeAlter(tdbb, dsqlScratch, transaction, true, false);
if (package.isEmpty())
{
@ -2896,10 +2922,10 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
else
P.RDB$PRIVATE_FLAG.NULL = TRUE;
if (ssDefiner.isAssigned())
if (ssDefiner.has_value())
{
P.RDB$SQL_SECURITY.NULL = FALSE;
P.RDB$SQL_SECURITY = ssDefiner.asBool() ? FB_TRUE : FB_FALSE;
P.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE;
}
else
P.RDB$SQL_SECURITY.NULL = TRUE;
@ -3011,6 +3037,52 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
return modified;
}
bool CreateAlterProcedureNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, bool secondPass, bool runTriggers)
{
Attachment* const attachment = transaction->getAttachment();
bool modifed = false;
AutoCacheRequest requestHandle(tdbb, drq_m_prm_prcs2, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
P IN RDB$PROCEDURES
WITH P.RDB$PROCEDURE_NAME EQ name.c_str() AND
P.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
{
if (P.RDB$SYSTEM_FLAG)
{
status_exception::raise(
Arg::Gds(isc_dyn_cannot_mod_sysproc) <<
MetaName(P.RDB$PROCEDURE_NAME));
}
if (!secondPass && runTriggers && package.isEmpty())
{
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
DDL_TRIGGER_ALTER_PROCEDURE, name, NULL);
}
MODIFY P
if (ssDefiner.has_value())
{
if(ssDefiner.value() != SqlSecurity::SS_DROP)
{
P.RDB$SQL_SECURITY.NULL = FALSE;
P.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE;
}
else
P.RDB$SQL_SECURITY.NULL = TRUE;
}
modifed = true;
END_MODIFY
}
END_FOR
return modifed;
}
void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction, USHORT parameterType, unsigned pos, ParameterClause* parameter,
const CollectedParameter* collectedParameter)
@ -3516,10 +3588,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 +3645,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);

View File

@ -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<ExternalClause> external;
bool deterministic;
Firebird::TriState deterministic;
Firebird::Array<NestConst<ParameterClause> > parameters;
NestConst<ParameterClause> returnType;
NestConst<LocalDeclarationsNode> localDeclList;
@ -482,7 +488,7 @@ public:
bool privateScope;
bool preserveDefaults;
SLONG udfReturnPos;
Firebird::TriState ssDefiner;
std::optional<SqlSecurity> ssDefiner;
};
@ -594,6 +600,9 @@ private:
void executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
bool executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction,
bool secondPass, bool runTriggers);
bool executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction,
bool secondPass, bool runTriggers);
void storeParameter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction,
USHORT parameterType, unsigned pos, ParameterClause* parameter,
const CollectedParameter* collectedParameter);
@ -616,7 +625,7 @@ public:
MetaName packageOwner;
bool privateScope;
bool preserveDefaults;
Firebird::TriState ssDefiner;
std::optional<SqlSecurity> ssDefiner;
};
@ -661,12 +670,6 @@ typedef RecreateNode<CreateAlterProcedureNode, DropProcedureNode, isc_dsql_recre
class TriggerDefinition
{
public:
enum SqlSecurity
{
SS_INVOKER,
SS_DEFINER,
SS_DROP
};
explicit TriggerDefinition(MemoryPool& p)
: name(p),

View File

@ -215,6 +215,9 @@ string CreateAlterPackageNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
if (alter && !items)
return DdlNode::dsqlPass(dsqlScratch);
MemoryPool& pool = dsqlScratch->getPool();
source.ltrim("\n\r\t ");
@ -319,9 +322,18 @@ void CreateAlterPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
const bool alterIndividualParameters = (alter && !items);
if (alter)
{
if (!executeAlter(tdbb, dsqlScratch, transaction))
if (alterIndividualParameters)
{
if (!executeAlterIndividualParameters(tdbb, dsqlScratch, transaction))
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
}
else if (!executeAlter(tdbb, dsqlScratch, transaction))
{
if (create) // create or alter
executeCreate(tdbb, dsqlScratch, transaction);
@ -371,10 +383,10 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
PKG.RDB$PACKAGE_HEADER_SOURCE.NULL = FALSE;
attachment->storeMetaDataBlob(tdbb, transaction, &PKG.RDB$PACKAGE_HEADER_SOURCE, source);
if (ssDefiner.isAssigned())
if (ssDefiner.has_value())
{
PKG.RDB$SQL_SECURITY.NULL = FALSE;
PKG.RDB$SQL_SECURITY = ssDefiner.asBool() ? FB_TRUE : FB_FALSE;
PKG.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE;
}
else
PKG.RDB$SQL_SECURITY.NULL = TRUE;
@ -445,10 +457,10 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
if (!PKG.RDB$VALID_BODY_FLAG.NULL)
PKG.RDB$VALID_BODY_FLAG = FALSE;
if (ssDefiner.isAssigned())
if (ssDefiner.has_value())
{
PKG.RDB$SQL_SECURITY.NULL = FALSE;
PKG.RDB$SQL_SECURITY = ssDefiner.asBool() ? FB_TRUE : FB_FALSE;
PKG.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE;
}
else
PKG.RDB$SQL_SECURITY.NULL = TRUE;
@ -475,6 +487,44 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
}
bool CreateAlterPackageNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
AutoCacheRequest requestHandle(tdbb, drq_m_prm_pkg, DYN_REQUESTS);
bool modified = false;
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
{
modified = true;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
MODIFY PKG
if (ssDefiner.has_value())
{
if (ssDefiner.value() != SqlSecurity::SS_DROP)
{
PKG.RDB$SQL_SECURITY.NULL = FALSE;
PKG.RDB$SQL_SECURITY = ssDefiner.value() == SqlSecurity::SS_DEFINER ? FB_TRUE : FB_FALSE;
}
else
PKG.RDB$SQL_SECURITY.NULL = TRUE;
}
END_MODIFY
}
END_FOR
if (modified)
{
executeDdlTrigger(tdbb, dsqlScratch, transaction,
DTW_AFTER, DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
}
return modified;
}
void CreateAlterPackageNode::executeItems(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
jrd_tra* transaction)
{

View File

@ -100,6 +100,7 @@ protected:
private:
void executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
bool executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
bool executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
void executeItems(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
public:
@ -110,7 +111,7 @@ public:
Firebird::Array<Item>* items;
Firebird::SortedArray<MetaName> functionNames;
Firebird::SortedArray<MetaName> procedureNames;
Firebird::TriState ssDefiner;
std::optional<SqlSecurity> ssDefiner;
private:
MetaName owner;

View File

@ -737,7 +737,7 @@ using namespace Firebird;
std::optional<int> nullableIntVal;
Firebird::TriState triState;
std::optional<Jrd::TriggerDefinition::SqlSecurity> nullableSqlSecurityVal;
std::optional<Jrd::SqlSecurity> nullableSqlSecurityVal;
std::optional<Jrd::OverrideClause> nullableOverrideClause;
struct { bool first; bool second; } boolPair;
bool boolVal;
@ -2710,7 +2710,7 @@ procedure_clause
%type <createAlterProcedureNode> psql_procedure_clause
psql_procedure_clause
: procedure_clause_start sql_security_clause_opt AS local_declarations_opt full_proc_block
: procedure_clause_start optional_sql_security_full_alter_clause AS local_declarations_opt full_proc_block
{
$$ = $1;
$$->ssDefiner = $2;
@ -2739,6 +2739,17 @@ procedure_clause_start
{ $$ = $2; }
;
%type <createAlterProcedureNode> partial_alter_procedure_clause
partial_alter_procedure_clause
: symbol_procedure_name
{ $$ = newNode<CreateAlterProcedureNode>(*$1); }
optional_sql_security_partial_alter_clause
{
$$ = $2;
$$->ssDefiner = $3;
}
;
%type <createAlterProcedureNode> alter_procedure_clause
alter_procedure_clause
: procedure_clause
@ -2747,6 +2758,12 @@ alter_procedure_clause
$$->alter = true;
$$->create = false;
}
| partial_alter_procedure_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
;
%type <createAlterProcedureNode> replace_procedure_clause
@ -2832,14 +2849,10 @@ function_clause
: psql_function_clause
| external_function_clause;
%type <createAlterFunctionNode> change_opt_function_clause
change_opt_function_clause
: change_deterministic_opt_function_clause
;
%type <createAlterFunctionNode> 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;
@ -2873,17 +2886,27 @@ function_clause_start
}
;
%type <createAlterFunctionNode> change_deterministic_opt_function_clause
change_deterministic_opt_function_clause
%type <createAlterFunctionNode> partial_alter_function_clause
partial_alter_function_clause
: symbol_UDF_name
{ $$ = newNode<CreateAlterFunctionNode>(*$1); }
deterministic_clause
{
$$ = $2;
$$->deterministic = $3;
}
alter_individual_ops($2)
{ $$ = $2; }
;
%type alter_individual_ops(<createAlterFunctionNode>)
alter_individual_ops($createAlterFunctionNode)
: alter_individual_op($createAlterFunctionNode)
| alter_individual_ops alter_individual_op($createAlterFunctionNode)
;
%type alter_individual_op(<createAlterFunctionNode>)
alter_individual_op($createAlterFunctionNode)
: deterministic_clause
{ setClause($createAlterFunctionNode->deterministic, "DETERMINISTIC", $1); }
| optional_sql_security_partial_alter_clause
{ setClause($createAlterFunctionNode->ssDefiner, "SQL SECURITY", $1); }
;
%type <boolVal> deterministic_clause
deterministic_clause
@ -2926,7 +2949,7 @@ alter_function_clause
$$->alter = true;
$$->create = false;
}
| change_opt_function_clause
| partial_alter_function_clause
{
$$ = $1;
$$->alter = true;
@ -2948,7 +2971,7 @@ replace_function_clause
%type <createAlterPackageNode> package_clause
package_clause
: symbol_package_name sql_security_clause_opt AS BEGIN package_items_opt END
: symbol_package_name optional_sql_security_full_alter_clause AS BEGIN package_items_opt END
{
CreateAlterPackageNode* node = newNode<CreateAlterPackageNode>(*$1);
node->ssDefiner = $2;
@ -2958,6 +2981,16 @@ package_clause
}
;
%type <createAlterPackageNode> partial_alter_package_clause
partial_alter_package_clause
: symbol_package_name optional_sql_security_partial_alter_clause
{
CreateAlterPackageNode* node = newNode<CreateAlterPackageNode>(*$1);
node->ssDefiner = $2;
$$ = node;
}
;
%type <packageItems> package_items_opt
package_items_opt
: package_items
@ -2995,6 +3028,12 @@ alter_package_clause
$$->alter = true;
$$->create = false;
}
| partial_alter_package_clause
{
$$ = $1;
$$->alter = true;
$$->create = false;
}
;
%type <createAlterPackageNode> replace_package_clause
@ -4673,16 +4712,38 @@ trigger_type_opt // we do not allow alter database triggers, hence we do not use
{ $$ = std::nullopt; }
;
%type <nullableSqlSecurityVal> optional_sql_security_clause
optional_sql_security_clause
: SQL SECURITY DEFINER
{ $$ = SS_DEFINER; }
| SQL SECURITY INVOKER
{ $$ = SS_INVOKER; }
;
%type <nullableSqlSecurityVal> optional_sql_security_full_alter_clause
optional_sql_security_full_alter_clause
: optional_sql_security_clause
{ $$ = $1; }
| // nothing
{ $$ = std::nullopt; }
;
%type <nullableSqlSecurityVal> optional_sql_security_partial_alter_clause
optional_sql_security_partial_alter_clause
: optional_sql_security_clause
{ $$ = $1; }
| DROP SQL SECURITY
{ $$ = SS_DROP; }
;
%type <nullableSqlSecurityVal> 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

View File

@ -182,6 +182,7 @@ enum drq_type_t
drq_s_prms4,
drq_s_prm_src2,
drq_m_prcs2,
drq_m_prm_prcs2, // modify individual procedure parameters (CreateAlterProcedureNode)
drq_e_prms2,
drq_m_trigger2,
drq_e_prcs2,
@ -199,6 +200,7 @@ enum drq_type_t
drq_m_pkg_prc, // drop package body
drq_m_pkg_fun, // drop package body
drq_m_pkg, // alter package
drq_m_prm_pkg, // modify individual package parameters
drq_l_pkg_funcs, // lookup packaged functions
drq_l_pkg_func_args, // lookup packaged function arguments
drq_l_pkg_procs, // lookup packaged procedures