Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5aa9116
Implement package constants
Feb 11, 2026
251615c
Add "is constant" flag to nodes
Feb 11, 2026
2d35ecc
Fix blr parsing, generate unique names for constant FIELD_NAME, fix w…
Feb 11, 2026
75db5ab
Improve error message for non constant expression
Feb 11, 2026
e54c9e6
Add missing SCHEMA set to package constants, fix incorrect cached con…
Feb 12, 2026
45d62b7
Add missing resource allocation and transfer for constants
Feb 12, 2026
06411d7
Fix invalid constant and package name in store_dependencies
Feb 12, 2026
3dc1d3d
Fix invalid constant drop
Feb 12, 2026
d048560
Fix constant evaluating in BLR Parse
Feb 13, 2026
6231dbc
Fix constants collecting and dtype_dec64 parsing
Feb 13, 2026
05342aa
Fix incorrect ambiguity check
Feb 16, 2026
459354f
Update support for complex dtypes
Feb 16, 2026
3c2c61e
Cleanup
Feb 17, 2026
fd208d1
Rollback unneccecery changes
Feb 17, 2026
8a982ac
Move all constant related routines to Constant class
Feb 18, 2026
c42bd55
Add description for package constants
Feb 24, 2026
4a556aa
Cleanup
Feb 24, 2026
44a7050
Delete string in impure
Feb 24, 2026
c2caa1b
Merge remote-tracking branch 'upstream/master' into metacache_package…
Feb 24, 2026
4294bc4
Merge remote-tracking branch 'origin/master' into metacache_package_c…
Feb 24, 2026
3148971
Resolve incorrect merge with LTT
Feb 24, 2026
51fc8d7
One more cleanup (preparation) before PR
Feb 25, 2026
bd085c9
Add ability to add comment on package constant
Feb 25, 2026
4695050
Remove unneccecery namespace scope
Feb 26, 2026
e606d59
Make Constant value in reload state when MINISCAN is set
Feb 26, 2026
cf7929e
Remove not used variable and omit unneccecery namespace scope
Feb 26, 2026
12a7b2b
Update src/isql/show.epp
Noremos Feb 27, 2026
edca2c5
First part of fixes/corrections related to PR issues
Feb 27, 2026
cfdf444
Resolve more PR issues
Feb 27, 2026
816ad9c
Add missing search for FIELD SCHEMA
Feb 27, 2026
13b7df9
Use better name for method
Feb 27, 2026
46e0e5d
Fix type in test
Mar 1, 2026
51d9ab6
Omit unneccecery getConstant method and add assert for constant exist…
Mar 1, 2026
2ccea0f
Mark RecordKeyNode as non constant
Mar 1, 2026
8d85f05
Add missing code for backup-restore
Mar 1, 2026
2f11ba4
Add missing source for windows build
Mar 1, 2026
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
1 change: 1 addition & 0 deletions builds/win32/msvc15/engine_static.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<ClCompile Include="..\..\..\gen\jrd\scl.cpp" />
<ClCompile Include="..\..\..\gen\jrd\SystemTriggers.cpp" />
<ClCompile Include="..\..\..\gen\utilities\gstat\dba.cpp" />
<ClCompile Include="..\..\..\gen\jrd\Constant.cpp" />
<ClCompile Include="..\..\..\src\dsql\AggNodes.cpp" />
<ClCompile Include="..\..\..\src\dsql\BlrDebugWriter.cpp" />
<ClCompile Include="..\..\..\src\dsql\BoolNodes.cpp" />
Expand Down
1 change: 1 addition & 0 deletions doc/sql.extensions/README.ddl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ COMMENT ON <basic_type> name IS {'txt'|NULL};
COMMENT ON COLUMN table_or_view_name.field_name IS {'txt'|NULL};
COMMENT ON {PROCEDURE | [EXTERNAL] FUNCTION} [<package_name> .] name.param_name IS {'txt'|NULL};
COMMENT ON [PROCEDURE | FUNCTION] PARAMETER [<package_name> .] name.param_name IS {'txt'|NULL};
COMMENT ON CONSTANT [<schema_name> .] <package_name> . name IS {'txt'|NULL};

An empty literal string '' will act as NULL since the internal code (DYN in this case)
works this way with blobs.
Expand Down
21 changes: 17 additions & 4 deletions doc/sql.extensions/README.packages.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ Syntax:

<package_item> ::=
<function_decl> ; |
<procedure_decl> ;
<procedure_decl> ; |
<constant_decl> ;

<function_decl> ::=
FUNCTION <name> [( <parameters> )] RETURNS <type>

<procedure_decl> ::=
PROCEDURE <name> [( <parameters> ) [RETURNS ( <parameters> )]]

<constant_decl> ::=
CONSTANT <name> <type> = <constant expression>

<package_body> ::=
{ CREATE [OR ALTER] | ALTER | RECREATE } PACKAGE BODY <name>
AS
Expand All @@ -37,7 +41,8 @@ Syntax:

<package_body_item> ::=
<function_impl> |
<procedure_impl>
<procedure_impl> |
<constant_decl>

<function_impl> ::=
FUNCTION <name> [( <parameters> )] RETURNS <type>
Expand Down Expand Up @@ -75,7 +80,7 @@ Objectives:
1) The grouping is not represented in the database metadata.
2) They all participate in a flat namespace and all routines are callable by everyone (not
talking about security permissions here).

- Facilitate dependency tracking between its internal routines and between other packaged and
unpackaged routines.

Expand All @@ -90,9 +95,17 @@ Objectives:
tables that the package body depends on that object. If you want to, for example, drop that
object, you first need to remove who depends on it. As who depends on it is a package body,
you can just drop it even if some other database object depends on this package. When the body
is dropped, the header remains, allowing you to create its body again after changing it based
is dropped, the header remains, allowing you to create its body again after changing it based
on the object removal.

A package constant is a value initialized by a constant expression.
A constant expression is defined by a simple rule: its value does not change after recompilation.
Constants declared in the package specification are publicly visible and can be referenced using
the [<schema>.]<package>.<constant_name> notation.
Constants declared in the package body are private and cannot be accessed from outside the package.
However, they can be referenced directly by <constant_name> within <procedure_impl> and <function_impl>.
Header constants can also be used directly with just the name for package body elements.

- Facilitate permission management.

It's generally a good practice to create routines with a privileged database user and grant
Expand Down
62 changes: 62 additions & 0 deletions src/burp/backup.epp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ void write_triggers();
void write_trigger_messages();
void write_types();
void write_user_privileges();
void write_constants();
void general_on_error();


Expand Down Expand Up @@ -505,6 +506,13 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
write_pub_tables();
}

if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
{
// Write constants
BURP_verbose(USHORT(isc_gbak_writing_constants)); // writing constants
write_constants();
}

// Finish up

put(tdgbl, (UCHAR) rec_end);
Expand Down Expand Up @@ -4831,6 +4839,60 @@ void write_user_privileges()
MISC_release_request_silent(req_handle1);
}

void write_constants()
{
Firebird::IRequest* req_handle1 = nullptr;

BurpGlobals* tdgbl = BurpGlobals::getSpecific();

FOR (REQUEST_HANDLE req_handle1)
CONST IN RDB$CONSTANTS
{
QualifiedMetaString name(CONST.RDB$CONSTANT_NAME);

put(tdgbl, rec_constants);
PUT_TEXT(att_constant_name, CONST.RDB$CONSTANT_NAME);

if (!CONST.RDB$PACKAGE_NAME.NULL)
{
PUT_TEXT(att_constant_package, CONST.RDB$PACKAGE_NAME);
name.package = CONST.RDB$PACKAGE_NAME;
}

PUT_TEXT(att_constant_field_source, CONST.RDB$FIELD_SOURCE);

if (!CONST.RDB$PRIVATE_FLAG.NULL)
put_int32(att_constant_private_flag, CONST.RDB$PRIVATE_FLAG);

if (!CONST.RDB$CONSTANT_BLR.NULL)
put_blr_blob(att_constant_blr, CONST.RDB$CONSTANT_BLR);

if (!CONST.RDB$CONSTANT_SOURCE.NULL)
put_source_blob(att_constant_source, att_constant_source, CONST.RDB$CONSTANT_SOURCE);

if (!CONST.RDB$SCHEMA_NAME.NULL)
{
PUT_TEXT(att_constant_schema_name, CONST.RDB$SCHEMA_NAME);
name.schema = CONST.RDB$SCHEMA_NAME;
}

if (!CONST.RDB$DESCRIPTION.NULL)
{
put_source_blob (att_constant_description, att_constant_description, CONST.RDB$DESCRIPTION);
}

// writing constant %s
BURP_verbose(USHORT(isc_gbak_writing_constant), SafeArg() << name.toQuotedString().data());
put(tdgbl, att_end);
}
END_FOR;
ON_ERROR
general_on_error();
END_ERROR;

MISC_release_request_silent(req_handle1);
}

} // namespace

namespace Burp {
Expand Down
13 changes: 12 additions & 1 deletion src/burp/burp.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ enum rec_type {
rec_db_creator, // Database creator
rec_publication, // Publication
rec_pub_table, // Publication table
rec_schema // Schema
rec_schema, // Schema
rec_constants // Constants
};


Expand Down Expand Up @@ -701,6 +702,16 @@ enum att_type {
att_schema_security_class,
att_schema_owner_name,
att_schema_description,

// Constants
att_constant_name = SERIES,
att_constant_package,
att_constant_field_source,
att_constant_private_flag,
att_constant_blr,
att_constant_source,
att_constant_schema_name,
att_constant_description,
};


Expand Down
86 changes: 86 additions & 0 deletions src/burp/restore.epp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ bool get_trigger_old (BurpGlobals* tdgbl, burp_rel*);
bool get_type(BurpGlobals* tdgbl);
bool get_user_privilege(BurpGlobals* tdgbl);
bool get_view(BurpGlobals* tdgbl, burp_rel*);
bool get_constants_table(BurpGlobals* tdgbl);
void ignore_array(BurpGlobals* tdgbl, burp_rel*);
void ignore_blob(BurpGlobals* tdgbl);
rec_type ignore_data(BurpGlobals* tdgbl, burp_rel*);
Expand Down Expand Up @@ -10534,6 +10535,85 @@ bool get_view(BurpGlobals* tdgbl, burp_rel* relation)
return true;
}

bool get_constants_table(BurpGlobals* tdgbl)
{
if (tdgbl->runtimeODS < DB_VERSION_DDL14) // FB6
return false;

QualifiedMetaString name;

att_type attribute;
scan_attr_t scan_next_attr;

Firebird::ITransaction* local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;

STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_type_req_handle1)
CONST IN RDB$CONSTANTS
{
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
switch (attribute)
{
case att_constant_name:
CONST.RDB$CONSTANT_NAME.NULL = FALSE;
GET_TEXT(CONST.RDB$CONSTANT_NAME);
name.object = CONST.RDB$CONSTANT_NAME;
break;

case att_constant_package:
CONST.RDB$PACKAGE_NAME.NULL = FALSE;
GET_TEXT(CONST.RDB$PACKAGE_NAME);
name.package = CONST.RDB$PACKAGE_NAME;
break;

case att_constant_field_source:
CONST.RDB$FIELD_SOURCE.NULL = FALSE;
GET_TEXT(CONST.RDB$FIELD_SOURCE);
break;

case att_constant_private_flag:
CONST.RDB$PRIVATE_FLAG.NULL = FALSE;
CONST.RDB$PRIVATE_FLAG = (USHORT) get_int32(tdgbl);
break;

case att_constant_blr:
CONST.RDB$CONSTANT_BLR.NULL = FALSE;
get_blr_blob(tdgbl, CONST.RDB$CONSTANT_BLR, true);
break;

case att_constant_source:
CONST.RDB$CONSTANT_SOURCE.NULL = FALSE;
get_source_blob(tdgbl, CONST.RDB$CONSTANT_SOURCE, true);
break;

case att_constant_schema_name:
CONST.RDB$SCHEMA_NAME.NULL = FALSE;
GET_TEXT(CONST.RDB$SCHEMA_NAME);
name.schema = CONST.RDB$SCHEMA_NAME;
break;

case att_constant_description:
CONST.RDB$DESCRIPTION.NULL = FALSE;
get_source_blob(tdgbl, CONST.RDB$DESCRIPTION, true);
break;
default:
bad_attribute(scan_next_attr, attribute, USHORT(isc_gbak_constant));
break;
}
}

BURP_verbose(USHORT(isc_gbak_restoring_constant), SafeArg() << name.toQuotedString().data());
}
END_STORE;
ON_ERROR
general_on_error();
END_ERROR;

return true;
}

void ignore_array(BurpGlobals* tdgbl, burp_rel* relation)
{
/**************************************
Expand Down Expand Up @@ -11367,6 +11447,12 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
flag = true;
break;

case rec_constants:
if (!get_constants_table(tdgbl))
return false;
flag = true;
break;

default:
BURP_error(43, true, SafeArg() << record);
// msg 43 don't recognize record type %ld
Expand Down
1 change: 1 addition & 0 deletions src/common/ParserTokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ PARSER_TOKEN(TOK_CONDITIONAL, "CONDITIONAL", true)
PARSER_TOKEN(TOK_CONNECT, "CONNECT", false)
PARSER_TOKEN(TOK_CONNECTIONS, "CONNECTIONS", true)
PARSER_TOKEN(TOK_CONSISTENCY, "CONSISTENCY", true)
PARSER_TOKEN(TOK_CONSTANT, "CONSTANT", true)
PARSER_TOKEN(TOK_CONSTRAINT, "CONSTRAINT", false)
PARSER_TOKEN(TOK_CONTAINING, "CONTAINING", true)
PARSER_TOKEN(TOK_CONTINUE, "CONTINUE", true)
Expand Down
Loading
Loading