Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/dsql/ExprNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6470,7 +6470,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec

// Use context to check conflicts beween <relation>.<field> and <package>.<constant>
dsql_ctx packageContext(dsqlScratch->getPool());
{ // Consatnts
{ // Constants

QualifiedName constantName(dsqlName,
dsqlQualifier.schema.hasData() ? dsqlQualifier.schema : dsqlScratch->package.schema,
Expand All @@ -6480,15 +6480,18 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
{
dsqlScratch->qualifyExistingName(constantName, obj_package_constant);

if (PackageReferenceNode::constantExists(tdbb, dsqlScratch->getTransaction(), constantName))
dsc constantDsc{};
auto transaction = dsqlScratch->getTransaction();
if (PackageReferenceNode::constantExists(tdbb, transaction, constantName, &constantDsc))
{
// Alias is a package name, not a constant
packageContext.ctx_alias.push(QualifiedName(constantName.package, constantName.schema));
packageContext.ctx_flags |= CTX_package;
ambiguousCtxStack.push(&packageContext);

MemoryPool& pool = dsqlScratch->getPool();
node = FB_NEW_POOL(pool) PackageReferenceNode(pool, constantName, blr_pkg_reference_to_constant);
node = FB_NEW_POOL(pool) PackageReferenceNode(pool,
constantName, blr_pkg_reference_to_constant, &constantDsc);
}
}
}
Expand Down Expand Up @@ -14243,11 +14246,12 @@ ValueExprNode* VariableNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
thread_db* tdbb = JRD_get_thread_data();
QualifiedName constantFullName(dsqlName, dsqlScratch->package.schema, dsqlScratch->package.object);
if (PackageReferenceNode::constantExists(tdbb, dsqlScratch->getTransaction(), constantFullName))
dsc constantDsc{};
if (PackageReferenceNode::constantExists(tdbb, dsqlScratch->getTransaction(), constantFullName, &constantDsc))
{
delete node;
return FB_NEW_POOL(dsqlScratch->getPool()) PackageReferenceNode(dsqlScratch->getPool(),
constantFullName, blr_pkg_reference_to_constant);
constantFullName, blr_pkg_reference_to_constant, &constantDsc);
}
}

Expand Down
35 changes: 22 additions & 13 deletions src/dsql/PackageNodes.epp
Original file line number Diff line number Diff line change
Expand Up @@ -370,10 +370,14 @@ void PackageItemsHolder::clear()

static RegisterNode<PackageReferenceNode> regPackageReferenceNode({blr_package_reference});

PackageReferenceNode::PackageReferenceNode(MemoryPool& pool, const QualifiedName& fullName, const UCHAR itemType)
PackageReferenceNode::PackageReferenceNode(MemoryPool& pool, const QualifiedName& fullName, const UCHAR itemType,
const dsc* type)
: TypedNode<ValueExprNode, ExprNode::TYPE_PACKAGE_REFERENCE>(pool),
m_fullName(fullName), m_itemType(itemType)
{}
{
if (type)
m_cachedDsc = *type;
}

string PackageReferenceNode::internalPrint(NodePrinter& printer) const
{
Expand All @@ -392,7 +396,7 @@ ValueExprNode* PackageReferenceNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
thread_db* tdbb = JRD_get_thread_data();

bool isPrivate = false;
if (constantExists(tdbb, transaction, m_fullName, &isPrivate))
if (constantExists(tdbb, transaction, m_fullName, &m_cachedDsc, &isPrivate))
{
// External objects do not have access to private constants
if (isPrivate)
Expand All @@ -407,8 +411,7 @@ ValueExprNode* PackageReferenceNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
Arg::Str(m_fullName.toQuotedString()));
}

auto* node = FB_NEW_POOL(pool) PackageReferenceNode(pool, m_fullName, m_itemType);
return node;
return FB_NEW_POOL(pool) PackageReferenceNode(pool, m_fullName, m_itemType, &m_cachedDsc);
}

DmlNode* PackageReferenceNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR)
Expand All @@ -434,20 +437,23 @@ DmlNode* PackageReferenceNode::parse(thread_db* tdbb, MemoryPool& pool, Compiler
csb->addDependency(dependency);
}

ConstantValue* constant = nullptr;
{ // Package cache
auto package = MetadataCache::getVersioned<Cached::Package>(tdbb, fullName.getSchemaAndPackage(), CacheFlag::AUTOCREATE);
if (package)
{
node->m_package = csb->csb_resources->packages.registerResource(package->getPermanent());
constant = package->findConstant(fullName);
}
}

if (!node->m_package)
if (constant == nullptr)
{
status_exception::raise(Arg::Gds(isc_bad_constant_name) <<
Arg::Str(fullName.toQuotedString()));
}

node->m_cachedDsc = constant->getDesc();
return node;
}
// TODO: rowtype
Expand All @@ -474,13 +480,12 @@ void PackageReferenceNode::setParameterName(dsql_par* parameter) const

void PackageReferenceNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
{
jrd_tra* transaction = dsqlScratch->getTransaction();
thread_db* tdbb = JRD_get_thread_data();
*desc = ConstantValue::getDesc(tdbb, transaction, m_fullName);
fb_assert(m_cachedDsc.dsc_dtype != dtype_unknown);
*desc = m_cachedDsc;
}

bool PackageReferenceNode::constantExists(thread_db* tdbb, Jrd::jrd_tra* transaction,
const QualifiedName& fullName, bool* isPrivate)
const QualifiedName& fullName, dsc* outConstantDesc, bool* isPrivate)
{
if (fullName.package.isEmpty() || fullName.object.isEmpty())
return false;
Expand All @@ -500,18 +505,22 @@ bool PackageReferenceNode::constantExists(thread_db* tdbb, Jrd::jrd_tra* transac
if (isPrivate)
*isPrivate = value->isPrivate;

if (outConstantDesc)
*outConstantDesc = value->getDesc();

return true;
}

void PackageReferenceNode::getDesc(thread_db* tdbb, CompilerScratch*, dsc* desc)
void PackageReferenceNode::getDesc(thread_db*, CompilerScratch*, dsc* desc)
{
*desc = ConstantValue::getDesc(tdbb, tdbb->getTransaction(), m_fullName);
fb_assert(m_cachedDsc.dsc_dtype != dtype_unknown);
*desc = m_cachedDsc;
}

ValueExprNode* PackageReferenceNode::copy(thread_db* tdbb, NodeCopier& copier) const
{
MemoryPool& pool = *tdbb->getDefaultPool();
auto* node = FB_NEW_POOL(pool) PackageReferenceNode(pool, m_fullName, m_itemType);
auto* node = FB_NEW_POOL(pool) PackageReferenceNode(pool, m_fullName, m_itemType, &m_cachedDsc);

node->m_package = copier.csb->csb_resources->packages.registerResource(m_package());

Expand Down
5 changes: 3 additions & 2 deletions src/dsql/PackageNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class PackageReferenceNode final : public TypedNode<ValueExprNode, ExprNode::TYP
{
public:
PackageReferenceNode(Firebird::MemoryPool& pool, const QualifiedName& name,
const UCHAR itemType);
const UCHAR itemType, const dsc* type = nullptr);

Firebird::string internalPrint(NodePrinter& printer) const override;

Expand All @@ -142,7 +142,7 @@ class PackageReferenceNode final : public TypedNode<ValueExprNode, ExprNode::TYP

// Search for a package constant by its fully qualified name
static bool constantExists(thread_db* tdbb, Jrd::jrd_tra* transaction,
const QualifiedName& name, bool* isPrivate = nullptr);
const QualifiedName& name, dsc* outConstantDesc = nullptr, bool* isPrivate = nullptr);

void getDesc(thread_db*, CompilerScratch*, dsc*) override;

Expand All @@ -159,6 +159,7 @@ class PackageReferenceNode final : public TypedNode<ValueExprNode, ExprNode::TYP
private:
CachedResource<Package, PackagePermanent> m_package;
const QualifiedName m_fullName;
dsc m_cachedDsc = {};

const UCHAR m_itemType;
ULONG m_impureOffset = 0;
Expand Down
139 changes: 60 additions & 79 deletions src/jrd/Package.epp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ static_assert(DSC_SIZE_TO_HASH - offsetof(dsc, dsc_flags) == sizeof(dsc::dsc_fla

bool ConstantValue::hash(thread_db* tdbb, Firebird::sha512& digest) const
{
fb_assert(m_value.vlu_desc.dsc_dtype != dtype_unknown);
digest.process(DSC_SIZE_TO_HASH, &m_value.vlu_desc);
fb_assert(m_type.dsc_dtype != dtype_unknown);
digest.process(DSC_SIZE_TO_HASH, &m_type);

// The value hashing is unneccecery as Alex Peshkoff explained
// See https://groups.google.com/g/firebird-devel/c/xIxhL_QAjEg/m/9RGT47ugAwAJ
Expand All @@ -72,46 +72,6 @@ bool ConstantValue::hash(thread_db* tdbb, Firebird::sha512& digest) const
return true;
}

dsc ConstantValue::getDesc(thread_db* tdbb, Jrd::jrd_tra* transaction, const QualifiedName& name)
{
dsc desc{};
bool found = false;

FbLocalStatus status;
static const CachedRequestId requestId;
AutoCacheRequest getConstantDscRequest(tdbb, requestId);
FOR(REQUEST_HANDLE getConstantDscRequest TRANSACTION_HANDLE transaction)
CONST IN RDB$CONSTANTS CROSS FLD IN RDB$FIELDS
WITH CONST.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
CONST.RDB$PACKAGE_NAME EQ name.package.c_str() AND
CONST.RDB$CONSTANT_NAME EQ name.object.c_str() AND
FLD.RDB$SCHEMA_NAME EQ CONST.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ CONST.RDB$FIELD_SOURCE
{
found = true;

const bool succeed = DSC_make_descriptor(&desc,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
CSetId(FLD.RDB$CHARACTER_SET_ID),
CollId(FLD.RDB$COLLATION_ID));

if (!succeed)
(Arg::Gds(isc_bad_constant_desc) << Arg::Str(name.toQuotedString())).raise();

desc.setNullable(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0);
}

END_FOR

if (!found)
(Arg::Gds(isc_bad_constant_name) << Arg::Str(name.toQuotedString())).raise();

return desc;
}

void ConstantValue::genConstantBlr(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
ValueExprNode* constExpr, dsql_fld* type, const MetaName& schema)
{
Expand Down Expand Up @@ -251,7 +211,7 @@ void ConstantValue::executeCsbNode(thread_db* tdbb, CompilerScratch* csb)
}
else
{
exprNode->getDesc(tdbb, csb, &m_value.vlu_desc);
m_value.vlu_desc = m_type;
m_value.vlu_desc.setNull();
}
}
Expand Down Expand Up @@ -330,27 +290,8 @@ ScanResult Package::scan(thread_db* tdbb, ObjectBase::Flag flags)
END_FOR
}

{ // Constants
static const CachedRequestId requestId;
AutoCacheRequest requestConst(tdbb, requestId);

FOR(REQUEST_HANDLE requestConst TRANSACTION_HANDLE metaTransaction)
PKG IN RDB$PACKAGES CROSS CONST IN RDB$CONSTANTS
WITH PKG.RDB$PACKAGE_ID EQ getId() AND
PKG.RDB$PACKAGE_NAME EQ CONST.RDB$PACKAGE_NAME AND
PKG.RDB$SCHEMA_NAME EQ CONST.RDB$SCHEMA_NAME
{
addConstant(tdbb,
QualifiedName(CONST.RDB$CONSTANT_NAME, CONST.RDB$SCHEMA_NAME, CONST.RDB$PACKAGE_NAME),
CONST.RDB$PRIVATE_FLAG != 0,
CONST.RDB$CONSTANT_BLR,
skipMakeValue);

if (skipMakeValue)
this->m_callReload = true; // Value is necessary for to calculate hash
}
END_FOR
}
fb_assert(constants.values.isEmpty());
collectConstants(tdbb, skipMakeValue);

return this->m_callReload ? ScanResult::REPEAT : ScanResult::COMPLETE;
}
Expand All @@ -373,18 +314,7 @@ ScanResult Package::reload(thread_db* tdbb, ObjectBase::Flag fl)
AutoCacheRequest requestConst(tdbb, requestId);

constants.clear();
FOR(REQUEST_HANDLE requestConst TRANSACTION_HANDLE metaTransaction)
PKG IN RDB$PACKAGES CROSS CONST IN RDB$CONSTANTS
WITH PKG.RDB$PACKAGE_ID EQ getId() AND
PKG.RDB$PACKAGE_NAME EQ CONST.RDB$PACKAGE_NAME AND
PKG.RDB$SCHEMA_NAME EQ CONST.RDB$SCHEMA_NAME
{
addConstant(tdbb,
QualifiedName(CONST.RDB$CONSTANT_NAME, CONST.RDB$SCHEMA_NAME, CONST.RDB$PACKAGE_NAME),
CONST.RDB$PRIVATE_FLAG != 0,
CONST.RDB$CONSTANT_BLR);
}
END_FOR
collectConstants(tdbb, false);

m_callReload = false;
return ScanResult::COMPLETE;
Expand Down Expand Up @@ -412,19 +342,21 @@ ConstantValue& Package::addConstant(thread_db* tdbb,
DsqlDescMaker::fromField(&typeDesc, type);

auto& value = constants.add(constName, isPrivate);
value.updateValue(typeDesc);
value.setType(typeDesc);

return value;
}

ConstantValue& Package::addConstant(thread_db* tdbb,
const QualifiedName& constName,
const bool isPrivate,
const dsc type,
const bid blrBlobId,
const bool skipMakeValue)
{
auto& value = constants.add(constName, isPrivate);
value.updateValue(blrBlobId);
value.setType(type);
value.setValue(blrBlobId);
if (!skipMakeValue)
value.makeValue(tdbb, nullptr);

Expand All @@ -443,7 +375,7 @@ ConstantValue& Package::updateConstant(thread_db* tdbb, const QualifiedName& nam

auto& constant = constants.values[*innerId];
constant.isPrivate = isPrivate;
constant.updateValue(typeDesc);
constant.setType(typeDesc);

return constant;
}
Expand All @@ -457,3 +389,52 @@ ConstantValue* Package::findConstant(const QualifiedName& name)

return nullptr;
}

void Package::collectConstants(thread_db* tdbb, const bool skipMakingValue)
{
Attachment* attachment = tdbb->getAttachment();
jrd_tra* metaTransaction = attachment->getMetaTransaction(tdbb);
Database* dbb = tdbb->getDatabase();

MemoryPool& pool = getPermanent()->getPool();

static const CachedRequestId requestId;
AutoCacheRequest requestConst(tdbb, requestId);
FOR(REQUEST_HANDLE requestConst TRANSACTION_HANDLE metaTransaction)
PKG IN RDB$PACKAGES
CROSS CONST IN RDB$CONSTANTS
CROSS FLD IN RDB$FIELDS
WITH PKG.RDB$PACKAGE_ID EQ getId() AND
PKG.RDB$PACKAGE_NAME EQ CONST.RDB$PACKAGE_NAME AND
PKG.RDB$SCHEMA_NAME EQ CONST.RDB$SCHEMA_NAME AND
FLD.RDB$SCHEMA_NAME EQ CONST.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ CONST.RDB$FIELD_SOURCE
{
QualifiedName name(CONST.RDB$CONSTANT_NAME, CONST.RDB$SCHEMA_NAME, CONST.RDB$PACKAGE_NAME);

dsc constantType{};
const bool succeed = DSC_make_descriptor(&constantType,
FLD.RDB$FIELD_TYPE,
FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH,
FLD.RDB$FIELD_SUB_TYPE,
CSetId(FLD.RDB$CHARACTER_SET_ID),
CollId(FLD.RDB$COLLATION_ID));

if (!succeed)
(Arg::Gds(isc_bad_constant_desc) << Arg::Str(name.toQuotedString())).raise();

constantType.setNullable(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0);

addConstant(tdbb,
name,
CONST.RDB$PRIVATE_FLAG != 0,
constantType,
CONST.RDB$CONSTANT_BLR,
skipMakingValue);

if (skipMakingValue)
this->m_callReload = true; // Value is necessary to calculate hash
}
END_FOR
}
Loading
Loading