mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
WIP (saved before fbconf)
This commit is contained in:
parent
af683fc5b8
commit
c801683372
@ -2813,6 +2813,8 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
|
||||
METD_drop_procedure(transaction, QualifiedName(name, package));
|
||||
MetadataCache::dsql_cache_release(tdbb, SYM_procedure, name, package);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||
@ -4130,6 +4132,14 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
||||
|
||||
storePrivileges(tdbb, transaction, name, obj_collation, USAGE_PRIVILEGES);
|
||||
|
||||
auto* cs = MetadataCache::getCharSet(tdbb, forCharSetId, CacheFlag::AUTOCREATE | CacheFlag::NOCOMMIT);
|
||||
if (!cs)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
||||
Arg::Gds(isc_charset_not_found) << Arg::Num(forCharSetId));
|
||||
}
|
||||
cs->resetDependentObject(tdbb, ElementBase::ResetType::Recompile);
|
||||
|
||||
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
|
||||
DDL_TRIGGER_CREATE_COLLATION, name, NULL);
|
||||
|
||||
|
@ -4844,7 +4844,7 @@ DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
{
|
||||
Dependency dependency(obj_relation);
|
||||
dependency.relation = MetadataCache::lookupRelation(tdbb, relationName, CacheFlag::AUTOCREATE);
|
||||
dependency.subName = FB_NEW_POOL(pool) MetaName(fieldName);
|
||||
dependency.subName = fieldName;
|
||||
csb->addDependency(dependency);
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
// If field is not specified with NATIONAL, or CHARACTER SET
|
||||
// treat it as a single-byte-per-character field of character set NONE.
|
||||
assign_field_length(field, 1);
|
||||
field->textType = 0;
|
||||
field->textType = ttype_none;
|
||||
|
||||
if (collation_name.isEmpty())
|
||||
return;
|
||||
|
@ -240,7 +240,7 @@ public:
|
||||
USHORT charLength; // Length of field in characters
|
||||
Nullable<CSetId> charSetId;
|
||||
CollId collationId;
|
||||
SSHORT textType;
|
||||
TTypeId textType;
|
||||
bool fullDomain; // Domain name without TYPE OF prefix
|
||||
bool notNull; // NOT NULL was explicit specified
|
||||
MetaName fieldSource;
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
static Lock* makeLock(thread_db* tdbb, MemoryPool& p);
|
||||
bool scan(thread_db* tdbb, ObjectBase::Flag flags);
|
||||
|
||||
Collation* getCollation(TTypeId tt_id);
|
||||
Collation* getCollation(CollId id);
|
||||
Collation* getCollation(MetaName name);
|
||||
Cached::CharSet* getContainer() const
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace Jrd
|
||||
static int blockingAst(void* ast_object);
|
||||
|
||||
static Function* lookup(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
static Function* lookup(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags = 0);
|
||||
static Function* lookup(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags);
|
||||
|
||||
private:
|
||||
explicit Function(Cached::Function* perm)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "../jrd/Database.h"
|
||||
#include "../jrd/tra.h"
|
||||
#include "../jrd/met.h"
|
||||
#include "../jrd/tpc_proto.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
@ -64,6 +65,11 @@ TraNumber TransactionNumber::next(thread_db* tdbb)
|
||||
return tdbb->getDatabase()->dbb_next_transaction;
|
||||
}
|
||||
|
||||
bool TransactionNumber::isDead(thread_db* tdbb, TraNumber traNumber)
|
||||
{
|
||||
return TPC_cache_state(tdbb, traNumber) == tra_dead;
|
||||
}
|
||||
|
||||
|
||||
// class VersionSupport
|
||||
|
||||
|
@ -125,7 +125,7 @@ public:
|
||||
|
||||
// atomically replaces 'where' with 'newVal', using *this as old value for comparison
|
||||
// sets *this to actual data from 'where' if replace failed
|
||||
bool replace2(atomics::atomic<T*>& where, T* newVal)
|
||||
bool replace(atomics::atomic<T*>& where, T* newVal)
|
||||
{
|
||||
T* val = get<T>();
|
||||
bool rc = where.compare_exchange_strong(val, newVal,
|
||||
@ -452,6 +452,7 @@ namespace CacheFlag
|
||||
static const ObjectBase::Flag NOSCAN = 0x04;
|
||||
static const ObjectBase::Flag AUTOCREATE = 0x08;
|
||||
static const ObjectBase::Flag NOCOMMIT = 0x10;
|
||||
static const ObjectBase::Flag RET_ERASED = 0x20;
|
||||
|
||||
static const ObjectBase::Flag IGNORE_MASK = COMMITTED | ERASED;
|
||||
}
|
||||
@ -469,6 +470,16 @@ public:
|
||||
static MemoryPool& get(thread_db* tdbb);
|
||||
};
|
||||
|
||||
class TransactionNumber
|
||||
{
|
||||
public:
|
||||
static TraNumber current(thread_db* tdbb);
|
||||
static TraNumber oldestActive(thread_db* tdbb);
|
||||
static TraNumber next(thread_db* tdbb);
|
||||
static bool isDead(thread_db* tdbb, TraNumber traNumber);
|
||||
};
|
||||
|
||||
|
||||
class StartupBarrier
|
||||
{
|
||||
public:
|
||||
@ -562,7 +573,9 @@ class ListEntry : public HazardObject
|
||||
public:
|
||||
ListEntry(OBJ* obj, TraNumber currentTrans, ObjectBase::Flag fl)
|
||||
: object(obj), traNumber(currentTrans), cacheFlags(fl)
|
||||
{ }
|
||||
{
|
||||
//printf("%s %lld\n", object->c_name(), traNumber);
|
||||
}
|
||||
|
||||
~ListEntry()
|
||||
{
|
||||
@ -591,6 +604,10 @@ public:
|
||||
{
|
||||
ObjectBase::Flag f(listEntry->getFlags());
|
||||
|
||||
//printf("gO %s %02x %lld (%lld)\n", listEntry->object->c_name(), f, listEntry->traNumber, currentTrans);
|
||||
if ((!(f & CacheFlag::COMMITTED)) && (listEntry->traNumber != currentTrans))
|
||||
printf("Oblom\n");
|
||||
|
||||
if ((f & CacheFlag::COMMITTED) ||
|
||||
// committed (i.e. confirmed) objects are freely available
|
||||
(listEntry->traNumber == currentTrans))
|
||||
@ -609,6 +626,7 @@ public:
|
||||
|
||||
// required entry found in the list
|
||||
auto* obj = listEntry->object;
|
||||
//printf("found\n");
|
||||
if (obj)
|
||||
{
|
||||
listEntry->scan(
|
||||
@ -627,7 +645,7 @@ public:
|
||||
|
||||
bool isBusy(TraNumber currentTrans) const noexcept
|
||||
{
|
||||
return traNumber != currentTrans && !(getFlags() & CacheFlag::COMMITTED);
|
||||
return !((getFlags() & CacheFlag::COMMITTED) || (traNumber == currentTrans));
|
||||
}
|
||||
|
||||
ObjectBase::Flag getFlags() const noexcept
|
||||
@ -636,16 +654,26 @@ public:
|
||||
}
|
||||
|
||||
// add new entry to the list
|
||||
static bool add(atomics::atomic<ListEntry*>& list, ListEntry* newVal)
|
||||
static bool add(thread_db* tdbb, atomics::atomic<ListEntry*>& list, ListEntry* newVal)
|
||||
{
|
||||
HazardPtr<ListEntry> oldVal(list);
|
||||
|
||||
do
|
||||
{
|
||||
if (oldVal && oldVal->isBusy(newVal->traNumber)) // modified in other transaction
|
||||
return false;
|
||||
newVal->next.store(oldVal.getPointer(), atomics::memory_order_acquire);
|
||||
} while (! oldVal.replace2(list, newVal));
|
||||
while(oldVal && oldVal->isBusy(oldVal->traNumber))
|
||||
{
|
||||
// modified in transaction oldVal->traNumber
|
||||
if (TransactionNumber::isDead(tdbb, oldVal->traNumber))
|
||||
{
|
||||
rollback(tdbb, list, oldVal->traNumber);
|
||||
oldVal.set(list);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
newVal->next.store(oldVal.getPointer());
|
||||
} while (!oldVal.replace(list, newVal));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -672,7 +700,7 @@ public:
|
||||
break; // someone else also performs GC
|
||||
|
||||
// split remaining list off
|
||||
if (entry.replace2(list, nullptr))
|
||||
if (entry.replace(list, nullptr))
|
||||
{
|
||||
while (entry && !(entry->cacheFlags.fetch_or(CacheFlag::ERASED) & CacheFlag::ERASED))
|
||||
{
|
||||
@ -696,6 +724,7 @@ public:
|
||||
{
|
||||
fb_assert((getFlags() & CacheFlag::IGNORE_MASK) == 0);
|
||||
fb_assert(traNumber == currentTrans);
|
||||
printf("commit %s %lld=>%lld\n", object->c_name(), traNumber, nextTrans);
|
||||
traNumber = nextTrans;
|
||||
version = VersionSupport::next(tdbb);
|
||||
|
||||
@ -716,7 +745,7 @@ public:
|
||||
break;
|
||||
fb_assert(entry->traNumber == currentTran);
|
||||
|
||||
if (entry.replace2(list, entry->next))
|
||||
if (entry.replace(list, entry->next))
|
||||
{
|
||||
entry->retire();
|
||||
OBJ::destroy(tdbb, entry->object);
|
||||
@ -768,15 +797,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class TransactionNumber
|
||||
{
|
||||
public:
|
||||
static TraNumber current(thread_db* tdbb);
|
||||
static TraNumber oldestActive(thread_db* tdbb);
|
||||
static TraNumber next(thread_db* tdbb);
|
||||
};
|
||||
|
||||
|
||||
typedef class Lock* MakeLock(thread_db*, MemoryPool&);
|
||||
|
||||
template <class V, class P>
|
||||
@ -787,11 +807,11 @@ public:
|
||||
typedef P Permanent;
|
||||
|
||||
CacheElement(thread_db* tdbb, MemoryPool& p, MetaId id, MakeLock* makeLock) :
|
||||
Permanent(tdbb, p, id, makeLock), list(nullptr), resetAt(0), myId(id)
|
||||
Permanent(tdbb, p, id, makeLock), list(nullptr), resetAt(0)
|
||||
{ }
|
||||
|
||||
CacheElement(MemoryPool& p) :
|
||||
Permanent(p), list(nullptr), resetAt(0), myId(0)
|
||||
Permanent(p), list(nullptr), resetAt(0)
|
||||
{ }
|
||||
|
||||
static void cleanup(thread_db* tdbb, CacheElement* element)
|
||||
@ -896,7 +916,7 @@ public:
|
||||
|
||||
TraNumber cur = TransactionNumber::current(tdbb);
|
||||
ListEntry<Versioned>* newEntry = FB_NEW_POOL(*getDefaultMemoryPool()) ListEntry<Versioned>(obj, cur, fl);
|
||||
if (!ListEntry<Versioned>::add(list, newEntry))
|
||||
if (!ListEntry<Versioned>::add(tdbb, list, newEntry))
|
||||
{
|
||||
newEntry->cleanup(tdbb);
|
||||
delete newEntry;
|
||||
@ -1013,10 +1033,6 @@ private:
|
||||
private:
|
||||
atomics::atomic<ListEntry<Versioned>*> list;
|
||||
atomics::atomic<TraNumber> resetAt;
|
||||
|
||||
public:
|
||||
//atomics::atomic<ULONG> flags; // control non-versioned features (like foreign keys)
|
||||
const MetaId myId;
|
||||
};
|
||||
|
||||
|
||||
@ -1226,20 +1242,6 @@ public:
|
||||
m_objects.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
bool replace2(MetaId id, HazardPtr<Versioned>& oldVal, Versioned* const newVal)
|
||||
{
|
||||
if (id >= getCount())
|
||||
grow(id + 1);
|
||||
|
||||
auto a = m_objects.readAccessor();
|
||||
SubArrayData* sub = a->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire);
|
||||
fb_assert(sub);
|
||||
sub = &sub[id & SUBARRAY_MASK];
|
||||
|
||||
return oldVal.replace2(sub, newVal);
|
||||
}
|
||||
*/
|
||||
bool clear(MetaId id)
|
||||
{
|
||||
if (id >= getCount())
|
||||
@ -1253,32 +1255,7 @@ public:
|
||||
sub->store(nullptr, atomics::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
bool load(MetaId id, HazardPtr<Versioned>& val) const
|
||||
{
|
||||
auto a = m_objects.readAccessor();
|
||||
if (id < getCount(a))
|
||||
{
|
||||
SubArrayData* sub = a->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire);
|
||||
if (sub)
|
||||
{
|
||||
val.set(sub[id & SUBARRAY_MASK]);
|
||||
if (val && val->hasData())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HazardPtr<Versioned> load(MetaId id) const
|
||||
{
|
||||
HazardPtr<Versioned> val;
|
||||
if (!load(id, val))
|
||||
val.clear();
|
||||
return val;
|
||||
}
|
||||
*/
|
||||
HazardPtr<typename Storage::Generation> readAccessor() const
|
||||
{
|
||||
return m_objects.readAccessor();
|
||||
@ -1295,11 +1272,6 @@ public:
|
||||
return get();
|
||||
}
|
||||
|
||||
/* StoredElement& operator->()
|
||||
{
|
||||
return get();
|
||||
}
|
||||
*/
|
||||
Iterator& operator++()
|
||||
{
|
||||
index = locateData(index + 1);
|
||||
|
529
src/jrd/dfw.epp
529
src/jrd/dfw.epp
@ -678,6 +678,480 @@ struct deferred_task
|
||||
dfw_task_routine task_routine;
|
||||
};
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Self, typename T, int objType,
|
||||
T* (*lookupById)(thread_db*, MetaId, ObjectBase::Flag),
|
||||
T* (*lookupByName)(Jrd::thread_db*, const QualifiedName&, ObjectBase::Flag)
|
||||
>
|
||||
class RoutineManager
|
||||
{
|
||||
public:
|
||||
// Create a new routine.
|
||||
static bool createRoutine(thread_db* tdbb, SSHORT phase, DeferredWork* work,
|
||||
jrd_tra* transaction)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
return true;
|
||||
|
||||
case 5:
|
||||
{
|
||||
const bool compile = !work->findArg(dfw_arg_check_blr);
|
||||
getDependencies(work, compile, transaction);
|
||||
|
||||
T* routine = lookupByName(tdbb,
|
||||
QualifiedName(work->dfw_name, work->dfw_package), compile ? CacheFlag::NOSCAN : 0);
|
||||
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform required actions when modifying a routine.
|
||||
static bool modifyRoutine(thread_db* tdbb, SSHORT phase, DeferredWork* work,
|
||||
jrd_tra* transaction)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
const QualifiedName name(work->dfw_name, work->dfw_package);
|
||||
Routine* routine;
|
||||
|
||||
fprintf(stderr, "routine %d %s ph %d\n", work->dfw_id, name.c_str(), phase);
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case 0:
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::NOSCAN);
|
||||
if (routine && routine->getPermanent()->existenceLock)
|
||||
LCK_release(tdbb, routine->getPermanent()->existenceLock);
|
||||
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::NOSCAN);
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
if (routine->getPermanent()->existenceLock)
|
||||
{
|
||||
// Let routine be deleted if only this transaction is using it
|
||||
|
||||
//if (!routine->getPermanent()->existenceLock->exclLock(tdbb))
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!! raiseRoutineInUseError(routine, name);
|
||||
}
|
||||
|
||||
// If we are in a multi-client server, someone else may have marked
|
||||
// routine obsolete. Unmark and we will remark it later.
|
||||
|
||||
//routine->flags &= ~Routine::FLAG_OBSOLETE;
|
||||
return true;
|
||||
|
||||
case 4:
|
||||
{
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::NOSCAN);
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
if (routine->getStatement())
|
||||
{
|
||||
//if (routine->getStatement()->isActive())
|
||||
// raiseRoutineInUseError(routine, name);
|
||||
|
||||
// release the request
|
||||
|
||||
routine->releaseStatement(tdbb);
|
||||
}
|
||||
|
||||
// delete dependency lists
|
||||
|
||||
if (work->dfw_package.isEmpty())
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, objType, transaction);
|
||||
|
||||
/* the routine has just been scanned by lookupById
|
||||
and its Routine::FLAG_SCANNED flag is set. We are going to reread it
|
||||
from file (create all new dependencies) and do not want this
|
||||
flag to be set. That is why we do not add Routine::FLAG_OBSOLETE and
|
||||
Routine::FLAG_BEING_ALTERED flags, we set only these two flags
|
||||
*/
|
||||
// routine->flags = (Routine::FLAG_OBSOLETE | Routine::FLAG_BEING_ALTERED);
|
||||
|
||||
if (routine->getPermanent()->existenceLock)
|
||||
LCK_release(tdbb, routine->getPermanent()->existenceLock);
|
||||
|
||||
// Now handle the new definition
|
||||
bool compile = !work->findArg(dfw_arg_check_blr);
|
||||
getDependencies(work, compile, transaction);
|
||||
|
||||
// routine->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_BEING_ALTERED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case 5:
|
||||
if (work->findArg(dfw_arg_check_blr))
|
||||
{
|
||||
SSHORT validBlr = FALSE;
|
||||
|
||||
Jrd::Database* dbb = tdbb->getDatabase();
|
||||
MemoryPool* newPool = dbb->createPool();
|
||||
try
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, newPool);
|
||||
|
||||
// compile the routine to know if the BLR is still valid
|
||||
if (lookupById(tdbb, work->dfw_id, CacheFlag::AUTOCREATE))
|
||||
validBlr = TRUE;
|
||||
}
|
||||
catch (const Firebird::Exception&)
|
||||
{
|
||||
fb_utils::init_status(tdbb->tdbb_status_vector);
|
||||
}
|
||||
|
||||
dbb->deletePool(newPool);
|
||||
|
||||
Self::validate(tdbb, transaction, work, validBlr);
|
||||
}
|
||||
return true;
|
||||
|
||||
case 6:
|
||||
Self::checkOutParamDependencies(tdbb, work, transaction);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it is allowed to delete a routine, and if so, clean up after it.
|
||||
static bool deleteRoutine(thread_db* tdbb, SSHORT phase, DeferredWork* work,
|
||||
jrd_tra* transaction)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
const QualifiedName name(work->dfw_name, work->dfw_package);
|
||||
T* routine;
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case 0:
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::NOSCAN);
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
if (routine->getPermanent()->existenceLock)
|
||||
LCK_release(tdbb, routine->getPermanent()->existenceLock);
|
||||
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
check_dependencies(tdbb, work->dfw_name.c_str(), NULL, work->dfw_package.c_str(),
|
||||
objType, transaction);
|
||||
return true;
|
||||
|
||||
case 2:
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::NOSCAN);
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
return true;
|
||||
|
||||
case 4:
|
||||
{
|
||||
routine = lookupById(tdbb, work->dfw_id, CacheFlag::RET_ERASED | CacheFlag::NOSCAN);
|
||||
if (!routine)
|
||||
return false;
|
||||
|
||||
if (routine->getStatement())
|
||||
{
|
||||
routine->releaseStatement(tdbb);
|
||||
}
|
||||
|
||||
// delete dependency lists
|
||||
|
||||
if (work->dfw_package.isEmpty())
|
||||
MET_delete_dependencies(tdbb, work->dfw_name, objType, transaction);
|
||||
|
||||
//if (routine->getPermanent()->existenceLock)
|
||||
// routine->getPermanent()->existenceLock->releaseLock(tdbb, ExistenceLock::ReleaseMethod::DropObject);
|
||||
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Get relations and fields on which this routine depends, either when it's being
|
||||
// created or when it's modified.
|
||||
static void getDependencies(DeferredWork* work, bool compile, jrd_tra* transaction)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
Jrd::Database* dbb = tdbb->getDatabase();
|
||||
|
||||
if (compile)
|
||||
compile = !tdbb->getAttachment()->isGbak();
|
||||
|
||||
bid blobId;
|
||||
blobId.clear();
|
||||
Routine* routine = Self::lookupBlobId(tdbb, work, blobId, compile);
|
||||
|
||||
MetadataCache::verify_cache(tdbb);
|
||||
|
||||
// get any dependencies now by parsing the blr
|
||||
|
||||
if (!routine)
|
||||
return;
|
||||
|
||||
const MetaName depName(work->dfw_package.isEmpty() ?
|
||||
MetaName(work->dfw_name) : work->dfw_package);
|
||||
|
||||
if (!blobId.isEmpty())
|
||||
{
|
||||
Statement* statement = NULL;
|
||||
// Nickolay Samofatov: allocate statement memory pool...
|
||||
MemoryPool* new_pool = dbb->createPool();
|
||||
// block is used to ensure verify_cache()
|
||||
// works in not deleted context
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &blobId,
|
||||
(compile ? &statement : NULL),
|
||||
NULL, depName,
|
||||
(work->dfw_package.isEmpty() ? objType : obj_package_body),
|
||||
0, transaction);
|
||||
|
||||
if (statement)
|
||||
statement->release(tdbb);
|
||||
else
|
||||
dbb->deletePool(new_pool);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array<Dependency> dependencies;
|
||||
|
||||
const auto allParameters = {&routine->getInputFields(), &routine->getOutputFields()};
|
||||
|
||||
for (const auto parameters : allParameters)
|
||||
{
|
||||
for (const auto parameter : *parameters)
|
||||
{
|
||||
if (parameter->prm_type_of_table.hasData())
|
||||
{
|
||||
Dependency dependency(obj_relation);
|
||||
dependency.relation = MetadataCache::lookupRelation(tdbb,
|
||||
parameter->prm_type_of_table, CacheFlag::AUTOCREATE);
|
||||
dependency.subName = parameter->prm_type_of_column;
|
||||
dependencies.push(dependency);
|
||||
}
|
||||
else if (!fb_utils::implicit_domain(parameter->prm_field_source.c_str()))
|
||||
{
|
||||
Dependency dependency(obj_field);
|
||||
dependency.name = parameter->prm_field_source;
|
||||
dependencies.push(dependency);
|
||||
}
|
||||
|
||||
if (parameter->prm_text_type.isAssigned())
|
||||
{
|
||||
Dependency dependency(obj_collation);
|
||||
dependency.number = parameter->prm_text_type.value;
|
||||
dependencies.push(dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MET_store_dependencies(tdbb, dependencies, nullptr, depName,
|
||||
(work->dfw_package.isEmpty() ? objType : obj_package_header),
|
||||
transaction);
|
||||
}
|
||||
|
||||
MetadataCache::verify_cache(tdbb);
|
||||
}
|
||||
};
|
||||
|
||||
class FunctionManager : public RoutineManager<FunctionManager, Function, obj_udf,
|
||||
Function::lookup, Function::lookup>
|
||||
{
|
||||
public:
|
||||
static const char* const getTypeStr()
|
||||
{
|
||||
return "function";
|
||||
}
|
||||
|
||||
static Routine* lookupBlobId(thread_db* tdbb, DeferredWork* work, bid& blobId, bool compile);
|
||||
static void validate(thread_db* tdbb, jrd_tra* transaction, DeferredWork* work,
|
||||
SSHORT validBlr);
|
||||
static void checkOutParamDependencies(thread_db* tdbb, DeferredWork* work, jrd_tra* transaction);
|
||||
};
|
||||
|
||||
class ProcedureManager : public RoutineManager<ProcedureManager, jrd_prc, obj_procedure,
|
||||
MetadataCache::lookup_procedure_id, MetadataCache::lookup_procedure>
|
||||
{
|
||||
public:
|
||||
static const char* const getTypeStr()
|
||||
{
|
||||
return "procedure";
|
||||
}
|
||||
|
||||
static Routine* lookupBlobId(thread_db* tdbb, DeferredWork* work, bid& blobId, bool compile);
|
||||
static void validate(thread_db* tdbb, jrd_tra* transaction, DeferredWork* work,
|
||||
SSHORT validBlr);
|
||||
static void checkOutParamDependencies(thread_db* tdbb, DeferredWork* work, jrd_tra* transaction);
|
||||
};
|
||||
|
||||
// These methods cannot be defined inline, because GPRE generates wrong code.
|
||||
|
||||
Routine* FunctionManager::lookupBlobId(thread_db* tdbb, DeferredWork* work, bid& blobId,
|
||||
bool compile)
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest handle(tdbb, irq_c_fun_dpd, IRQ_REQUESTS);
|
||||
Routine* routine = nullptr;
|
||||
|
||||
FOR(REQUEST_HANDLE handle)
|
||||
X IN RDB$FUNCTIONS WITH
|
||||
X.RDB$FUNCTION_NAME EQ work->dfw_name.c_str() AND
|
||||
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);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return routine;
|
||||
}
|
||||
|
||||
void FunctionManager::validate(thread_db* tdbb, jrd_tra* transaction, DeferredWork* work,
|
||||
SSHORT validBlr)
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest request(tdbb, irq_fun_validate, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
FUN IN RDB$FUNCTIONS
|
||||
WITH FUN.RDB$FUNCTION_ID EQ work->dfw_id AND
|
||||
FUN.RDB$FUNCTION_BLR NOT MISSING
|
||||
{
|
||||
MODIFY FUN USING
|
||||
FUN.RDB$VALID_BLR = validBlr;
|
||||
FUN.RDB$VALID_BLR.NULL = FALSE;
|
||||
END_MODIFY
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
|
||||
void FunctionManager::checkOutParamDependencies(thread_db* tdbb, DeferredWork* work, jrd_tra* transaction)
|
||||
{
|
||||
// Do nothing, as function output is unnamed.
|
||||
}
|
||||
|
||||
Routine* ProcedureManager::lookupBlobId(thread_db* tdbb, DeferredWork* work, bid& blobId,
|
||||
bool compile)
|
||||
{
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest handle(tdbb, irq_c_prc_dpd, IRQ_REQUESTS);
|
||||
Routine* routine = nullptr;
|
||||
|
||||
FOR(REQUEST_HANDLE handle)
|
||||
X IN RDB$PROCEDURES WITH
|
||||
X.RDB$PROCEDURE_NAME EQ work->dfw_name.c_str() AND
|
||||
X.RDB$PACKAGE_NAME EQUIV NULLIF(work->dfw_package.c_str(), '')
|
||||
{
|
||||
blobId = X.RDB$PROCEDURE_BLR;
|
||||
routine = MetadataCache::lookup_procedure(tdbb,
|
||||
QualifiedName(work->dfw_name, work->dfw_package), !compile);
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return routine;
|
||||
}
|
||||
|
||||
void ProcedureManager::validate(thread_db* tdbb, jrd_tra* transaction, DeferredWork* work,
|
||||
SSHORT validBlr)
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest request(tdbb, irq_prc_validate, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
PRC IN RDB$PROCEDURES
|
||||
WITH PRC.RDB$PROCEDURE_ID EQ work->dfw_id AND
|
||||
PRC.RDB$PROCEDURE_BLR NOT MISSING
|
||||
{
|
||||
MODIFY PRC USING
|
||||
PRC.RDB$VALID_BLR = validBlr;
|
||||
PRC.RDB$VALID_BLR.NULL = FALSE;
|
||||
END_MODIFY
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
|
||||
void ProcedureManager::checkOutParamDependencies(thread_db* tdbb, DeferredWork* work, jrd_tra* transaction)
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest handle(tdbb, irq_out_proc_param_dep, IRQ_REQUESTS);
|
||||
ObjectsArray<string> names;
|
||||
int depCount = 0;
|
||||
|
||||
FOR (REQUEST_HANDLE handle)
|
||||
DEP IN RDB$DEPENDENCIES
|
||||
WITH DEP.RDB$DEPENDED_ON_NAME EQ work->dfw_name.c_str() AND
|
||||
DEP.RDB$PACKAGE_NAME EQUIV NULLIF(work->dfw_package.c_str(), '') AND
|
||||
DEP.RDB$DEPENDED_ON_TYPE = obj_procedure AND
|
||||
NOT DEP.RDB$FIELD_NAME MISSING AND
|
||||
NOT ANY PP IN RDB$PROCEDURE_PARAMETERS
|
||||
WITH PP.RDB$PROCEDURE_NAME EQ DEP.RDB$DEPENDED_ON_NAME AND
|
||||
PP.RDB$PACKAGE_NAME EQUIV DEP.RDB$PACKAGE_NAME AND
|
||||
PP.RDB$PARAMETER_NAME EQ DEP.RDB$FIELD_NAME AND
|
||||
PP.RDB$PARAMETER_TYPE EQ 1
|
||||
{
|
||||
// If the found object is also being deleted, there's no dependency
|
||||
|
||||
if (!find_depend_in_dfw(tdbb, DEP.RDB$DEPENDENT_NAME, DEP.RDB$DEPENDENT_TYPE, 0, transaction))
|
||||
{
|
||||
string& name = names.add();
|
||||
name.printf("%s.%s", work->dfw_name.c_str(), DEP.RDB$FIELD_NAME);
|
||||
|
||||
++depCount;
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
|
||||
if (names.hasData())
|
||||
{
|
||||
Arg::StatusVector status;
|
||||
status << Arg::Gds(isc_no_meta_update) << Arg::Gds(isc_no_delete);
|
||||
|
||||
for (auto& name : names)
|
||||
status << Arg::Gds(isc_parameter_name) << Arg::Str(name);
|
||||
|
||||
status << Arg::Gds(isc_dependency) << Arg::Num(depCount);
|
||||
|
||||
ERR_post(status);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
static const deferred_task task_table[] =
|
||||
{
|
||||
/*
|
||||
@ -709,6 +1183,7 @@ static const deferred_task task_table[] =
|
||||
{ dfw_drop_package_header, drop_package_header }, // packages should be before procedures
|
||||
{ dfw_modify_package_header, modify_package_header }, // packages should be before procedures
|
||||
{ dfw_drop_package_body, drop_package_body }, // packages should be before procedures
|
||||
*/
|
||||
{ dfw_create_procedure, ProcedureManager::createRoutine },
|
||||
{ dfw_create_function, FunctionManager::createRoutine },
|
||||
{ dfw_delete_procedure, ProcedureManager::deleteRoutine },
|
||||
@ -716,7 +1191,7 @@ 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 },
|
||||
/*
|
||||
@ -2223,18 +2698,7 @@ static bool create_collation(thread_db* tdbb, SSHORT phase, DeferredWork* work,
|
||||
return true;
|
||||
|
||||
case 2:
|
||||
return true;
|
||||
|
||||
case 3:
|
||||
{
|
||||
auto* cs = MetadataCache::getCharSet(tdbb, TTypeId(work->dfw_id), CacheFlag::NOCOMMIT);
|
||||
if (!cs)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_no_meta_update) <<
|
||||
Arg::Gds(isc_charset_not_found) << Arg::Num(CSetId(TTypeId(work->dfw_id))));
|
||||
}
|
||||
cs->resetDependentObject(tdbb, ElementBase::ResetType::Recompile);
|
||||
}
|
||||
return true;
|
||||
|
||||
case 4:
|
||||
@ -2296,3 +2760,44 @@ static bool delete_collation(thread_db* tdbb, SSHORT phase, DeferredWork* work,
|
||||
}
|
||||
|
||||
|
||||
static bool delete_parameter(thread_db* tdbb, SSHORT phase, DeferredWork*, jrd_tra*)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* d e l e t e _ p a r a m e t e r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Return an error if someone attempts to
|
||||
* delete a field from a procedure and it is
|
||||
* used by a view or procedure.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case 1:
|
||||
/* hvlad: temporary disable procedure parameters dependency check
|
||||
until proper solution (something like dyn_mod_parameter)
|
||||
will be implemented. This check never worked properly
|
||||
so no harm is done
|
||||
|
||||
if (MetadataCache::lookup_procedure_id(tdbb, work->dfw_id, CacheFlag::NOSCAN))
|
||||
{
|
||||
const DeferredWork* arg = work->dfw_args;
|
||||
fb_assert(arg && (arg->dfw_type == dfw_arg_proc_name));
|
||||
|
||||
check_dependencies(tdbb, arg->dfw_name.c_str(), work->dfw_name.c_str(),
|
||||
obj_procedure, transaction);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -409,11 +409,11 @@ struct Dependency
|
||||
Cached::Relation* relation;
|
||||
Cached::Function* function;
|
||||
Cached::Procedure* procedure;
|
||||
MetaName* name;
|
||||
MetaName name;
|
||||
SLONG number;
|
||||
};
|
||||
|
||||
const MetaName* subName;
|
||||
MetaName subName;
|
||||
SLONG subNumber;
|
||||
};
|
||||
|
||||
|
@ -223,6 +223,8 @@ CharSetContainer::CharSetContainer(thread_db* tdbb, MemoryPool& p, MetaId id, Ma
|
||||
cs(NULL),
|
||||
cs_lock(nullptr)
|
||||
{
|
||||
printf("CharSetContainer::CharSetContainer(..., %04x)\n", id);
|
||||
|
||||
SubtypeInfo info;
|
||||
CSetId cs_id(id);
|
||||
|
||||
@ -265,11 +267,10 @@ CsConvert CharSetContainer::lookupConverter(thread_db* tdbb, CSetId toCsId)
|
||||
return CsConvert(cs->getStruct(), toCs->getStruct());
|
||||
}
|
||||
|
||||
Collation* CharSetVers::getCollation(TTypeId tt_id)
|
||||
Collation* CharSetVers::getCollation(CollId id)
|
||||
{
|
||||
const auto id = CollId(tt_id);
|
||||
if (!charset_collations[id])
|
||||
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(tt_id));
|
||||
if (USHORT(id) >= charset_collations.getCount() || !charset_collations[id])
|
||||
return nullptr;
|
||||
|
||||
return charset_collations[id];
|
||||
}
|
||||
@ -879,7 +880,14 @@ Collation* INTL_texttype_lookup(thread_db* tdbb, TTypeId parm1)
|
||||
|
||||
auto* vers = MetadataCache::lookup_charset(tdbb, parm1, CacheFlag::AUTOCREATE);
|
||||
|
||||
return vers ? vers->getCollation(parm1) : nullptr;
|
||||
if (vers)
|
||||
{
|
||||
auto* coll = vers->getCollation(parm1);
|
||||
if (coll)
|
||||
return coll;
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(parm1));
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct IdStorage
|
||||
struct TTypeId : public IdStorage
|
||||
{
|
||||
TTypeId() : IdStorage(0) { }
|
||||
explicit TTypeId(USHORT id) : IdStorage(id & 0xFF) { }
|
||||
explicit TTypeId(USHORT id) : IdStorage(id) { }
|
||||
constexpr TTypeId(CSetId id);
|
||||
TTypeId(CSetId cs, CollId col);
|
||||
};
|
||||
|
@ -295,9 +295,11 @@ void MetadataCache::update_partners(thread_db* tdbb)
|
||||
}
|
||||
|
||||
|
||||
#ifdef NEVERDEF //DEV_BUILD
|
||||
void MetadataCache::verify_cache(thread_db* tdbb)
|
||||
{
|
||||
#ifndef NEVERDEF //DEV_BUILD
|
||||
}
|
||||
#else // NEVERDEF
|
||||
/**************************************
|
||||
*
|
||||
* M E T _ v e r i f y _ c a c h e
|
||||
@ -467,7 +469,7 @@ void MetadataCache::verify_cache(thread_db* tdbb)
|
||||
routine->intUseCount = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // NEVERDEF
|
||||
|
||||
|
||||
// Done before MDC is deleted
|
||||
@ -4592,7 +4594,7 @@ void MET_store_dependencies(thread_db* tdbb,
|
||||
Dependency dependency = dependencies.pop();
|
||||
|
||||
if (!dependency.relation && !dependency.function && !dependency.procedure &&
|
||||
!dependency.name && !dependency.number)
|
||||
!dependency.name.hasData() && !dependency.number)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -4662,7 +4664,7 @@ void MET_store_dependencies(thread_db* tdbb,
|
||||
break;
|
||||
|
||||
case obj_field:
|
||||
dpdo_name = *(dependency.name);
|
||||
dpdo_name = dependency.name;
|
||||
break;
|
||||
|
||||
case obj_generator:
|
||||
@ -4686,14 +4688,14 @@ void MET_store_dependencies(thread_db* tdbb,
|
||||
break;
|
||||
|
||||
case obj_index:
|
||||
name = *dependency.name;
|
||||
name = dependency.name;
|
||||
dpdo_name = name;
|
||||
break;
|
||||
}
|
||||
|
||||
MetaName field_name;
|
||||
|
||||
if (dependency.subNumber || dependency.subName)
|
||||
if (dependency.subNumber || dependency.subName.hasData())
|
||||
{
|
||||
if (dependency.subNumber)
|
||||
{
|
||||
@ -4715,7 +4717,7 @@ void MET_store_dependencies(thread_db* tdbb,
|
||||
}
|
||||
}
|
||||
else
|
||||
field_name = *dependency.subName;
|
||||
field_name = dependency.subName;
|
||||
}
|
||||
|
||||
if (field_name.hasData())
|
||||
|
@ -292,7 +292,7 @@ public:
|
||||
static Function* lookup_function(thread_db* tdbb, const QualifiedName& name);
|
||||
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 = 0);
|
||||
static Cached::Procedure* lookupProcedure(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
static Cached::Function* lookupFunction(thread_db* tdbb, const QualifiedName& name, ObjectBase::Flag flags);
|
||||
//static Cached::Function* lookupFunction(thread_db* tdbb, MetaId id, ObjectBase::Flag flags);
|
||||
static jrd_rel* lookup_relation(thread_db*, const MetaName&);
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "../dsql/BoolNodes.h"
|
||||
#include "../dsql/ExprNodes.h"
|
||||
#include "../dsql/StmtNodes.h"
|
||||
#include "../jrd/intl_proto.h"
|
||||
|
||||
|
||||
using namespace Jrd;
|
||||
@ -163,6 +164,27 @@ namespace
|
||||
AutoPtr<CompilerScratch> m_csb;
|
||||
CompilerScratch** const m_csbPtr;
|
||||
};
|
||||
|
||||
class VldTTypeId : public TTypeId
|
||||
{
|
||||
public:
|
||||
VldTTypeId(thread_db* tdbb, USHORT a_id) : TTypeId(a_id)
|
||||
{
|
||||
TTypeId parm1(a_id);
|
||||
if (parm1 == ttype_dynamic)
|
||||
parm1 = tdbb->getCharSet();
|
||||
|
||||
auto* vers = MetadataCache::lookup_charset(tdbb, parm1, CacheFlag::AUTOCREATE);
|
||||
if (vers)
|
||||
{
|
||||
CollId coll(parm1);
|
||||
if (USHORT(coll) == 0 || vers->getCollation(coll))
|
||||
return;
|
||||
}
|
||||
|
||||
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(parm1));
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -251,7 +273,7 @@ BoolExprNode* PAR_validation_blr(thread_db* tdbb, Cached::Relation* relation, co
|
||||
|
||||
|
||||
// Parse a BLR datatype. Return the alignment requirements of the datatype.
|
||||
USHORT PAR_datatype(BlrReader& blrReader, dsc* desc)
|
||||
USHORT PAR_datatype(thread_db* tdbb, BlrReader& blrReader, dsc* desc)
|
||||
{
|
||||
desc->clear();
|
||||
|
||||
@ -278,18 +300,18 @@ USHORT PAR_datatype(BlrReader& blrReader, dsc* desc)
|
||||
break;
|
||||
|
||||
case blr_text2:
|
||||
textType = TTypeId(blrReader.getWord());
|
||||
textType = VldTTypeId(tdbb, blrReader.getWord());
|
||||
desc->makeText(blrReader.getWord(), textType);
|
||||
break;
|
||||
|
||||
case blr_cstring2:
|
||||
desc->dsc_dtype = dtype_cstring;
|
||||
desc->setTextType(TTypeId(blrReader.getWord()));
|
||||
desc->setTextType(VldTTypeId(tdbb, blrReader.getWord()));
|
||||
desc->dsc_length = blrReader.getWord();
|
||||
break;
|
||||
|
||||
case blr_varying2:
|
||||
textType = TTypeId(blrReader.getWord());
|
||||
textType = VldTTypeId(tdbb, blrReader.getWord());
|
||||
desc->makeVarying(blrReader.getWord(), textType);
|
||||
break;
|
||||
|
||||
@ -383,7 +405,7 @@ USHORT PAR_datatype(BlrReader& blrReader, dsc* desc)
|
||||
desc->dsc_dtype = dtype_blob;
|
||||
desc->dsc_length = sizeof(ISC_QUAD);
|
||||
desc->dsc_sub_type = blrReader.getWord();
|
||||
textType = TTypeId(blrReader.getWord());
|
||||
textType = VldTTypeId(tdbb, blrReader.getWord());
|
||||
desc->dsc_scale = textType & 0xFF; // BLOB character set
|
||||
desc->dsc_flags = textType & 0xFF00; // BLOB collation
|
||||
break;
|
||||
@ -426,14 +448,14 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
case blr_domain_name2:
|
||||
{
|
||||
const bool fullDomain = (csb->csb_blr_reader.getByte() == blr_domain_full);
|
||||
MetaName* name = FB_NEW_POOL(csb->csb_pool) MetaName(csb->csb_pool);
|
||||
csb->csb_blr_reader.getMetaName(*name);
|
||||
MetaName name;
|
||||
csb->csb_blr_reader.getMetaName(name);
|
||||
|
||||
MetaNamePair namePair(*name, "");
|
||||
MetaNamePair namePair(name, "");
|
||||
|
||||
FieldInfo fieldInfo;
|
||||
bool exist = csb->csb_map_field_info.get(namePair, fieldInfo);
|
||||
MET_get_domain(tdbb, csb->csb_pool, *name, desc, (exist ? NULL : &fieldInfo));
|
||||
MET_get_domain(tdbb, csb->csb_pool, name, desc, (exist ? NULL : &fieldInfo));
|
||||
|
||||
if (!exist)
|
||||
csb->csb_map_field_info.put(namePair, fieldInfo);
|
||||
@ -453,7 +475,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
|
||||
if (dtype == blr_domain_name2)
|
||||
{
|
||||
const auto ttype = TTypeId(csb->csb_blr_reader.getWord());
|
||||
const auto ttype = VldTTypeId(tdbb, csb->csb_blr_reader.getWord());
|
||||
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
@ -486,14 +508,14 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
const bool fullDomain = (csb->csb_blr_reader.getByte() == blr_domain_full);
|
||||
MetaName* relationName = FB_NEW_POOL(csb->csb_pool) MetaName(csb->csb_pool);
|
||||
csb->csb_blr_reader.getMetaName(*relationName);
|
||||
MetaName* fieldName = FB_NEW_POOL(csb->csb_pool) MetaName(csb->csb_pool);
|
||||
csb->csb_blr_reader.getMetaName(*fieldName);
|
||||
MetaName fieldName;
|
||||
csb->csb_blr_reader.getMetaName(fieldName);
|
||||
|
||||
MetaNamePair namePair(*relationName, *fieldName);
|
||||
MetaNamePair namePair(*relationName, fieldName);
|
||||
|
||||
FieldInfo fieldInfo;
|
||||
bool exist = csb->csb_map_field_info.get(namePair, fieldInfo);
|
||||
MET_get_relation_field(tdbb, csb->csb_pool, *relationName, *fieldName, desc,
|
||||
MET_get_relation_field(tdbb, csb->csb_pool, *relationName, fieldName, desc,
|
||||
(exist ? NULL : &fieldInfo));
|
||||
|
||||
if (!exist)
|
||||
@ -514,7 +536,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
|
||||
if (dtype == blr_column_name2)
|
||||
{
|
||||
const auto ttype = TTypeId(csb->csb_blr_reader.getWord());
|
||||
const auto ttype = VldTTypeId(tdbb, csb->csb_blr_reader.getWord());
|
||||
|
||||
switch (desc->dsc_dtype)
|
||||
{
|
||||
@ -547,7 +569,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
|
||||
default:
|
||||
csb->csb_blr_reader.seekBackward(1);
|
||||
PAR_datatype(csb->csb_blr_reader, desc);
|
||||
PAR_datatype(tdbb, csb->csb_blr_reader, desc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -906,7 +928,7 @@ void PAR_dependency(thread_db* tdbb, CompilerScratch* csb, StreamType stream, SS
|
||||
}
|
||||
|
||||
if (field_name.length() > 0)
|
||||
dependency.subName = FB_NEW_POOL(*tdbb->getDefaultPool()) MetaName(*tdbb->getDefaultPool(), field_name);
|
||||
dependency.subName = field_name;
|
||||
else if (id >= 0)
|
||||
dependency.subNumber = id;
|
||||
|
||||
@ -1076,7 +1098,7 @@ static PlanNode* par_plan(thread_db* tdbb, CompilerScratch* csb)
|
||||
if (csb->collectingDependencies())
|
||||
{
|
||||
Dependency dependency(obj_index);
|
||||
dependency.name = &item.indexName;
|
||||
dependency.name = item.indexName;
|
||||
csb->addDependency(dependency);
|
||||
}
|
||||
|
||||
@ -1146,7 +1168,7 @@ static PlanNode* par_plan(thread_db* tdbb, CompilerScratch* csb)
|
||||
if (csb->collectingDependencies())
|
||||
{
|
||||
Dependency dependency(obj_index);
|
||||
dependency.name = &item.indexName;
|
||||
dependency.name = item.indexName;
|
||||
csb->addDependency(dependency);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ Jrd::BoolExprNode* PAR_validation_blr(Jrd::thread_db*, Jrd::Cached::Relation*, c
|
||||
StreamType PAR_context(Jrd::CompilerScratch*, SSHORT*);
|
||||
void PAR_dependency(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, StreamType stream,
|
||||
SSHORT id, const Jrd::MetaName& field_name);
|
||||
USHORT PAR_datatype(Firebird::BlrReader&, dsc*);
|
||||
USHORT PAR_datatype(Jrd::thread_db*, Firebird::BlrReader&, dsc*);
|
||||
USHORT PAR_desc(Jrd::thread_db*, Jrd::CompilerScratch*, dsc*, Jrd::ItemInfo* = NULL);
|
||||
void PAR_error(Jrd::CompilerScratch*, const Firebird::Arg::StatusVector&, bool isSyntaxError = true);
|
||||
SSHORT PAR_find_proc_field(const Jrd::jrd_prc*, const Jrd::MetaName&);
|
||||
|
Loading…
Reference in New Issue
Block a user