mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Functions support
This commit is contained in:
parent
38ffaf4a1f
commit
bfe98c33e5
@ -1791,7 +1791,12 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql
|
||||
|
||||
compile(tdbb, dsqlScratch);
|
||||
|
||||
executeAlter(tdbb, dsqlScratch, transaction, true, false); // second pass
|
||||
{ // scope
|
||||
// avoid modify routine dfw during second pass on CREATE
|
||||
AutoSetRestoreFlag<ULONG> noDfw(&tdbb->tdbb_flags, altered ? 0 : TDBB_dont_post_dfw, true);
|
||||
|
||||
executeAlter(tdbb, dsqlScratch, transaction, true, false); // second pass
|
||||
}
|
||||
|
||||
if (package.isEmpty())
|
||||
{
|
||||
@ -1889,6 +1894,9 @@ void CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
|
||||
if (package.isEmpty())
|
||||
storePrivileges(tdbb, transaction, name, obj_udf, EXEC_PRIVILEGES);
|
||||
|
||||
// avoid modify routine dfw when execute CREATE
|
||||
AutoSetRestoreFlag<ULONG> noDfw(&tdbb->tdbb_flags, TDBB_dont_post_dfw, true);
|
||||
|
||||
executeAlter(tdbb, dsqlScratch, transaction, false, false);
|
||||
}
|
||||
|
||||
@ -1899,6 +1907,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
|
||||
|
||||
bool modified = false;
|
||||
unsigned returnPos = 0;
|
||||
MetaId id;
|
||||
|
||||
AutoCacheRequest requestHandle(tdbb, drq_m_funcs2, DYN_REQUESTS);
|
||||
|
||||
@ -1913,10 +1922,17 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
|
||||
Arg::Gds(isc_dyn_cannot_mod_sysfunc) << MetaName(FUN.RDB$FUNCTION_NAME));
|
||||
}
|
||||
|
||||
if (!secondPass && runTriggers && package.isEmpty())
|
||||
id = FUN.RDB$FUNCTION_ID;
|
||||
|
||||
if (!secondPass && runTriggers)
|
||||
{
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||
DDL_TRIGGER_ALTER_FUNCTION, name, NULL);
|
||||
if (package.isEmpty())
|
||||
{
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
|
||||
DDL_TRIGGER_ALTER_FUNCTION, name, NULL);
|
||||
}
|
||||
|
||||
MetadataCache::oldVersion(tdbb, obj_udf, id);
|
||||
}
|
||||
|
||||
MODIFY FUN
|
||||
@ -2104,6 +2120,9 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
|
||||
}
|
||||
}
|
||||
|
||||
if (secondPass && modified)
|
||||
MetadataCache::newVersion(tdbb, obj_udf, id);
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
@ -2442,6 +2461,7 @@ void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* ds
|
||||
|
||||
AutoCacheRequest request(tdbb, drq_m_fun, DYN_REQUESTS);
|
||||
bool found = false;
|
||||
MetaId id;
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
FUN IN RDB$FUNCTIONS
|
||||
@ -2456,6 +2476,8 @@ void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* ds
|
||||
if (!FUN.RDB$ENGINE_NAME.NULL || !FUN.RDB$FUNCTION_BLR.NULL)
|
||||
status_exception::raise(Arg::Gds(isc_dyn_newfc_oldsyntax) << name);
|
||||
|
||||
MetadataCache::oldVersion(tdbb, obj_udf, (id = FUN.RDB$FUNCTION_ID));
|
||||
|
||||
MODIFY FUN
|
||||
if (clauses.name.hasData())
|
||||
{
|
||||
@ -2480,6 +2502,7 @@ void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* ds
|
||||
|
||||
if (found)
|
||||
{
|
||||
MetadataCache::newVersion(tdbb, obj_udf, id);
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_FUNCTION,
|
||||
name, NULL);
|
||||
}
|
||||
@ -2566,6 +2589,10 @@ void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
bool found = false;
|
||||
MetaId id;
|
||||
|
||||
//MetadataCache::oldVersion(tdbb, obj_udf, id); missing ID in the node
|
||||
MetadataCache::lookup_function(tdbb, QualifiedName(name, ""), CacheFlag::AUTOCREATE);
|
||||
|
||||
dropArguments(tdbb, transaction, name, package);
|
||||
|
||||
@ -2589,12 +2616,12 @@ void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
name, NULL);
|
||||
}
|
||||
|
||||
id = FUN.RDB$FUNCTION_ID;
|
||||
ERASE FUN;
|
||||
found = true;
|
||||
|
||||
if (!FUN.RDB$SECURITY_CLASS.NULL)
|
||||
deleteSecurityClass(tdbb, transaction, FUN.RDB$SECURITY_CLASS);
|
||||
|
||||
found = true;
|
||||
}
|
||||
END_FOR
|
||||
|
||||
@ -2617,10 +2644,15 @@ void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
END_FOR
|
||||
}
|
||||
|
||||
if (found && package.isEmpty())
|
||||
if (found)
|
||||
{
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_FUNCTION,
|
||||
name, NULL);
|
||||
MetadataCache::erase(tdbb, obj_udf, id);
|
||||
|
||||
if (package.isEmpty())
|
||||
{
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_FUNCTION,
|
||||
name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
savePoint.release(); // everything is ok
|
||||
|
@ -64,7 +64,7 @@ Function* Function::lookup(thread_db* tdbb, MetaId id, ObjectBase::Flag flags)
|
||||
{
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
Function* function = dbb->dbb_mdc->getFunction(tdbb, id, flags | CacheFlag::AUTOCREATE);
|
||||
Function* function = dbb->dbb_mdc->getFunction(tdbb, id, flags);
|
||||
return function;
|
||||
}
|
||||
|
||||
@ -77,27 +77,7 @@ Function* Function::create(thread_db* tdbb, MemoryPool& pool, Cached::Function*
|
||||
|
||||
Function* Function::lookup(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags)
|
||||
{
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
// See if we already know the function by name
|
||||
Function* function = dbb->dbb_mdc->lookup_function(tdbb, name);
|
||||
if (function)
|
||||
return function;
|
||||
|
||||
// We need to look up the function in RDB$FUNCTIONS
|
||||
AutoCacheRequest request(tdbb, irq_l_fun_name, IRQ_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request)
|
||||
X IN RDB$FUNCTIONS
|
||||
WITH X.RDB$FUNCTION_NAME EQ name.identifier.c_str() AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
|
||||
{
|
||||
if (!function)
|
||||
function = dbb->dbb_mdc->getFunction(tdbb, X.RDB$FUNCTION_ID, flags);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return function;
|
||||
return MetadataCache::lookup_function(tdbb, name, flags);
|
||||
}
|
||||
|
||||
Lock* Function::makeLock(thread_db* tdbb, MemoryPool& p)
|
||||
|
@ -911,7 +911,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
case blr_pid:
|
||||
case blr_pid2:
|
||||
{
|
||||
const SSHORT pid = csb->csb_blr_reader.getWord();
|
||||
const SSHORT procId = csb->csb_blr_reader.getWord();
|
||||
|
||||
if (blrOp == blr_pid2)
|
||||
{
|
||||
@ -919,8 +919,8 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
csb->csb_blr_reader.getString(*aliasString);
|
||||
}
|
||||
|
||||
proc = MetadataCache::lookupProcedure(tdbb, pid, CacheFlag::AUTOCREATE);
|
||||
name.identifier.printf("id %d", pid);
|
||||
proc = MetadataCache::lookupProcedure(tdbb, procId, CacheFlag::AUTOCREATE);
|
||||
name.identifier.printf("id %d", procId);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1095,8 +1095,8 @@ namespace
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(work->dfw_package.c_str(), '')
|
||||
{
|
||||
blobId = X.RDB$FUNCTION_BLR;
|
||||
routine = Function::lookup(tdbb,
|
||||
QualifiedName(work->dfw_name, work->dfw_package), !compile);
|
||||
routine = Function::lookup(tdbb, QualifiedName(work->dfw_name, work->dfw_package),
|
||||
(compile ? 0 : CacheFlag::NOSCAN) | CacheFlag::AUTOCREATE);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
@ -1254,7 +1254,6 @@ static const deferred_task task_table[] =
|
||||
{ dfw_modify_procedure, ProcedureManager::modifyRoutine },
|
||||
{ dfw_modify_function, FunctionManager::modifyRoutine },
|
||||
{ dfw_delete_prm, delete_parameter },
|
||||
|
||||
{ dfw_create_collation, create_collation },
|
||||
{ dfw_delete_collation, delete_collation },
|
||||
/*
|
||||
|
@ -2591,18 +2591,18 @@ jrd_prc* MetadataCache::lookup_procedure(thread_db* tdbb, const QualifiedName& n
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
MetadataCache* mdc = attachment->att_database->dbb_mdc;
|
||||
|
||||
|
||||
// See if we already know the procedure by name
|
||||
for (auto procedure : mdc->mdc_procedures)
|
||||
{
|
||||
if (procedure && procedure->getName() == name)
|
||||
{
|
||||
return procedure->getObject(tdbb, CacheFlag::AUTOCREATE);
|
||||
}
|
||||
}
|
||||
|
||||
auto* proc = mdc->mdc_procedures.lookup(tdbb,
|
||||
[name] (Cached::Procedure* proc) { return proc->getName() == name; });
|
||||
if (proc)
|
||||
return proc->getObject(tdbb, flags);
|
||||
|
||||
if (!(flags & CacheFlag::AUTOCREATE))
|
||||
return nullptr;
|
||||
|
||||
|
||||
// We need to look up the procedure name in RDB$PROCEDURES
|
||||
|
||||
jrd_prc* procedure = nullptr;
|
||||
@ -2614,11 +2614,11 @@ jrd_prc* MetadataCache::lookup_procedure(thread_db* tdbb, const QualifiedName& n
|
||||
WITH P.RDB$PROCEDURE_NAME EQ name.identifier.c_str() AND
|
||||
P.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
|
||||
{
|
||||
fb_assert(!procedure);
|
||||
procedure = mdc->mdc_procedures.getObject(tdbb, P.RDB$PROCEDURE_ID, flags);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@ -2643,7 +2643,7 @@ jrd_prc* MetadataCache::lookup_procedure_id(thread_db* tdbb, MetaId id, ObjectBa
|
||||
}
|
||||
|
||||
|
||||
Function* MetadataCache::lookup_function(thread_db* tdbb, const QualifiedName& name)
|
||||
Function* MetadataCache::lookup_function(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags)
|
||||
{
|
||||
/************************************************
|
||||
*
|
||||
@ -2656,7 +2656,38 @@ Function* MetadataCache::lookup_function(thread_db* tdbb, const QualifiedName& n
|
||||
* ASCIZ name.
|
||||
*
|
||||
**************************************/
|
||||
return Function::lookup(tdbb, name, CacheFlag::AUTOCREATE);
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
MetadataCache* mdc = attachment->att_database->dbb_mdc;
|
||||
|
||||
|
||||
// See if we already know the function by name
|
||||
|
||||
auto* func = mdc->mdc_functions.lookup(tdbb,
|
||||
[name] (Cached::Function* func) { return func->getName() == name; });
|
||||
if (func)
|
||||
return func->getObject(tdbb, flags);
|
||||
|
||||
if (!(flags & CacheFlag::AUTOCREATE))
|
||||
return nullptr;
|
||||
|
||||
|
||||
// We need to look up the function in RDB$FUNCTIONS
|
||||
|
||||
Function* function = nullptr;
|
||||
|
||||
AutoCacheRequest request(tdbb, irq_l_fun_name, IRQ_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request)
|
||||
X IN RDB$FUNCTIONS
|
||||
WITH X.RDB$FUNCTION_NAME EQ name.identifier.c_str() AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
|
||||
{
|
||||
fb_assert(!function);
|
||||
function = mdc->getFunction(tdbb, X.RDB$FUNCTION_ID, flags);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
@ -5217,7 +5248,7 @@ Cached::Function* MetadataCache::lookupFunction(thread_db* tdbb, const Qualified
|
||||
|
||||
MetadataCache* mdc = tdbb->getDatabase()->dbb_mdc;
|
||||
|
||||
// See if we already know the relation by name
|
||||
// See if we already know the function by name
|
||||
auto* rc = mdc->mdc_functions.lookup(tdbb, [name](RoutinePermanent* func) { return func->name == name; });
|
||||
|
||||
if (rc || !(flags & CacheFlag::AUTOCREATE))
|
||||
@ -5353,6 +5384,10 @@ void MetadataCache::changeVersion(thread_db* tdbb, Changer cmd, ObjectType objTy
|
||||
changeVers(tdbb, cmd, mdc->mdc_charsets, id);
|
||||
break;
|
||||
|
||||
case obj_udf:
|
||||
changeVers(tdbb, cmd, mdc->mdc_functions, id);
|
||||
break;
|
||||
|
||||
/*
|
||||
case :
|
||||
changeVers(tdbb, cmd, mdc->, id);
|
||||
|
@ -288,7 +288,7 @@ public:
|
||||
void load_ddl_triggers(thread_db* tdbb, bool force = false);
|
||||
static jrd_prc* lookup_procedure(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags);
|
||||
static jrd_prc* lookup_procedure_id(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
static Function* lookup_function(thread_db* tdbb, const QualifiedName& name);
|
||||
static Function* lookup_function(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags);
|
||||
static Function* lookup_function(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
static Cached::Procedure* lookupProcedure(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags);
|
||||
static Cached::Procedure* lookupProcedure(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
|
Loading…
Reference in New Issue
Block a user