-
-
Notifications
You must be signed in to change notification settings - Fork 263
Package constants #8916
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Package constants #8916
Changes from all commits
5aa9116
251615c
2d35ecc
75db5ab
e54c9e6
45d62b7
06411d7
3dc1d3d
d048560
6231dbc
05342aa
459354f
3c2c61e
fd208d1
8a982ac
c42bd55
4a556aa
44a7050
c2caa1b
4294bc4
3148971
51fc8d7
bd085c9
4695050
e606d59
cf7929e
12a7b2b
edca2c5
cfdf444
816ad9c
13b7df9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,6 +80,7 @@ | |
| #include "../jrd/ini.h" | ||
| #include "../jrd/GarbageCollector.h" | ||
| #include "../jrd/ProtectRelations.h" | ||
| #include "../dsql/PackageNodes.h" | ||
|
|
||
| namespace Jrd { | ||
|
|
||
|
|
@@ -130,16 +131,6 @@ static rel_t relationType(SSHORT relationTypeNull, SSHORT relationType) noexcept | |
| static void saveField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, const MetaName& fieldName); | ||
| static dsql_rel* saveRelation(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, | ||
| const QualifiedName& relationName, bool view, bool creating); | ||
| static void updateRdbFields(const TypeClause* type, | ||
| SSHORT& fieldType, | ||
| SSHORT& fieldLength, | ||
| SSHORT& fieldSubTypeNull, SSHORT& fieldSubType, | ||
| SSHORT& fieldScaleNull, SSHORT& fieldScale, | ||
| SSHORT& characterSetIdNull, SSHORT& characterSetId, | ||
| SSHORT& characterLengthNull, SSHORT& characterLength, | ||
| SSHORT& fieldPrecisionNull, SSHORT& fieldPrecision, | ||
| SSHORT& collationIdNull, SSHORT& collationId, | ||
| SSHORT& segmentLengthNull, SSHORT& segmentLength); | ||
| static ISC_STATUS getErrorCodeByObjectType(int obj_type); | ||
|
|
||
| static constexpr const char* CHECK_CONSTRAINT_EXCEPTION = "check_constraint"; | ||
|
|
@@ -887,7 +878,7 @@ static dsql_rel* saveRelation(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, | |
| } | ||
|
|
||
| // Update RDB$FIELDS received by reference. | ||
| static void updateRdbFields(const TypeClause* type, | ||
| void DdlNode::updateRdbFields(const TypeClause* type, | ||
| SSHORT& fieldType, | ||
| SSHORT& fieldLength, | ||
| SSHORT& fieldSubTypeNull, SSHORT& fieldSubType, | ||
|
|
@@ -1486,6 +1477,20 @@ DdlNode* CommentOnNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) | |
| dsqlScratch->resolveRoutineOrRelation(name, {objType}); | ||
| break; | ||
|
|
||
| case obj_package_constant: | ||
| { | ||
| QualifiedName constantName(subName, name.schema, name.object); // name is a package | ||
| if (constantName.schema.isEmpty()) | ||
| constantName.schema = PUBLIC_SCHEMA; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was not necessary in any other command in DdlNodes.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actuality, as I can see, something similar (but more more complicated) is happening for procedures and functions in resolveRoutineOrRelation(...). Without the check, scheme will remain NULL. |
||
|
|
||
| if (!PackageReferenceNode::constantExists(tdbb, transaction, constantName)) | ||
| { | ||
| status_exception::raise(Arg::Gds(isc_bad_constant_name) << constantName.toQuotedString()); | ||
| } | ||
| name = constantName; | ||
| break; | ||
| } | ||
|
|
||
| default: | ||
| dsqlScratch->qualifyExistingName(name, objType); | ||
| break; | ||
|
|
@@ -1590,6 +1595,10 @@ void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction) | |
| SCL_check_package(tdbb, name, SCL_alter); | ||
| break; | ||
|
|
||
| case obj_package_constant: | ||
| SCL_check_package(tdbb, name.getSchemaAndPackage(), SCL_alter); | ||
| break; | ||
|
|
||
| default: | ||
| fb_assert(false); | ||
| } | ||
|
|
@@ -1753,6 +1762,12 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j | |
| status << Arg::Gds(isc_dyn_package_not_found) << Arg::Str(objNameStr); | ||
| break; | ||
|
|
||
| case obj_package_constant: | ||
| tableClause = "rdb$constants"; | ||
| columnClause = "rdb$constant_name"; | ||
| status << Arg::Gds(isc_bad_constant_name) << Arg::Str(objNameStr); | ||
| break; | ||
|
|
||
| default: | ||
| fb_assert(false); | ||
| return; | ||
|
|
@@ -1776,7 +1791,7 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j | |
| sql << "and" << subColumnClause << "=" << subName; | ||
| } | ||
|
|
||
| if (objType == obj_procedure || objType == obj_udf) | ||
| if (objType == obj_procedure || objType == obj_udf || objType == obj_package_constant) | ||
| sql << "and rdb$package_name is not distinct from nullif(" << name.package << ", '')"; | ||
|
|
||
| if (addWhereClause) | ||
|
|
@@ -11562,11 +11577,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra | |
| ValueExprNode* nameNode = fieldNode; | ||
| const char* aliasName = NULL; | ||
|
|
||
| while (nodeIs<DsqlAliasNode>(nameNode) || nodeIs<DerivedFieldNode>(nameNode) || nodeIs<DsqlMapNode>(nameNode)) | ||
| while (nodeIs<DsqlAliasNode>(nameNode) || nodeIs<DerivedFieldNode>(nameNode) || nodeIs<DsqlMapNode>(nameNode) || | ||
| nodeAs<PackageReferenceNode>(nameNode)) | ||
| { | ||
| DsqlAliasNode* aliasNode; | ||
| DsqlMapNode* mapNode; | ||
| DerivedFieldNode* derivedField; | ||
| PackageReferenceNode* referenceNode; | ||
|
|
||
| if ((aliasNode = nodeAs<DsqlAliasNode>(nameNode))) | ||
| { | ||
|
|
@@ -11582,6 +11599,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra | |
| aliasName = derivedField->name.c_str(); | ||
| nameNode = derivedField->value; | ||
| } | ||
| else if ((referenceNode = nodeAs<PackageReferenceNode>(nameNode))) | ||
| { | ||
| if (!aliasName) | ||
| aliasName = referenceNode->getName(); | ||
|
|
||
| nameNode = nullptr; | ||
| } | ||
| } | ||
|
|
||
| const dsql_fld* nameField = NULL; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,8 @@ | |
| #include "../jrd/trace/TraceObjects.h" | ||
| #include "../jrd/trace/TraceJrdHelpers.h" | ||
|
|
||
| #include "../dsql/PackageNodes.h" | ||
|
|
||
| using namespace Firebird; | ||
| using namespace Jrd; | ||
|
|
||
|
|
@@ -466,6 +468,23 @@ void ExprNode::collectStreams(SortedStreamList& streamList) const | |
| } | ||
| } | ||
|
|
||
| bool ExprNode::isChildrenConstant() const | ||
| { | ||
| NodeRefsHolder holder; | ||
| getChildren(holder, false); | ||
|
|
||
| for (auto i : holder.refs) | ||
| { | ||
| if (*i == nullptr) | ||
| continue; | ||
|
|
||
| if (!(*i)->constant()) | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool ExprNode::computable(CompilerScratch* csb, StreamType stream, | ||
| bool allowOnlyCurrentStream, ValueExprNode* /*value*/) | ||
| { | ||
|
|
@@ -6448,6 +6467,28 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec | |
| } | ||
| } | ||
|
|
||
| // Use context to check conflicts beween <relation>.<field> and <package>.<constant> | ||
| dsql_ctx packageContext(dsqlScratch->getPool()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why package becomes a context.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to check name conflict between |
||
| { // Consatnts | ||
|
|
||
| const QualifiedName constantName(dsqlName, | ||
| dsqlQualifier.schema.hasData() ? dsqlQualifier.schema : (dsqlScratch->package.schema.hasData() ? dsqlScratch->package.schema : PUBLIC_SCHEMA), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think should use PUBLIC_SCHEMA here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without it, schema will be NULL. Or I am doing something wrong |
||
| dsqlQualifier.object.hasData() ? dsqlQualifier.object : dsqlScratch->package.object); | ||
|
|
||
| if (PackageReferenceNode::constantExists(tdbb, dsqlScratch->getTransaction(), constantName)) | ||
| { | ||
| packageContext.ctx_relation = nullptr; | ||
| packageContext.ctx_procedure = nullptr; | ||
| // 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); | ||
| } | ||
| } | ||
|
|
||
| // CVC: We can't return blindly if this is a check constraint, because there's | ||
| // the possibility of an invalid field that wasn't found. The multiple places that | ||
| // call this function pass1_field() don't expect a NULL pointer, hence will crash. | ||
|
|
@@ -12463,7 +12504,12 @@ void SysFuncCallNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc) | |
|
|
||
| bool SysFuncCallNode::deterministic(thread_db* tdbb) const | ||
| { | ||
| return ExprNode::deterministic(tdbb) && function->deterministic; | ||
| return ExprNode::deterministic(tdbb) && function->isDeterministic(); | ||
| } | ||
|
|
||
| bool SysFuncCallNode::constant() const | ||
| { | ||
| return ExprNode::isChildrenConstant() && function->isConstant(); | ||
| } | ||
|
|
||
| void SysFuncCallNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) | ||
|
|
@@ -14151,6 +14197,17 @@ ValueExprNode* VariableNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) | |
| if (!node->dsqlVar || | ||
| (node->dsqlVar->type == dsql_var::TYPE_LOCAL && !node->dsqlVar->initialized && !dsqlScratch->mainScratch)) | ||
| { | ||
| if (dsqlScratch->package.object.hasData()) | ||
| { | ||
| thread_db* tdbb = JRD_get_thread_data(); | ||
| QualifiedName constantFullName(dsqlName, dsqlScratch->package.schema, dsqlScratch->package.object); | ||
| if (PackageReferenceNode::constantExists(tdbb, dsqlScratch->getTransaction(), constantFullName)) | ||
| { | ||
| delete node; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Weird that it first creates a variable to later delete it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but I don't want to change existing code too much in this case |
||
| return FB_NEW_POOL(dsqlScratch->getPool()) PackageReferenceNode(dsqlScratch->getPool(), constantFullName); | ||
| } | ||
| } | ||
|
|
||
| PASS1_field_unknown(NULL, dsqlName.toQuotedString().c_str(), this); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears that package header constant cannot be referenced in its own body without the qualified package name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I corrected the desription