diff --git a/builds/install/misc/replication.conf b/builds/install/misc/replication.conf
index f9cf1c37f8..eb580d6afe 100644
--- a/builds/install/misc/replication.conf
+++ b/builds/install/misc/replication.conf
@@ -11,15 +11,25 @@ database
#
# plugin =
+ # Pattern (regular expression) that defines what schemas must be included into
+ # replication. By default, tables from all schemas are replicated.
+ #
+ # include_schema_filter =
+
+ # Pattern (regular expression) that defines what schemas must be excluded from
+ # replication. By default, tables from all schemas are replicated.
+ #
+ # exclude_schema_filter =
+
# Pattern (regular expression) that defines what tables must be included into
# replication. By default, all tables are replicated.
#
- # include_filter =
+ # include_filter =
# Pattern (regular expression) that defines what tables must be excluded from
# replication. By default, all tables are replicated.
#
- # exclude_filter =
+ # exclude_filter =
# Boolean parameters describing how replication errors must be handled.
#
@@ -42,20 +52,20 @@ database
# Directory to store replication journal files.
#
- # journal_directory =
+ # journal_directory =
# Prefix for replication journal file names. It will be automatically suffixed
# with an ordinal sequential number. If not specified, database filename
# (without path) is used as a prefix.
#
- # journal_file_prefix =
+ # journal_file_prefix =
# Maximum allowed size for a single replication segment.
#
# journal_segment_size = 16777216 # 16MB
# Maximum allowed number of full replication segments. Once this limit is reached,
- # the replication process is temporarily delayed to allow the archiving to catch up.
+ # the replication process is temporarily delayed to allow the archiving to catch up.
# If any of the full segments is not archived during one minute,
# the replication fails with an error.
#
@@ -76,7 +86,7 @@ database
# Directory to store archived replication segments.
# It also defines the $(archpathname) substitution macro (see below).
#
- # journal_archive_directory =
+ # journal_archive_directory =
# Program (complete command line with arguments) that is executed when some
# replication segment gets full and needs archiving.
@@ -97,7 +107,7 @@ database
# or
# Windows: "copy $(pathname) $(archivepathname)"
#
- # journal_archive_command =
+ # journal_archive_command =
# Timeout, in seconds, to wait until incomplete segment is scheduled for archiving.
# It allows to minimize the replication gap if the database is modified rarely.
@@ -121,7 +131,7 @@ database
#
# Multiple entries are allowed (for different synchronous replicas).
#
- # sync_replica =
+ # sync_replica =
#
# It's also possible to configure replicas as separate sub-sections, e.g.:
#
@@ -175,13 +185,13 @@ database
# Directory to search for the journal files to be replicated.
#
- # journal_source_directory =
+ # journal_source_directory =
# Filter to limit replication to the particular source database (based on its GUID).
# Expected format: "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
# Note that double quotes are mandatory, as well as curly braces.
#
- # source_guid =
+ # source_guid =
# If enabled, replication.log contains the detailed log of operations performed
# by the replication server. Otherwise (by default), only errors and warnings are logged.
@@ -202,6 +212,14 @@ database
# then reconnects back and tries to re-apply the latest segments from the point of failure.
#
# apply_error_timeout = 60
+
+ # Schema search path for compatibility with Firebird versions below 6.0
+ #
+ # Firebird master databases below v6 has no schemas, so use this search path in the replica to
+ # locate the objects.
+ # Used only with asynchronous replication.
+ #
+ # schema_search_path =
}
#
diff --git a/builds/win32/msvc15/common.vcxproj b/builds/win32/msvc15/common.vcxproj
index 18c9bbba9d..73eb3cbb94 100644
--- a/builds/win32/msvc15/common.vcxproj
+++ b/builds/win32/msvc15/common.vcxproj
@@ -144,7 +144,7 @@
-
+
diff --git a/builds/win32/msvc15/common.vcxproj.filters b/builds/win32/msvc15/common.vcxproj.filters
index b0e5eebb49..dfe049bf3b 100644
--- a/builds/win32/msvc15/common.vcxproj.filters
+++ b/builds/win32/msvc15/common.vcxproj.filters
@@ -449,7 +449,7 @@
headers
-
+
headers
diff --git a/builds/win32/msvc15/common_test.vcxproj b/builds/win32/msvc15/common_test.vcxproj
index 8ba6d3fc3e..85d411e994 100644
--- a/builds/win32/msvc15/common_test.vcxproj
+++ b/builds/win32/msvc15/common_test.vcxproj
@@ -181,7 +181,11 @@
+
+
+
+
@@ -197,4 +201,4 @@
-
\ No newline at end of file
+
diff --git a/builds/win32/msvc15/common_test.vcxproj.filters b/builds/win32/msvc15/common_test.vcxproj.filters
index 3e8ce6deae..cf423d69fd 100644
--- a/builds/win32/msvc15/common_test.vcxproj.filters
+++ b/builds/win32/msvc15/common_test.vcxproj.filters
@@ -30,11 +30,23 @@
source
+
+ source
+
source
+
+ source
+
+
+ source
+
+
+ source
+
source
-
\ No newline at end of file
+
diff --git a/doc/README.replication.md b/doc/README.replication.md
index 4d7ee04996..3fc48f6d13 100644
--- a/doc/README.replication.md
+++ b/doc/README.replication.md
@@ -47,7 +47,8 @@ ALTER DATABASE EXCLUDE ALL FROM PUBLICATION
-- to disable replication of specific tables:
ALTER DATABASE EXCLUDE TABLE T1, T2, T3 FROM PUBLICATION
-Tables enabled for replicated can be additionally filtered using two settings in the configuration file: include\_filter and exclude\_filter. They are regular expressions that are applied to table names and define rules for inclusion table\(s\) into the replication set or excluding them from the replication set.
+Tables enabled for replicated can be additionally filtered using four settings in the configuration file: include\_schema\_filter, exclude\_schema\_filter, include\_filter and exclude\_filter.
+They are regular expressions that are applied to schema and table names and define rules for inclusion table\(s\) into the replication set or excluding them from the replication set.
Synchronous replication can be turned on using the sync\_replica setting \(multiple entries are allowed\). It must specify a connection string to the replica database, prefixed with username/password. In SuperServer and SuperClassic architectures, replica database is being internally attached when the first user gets connected to the master database and detached when the last user disconnects from the master database. In Classic Server architecture, every server process keeps an active connection to the replica database.
diff --git a/doc/sql.extensions/README.ddl_triggers.txt b/doc/sql.extensions/README.ddl_triggers.txt
index 1ddcd8c1ba..a146f94a33 100644
--- a/doc/sql.extensions/README.ddl_triggers.txt
+++ b/doc/sql.extensions/README.ddl_triggers.txt
@@ -119,6 +119,7 @@ DDL_TRIGGER context namespace:
- EVENT_TYPE: event type (CREATE, ALTER, DROP)
- OBJECT_TYPE: object type (TABLE, VIEW, etc)
- DDL_EVENT: event name (), where is EVENT_TYPE || ' ' || OBJECT_TYPE
+ - SCHEMA_NAME: object's schema name
- OBJECT_NAME: metadata object name
- OLD_OBJECT_NAME: metadata object name before a rename
- NEW_OBJECT_NAME: metadata object name after a rename
@@ -294,51 +295,51 @@ commit;
select id, ddl_event, object_name, old_object_name, new_object_name, sql_text, ok from ddl_log order by id;
- ID DDL_EVENT OBJECT_NAME OLD_OBJECT_NAME NEW_OBJECT_NAME SQL_TEXT OK
-===================== ========================= =============================== =============================== =============================== ================= ======
- 2 CREATE TABLE T1 80:0 Y
+ ID DDL_EVENT OBJECT_NAME OLD_OBJECT_NAME NEW_OBJECT_NAME SQL_TEXT OK
+===================== ========================= =============================== =============================== =============================== ================= ======
+ 2 CREATE TABLE T1 80:0 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
recreate table t1 (
n1 integer,
n2 integer
)
==============================================================================
- 3 CREATE TABLE T1 80:1 N
+ 3 CREATE TABLE T1 80:1 N
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
create table t1 (
n1 integer,
n2 integer
)
==============================================================================
- 4 DROP TABLE T1 80:2 Y
+ 4 DROP TABLE T1 80:2 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
recreate table t1 (
n integer
)
==============================================================================
- 5 CREATE TABLE T1 80:3 Y
+ 5 CREATE TABLE T1 80:3 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
recreate table t1 (
n integer
)
==============================================================================
- 6 CREATE DOMAIN DOM1 80:4 Y
+ 6 CREATE DOMAIN DOM1 80:4 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
create domain dom1 as integer
==============================================================================
- 7 ALTER DOMAIN DOM1 80:5 Y
+ 7 ALTER DOMAIN DOM1 80:5 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
alter domain dom1 type bigint
==============================================================================
- 8 ALTER DOMAIN DOM1 DOM1 DOM2 80:6 Y
+ 8 ALTER DOMAIN DOM1 DOM1 DOM2 80:6 Y
==============================================================================
-SQL_TEXT:
+SQL_TEXT:
alter domain dom1 to dom2
==============================================================================
diff --git a/doc/sql.extensions/README.profiler.md b/doc/sql.extensions/README.profiler.md
index 3d74055442..ecdb2e3845 100644
--- a/doc/sql.extensions/README.profiler.md
+++ b/doc/sql.extensions/README.profiler.md
@@ -109,6 +109,8 @@ execute procedure rdb$profiler.finish_session(true);
-- Data analysis
+set search_path to plg$profiler, public, system;
+
set transaction read committed;
select * from plg$prof_sessions;
@@ -243,7 +245,9 @@ Input parameters:
# Snapshot tables
-Snapshot tables (as well views and sequence) are automatically created in the first usage of the profiler. They are owned by the database owner, with read/write permissions for `PUBLIC`.
+The profiler schema, snapshot tables, views and sequence are automatically created in the first usage of the profiler.
+
+They are owned by the database owner, with usage/read/write permissions for the RDB$PROFILER role, granted by default to `PUBLIC`.
When a session is deleted, the related data in other profiler snapshot tables are automatically deleted too through foreign keys with `DELETE CASCADE` option.
diff --git a/doc/sql.extensions/README.sql_package.md b/doc/sql.extensions/README.sql_package.md
index 676b000f0b..3f2140b5c3 100644
--- a/doc/sql.extensions/README.sql_package.md
+++ b/doc/sql.extensions/README.sql_package.md
@@ -17,6 +17,7 @@ Output parameters:
- `RECORD_SOURCE_ID` type `BIGINT NOT NULL` - record source id
- `PARENT_RECORD_SOURCE_ID` type `BIGINT` - parent record source id
- `LEVEL` type `INTEGER NOT NULL` - indentation level (may have gaps in relation to parent's level)
+- `SCHEMA_NAME` type `RDB$SCHEMA_NAME` - schema name of a stored procedure
- `PACKAGE_NAME` type `RDB$PACKAGE_NAME` - package name of a stored procedure
- `OBJECT_NAME` type `RDB$RELATION_NAME` - object (table, procedure) name
- `ALIAS` type `RDB$SHORT_DESCRIPTION` - alias name
diff --git a/examples/replication/fbSampleReplicator.cpp b/examples/replication/fbSampleReplicator.cpp
index fcf59537b2..84dc3037c8 100644
--- a/examples/replication/fbSampleReplicator.cpp
+++ b/examples/replication/fbSampleReplicator.cpp
@@ -35,7 +35,8 @@ public:
void setAttachment(IAttachment* attachment) override;
IReplicatedTransaction* startTransaction(ITransaction* transaction, ISC_INT64 number) override;
FB_BOOLEAN cleanupTransaction(ISC_INT64 number) override;
- FB_BOOLEAN setSequence(const char* name, ISC_INT64 value) override;
+ FB_BOOLEAN deprecatedSetSequence(const char* name, ISC_INT64 value) override;
+ FB_BOOLEAN setSequence2(const char* schemaName, const char* genName, ISC_INT64 value) override;
private:
friend class ReplTransaction;
@@ -64,11 +65,17 @@ public:
FB_BOOLEAN startSavepoint() override;
FB_BOOLEAN releaseSavepoint() override;
FB_BOOLEAN rollbackSavepoint() override;
- FB_BOOLEAN insertRecord(const char* name, IReplicatedRecord* record) override;
- FB_BOOLEAN updateRecord(const char* name, IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord) override;
- FB_BOOLEAN deleteRecord(const char* name, IReplicatedRecord* record) override;
- FB_BOOLEAN executeSql(const char* sql) override;
- FB_BOOLEAN executeSqlIntl(unsigned charset, const char* sql) override;
+ FB_BOOLEAN deprecatedInsertRecord(const char* name, IReplicatedRecord* record) override;
+ FB_BOOLEAN insertRecord2(const char* schemaName, const char* tableName, IReplicatedRecord* record) override;
+ FB_BOOLEAN deprecatedUpdateRecord(const char* name,
+ IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord) override;
+ FB_BOOLEAN updateRecord2(const char* schemaName, const char* tableName,
+ IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord) override;
+ FB_BOOLEAN deprecatedDeleteRecord(const char* name, IReplicatedRecord* record) override;
+ FB_BOOLEAN deleteRecord2(const char* schemaName, const char* tableName, IReplicatedRecord* record) override;
+ FB_BOOLEAN deprecatedExecuteSql(const char* sql) override;
+ FB_BOOLEAN deprecatedExecuteSqlIntl(unsigned charset, const char* sql) override;
+ FB_BOOLEAN executeSqlIntl2(unsigned charset, const char* schemaSearchPath, const char* sql) override;
private:
ReplPlugin* parent;
@@ -245,9 +252,15 @@ FB_BOOLEAN ReplPlugin::cleanupTransaction(ISC_INT64 number)
return FB_TRUE;
}
-FB_BOOLEAN ReplPlugin::setSequence(const char* name, ISC_INT64 value)
+FB_BOOLEAN ReplPlugin::deprecatedSetSequence(const char* name, ISC_INT64 value)
{
- WriteLog(log, "%p\tsetSequence(%s, %lld)\n", this, name, value);
+ WriteLog(log, "%p\tdeprecatedSetSequence(%s, %lld)\n", this, name, value);
+ return FB_TRUE;
+}
+
+FB_BOOLEAN ReplPlugin::setSequence2(const char* schemaName, const char* genName, ISC_INT64 value)
+{
+ WriteLog(log, "%p\tsetSequence2(%s.%s, %lld)\n", this, schemaName, genName, value);
return FB_TRUE;
}
@@ -506,9 +519,9 @@ bool ReplTransaction::dumpData(IReplicatedRecord* record)
return true;
}
-FB_BOOLEAN ReplTransaction::insertRecord(const char* name, IReplicatedRecord* record)
+FB_BOOLEAN ReplTransaction::deprecatedInsertRecord(const char* name, IReplicatedRecord* record)
{
- WriteLog(parent->log, "%p\tInsert record into %s\n", this, name);
+ WriteLog(parent->log, "%p\tdeprecated Insert record into %s\n", this, name);
try
{
return dumpData(record) ? FB_TRUE : FB_FALSE;
@@ -520,9 +533,24 @@ FB_BOOLEAN ReplTransaction::insertRecord(const char* name, IReplicatedRecord* re
}
}
-FB_BOOLEAN ReplTransaction::updateRecord(const char* name, IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord)
+FB_BOOLEAN ReplTransaction::insertRecord2(const char* schemaName, const char* tableName, IReplicatedRecord* record)
{
- WriteLog(parent->log, "%p\tUpdate %s\nOldData:\n", this, name);
+ WriteLog(parent->log, "%p\tInsert record into %s.%s\n", this, schemaName, tableName);
+ try
+ {
+ return dumpData(record) ? FB_TRUE : FB_FALSE;
+ }
+ catch (const int)
+ {
+ parent->status->setErrors(err);
+ return FB_FALSE;
+ }
+}
+
+FB_BOOLEAN ReplTransaction::deprecatedUpdateRecord(const char* name,
+ IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord)
+{
+ WriteLog(parent->log, "%p\tdeprecated Update %s\nOldData:\n", this, name);
try
{
if (!dumpData(orgRecord))
@@ -538,9 +566,28 @@ FB_BOOLEAN ReplTransaction::updateRecord(const char* name, IReplicatedRecord* or
}
}
-FB_BOOLEAN ReplTransaction::deleteRecord(const char* name, IReplicatedRecord* record)
+FB_BOOLEAN ReplTransaction::updateRecord2(const char* schemaName, const char* tableName,
+ IReplicatedRecord* orgRecord, IReplicatedRecord* newRecord)
{
- WriteLog(parent->log, "%p\tDelete from %s\n", this, name);
+ WriteLog(parent->log, "%p\tUpdate %s.%s\nOldData:\n", this, schemaName, tableName);
+ try
+ {
+ if (!dumpData(orgRecord))
+ return FB_FALSE;
+
+ WriteLog(parent->log, "NewData:\n");
+ return dumpData(newRecord) ? FB_TRUE : FB_FALSE;
+ }
+ catch (const int)
+ {
+ parent->status->setErrors(err);
+ return FB_FALSE;
+ }
+}
+
+FB_BOOLEAN ReplTransaction::deprecatedDeleteRecord(const char* name, IReplicatedRecord* record)
+{
+ WriteLog(parent->log, "%p\tdeprecated Delete from %s\n", this, name);
try
{
return dumpData(record) ? FB_TRUE : FB_FALSE;
@@ -552,14 +599,34 @@ FB_BOOLEAN ReplTransaction::deleteRecord(const char* name, IReplicatedRecord* re
}
}
-FB_BOOLEAN ReplTransaction::executeSql(const char* sql)
+FB_BOOLEAN ReplTransaction::deleteRecord2(const char* schemaName, const char* tableName, IReplicatedRecord* record)
{
- WriteLog(parent->log, "%p\tExecuteSql(%s)\n", this, sql);
+ WriteLog(parent->log, "%p\tDelete from %s.%s\n", this, schemaName, tableName);
+ try
+ {
+ return dumpData(record) ? FB_TRUE : FB_FALSE;
+ }
+ catch (const int)
+ {
+ parent->status->setErrors(err);
+ return FB_FALSE;
+ }
+}
+
+FB_BOOLEAN ReplTransaction::deprecatedExecuteSql(const char* sql)
+{
+ WriteLog(parent->log, "%p\tdeprecatedExecuteSql(%s)\n", this, sql);
return FB_TRUE;
}
-FB_BOOLEAN ReplTransaction::executeSqlIntl(unsigned charset, const char* sql)
+FB_BOOLEAN ReplTransaction::deprecatedExecuteSqlIntl(unsigned charset, const char* sql)
{
- WriteLog(parent->log, "%p\tExecuteSqlIntl(%u, %s)\n", this, charset, sql);
+ WriteLog(parent->log, "%p\tdeprecatedExecuteSqlIntl(%u, %s)\n", this, charset, sql);
+ return FB_TRUE;
+}
+
+FB_BOOLEAN ReplTransaction::executeSqlIntl2(unsigned charset, const char* schemaSearchPath, const char* sql)
+{
+ WriteLog(parent->log, "%p\tExecuteSqlIntl2(%u, %s, %s)\n", this, charset, schemaSearchPath, sql);
return FB_TRUE;
}
diff --git a/src/alice/exe.cpp b/src/alice/exe.cpp
index bd56dc06e6..43c4c93f5b 100644
--- a/src/alice/exe.cpp
+++ b/src/alice/exe.cpp
@@ -202,6 +202,7 @@ static void buildDpb(Firebird::ClumpletWriter& dpb, const SINT64 switches)
dpb.reset(isc_dpb_version1);
dpb.insertTag(isc_dpb_gfix_attach);
tdgbl->uSvc->fillDpb(dpb);
+ dpb.insertString(isc_dpb_search_path, SYSTEM_SCHEMA, fb_strlen(SYSTEM_SCHEMA));
if (switches & sw_sweep) {
dpb.insertByte(isc_dpb_sweep, isc_dpb_records);
diff --git a/src/auth/SecureRemotePassword/manage/SrpManagement.cpp b/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
index db795d0312..7264d9addd 100644
--- a/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
+++ b/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
@@ -68,28 +68,28 @@ private:
void prepareDataStructures()
{
const char* script[] = {
- "CREATE TABLE PLG$SRP (PLG$USER_NAME SEC$USER_NAME NOT NULL PRIMARY KEY, "
+ "CREATE TABLE PUBLIC.PLG$SRP (PLG$USER_NAME SYSTEM.SEC$USER_NAME NOT NULL PRIMARY KEY, "
"PLG$VERIFIER VARCHAR(128) CHARACTER SET OCTETS NOT NULL, "
"PLG$SALT VARCHAR(32) CHARACTER SET OCTETS NOT NULL, "
- "PLG$COMMENT RDB$DESCRIPTION, PLG$FIRST SEC$NAME_PART, "
- "PLG$MIDDLE SEC$NAME_PART, PLG$LAST SEC$NAME_PART, "
- "PLG$ATTRIBUTES RDB$DESCRIPTION, "
+ "PLG$COMMENT SYSTEM.RDB$DESCRIPTION, PLG$FIRST SYSTEM.SEC$NAME_PART, "
+ "PLG$MIDDLE SYSTEM.SEC$NAME_PART, PLG$LAST SYSTEM.SEC$NAME_PART, "
+ "PLG$ATTRIBUTES SYSTEM.RDB$DESCRIPTION, "
"PLG$ACTIVE BOOLEAN)"
,
- "CREATE VIEW PLG$SRP_VIEW AS "
+ "CREATE VIEW PUBLIC.PLG$SRP_VIEW AS "
"SELECT PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$COMMENT, "
" PLG$FIRST, PLG$MIDDLE, PLG$LAST, PLG$ATTRIBUTES, PLG$ACTIVE "
- "FROM PLG$SRP WHERE RDB$SYSTEM_PRIVILEGE(USER_MANAGEMENT) "
+ "FROM PUBLIC.PLG$SRP WHERE RDB$SYSTEM_PRIVILEGE(USER_MANAGEMENT) "
" OR CURRENT_USER = PLG$SRP.PLG$USER_NAME"
,
- "GRANT ALL ON PLG$SRP TO VIEW PLG$SRP_VIEW"
+ "GRANT ALL ON PUBLIC.PLG$SRP TO VIEW PUBLIC.PLG$SRP_VIEW"
,
- "GRANT SELECT ON PLG$SRP_VIEW TO PUBLIC"
+ "GRANT SELECT ON PUBLIC.PLG$SRP_VIEW TO PUBLIC"
,
"GRANT UPDATE(PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST, "
- " PLG$COMMENT, PLG$ATTRIBUTES) ON PLG$SRP_VIEW TO PUBLIC"
+ " PLG$COMMENT, PLG$ATTRIBUTES) ON PUBLIC.PLG$SRP_VIEW TO PUBLIC"
,
- "GRANT ALL ON PLG$SRP_VIEW TO SYSTEM PRIVILEGE USER_MANAGEMENT"
+ "GRANT ALL ON PUBLIC.PLG$SRP_VIEW TO SYSTEM PRIVILEGE USER_MANAGEMENT"
,
NULL
};
@@ -160,7 +160,7 @@ private:
Firebird::string userName2(user->userName()->get());
prepareName(userName2, '\'');
Firebird::string selGrantor;
- selGrantor.printf("SELECT RDB$GRANTOR FROM RDB$USER_PRIVILEGES "
+ selGrantor.printf("SELECT RDB$GRANTOR FROM SYSTEM.RDB$USER_PRIVILEGES "
"WHERE RDB$USER = '%s' AND RDB$RELATION_NAME = '%s' AND RDB$PRIVILEGE = 'M'",
userName2.c_str(), ADMIN_ROLE);
Message out;
@@ -353,7 +353,7 @@ public:
case Firebird::IUser::OP_USER_ADD:
{
const char* insert =
- "INSERT INTO plg$srp_view(PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST,"
+ "INSERT INTO public.plg$srp_view(PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST,"
"PLG$COMMENT, PLG$ATTRIBUTES, PLG$ACTIVE) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)";
Firebird::IStatement* stmt = NULL;
@@ -455,7 +455,7 @@ public:
case Firebird::IUser::OP_USER_MODIFY:
{
- Firebird::string update = "UPDATE plg$srp_view SET ";
+ Firebird::string update = "UPDATE public.plg$srp_view SET ";
Firebird::AutoPtr verifier, slt;
if (user->password()->entered())
@@ -558,7 +558,7 @@ public:
case Firebird::IUser::OP_USER_DELETE:
{
- const char* del = "DELETE FROM plg$srp_view WHERE PLG$USER_NAME=?";
+ const char* del = "DELETE FROM public.plg$srp_view WHERE PLG$USER_NAME=?";
Firebird::IStatement* stmt = NULL;
try
{
@@ -601,11 +601,11 @@ public:
case Firebird::IUser::OP_USER_DISPLAY:
{
Firebird::string disp =
- "WITH ADMINS AS (SELECT RDB$USER FROM RDB$USER_PRIVILEGES "
+ "WITH ADMINS AS (SELECT RDB$USER FROM SYSTEM.RDB$USER_PRIVILEGES "
" WHERE RDB$RELATION_NAME = 'RDB$ADMIN' AND RDB$PRIVILEGE = 'M' GROUP BY RDB$USER) "
"SELECT PLG$USER_NAME, PLG$FIRST, PLG$MIDDLE, PLG$LAST, PLG$COMMENT, PLG$ATTRIBUTES, "
" CASE WHEN RDB$USER IS NULL THEN FALSE ELSE TRUE END, PLG$ACTIVE "
- "FROM PLG$SRP_VIEW LEFT JOIN ADMINS "
+ "FROM SYSTEM.PLG$SRP_VIEW LEFT JOIN ADMINS "
" ON PLG$SRP_VIEW.PLG$USER_NAME = ADMINS.RDB$USER ";
if (user->userName()->entered())
{
diff --git a/src/auth/SecureRemotePassword/server/SrpServer.cpp b/src/auth/SecureRemotePassword/server/SrpServer.cpp
index 3d7abb15f7..f88efbace0 100644
--- a/src/auth/SecureRemotePassword/server/SrpServer.cpp
+++ b/src/auth/SecureRemotePassword/server/SrpServer.cpp
@@ -196,7 +196,7 @@ public:
HANDSHAKE_DEBUG(fprintf(stderr, "Srv: SRP1: started transaction\n"));
const char* sql =
- "SELECT PLG$VERIFIER, PLG$SALT FROM PLG$SRP WHERE PLG$USER_NAME = ? AND PLG$ACTIVE";
+ "SELECT PLG$VERIFIER, PLG$SALT FROM PUBLIC.PLG$SRP WHERE PLG$USER_NAME = ? AND PLG$ACTIVE";
stmt = att->prepare(&status, tra, 0, sql, 3, IStatement::PREPARE_PREFETCH_METADATA);
if (status->getState() & IStatus::STATE_ERRORS)
{
diff --git a/src/auth/SecurityDatabase/LegacyManagement.epp b/src/auth/SecurityDatabase/LegacyManagement.epp
index 80cbc070dc..fb57ace891 100644
--- a/src/auth/SecurityDatabase/LegacyManagement.epp
+++ b/src/auth/SecurityDatabase/LegacyManagement.epp
@@ -129,6 +129,7 @@ void SecurityDatabaseManagement::start(Firebird::CheckStatusWrapper* st, Firebir
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::dpbList, MAX_DPB_SIZE);
dpb.insertByte(isc_dpb_sec_attach, TRUE);
dpb.insertString(isc_dpb_config, Firebird::ParsedList::getNonLoopbackProviders(secDbName));
+ dpb.insertString(isc_dpb_search_path, SYSTEM_SCHEMA, fb_strlen(SYSTEM_SCHEMA)); // FIXME: plugin schema
unsigned int authBlockSize;
const unsigned char* authBlock = logonInfo->authBlock(&authBlockSize);
@@ -343,6 +344,7 @@ int SecurityDatabaseManagement::execute(Firebird::CheckStatusWrapper* st, Firebi
// this checks the "entered" flags for each parameter (except the name)
// and makes all non-entered parameters null valued
+ // FIXME: epp queries outside engine has not exclusive schema search path set to SYSTEM
STORE (TRANSACTION_HANDLE transaction REQUEST_HANDLE request) U IN PLG$VIEW_USERS USING
STR_STORE(U.PLG$USER_NAME, user->userName()->get());
diff --git a/src/auth/SecurityDatabase/LegacyServer.cpp b/src/auth/SecurityDatabase/LegacyServer.cpp
index 03715e9615..4b59c8709d 100644
--- a/src/auth/SecurityDatabase/LegacyServer.cpp
+++ b/src/auth/SecurityDatabase/LegacyServer.cpp
@@ -64,7 +64,11 @@ const UCHAR PWD_REQUEST[] =
blr_begin,
blr_for,
blr_rse, 1,
- blr_relation, 9, 'P', 'L', 'G', '$', 'U', 'S', 'E', 'R', 'S', 0,
+ blr_relation3,
+ 6, 'P', 'U', 'B', 'L', 'I', 'C', // PUBLIC_SCHEMA // FIXME:
+ 9, 'P', 'L', 'G', '$', 'U', 'S', 'E', 'R', 'S',
+ 0,
+ 0,
blr_first,
blr_literal, blr_short, 0, 1, 0,
blr_boolean,
diff --git a/src/burp/BurpTasks.cpp b/src/burp/BurpTasks.cpp
index 396e1d7ea5..af4d4c6b4b 100644
--- a/src/burp/BurpTasks.cpp
+++ b/src/burp/BurpTasks.cpp
@@ -561,7 +561,7 @@ bool BackupRelationTask::fileWriter(Item& item)
BurpGlobals* tdgbl = item.m_gbl;
fb_assert(tdgbl == m_masterGbl);
- BURP_verbose(142, m_relation->rel_name);
+ BURP_verbose(142, m_relation->rel_name.toQuotedString().c_str());
// msg 142 writing data for relation %s
IOBuffer*& buf = item.m_buffer = NULL;
diff --git a/src/burp/OdsDetection.epp b/src/burp/OdsDetection.epp
index 024adfe776..2ca6036133 100644
--- a/src/burp/OdsDetection.epp
+++ b/src/burp/OdsDetection.epp
@@ -45,6 +45,7 @@ namespace
{"RDB$ROLES", 0, DB_VERSION_DDL9}, // IB5
{"RDB$PACKAGES", 0, DB_VERSION_DDL12}, // FB3
{"RDB$PUBLICATIONS", 0, DB_VERSION_DDL13}, // FB4
+ {"RDB$SCHEMAS", 0, DB_VERSION_DDL14}, // FB6
{0, 0, 0}
};
@@ -102,13 +103,16 @@ void detectRuntimeODS()
Firebird::IRequest* req_handle = nullptr;
FOR (REQUEST_HANDLE req_handle)
RFR IN RDB$RELATION_FIELDS
- WITH (RFR.RDB$RELATION_NAME = 'RDB$RELATIONS' OR RFR.RDB$RELATION_NAME = 'RDB$RELATION_FIELDS')
- AND RFR.RDB$FIELD_NAME = 'RDB$SYSTEM_FLAG'
+ WITH (RFR.RDB$RELATION_NAME = 'RDB$RELATIONS' OR RFR.RDB$RELATION_NAME = 'RDB$RELATION_FIELDS') AND
+ RFR.RDB$FIELD_NAME = 'RDB$SYSTEM_FLAG' AND
+ (RFR.RDB$SCHEMA_NAME MISSING OR RFR.RDB$SCHEMA_NAME = SYSTEM_SCHEMA)
+ {
++count;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle);
if (count != 2)
@@ -119,14 +123,17 @@ void detectRuntimeODS()
{
FOR (REQUEST_HANDLE req_handle2)
FIRST 1 X IN RDB$RELATIONS
- WITH X.RDB$RELATION_NAME = rel->relation
- AND X.RDB$SYSTEM_FLAG = 1
+ WITH X.RDB$RELATION_NAME = rel->relation AND
+ X.RDB$SYSTEM_FLAG = 1 AND
+ (X.RDB$SCHEMA_NAME MISSING OR X.RDB$SCHEMA_NAME = SYSTEM_SCHEMA)
+ {
if (tdgbl->runtimeODS < rel->ods_version)
tdgbl->runtimeODS = rel->ods_version;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle2);
@@ -138,15 +145,18 @@ void detectRuntimeODS()
{
FOR (REQUEST_HANDLE req_handle3)
FIRST 1 X2 IN RDB$RELATION_FIELDS
- WITH X2.RDB$RELATION_NAME = rf->relation
- AND X2.RDB$FIELD_NAME = rf->field
- AND X2.RDB$SYSTEM_FLAG = 1
+ WITH X2.RDB$RELATION_NAME = rf->relation AND
+ X2.RDB$FIELD_NAME = rf->field AND
+ X2.RDB$SYSTEM_FLAG = 1 AND
+ (X2.RDB$SCHEMA_NAME MISSING OR X2.RDB$SCHEMA_NAME = SYSTEM_SCHEMA)
+ {
if (tdgbl->runtimeODS < rf->ods_version)
tdgbl->runtimeODS = rf->ods_version;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle3);
}
diff --git a/src/burp/OdsDetection.h b/src/burp/OdsDetection.h
index 5abaf29852..a22087c160 100644
--- a/src/burp/OdsDetection.h
+++ b/src/burp/OdsDetection.h
@@ -69,6 +69,7 @@ const int DB_VERSION_DDL11_2 = 112; // ods11.2 db, FB2.5
const int DB_VERSION_DDL12 = 120; // ods12.0 db, FB3.0
const int DB_VERSION_DDL13 = 130; // ods13.0 db, FB4.0
const int DB_VERSION_DDL13_1 = 131; // ods13.1 db, FB5.0
+const int DB_VERSION_DDL14 = 140; // ods14 db, FB6.0
const int DB_VERSION_OLDEST_SUPPORTED = DB_VERSION_DDL8; // IB4.0 is ods8
diff --git a/src/burp/backup.epp b/src/burp/backup.epp
index ebfe71f168..0d59b58adf 100644
--- a/src/burp/backup.epp
+++ b/src/burp/backup.epp
@@ -111,7 +111,7 @@ inline const UCHAR* put_block(BurpGlobals* tdgbl, const UCHAR* p, ULONG n)
void compress(const UCHAR*, ULONG);
int copy(const TEXT*, TEXT*, ULONG);
burp_fld* get_fields(burp_rel*);
-SINT64 get_gen_id(const TEXT*, SSHORT);
+SINT64 get_gen_id(const QualifiedMetaString& name);
void get_ranges(burp_fld*);
void put_array(burp_fld*, burp_rel*, ISC_QUAD*);
void put_asciz(const att_type, const TEXT*);
@@ -126,6 +126,7 @@ void put_boolean(att_type, FB_BOOLEAN value);
void put_relation(burp_rel*);
bool put_source_blob(att_type, att_type, ISC_QUAD&);
int put_text(att_type, const TEXT*, SSHORT);
+int put_text(att_type attribute, const MetaString& name);
void write_character_sets();
void write_check_constraints();
void write_collations();
@@ -134,7 +135,7 @@ void write_exceptions();
void write_field_dimensions();
void write_filters();
void write_functions();
-void write_function_args(const GDS_NAME, GDS_NAME);
+void write_function_args(const QualifiedMetaString& name);
void write_global_fields();
void write_generators();
void write_sql_roles();
@@ -142,12 +143,13 @@ void write_mapping();
void write_db_creators();
void write_packages();
void write_procedures();
-void write_procedure_prms(const GDS_NAME, const GDS_NAME);
+void write_procedure_prms(const QualifiedMetaString& name);
void write_publications();
void write_pub_tables();
void write_ref_constraints();
void write_rel_constraints();
void write_relations();
+void write_schemas();
void write_secclasses();
void write_shadow_files();
void write_triggers();
@@ -338,6 +340,13 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
write_database(dbb_file);
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ {
+ // Write schemas
+ BURP_verbose(412); // msg 412 writing schemas
+ write_schemas();
+ }
+
// Write global fields
BURP_verbose(150);
@@ -411,7 +420,12 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
for (burp_rel* relation = tdgbl->relations; relation; relation = relation->rel_next)
{
put(tdgbl, (UCHAR) rec_relation_data);
- PUT_TEXT(att_relation_name, relation->rel_name);
+
+ if (relation->rel_name.schema.hasData())
+ put_text(att_relation_schema_name, relation->rel_name.schema);
+
+ put_text(att_relation_name, relation->rel_name.object);
+
put(tdgbl, att_end);
if (!(relation->rel_flags & REL_view) && !(relation->rel_flags & REL_external))
@@ -656,8 +670,10 @@ burp_fld* get_fields( burp_rel* relation)
FOR (REQUEST_HANDLE tdgbl->handles_get_fields_req_handle1)
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$FIELDS WITH
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME EQUIV Y.RDB$SCHEMA_NAME AND
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME AND
- X.RDB$RELATION_NAME EQ relation->rel_name
+ X.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ X.RDB$RELATION_NAME EQ relation->rel_name.object.c_str()
{
field = (burp_fld*) BURP_alloc_zero(sizeof(burp_fld));
field->fld_number = count++;
@@ -692,7 +708,12 @@ burp_fld* get_fields( burp_rel* relation)
field->fld_update_flag = X.RDB$UPDATE_FLAG;
COPY (X.RDB$FIELD_NAME, field->fld_name);
- COPY (X.RDB$FIELD_SOURCE, field->fld_source);
+
+ if (!X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL)
+ field->fld_source.schema = X.RDB$FIELD_SOURCE_SCHEMA_NAME;
+
+ field->fld_source.object = X.RDB$FIELD_SOURCE;
+
COPY (X.RDB$BASE_FIELD, field->fld_base);
COPY (X.RDB$QUERY_NAME, field->fld_query_name);
COPY (X.RDB$EDIT_STRING, field->fld_edit_string);
@@ -776,7 +797,7 @@ burp_fld* get_fields( burp_rel* relation)
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$FIELDS WITH
X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME AND
- X.RDB$RELATION_NAME EQ relation->rel_name
+ X.RDB$RELATION_NAME EQ relation->rel_name.object.c_str()
{
field = (burp_fld*) BURP_alloc_zero(sizeof(burp_fld));
field->fld_number = count++;
@@ -811,7 +832,7 @@ burp_fld* get_fields( burp_rel* relation)
field->fld_update_flag = X.RDB$UPDATE_FLAG;
COPY (X.RDB$FIELD_NAME, field->fld_name);
- COPY (X.RDB$FIELD_SOURCE, field->fld_source);
+ field->fld_source.object = X.RDB$FIELD_SOURCE;
COPY (X.RDB$BASE_FIELD, field->fld_base);
COPY (X.RDB$QUERY_NAME, field->fld_query_name);
COPY (X.RDB$EDIT_STRING, field->fld_edit_string);
@@ -896,7 +917,7 @@ burp_fld* get_fields( burp_rel* relation)
}
-SINT64 get_gen_id( const TEXT* name, SSHORT name_len)
+SINT64 get_gen_id(const QualifiedMetaString& name)
{
/**************************************
*
@@ -912,10 +933,8 @@ SINT64 get_gen_id( const TEXT* name, SSHORT name_len)
{
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
- Firebird::string nm, sql;
- nm.assign(name, name_len);
- BURP_makeSymbol(tdgbl, nm);
- sql = "select first(1) gen_id(" + nm + ", 0) from rdb$database";
+ Firebird::string sql;
+ sql = "select first(1) gen_id(" + name.toQuotedString() + ", 0) from rdb$database";
BurpSql getGenerator(tdgbl, sql.c_str());
FB_MESSAGE(GetGen, Firebird::ThrowWrapper, (FB_BIGINT, id));
@@ -961,20 +980,21 @@ void get_ranges( burp_fld* field)
FOR (REQUEST_HANDLE tdgbl->handles_get_ranges_req_handle1)
X IN RDB$FIELD_DIMENSIONS
- WITH X.RDB$FIELD_NAME EQ field->fld_source
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(field->fld_source.schema.c_str(), '') AND
+ X.RDB$FIELD_NAME EQ field->fld_source.object.c_str()
SORTED BY X.RDB$DIMENSION
-
+ {
if (count != X.RDB$DIMENSION)
BURP_error_redirect (NULL, 52, SafeArg() << field->fld_name);
// msg 52 array dimension for field %s is invalid
*rp++ = X.RDB$LOWER_BOUND;
*rp++ = X.RDB$UPPER_BOUND;
count++;
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
if (count != field->fld_dimensions)
BURP_error_redirect(NULL, 52, SafeArg() << field->fld_name);
@@ -1611,7 +1631,6 @@ void put_index( burp_rel* relation)
*
**************************************/
ULONG count;
- TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -1625,19 +1644,22 @@ void put_index( burp_rel* relation)
{
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle1)
X IN RDB$INDICES WITH
- X.RDB$RELATION_NAME EQ relation->rel_name
-
+ X.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ X.RDB$RELATION_NAME EQ relation->rel_name.object.c_str()
+ {
count = 0;
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle2)
I_S IN RDB$INDEX_SEGMENTS CROSS
RFR IN RDB$RELATION_FIELDS WITH
I_S.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND
+ I_S.RDB$SCHEMA_NAME EQUIV X.RDB$SCHEMA_NAME AND
I_S.RDB$INDEX_NAME = X.RDB$INDEX_NAME AND
- RFR.RDB$RELATION_NAME = relation->rel_name
-
+ RFR.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ RFR.RDB$RELATION_NAME = relation->rel_name.object.c_str()
+ {
count++;
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -1649,22 +1671,23 @@ void put_index( burp_rel* relation)
}
put(tdgbl, rec_index);
- const ULONG l = PUT_TEXT (att_index_name, X.RDB$INDEX_NAME);
- MISC_terminate (X.RDB$INDEX_NAME, temp, l, sizeof(temp));
- BURP_verbose (151, temp);
+ PUT_TEXT(att_index_name, X.RDB$INDEX_NAME);
+ BURP_verbose(151, QualifiedMetaString(X.RDB$INDEX_NAME, relation->rel_name.schema).toQuotedString().c_str());
// msg 151 writing index %s
+
put_int32 (att_segment_count, X.RDB$SEGMENT_COUNT);
put_int32 (att_index_inactive, X.RDB$INDEX_INACTIVE);
put_int32 (att_index_unique_flag, X.RDB$UNIQUE_FLAG);
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle5)
Y IN RDB$INDEX_SEGMENTS WITH
+ Y.RDB$SCHEMA_NAME EQUIV X.RDB$SCHEMA_NAME AND
Y.RDB$INDEX_NAME EQ X.RDB$INDEX_NAME
SORTED BY Y.RDB$FIELD_POSITION
-
+ {
PUT_TEXT (att_index_field_name, Y.RDB$FIELD_NAME);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -1680,6 +1703,9 @@ void put_index( burp_rel* relation)
if (!X.RDB$EXPRESSION_BLR.NULL)
put_blr_blob(att_index_expression_blr, X.RDB$EXPRESSION_BLR);
+ if (!X.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_index_foreign_key_schema_name, X.RDB$FOREIGN_KEY_SCHEMA_NAME);
+
if (!X.RDB$FOREIGN_KEY.NULL)
PUT_TEXT (att_index_foreign_key, X.RDB$FOREIGN_KEY);
@@ -1692,8 +1718,8 @@ void put_index( burp_rel* relation)
put_blr_blob(att_index_condition_blr, X.RDB$CONDITION_BLR);
put(tdgbl, att_end);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -1702,7 +1728,7 @@ void put_index( burp_rel* relation)
{
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle1)
X IN RDB$INDICES WITH
- X.RDB$RELATION_NAME EQ relation->rel_name
+ X.RDB$RELATION_NAME EQ relation->rel_name.object.c_str()
count = 0;
FOR (REQUEST_HANDLE tdgbl->handles_put_index_req_handle2)
@@ -1710,7 +1736,7 @@ void put_index( burp_rel* relation)
RFR IN RDB$RELATION_FIELDS WITH
I_S.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND
I_S.RDB$INDEX_NAME = X.RDB$INDEX_NAME AND
- RFR.RDB$RELATION_NAME = relation->rel_name
+ RFR.RDB$RELATION_NAME = relation->rel_name.object.c_str()
count++;
@@ -1726,9 +1752,8 @@ void put_index( burp_rel* relation)
}
put(tdgbl, rec_index);
- const ULONG l = PUT_TEXT (att_index_name, X.RDB$INDEX_NAME);
- MISC_terminate (X.RDB$INDEX_NAME, temp, l, sizeof(temp));
- BURP_verbose (151, temp);
+ PUT_TEXT(att_index_name, X.RDB$INDEX_NAME);
+ BURP_verbose(151, MetaString(X.RDB$INDEX_NAME).toQuotedString().c_str());
// msg 151 writing index %s
put_int32 (att_segment_count, X.RDB$SEGMENT_COUNT);
put_int32 (att_index_inactive, X.RDB$INDEX_INACTIVE);
@@ -1904,8 +1929,6 @@ void put_relation( burp_rel* relation)
* Write relation meta-data and data.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
-
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
// Write local field information. This is made slightly more complicated
@@ -1985,11 +2008,15 @@ void put_relation( burp_rel* relation)
for (field = relation->rel_fields; field; field = field->fld_next)
{
put(tdgbl, (UCHAR) rec_field);
- const USHORT l = PUT_TEXT(att_field_name, field->fld_name);
- MISC_terminate(field->fld_name, temp, l, sizeof(temp));
- BURP_verbose(144, temp);
+ PUT_TEXT(att_field_name, field->fld_name);
+ BURP_verbose(144, MetaString(field->fld_name).toQuotedString().c_str());
// msg 144 writing field %s
- PUT_TEXT(att_field_source, field->fld_source);
+
+ if (field->fld_source.schema.hasData())
+ put_text(att_field_schema_name, field->fld_source.schema);
+
+ put_text(att_field_source, field->fld_source.object);
+
if (field->fld_query_name[0])
PUT_TEXT(att_field_query_name, field->fld_query_name);
if (field->fld_complex_name[0])
@@ -2056,9 +2083,17 @@ void put_relation( burp_rel* relation)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
FOR (REQUEST_HANDLE tdgbl->handles_put_relation_req_handle1)
- X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ relation->rel_name
+ X IN RDB$VIEW_RELATIONS
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ X.RDB$VIEW_NAME EQ relation->rel_name.object.c_str()
+ {
put(tdgbl, rec_view);
- PUT_TEXT (att_view_relation_name, X.RDB$RELATION_NAME);
+
+ if (!X.RDB$RELATION_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_view_relation_schema_name, X.RDB$RELATION_SCHEMA_NAME);
+
+ PUT_TEXT(att_view_relation_name, X.RDB$RELATION_NAME);
+
put_int32 (att_view_context_id, X.RDB$VIEW_CONTEXT);
// Will need PUT_MESSAGE if this field grows to more than 255 bytes.
PUT_TEXT (att_view_context_name, X.RDB$CONTEXT_NAME);
@@ -2067,6 +2102,7 @@ void put_relation( burp_rel* relation)
if (!X.RDB$PACKAGE_NAME.NULL)
PUT_TEXT(att_view_context_package, X.RDB$PACKAGE_NAME);
put(tdgbl, att_end);
+ }
END_FOR
ON_ERROR
general_on_error();
@@ -2075,7 +2111,7 @@ void put_relation( burp_rel* relation)
else
{
FOR (REQUEST_HANDLE tdgbl->handles_put_relation_req_handle1)
- X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ relation->rel_name
+ X IN RDB$VIEW_RELATIONS WITH X.RDB$VIEW_NAME EQ relation->rel_name.object.c_str()
put(tdgbl, rec_view);
PUT_TEXT (att_view_relation_name, X.RDB$RELATION_NAME);
put_int32 (att_view_context_id, X.RDB$VIEW_CONTEXT);
@@ -2232,7 +2268,7 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
}
-int put_text( att_type attribute, const TEXT* text, SSHORT size_len)
+int put_text(att_type attribute, const TEXT* text, SSHORT size_len)
{
/**************************************
*
@@ -2269,6 +2305,12 @@ int put_text( att_type attribute, const TEXT* text, SSHORT size_len)
}
+int put_text(att_type attribute, const MetaString& name)
+{
+ return put_text(attribute, name.c_str(), name.length() + 1);
+}
+
+
void write_character_sets()
{
/**************************************
@@ -2291,9 +2333,14 @@ void write_character_sets()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$CHARACTER_SETS
WITH X.RDB$SYSTEM_FLAG NE 1 OR
- X.RDB$DEFAULT_COLLATE_NAME NE X.RDB$CHARACTER_SET_NAME
-
+ NOT (X.RDB$DEFAULT_COLLATE_SCHEMA_NAME EQUIV X.RDB$SCHEMA_NAME AND
+ X.RDB$DEFAULT_COLLATE_NAME = X.RDB$CHARACTER_SET_NAME)
+ {
put(tdgbl, rec_charset);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ PUT_TEXT(att_charset_schema_name, X.RDB$SCHEMA_NAME);
+
PUT_TEXT (att_charset_name, X.RDB$CHARACTER_SET_NAME);
if (X.RDB$SYSTEM_FLAG != 1)
@@ -2320,12 +2367,16 @@ void write_character_sets()
PUT_TEXT(att_charset_owner_name, X.RDB$OWNER_NAME);
}
- PUT_TEXT (att_charset_coll, X.RDB$DEFAULT_COLLATE_NAME);
+ if (!X.RDB$DEFAULT_COLLATE_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_charset_coll_schema_name, X.RDB$DEFAULT_COLLATE_SCHEMA_NAME);
+
+ PUT_TEXT(att_charset_coll, X.RDB$DEFAULT_COLLATE_NAME);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
@@ -2386,13 +2437,19 @@ void write_check_constraints()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$CHECK_CONSTRAINTS
+ {
put(tdgbl, rec_chk_constraint);
- PUT_TEXT (att_chk_constraint_name, X.RDB$CONSTRAINT_NAME);
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ PUT_TEXT(att_chk_schema_name, X.RDB$SCHEMA_NAME);
+
+ PUT_TEXT(att_chk_constraint_name, X.RDB$CONSTRAINT_NAME);
+
if (!X.RDB$TRIGGER_NAME.NULL)
PUT_TEXT (att_chk_trigger_name, X.RDB$TRIGGER_NAME);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -2422,7 +2479,12 @@ void write_collations()
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$COLLATIONS WITH X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_collation);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ PUT_TEXT(att_coll_schema_name, X.RDB$SCHEMA_NAME);
+
PUT_TEXT (att_coll_name, X.RDB$COLLATION_NAME);
put_int32 (att_coll_id, X.RDB$COLLATION_ID);
put_int32 (att_coll_cs_id, X.RDB$CHARACTER_SET_ID);
@@ -2433,8 +2495,10 @@ void write_collations()
put_source_blob (att_coll_description, att_coll_description, X.RDB$DESCRIPTION);
if (!X.RDB$FUNCTION_NAME.NULL)
PUT_TEXT (att_coll_funct, X.RDB$FUNCTION_NAME);
+
if (!X.RDB$BASE_COLLATION_NAME.NULL)
PUT_TEXT(att_coll_base_collation_name, X.RDB$BASE_COLLATION_NAME);
+
if (!X.RDB$SPECIFIC_ATTRIBUTES.NULL)
put_source_blob (att_coll_specific_attr, att_coll_specific_attr, X.RDB$SPECIFIC_ATTRIBUTES);
@@ -2444,10 +2508,11 @@ void write_collations()
PUT_TEXT(att_coll_owner_name, X.RDB$OWNER_NAME);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL11)
{
@@ -2607,16 +2672,20 @@ void write_database( const TEXT* dbb_file)
{
FOR (REQUEST_HANDLE req_handle1)
D IN RDB$DATABASE
+ {
if (!D.RDB$SECURITY_CLASS.NULL)
PUT_TEXT (att_database_security_class, D.RDB$SECURITY_CLASS);
put_source_blob (att_database_description2, att_database_description, D.RDB$DESCRIPTION);
+ if (!D.RDB$CHARACTER_SET_SCHEMA_NAME.NULL)
+ PUT_TEXT (att_database_dfl_charset_schema_name, D.RDB$CHARACTER_SET_SCHEMA_NAME);
if (!D.RDB$CHARACTER_SET_NAME.NULL)
PUT_TEXT (att_database_dfl_charset, D.RDB$CHARACTER_SET_NAME);
if (!D.RDB$LINGER.NULL)
put_int32(att_database_linger, D.RDB$LINGER);
if (!D.RDB$SQL_SECURITY.NULL)
put_boolean(att_database_sql_security, D.RDB$SQL_SECURITY);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -2676,7 +2745,7 @@ void write_exceptions()
* each exception.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -2686,11 +2755,20 @@ void write_exceptions()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$EXCEPTIONS
WITH X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_exception);
- const SSHORT l = PUT_TEXT (att_exception_name, X.RDB$EXCEPTION_NAME);
- MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (198, temp);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_exception_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_exception_name, X.RDB$EXCEPTION_NAME);
+ name.object = X.RDB$EXCEPTION_NAME;
+ BURP_verbose(198, name.toQuotedString().c_str());
// msg 198 writing exception %s
+
PUT_MESSAGE(att_exception_msg, att_exception_msg2, X.RDB$MESSAGE);
put_source_blob (att_exception_description2, att_exception_description, X.RDB$DESCRIPTION);
@@ -2700,7 +2778,8 @@ void write_exceptions()
PUT_TEXT(att_exception_owner_name, X.RDB$OWNER_NAME);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -2710,18 +2789,22 @@ void write_exceptions()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$EXCEPTIONS
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_exception);
- const SSHORT l = PUT_TEXT (att_exception_name, X.RDB$EXCEPTION_NAME);
- MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (198, temp);
+
+ PUT_TEXT(att_exception_name, X.RDB$EXCEPTION_NAME);
+ name.object = X.RDB$EXCEPTION_NAME;
+ BURP_verbose(198, name.toQuotedString().c_str());
// msg 198 writing exception %s
+
PUT_MESSAGE(att_exception_msg, att_exception_msg2, X.RDB$MESSAGE);
put_source_blob (att_exception_description2, att_exception_description, X.RDB$DESCRIPTION);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
@@ -2747,13 +2830,19 @@ void write_field_dimensions()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FIELD_DIMENSIONS
+ {
put(tdgbl, rec_field_dimensions);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ PUT_TEXT(att_field_schema_name, X.RDB$SCHEMA_NAME);
+
PUT_TEXT (att_field_name, X.RDB$FIELD_NAME);
put_int32 (att_field_dimensions, X.RDB$DIMENSION);
put_int32 (att_field_range_low, X.RDB$LOWER_BOUND);
put_int32 (att_field_range_high, X.RDB$UPPER_BOUND);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -2775,7 +2864,6 @@ void write_filters()
* each filter.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -2783,10 +2871,10 @@ void write_filters()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FILTERS
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_filter);
- const SSHORT l = PUT_TEXT (att_filter_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (145, temp);
+ PUT_TEXT(att_filter_name, X.RDB$FUNCTION_NAME);
+ BURP_verbose(145, MetaString(X.RDB$FUNCTION_NAME).toQuotedString().c_str());
// msg 145 writing filter %s
put_source_blob (att_filter_description2, att_filter_description, X.RDB$DESCRIPTION);
PUT_TEXT (att_filter_module_name, X.RDB$MODULE_NAME);
@@ -2794,10 +2882,11 @@ void write_filters()
put_int32 (att_filter_input_sub_type, X.RDB$INPUT_SUB_TYPE);
put_int32 (att_filter_output_sub_type, X.RDB$OUTPUT_SUB_TYPE);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
}
@@ -2816,8 +2905,7 @@ void write_functions()
* each function.
*
**************************************/
- GDS_NAME func;
- TEXT temp[GDS_NAME_LEN * 2];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -2826,21 +2914,26 @@ void write_functions()
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FUNCTIONS WITH X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_function);
- SSHORT prefixLen = 0;
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_function_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
if (!X.RDB$PACKAGE_NAME.NULL)
{
- prefixLen = PUT_TEXT(att_function_package_name, X.RDB$PACKAGE_NAME);
- MISC_terminate(X.RDB$PACKAGE_NAME, temp, prefixLen, sizeof(temp));
- temp[prefixLen++] = '.';
+ PUT_TEXT(att_function_package_name, X.RDB$PACKAGE_NAME);
+ name.package = X.RDB$PACKAGE_NAME;
}
- const SSHORT l = PUT_TEXT (att_function_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp + prefixLen, l, sizeof(temp) - prefixLen);
- BURP_verbose (147, temp);
+ PUT_TEXT(att_function_name, X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(147, name.toQuotedString().c_str());
// msg 147 writing function %.*s
+
put_source_blob (att_function_description2, att_function_description, X.RDB$DESCRIPTION);
if (!X.RDB$RETURN_ARGUMENT.NULL)
@@ -2879,10 +2972,11 @@ void write_functions()
put(tdgbl, att_end);
- COPY (X.RDB$FUNCTION_NAME, func);
- write_function_args ((X.RDB$PACKAGE_NAME.NULL ? "" : X.RDB$PACKAGE_NAME), func);
+ write_function_args(name);
+
put(tdgbl, rec_function_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -2891,11 +2985,14 @@ void write_functions()
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FUNCTIONS WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_function);
- const SSHORT l = PUT_TEXT (att_function_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (147, temp);
+
+ PUT_TEXT(att_function_name, X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(147, name.toQuotedString().c_str());
// msg 147 writing function %.*s
+
put_source_blob (att_function_description2, att_function_description, X.RDB$DESCRIPTION);
PUT_TEXT (att_function_module_name, X.RDB$MODULE_NAME);
PUT_TEXT (att_function_entrypoint, X.RDB$ENTRYPOINT);
@@ -2906,20 +3003,21 @@ void write_functions()
put_int32 (att_function_type, X.RDB$FUNCTION_TYPE);
PUT_TEXT (att_function_query_name, X.RDB$QUERY_NAME);
put(tdgbl, att_end);
- COPY (X.RDB$FUNCTION_NAME, func);
- write_function_args ("", func);
+ write_function_args(name);
+
put(tdgbl, rec_function_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
}
-void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
+void write_function_args(const QualifiedMetaString& name)
{
/**************************************
*
@@ -2931,8 +3029,6 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
* write all arguments for a function.
*
**************************************/
- TEXT temp[GDS_NAME_LEN * 2];
-
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
// if we have all capabilities, use the first request to get the
@@ -2945,23 +3041,20 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
{
FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle1)
X IN RDB$FUNCTION_ARGUMENTS
- WITH X.RDB$FUNCTION_NAME EQ funcptr AND
- X.RDB$PACKAGE_NAME EQUIV NULLIF(package, '')
-
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(name.schema.c_str(), '') AND
+ X.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ X.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
+ {
put(tdgbl, rec_function_arg);
- SSHORT prefixLen = 0;
+ if (name.schema.hasData())
+ put_text(att_functionarg_schema_name, name.schema);
- if (!X.RDB$PACKAGE_NAME.NULL)
- {
- prefixLen = PUT_TEXT(att_functionarg_package_name, X.RDB$PACKAGE_NAME);
- MISC_terminate(X.RDB$PACKAGE_NAME, temp, prefixLen, sizeof(temp));
- temp[prefixLen++] = '.';
- }
+ if (name.package.hasData())
+ put_text(att_functionarg_package_name, name.package);
- const SSHORT l = PUT_TEXT (att_functionarg_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp + prefixLen, l, sizeof(temp) - prefixLen);
- BURP_verbose (141, temp);
+ put_text(att_functionarg_name, name.object);
+ BURP_verbose(141, name.toQuotedString().c_str());
// msg 141 writing argument for function %s
if (!X.RDB$ARGUMENT_POSITION.NULL)
@@ -2980,6 +3073,8 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
if (!X.RDB$ARGUMENT_NAME.NULL)
PUT_TEXT(att_functionarg_arg_name, X.RDB$ARGUMENT_NAME);
+ if (!X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_functionarg_field_source_schema_name, X.RDB$FIELD_SOURCE_SCHEMA_NAME);
if (!X.RDB$FIELD_SOURCE.NULL)
PUT_TEXT(att_functionarg_field_source, X.RDB$FIELD_SOURCE);
if (!X.RDB$DEFAULT_VALUE.NULL)
@@ -2995,13 +3090,16 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
put_int32(att_functionarg_type_mechanism, X.RDB$ARGUMENT_MECHANISM);
if (!X.RDB$FIELD_NAME.NULL)
PUT_TEXT(att_functionarg_field_name, X.RDB$FIELD_NAME);
+ if (!X.RDB$RELATION_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_functionarg_relation_schema_name, X.RDB$RELATION_SCHEMA_NAME);
if (!X.RDB$RELATION_NAME.NULL)
PUT_TEXT(att_functionarg_relation_name, X.RDB$RELATION_NAME);
if (!X.RDB$DESCRIPTION.NULL)
put_source_blob(att_functionarg_description, att_functionarg_description, X.RDB$DESCRIPTION);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3010,12 +3108,12 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
{
FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle1)
X IN RDB$FUNCTION_ARGUMENTS WITH
- X.RDB$FUNCTION_NAME EQ funcptr
-
+ X.RDB$FUNCTION_NAME EQ name.object.c_str()
+ {
put(tdgbl, rec_function_arg);
- const SSHORT l = PUT_TEXT (att_functionarg_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (141, temp);
+
+ put_text(att_functionarg_name, name.object);
+ BURP_verbose(141, name.toQuotedString().c_str());
// msg 141 writing argument for function %s
if (!X.RDB$ARGUMENT_POSITION.NULL)
@@ -3032,21 +3130,22 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
if (!X.RDB$FIELD_PRECISION.NULL)
put_int32 (att_functionarg_field_precision, X.RDB$FIELD_PRECISION);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
FOR (REQUEST_HANDLE tdgbl->handles_write_function_args_req_handle1)
X IN RDB$FUNCTION_ARGUMENTS WITH
- X.RDB$FUNCTION_NAME EQ funcptr
-
+ X.RDB$FUNCTION_NAME EQ name.object.c_str()
+ {
put(tdgbl, rec_function_arg);
- const SSHORT l = PUT_TEXT (att_functionarg_name, X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (141, temp);
+
+ put_text(att_functionarg_name, name.object);
+ BURP_verbose(141, name.toQuotedString().c_str());
// msg 141 writing argument for function %s
if (!X.RDB$ARGUMENT_POSITION.NULL)
@@ -3065,11 +3164,11 @@ void write_function_args(const GDS_NAME package, GDS_NAME funcptr)
// bit and store the RDB$FIELD_PRECISION.
put(tdgbl, att_end);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
}
@@ -3087,7 +3186,7 @@ void write_generators()
*
**************************************/
Firebird::IRequest* req_handle1 = nullptr;
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3096,17 +3195,33 @@ void write_generators()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$GENERATORS
WITH X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_generator);
- const SSHORT l = PUT_TEXT (att_gen_generator, X.RDB$GENERATOR_NAME);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_gen_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_gen_generator, X.RDB$GENERATOR_NAME);
+ name.object = X.RDB$GENERATOR_NAME;
+
SINT64 value = 0;
if (!tdgbl->gbl_sw_meta)
{
- value = get_gen_id (X.RDB$GENERATOR_NAME, l);
+ value = get_gen_id(name);
+ put_int64(att_gen_value_int64, value);
+ }
+
+ BURP_verbose(165, SafeArg() << name.toQuotedString().c_str() << value);
+ // msg 165 writing generator %s value %ld
+
+ if (!tdgbl->gbl_sw_meta)
put_int64 (att_gen_value_int64, value);
- }
- if (!X.RDB$DESCRIPTION.NULL) {
+
+ if (!X.RDB$DESCRIPTION.NULL)
put_source_blob (att_gen_description, att_gen_description, X.RDB$DESCRIPTION);
- }
if (X.RDB$SYSTEM_FLAG)
put_int32(att_gen_sysflag, X.RDB$SYSTEM_FLAG);
@@ -3121,10 +3236,8 @@ void write_generators()
put_int32(att_gen_id_increment, X.RDB$GENERATOR_INCREMENT);
put(tdgbl, att_end);
- MISC_terminate (X.RDB$GENERATOR_NAME, temp, l, sizeof(temp));
- BURP_verbose (165, SafeArg() << temp << value);
- // msg 165 writing generator %s value %ld
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3134,47 +3247,55 @@ void write_generators()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$GENERATORS
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_generator);
- const SSHORT l = PUT_TEXT (att_gen_generator, X.RDB$GENERATOR_NAME);
+ PUT_TEXT(att_gen_generator, X.RDB$GENERATOR_NAME);
+ name.object = X.RDB$GENERATOR_NAME;
+
SINT64 value = 0;
if (!tdgbl->gbl_sw_meta)
{
- value = get_gen_id (X.RDB$GENERATOR_NAME, l);
- put_int64 (att_gen_value_int64, value);
+ value = get_gen_id(name);
+ put_int64(att_gen_value_int64, value);
}
if (!X.RDB$DESCRIPTION.NULL) {
put_source_blob (att_gen_description, att_gen_description, X.RDB$DESCRIPTION);
}
put(tdgbl, att_end);
- MISC_terminate (X.RDB$GENERATOR_NAME, temp, l, sizeof(temp));
- BURP_verbose (165, SafeArg() << temp << value);
+
+ BURP_verbose(165, SafeArg() << name.toQuotedString().c_str() << value);
// msg 165 writing generator %s value %ld
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$GENERATORS
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_generator);
- const SSHORT l = PUT_TEXT (att_gen_generator, X.RDB$GENERATOR_NAME);
+ PUT_TEXT(att_gen_generator, X.RDB$GENERATOR_NAME);
+ name.object = X.RDB$GENERATOR_NAME;
+
SINT64 value = 0;
if (!tdgbl->gbl_sw_meta)
{
- value = get_gen_id (X.RDB$GENERATOR_NAME, l);
- put_int64 (att_gen_value_int64, value);
+ value = get_gen_id(name);
+ put_int64(att_gen_value_int64, value);
}
put(tdgbl, att_end);
- MISC_terminate (X.RDB$GENERATOR_NAME, temp, l, sizeof(temp));
- BURP_verbose (165, SafeArg() << temp << value);
+
+ BURP_verbose(165, SafeArg() << name.toQuotedString().c_str() << value);
// msg 165 writing generator %s value %ld
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
@@ -3194,7 +3315,7 @@ void write_global_fields()
* each global field.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3210,11 +3331,20 @@ void write_global_fields()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$FIELDS WITH
X.RDB$SYSTEM_FLAG NE 1
-
+ {
put(tdgbl, rec_global_field);
- const SSHORT l = PUT_TEXT (att_field_name, X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (149, temp);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_field_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_field_name, X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+
+ BURP_verbose(149, name.toQuotedString().c_str());
+
// msg 149 writing global field %.*s
if (!X.RDB$QUERY_NAME.NULL && X.RDB$QUERY_NAME [0] != ' ')
PUT_TEXT (att_field_query_name, X.RDB$QUERY_NAME);
@@ -3270,8 +3400,8 @@ void write_global_fields()
PUT_TEXT(att_field_owner_name, X.RDB$OWNER_NAME);
put(tdgbl, att_end);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3284,10 +3414,13 @@ void write_global_fields()
X.RDB$SYSTEM_FLAG MISSING
put(tdgbl, rec_global_field);
- const SSHORT l = PUT_TEXT (att_field_name, X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (149, temp);
+
+ PUT_TEXT(att_field_name, X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+
+ BURP_verbose(149, name.toQuotedString().c_str());
// msg 149 writing global field %.*s
+
if (!X.RDB$QUERY_NAME.NULL && X.RDB$QUERY_NAME [0] != ' ')
PUT_TEXT (att_field_query_name, X.RDB$QUERY_NAME);
if (!X.RDB$EDIT_STRING.NULL && X.RDB$EDIT_STRING [0] != ' ')
@@ -3352,10 +3485,13 @@ void write_global_fields()
X.RDB$SYSTEM_FLAG MISSING
put(tdgbl, rec_global_field);
- const SSHORT l = PUT_TEXT (att_field_name, X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (149, temp);
+
+ PUT_TEXT(att_field_name, X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+
+ BURP_verbose(149, name.toQuotedString().c_str());
// msg 149 writing global field %.*s
+
if (!X.RDB$QUERY_NAME.NULL && X.RDB$QUERY_NAME [0] != ' ')
PUT_TEXT (att_field_query_name, X.RDB$QUERY_NAME);
if (!X.RDB$EDIT_STRING.NULL && X.RDB$EDIT_STRING [0] != ' ')
@@ -3425,7 +3561,7 @@ void write_packages()
* each package.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3436,10 +3572,17 @@ void write_packages()
WITH X.RDB$SYSTEM_FLAG NE 1
{
put(tdgbl, rec_package);
- const SSHORT l = PUT_TEXT(att_package_name, X.RDB$PACKAGE_NAME);
- MISC_terminate(X.RDB$PACKAGE_NAME, temp, l, sizeof(temp));
- BURP_verbose(335, temp); // msg 335 writing package @1
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_package_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_package_name, X.RDB$PACKAGE_NAME);
+ name.object = X.RDB$PACKAGE_NAME;
+
+ BURP_verbose(335, name.toQuotedString().c_str()); // msg 335 writing package @1
if (!X.RDB$PACKAGE_HEADER_SOURCE.NULL)
{
@@ -3491,8 +3634,7 @@ void write_procedures()
* each stored procedure.
*
**************************************/
- GDS_NAME proc;
- TEXT temp[GDS_NAME_LEN * 2];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3502,22 +3644,27 @@ void write_procedures()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$PROCEDURES
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_procedure);
- SSHORT prefixLen = 0;
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_procedure_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
if (!X.RDB$PACKAGE_NAME.NULL)
{
- prefixLen = PUT_TEXT(att_procedure_package_name, X.RDB$PACKAGE_NAME);
- MISC_terminate (X.RDB$PACKAGE_NAME, temp, prefixLen, sizeof(temp));
- temp[prefixLen++] = '.';
+ PUT_TEXT(att_procedure_package_name, X.RDB$PACKAGE_NAME);
+ name.package = X.RDB$PACKAGE_NAME;
}
- const SSHORT len = PUT_TEXT (att_procedure_name, X.RDB$PROCEDURE_NAME);
- MISC_terminate (X.RDB$PROCEDURE_NAME, temp + prefixLen, len, sizeof(temp) - prefixLen);
+ PUT_TEXT(att_procedure_name, X.RDB$PROCEDURE_NAME);
+ name.object = X.RDB$PROCEDURE_NAME;
- BURP_verbose (193, temp);
+ BURP_verbose(193, name.toQuotedString().c_str());
// msg 193 writing stored procedure %.*s
+
put_int32 (att_procedure_inputs, X.RDB$PROCEDURE_INPUTS);
put_int32 (att_procedure_outputs, X.RDB$PROCEDURE_OUTPUTS);
put_source_blob(att_procedure_description2, att_procedure_description, X.RDB$DESCRIPTION);
@@ -3550,24 +3697,28 @@ void write_procedures()
put_boolean(att_procedure_sql_security, X.RDB$SQL_SECURITY);
put(tdgbl, att_end);
- COPY(X.RDB$PROCEDURE_NAME, proc);
- write_procedure_prms ((X.RDB$PACKAGE_NAME.NULL ? "" : X.RDB$PACKAGE_NAME), proc);
+
+ write_procedure_prms(name);
put(tdgbl, rec_procedure_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$PROCEDURES
WITH X.RDB$SYSTEM_FLAG MISSING OR X.RDB$SYSTEM_FLAG NE 1
+ {
put(tdgbl, rec_procedure);
- const SSHORT l = PUT_TEXT (att_procedure_name, X.RDB$PROCEDURE_NAME);
- MISC_terminate (X.RDB$PROCEDURE_NAME, temp, l, sizeof(temp));
- BURP_verbose (193, temp);
+
+ PUT_TEXT(att_procedure_name, X.RDB$PROCEDURE_NAME);
+ name.object = X.RDB$PROCEDURE_NAME;
+ BURP_verbose(193, name.toQuotedString().c_str());
// msg 193 writing stored procedure %.*s
+
put_int32 (att_procedure_inputs, X.RDB$PROCEDURE_INPUTS);
put_int32 (att_procedure_outputs, X.RDB$PROCEDURE_OUTPUTS);
put_source_blob (att_procedure_description2, att_procedure_description, X.RDB$DESCRIPTION);
@@ -3578,20 +3729,21 @@ void write_procedures()
if (!X.RDB$SECURITY_CLASS.NULL)
PUT_TEXT (att_procedure_owner_name, X.RDB$OWNER_NAME);
put(tdgbl, att_end);
- COPY(X.RDB$PROCEDURE_NAME, proc);
- write_procedure_prms ("", proc);
+
+ write_procedure_prms(name);
put(tdgbl, rec_procedure_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
}
-void write_procedure_prms(const GDS_NAME package, const GDS_NAME procptr)
+void write_procedure_prms(const QualifiedMetaString& name)
{
/**************************************
*
@@ -3603,25 +3755,29 @@ void write_procedure_prms(const GDS_NAME package, const GDS_NAME procptr)
* write all parameters of a stored procedure.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
-
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
if (tdgbl->runtimeODS >= DB_VERSION_DDL11_1)
{
FOR (REQUEST_HANDLE tdgbl->handles_write_procedure_prms_req_handle1)
X IN RDB$PROCEDURE_PARAMETERS
- WITH X.RDB$PROCEDURE_NAME EQ procptr AND
- X.RDB$PACKAGE_NAME EQUIV NULLIF(package, '')
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(name.schema.c_str(), '') AND
+ X.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ X.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
put(tdgbl, rec_procedure_prm);
- const SSHORT l = PUT_TEXT (att_procedureprm_name, X.RDB$PARAMETER_NAME);
- MISC_terminate (X.RDB$PARAMETER_NAME, temp, l, sizeof(temp));
- BURP_verbose (194, temp);
+
+ PUT_TEXT(att_procedureprm_name, X.RDB$PARAMETER_NAME);
+ BURP_verbose(194, MetaString(X.RDB$PARAMETER_NAME).toQuotedString().c_str());
// msg 194 writing parameter %s for stored procedure
+
put_int32 (att_procedureprm_number, X.RDB$PARAMETER_NUMBER);
put_int32 (att_procedureprm_type, X.RDB$PARAMETER_type);
- PUT_TEXT (att_procedureprm_field_source, X.RDB$FIELD_SOURCE);
+
+ if (!X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_procedureprm_field_source_schema_name, X.RDB$FIELD_SOURCE_SCHEMA_NAME);
+
+ PUT_TEXT(att_procedureprm_field_source, X.RDB$FIELD_SOURCE);
put_source_blob(att_procedureprm_description2, att_procedureprm_description,
X.RDB$DESCRIPTION);
put_blr_blob (att_procedureprm_default_value, X.RDB$DEFAULT_VALUE);
@@ -3637,6 +3793,10 @@ void write_procedure_prms(const GDS_NAME package, const GDS_NAME procptr)
// DB_VERSION_DDL11_2
if (!X.RDB$FIELD_NAME.NULL)
PUT_TEXT(att_procedureprm_field_name, X.RDB$FIELD_NAME);
+
+ if (!X.RDB$RELATION_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_procedureprm_relation_schema_name, X.RDB$RELATION_SCHEMA_NAME);
+
if (!X.RDB$RELATION_NAME.NULL)
PUT_TEXT(att_procedureprm_relation_name, X.RDB$RELATION_NAME);
@@ -3645,27 +3805,30 @@ void write_procedure_prms(const GDS_NAME package, const GDS_NAME procptr)
END_FOR;
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
FOR (REQUEST_HANDLE tdgbl->handles_write_procedure_prms_req_handle1)
- X IN RDB$PROCEDURE_PARAMETERS WITH X.RDB$PROCEDURE_NAME EQ procptr
+ X IN RDB$PROCEDURE_PARAMETERS WITH X.RDB$PROCEDURE_NAME EQ name.object.c_str()
+ {
put(tdgbl, rec_procedure_prm);
- const SSHORT l = PUT_TEXT (att_procedureprm_name, X.RDB$PARAMETER_NAME);
- MISC_terminate (X.RDB$PARAMETER_NAME, temp, l, sizeof(temp));
- BURP_verbose (194, temp);
+
+ PUT_TEXT(att_procedureprm_name, X.RDB$PARAMETER_NAME);
+ BURP_verbose(194, MetaString(X.RDB$PARAMETER_NAME).toQuotedString().c_str());
// msg 194 writing parameter %s for stored procedure
+
put_int32 (att_procedureprm_number, X.RDB$PARAMETER_NUMBER);
put_int32 (att_procedureprm_type, X.RDB$PARAMETER_type);
PUT_TEXT (att_procedureprm_field_source, X.RDB$FIELD_SOURCE);
put_source_blob(att_procedureprm_description2, att_procedureprm_description,
X.RDB$DESCRIPTION);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
}
@@ -3683,7 +3846,6 @@ void write_publications()
* each publication.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
Firebird::IRequest* req_handle = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3694,10 +3856,9 @@ void write_publications()
{
put(tdgbl, rec_publication);
- const SSHORT l = PUT_TEXT(att_pub_name, X.RDB$PUBLICATION_NAME);
- MISC_terminate(X.RDB$PUBLICATION_NAME, temp, l, sizeof(temp));
+ PUT_TEXT(att_pub_name, X.RDB$PUBLICATION_NAME);
- BURP_verbose(397, temp);
+ BURP_verbose(397, MetaString(X.RDB$PUBLICATION_NAME).toQuotedString().c_str());
// msg 397 writing publication %s
if (!X.RDB$OWNER_NAME.NULL)
@@ -3733,7 +3894,7 @@ void write_pub_tables()
* each publication table.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString tableName;
Firebird::IRequest* req_handle = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3745,10 +3906,16 @@ void write_pub_tables()
PUT_TEXT(att_ptab_pub_name, X.RDB$PUBLICATION_NAME);
- const SSHORT l = PUT_TEXT(att_ptab_table_name, X.RDB$TABLE_NAME);
- MISC_terminate(X.RDB$TABLE_NAME, temp, l, sizeof(temp));
+ if (!X.RDB$TABLE_SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_ptab_table_schema_name, X.RDB$TABLE_NAME);
+ tableName.schema = X.RDB$TABLE_SCHEMA_NAME;
+ }
- BURP_verbose(398, temp);
+ PUT_TEXT(att_ptab_table_name, X.RDB$TABLE_NAME);
+ tableName.object = X.RDB$TABLE_NAME;
+
+ BURP_verbose(398, tableName.toQuotedString().c_str());
// msg 398 writing publication for table %s
put(tdgbl, att_end);
@@ -3781,14 +3948,25 @@ void write_ref_constraints()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$REF_CONSTRAINTS
+ {
put(tdgbl, rec_ref_constraint);
- PUT_TEXT (att_ref_constraint_name, X.RDB$CONSTRAINT_NAME);
- PUT_TEXT (att_ref_unique_const_name, X.RDB$CONST_NAME_UQ);
- PUT_TEXT (att_ref_match_option, X.RDB$MATCH_OPTION);
- PUT_TEXT (att_ref_update_rule, X.RDB$UPDATE_RULE);
- PUT_TEXT (att_ref_delete_rule, X.RDB$DELETE_RULE);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ PUT_TEXT(att_ref_schema_name, X.RDB$SCHEMA_NAME);
+
+ PUT_TEXT(att_ref_constraint_name, X.RDB$CONSTRAINT_NAME);
+
+ if (!X.RDB$CONST_SCHEMA_NAME_UQ.NULL)
+ PUT_TEXT(att_ref_unique_const_schema_name, X.RDB$CONST_SCHEMA_NAME_UQ);
+
+ PUT_TEXT(att_ref_unique_const_name, X.RDB$CONST_NAME_UQ);
+
+ PUT_TEXT(att_ref_match_option, X.RDB$MATCH_OPTION);
+ PUT_TEXT(att_ref_update_rule, X.RDB$UPDATE_RULE);
+ PUT_TEXT(att_ref_delete_rule, X.RDB$DELETE_RULE);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3810,7 +3988,7 @@ void write_rel_constraints()
* each relation constraint.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3818,13 +3996,23 @@ void write_rel_constraints()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$RELATION_CONSTRAINTS CROSS
REL IN RDB$RELATIONS
- WITH REL.RDB$RELATION_NAME EQ X.RDB$RELATION_NAME AND
+ WITH REL.RDB$SCHEMA_NAME EQUIV X.RDB$SCHEMA_NAME AND
+ REL.RDB$RELATION_NAME EQ X.RDB$RELATION_NAME AND
(REL.RDB$SYSTEM_FLAG MISSING OR REL.RDB$SYSTEM_FLAG NE 1)
+ {
put(tdgbl, rec_rel_constraint);
- const SSHORT l = PUT_TEXT (att_rel_constraint_name, X.RDB$CONSTRAINT_NAME);
- MISC_terminate (X.RDB$CONSTRAINT_NAME, temp, l, sizeof(temp));
- BURP_verbose (207, temp);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_rel_constraint_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_rel_constraint_name, X.RDB$CONSTRAINT_NAME);
+ name.object = X.RDB$CONSTRAINT_NAME;
+ BURP_verbose(207, name.toQuotedString().c_str());
// msg 207 writing constraint %s
+
PUT_TEXT (att_rel_constraint_type, X.RDB$CONSTRAINT_TYPE);
PUT_TEXT (att_rel_constraint_rel_name, X.RDB$RELATION_NAME);
PUT_TEXT (att_rel_constraint_defer, X.RDB$DEFERRABLE);
@@ -3832,7 +4020,8 @@ void write_rel_constraints()
if (!X.RDB$INDEX_NAME.NULL)
PUT_TEXT (att_rel_constraint_index, X.RDB$INDEX_NAME);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3854,7 +4043,7 @@ void write_relations()
* each relation.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -3870,15 +4059,23 @@ void write_relations()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$RELATIONS WITH X.RDB$SYSTEM_FLAG NE 1 OR
X.RDB$SYSTEM_FLAG MISSING
-
+ {
SSHORT flags = 0;
put(tdgbl, rec_relation);
- const SSHORT l = PUT_TEXT (att_relation_name, X.RDB$RELATION_NAME);
- MISC_terminate (X.RDB$RELATION_NAME, temp, l, sizeof(temp));
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_relation_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_relation_name, X.RDB$RELATION_NAME);
+ name.object = X.RDB$RELATION_NAME;
+
if (X.RDB$VIEW_BLR.NULL)
- BURP_verbose(153, temp); // msg 153 writing table @1
+ BURP_verbose(153, name.toQuotedString().c_str()); // msg 153 writing table @1
else
- BURP_verbose(345, temp); // msg 345 writing view @1
+ BURP_verbose(345, name.toQuotedString().c_str()); // msg 345 writing view @1
// RDB$VIEW_BLR must be the first blob field in the backup file.
// RESTORE.EPP makes this assumption in get_relation().
@@ -3919,10 +4116,15 @@ void write_relations()
relation->rel_next = tdgbl->relations;
tdgbl->relations = relation;
relation->rel_id = X.RDB$RELATION_ID;
- relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ relation->rel_name.schema = X.RDB$SCHEMA_NAME;
+
+ relation->rel_name = name;
relation->rel_flags |= flags;
put_relation (relation);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -3932,12 +4134,12 @@ void write_relations()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$RELATIONS WITH X.RDB$SYSTEM_FLAG NE 1 OR
X.RDB$SYSTEM_FLAG MISSING
-
+ {
SSHORT flags = 0;
put(tdgbl, rec_relation);
- const SSHORT l = PUT_TEXT(att_relation_name, X.RDB$RELATION_NAME);
- MISC_terminate (X.RDB$RELATION_NAME, temp, l, sizeof(temp));
- BURP_verbose (153, temp);
+ PUT_TEXT(att_relation_name, X.RDB$RELATION_NAME);
+ name.object = X.RDB$RELATION_NAME;
+ BURP_verbose(153, name.toQuotedString().c_str());
// msg 153 writing table %.*s
// RDB$VIEW_BLR must be the first blob field in the backup file.
@@ -3969,40 +4171,83 @@ void write_relations()
relation->rel_next = tdgbl->relations;
tdgbl->relations = relation;
relation->rel_id = X.RDB$RELATION_ID;
- relation->rel_name_length = COPY(X.RDB$RELATION_NAME, relation->rel_name);
+ relation->rel_name = name;
relation->rel_flags |= flags;
put_relation (relation);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
}
+// Write a record in the burp file for each schema.
+void write_schemas()
+{
+ IRequest* reqHandle1 = nullptr;
+ BurpGlobals* tdgbl = BurpGlobals::getSpecific();
+
+ FOR (REQUEST_HANDLE reqHandle1)
+ X IN RDB$SCHEMAS
+ WITH X.RDB$SYSTEM_FLAG NE 1
+ {
+ put(tdgbl, rec_schema);
+
+ PUT_TEXT(att_schema_name, X.RDB$SCHEMA_NAME);
+
+ BURP_verbose(411, MetaString(X.RDB$SCHEMA_NAME).toQuotedString().c_str()); // msg 411 writing schema @1
+
+ if (!X.RDB$CHARACTER_SET_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_schema_charset_schema_name, X.RDB$CHARACTER_SET_SCHEMA_NAME);
+
+ if (!X.RDB$CHARACTER_SET_NAME.NULL)
+ PUT_TEXT(att_schema_charset_name, X.RDB$CHARACTER_SET_NAME);
+
+ if (!X.RDB$SECURITY_CLASS.NULL)
+ PUT_TEXT(att_schema_security_class, X.RDB$SECURITY_CLASS);
+
+ if (!X.RDB$OWNER_NAME.NULL)
+ PUT_TEXT(att_schema_owner_name, X.RDB$OWNER_NAME);
+
+ if (!X.RDB$DESCRIPTION.NULL)
+ put_source_blob(att_schema_description, att_schema_description, X.RDB$DESCRIPTION);
+
+ put(tdgbl, att_end);
+ }
+ END_FOR
+ ON_ERROR
+ general_on_error();
+ END_ERROR
+
+ MISC_release_request_silent(reqHandle1);
+}
+
+
void write_secclasses()
{
- TEXT temp[GDS_NAME_LEN];
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$SECURITY_CLASSES WITH X.RDB$SECURITY_CLASS NOT STARTING "SQL$"
+ {
put(tdgbl, rec_security_class);
- const ULONG l = PUT_TEXT (att_class_security_class, X.RDB$SECURITY_CLASS);
- MISC_terminate (X.RDB$SECURITY_CLASS, temp, l, sizeof(temp));
- BURP_verbose (155, temp);
+ PUT_TEXT(att_class_security_class, X.RDB$SECURITY_CLASS);
+ BURP_verbose(155, MetaString(X.RDB$SECURITY_CLASS).toQuotedString().c_str());
// msg 155 writing security class @1
put_blr_blob (att_class_acl, X.RDB$ACL);
put_source_blob (att_class_description2, att_class_description, X.RDB$DESCRIPTION);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
}
@@ -4020,7 +4265,6 @@ void write_shadow_files()
* Write out files to use as shadows.
*
**************************************/
- BASED ON RDB$FILES.RDB$FILE_NAME temp;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -4029,10 +4273,10 @@ void write_shadow_files()
X IN RDB$FILES
WITH X.RDB$SHADOW_NUMBER NOT MISSING
AND X.RDB$SHADOW_NUMBER NE 0
+ {
put(tdgbl, rec_files);
- const SSHORT l = PUT_TEXT (att_file_filename, X.RDB$FILE_NAME);
- MISC_terminate (X.RDB$FILE_NAME, temp, l, sizeof(temp));
- BURP_verbose (163, temp);
+ PUT_TEXT(att_file_filename, X.RDB$FILE_NAME);
+ BURP_verbose(163, MetaString(X.RDB$FILE_NAME).toQuotedString().c_str());
// msg 163 writing shadow file %s
put_int32 (att_file_sequence, X.RDB$FILE_SEQUENCE);
put_int32 (att_file_start, X.RDB$FILE_START);
@@ -4040,10 +4284,11 @@ void write_shadow_files()
put_int32 (att_file_flags, X.RDB$FILE_FLAGS);
put_int32 (att_shadow_number, X.RDB$SHADOW_NUMBER);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
}
@@ -4063,7 +4308,6 @@ void write_sql_roles()
*
**************************************/
Firebird::IRequest* req_handle1 = nullptr;
- TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -4072,10 +4316,10 @@ void write_sql_roles()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$ROLES
WITH X.RDB$SYSTEM_FLAG EQ 0 OR X.RDB$SYSTEM_FLAG MISSING
-
+ {
put(tdgbl, rec_sql_roles);
- const SSHORT l = PUT_TEXT(att_role_name, X.RDB$ROLE_NAME);
- PUT_TEXT (att_role_owner_name, X.RDB$OWNER_NAME);
+ PUT_TEXT(att_role_name, X.RDB$ROLE_NAME);
+ PUT_TEXT(att_role_owner_name, X.RDB$OWNER_NAME);
if (!X.RDB$DESCRIPTION.NULL) {
put_source_blob (att_role_description, att_role_description, X.RDB$DESCRIPTION);
}
@@ -4086,32 +4330,30 @@ void write_sql_roles()
put_block(tdgbl, (const UCHAR*) (X.RDB$SYSTEM_PRIVILEGES), ll);
put(tdgbl, att_end);
- MISC_terminate (X.RDB$ROLE_NAME, temp, l, sizeof(temp));
- BURP_verbose (249, temp);
+ BURP_verbose(249, MetaString(X.RDB$ROLE_NAME).toQuotedString().c_str());
// msg 249 writing SQL role: %s
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
{
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$ROLES
-
+ {
put(tdgbl, rec_sql_roles);
- const SSHORT l = PUT_TEXT(att_role_name, X.RDB$ROLE_NAME);
- PUT_TEXT (att_role_owner_name, X.RDB$OWNER_NAME);
+ PUT_TEXT(att_role_name, X.RDB$ROLE_NAME);
+ PUT_TEXT(att_role_owner_name, X.RDB$OWNER_NAME);
put(tdgbl, att_end);
- MISC_terminate (X.RDB$ROLE_NAME, temp, l, sizeof(temp));
- BURP_verbose (249, temp);
+ BURP_verbose(249, MetaString(X.RDB$ROLE_NAME).toQuotedString().c_str());
// msg 249 writing SQL role: %s
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
@@ -4132,8 +4374,6 @@ void write_mapping()
*
**************************************/
Firebird::IRequest* req_handle = nullptr;
- TEXT temp[GDS_NAME_LEN];
-
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
@@ -4141,9 +4381,9 @@ void write_mapping()
FOR (REQUEST_HANDLE req_handle)
M IN RDB$AUTH_MAPPING
WITH M.RDB$SYSTEM_FLAG EQ 0
-
+ {
put(tdgbl, rec_mapping);
- const SSHORT l = PUT_TEXT(att_map_name, M.RDB$MAP_NAME);
+ PUT_TEXT(att_map_name, M.RDB$MAP_NAME);
PUT_TEXT(att_map_using, M.RDB$MAP_USING);
if (!M.RDB$MAP_PLUGIN.NULL)
@@ -4167,34 +4407,33 @@ void write_mapping()
put(tdgbl, att_end);
- MISC_terminate (M.RDB$MAP_NAME, temp, l, sizeof(temp));
- BURP_verbose (297, temp);
+ BURP_verbose(297, MetaString(M.RDB$MAP_NAME).toQuotedString().c_str());
// msg 297 writing mapping for %s
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL11_2)
{
FOR (REQUEST_HANDLE req_handle)
X IN RDB$ROLES
WITH X.RDB$ROLE_NAME EQ ADMIN_ROLE
-
+ {
if (X.RDB$SYSTEM_FLAG == 6) // constant 6 turns on auto admin mapping in FB 2.5
{
put(tdgbl, rec_mapping);
put_text(att_auto_map_role, ADMIN_ROLE, static_cast(strlen(ADMIN_ROLE) + 1));
put(tdgbl, att_end);
- BURP_verbose (297, ADMIN_ROLE);
+ BURP_verbose(297, MetaString(ADMIN_ROLE).toQuotedString().c_str());
// msg 297 writing mapping for @1
}
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle);
@@ -4215,7 +4454,6 @@ void write_db_creators()
*
**************************************/
Firebird::IRequest* req_handle = nullptr;
- TEXT temp[GDS_NAME_LEN];
bool first = true;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -4244,10 +4482,9 @@ void write_db_creators()
if (fl)
put(tdgbl, rec_db_creator);
fl = false;
- const SSHORT l = PUT_TEXT(att_dbc_user, C.RDB$USER);
+ PUT_TEXT(att_dbc_user, C.RDB$USER);
- MISC_terminate (C.RDB$USER, temp, l, sizeof(temp));
- BURP_verbose (392, temp);
+ BURP_verbose(392, MetaString(C.RDB$USER).toQuotedString().c_str());
// msg 392 writing db creator %s
}
@@ -4275,7 +4512,7 @@ void write_triggers()
* write the triggers in rdb$triggers
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -4292,11 +4529,18 @@ void write_triggers()
X IN RDB$TRIGGERS WITH
X.RDB$SYSTEM_FLAG NE 1 OR
X.RDB$SYSTEM_FLAG MISSING
-
+ {
put(tdgbl, rec_trigger);
- const SSHORT l = PUT_TEXT (att_trig_name, X.RDB$TRIGGER_NAME);
- MISC_terminate (X.RDB$TRIGGER_NAME, temp, l, sizeof(temp));
- BURP_verbose (156, temp);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_trig_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_trig_name, X.RDB$TRIGGER_NAME);
+ name.object = X.RDB$TRIGGER_NAME;
+ BURP_verbose(156, name.toQuotedString().c_str());
// msg 156 writing trigger %s
if (!X.RDB$RELATION_NAME.NULL)
@@ -4334,8 +4578,8 @@ void write_triggers()
put_boolean(att_trig_sql_security, X.RDB$SQL_SECURITY);
put(tdgbl, att_end);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -4346,11 +4590,12 @@ void write_triggers()
X IN RDB$TRIGGERS WITH
X.RDB$SYSTEM_FLAG NE 1 OR
X.RDB$SYSTEM_FLAG MISSING
-
+ {
put(tdgbl, rec_trigger);
- const SSHORT l = PUT_TEXT (att_trig_name, X.RDB$TRIGGER_NAME);
- MISC_terminate (X.RDB$TRIGGER_NAME, temp, l, sizeof(temp));
- BURP_verbose (156, temp);
+
+ PUT_TEXT(att_trig_name, X.RDB$TRIGGER_NAME);
+ name.object = X.RDB$TRIGGER_NAME;
+ BURP_verbose(156, name.toQuotedString().c_str());
// msg 156 writing trigger %s
if (!X.RDB$RELATION_NAME.NULL)
@@ -4368,11 +4613,11 @@ void write_triggers()
put_int32 (att_trig_flags, X.RDB$FLAGS);
put(tdgbl, att_end);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
MISC_release_request_silent(req_handle1);
@@ -4392,25 +4637,37 @@ void write_trigger_messages()
* each trigger message.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString name;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
FOR (REQUEST_HANDLE req_handle1)
- T IN RDB$TRIGGERS CROSS X IN RDB$TRIGGER_MESSAGES
- OVER RDB$TRIGGER_NAME
- WITH T.RDB$SYSTEM_FLAG NE 1 OR T.RDB$SYSTEM_FLAG MISSING
-
+ T IN RDB$TRIGGERS
+ CROSS X IN RDB$TRIGGER_MESSAGES
+ WITH X.RDB$SCHEMA_NAME EQUIV T.RDB$SCHEMA_NAME AND
+ X.RDB$TRIGGER_NAME EQ T.RDB$TRIGGER_NAME AND
+ T.RDB$SYSTEM_FLAG NE 1 OR T.RDB$SYSTEM_FLAG MISSING
+ {
put(tdgbl, rec_trigger_message);
- const SSHORT l = PUT_TEXT (att_trigmsg_name, X.RDB$TRIGGER_NAME);
- MISC_terminate (X.RDB$TRIGGER_NAME, temp, l, sizeof(temp));
- BURP_verbose (157, temp);
+
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_trigmsg_schema_name, X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_trigmsg_name, X.RDB$TRIGGER_NAME);
+ name.object = X.RDB$TRIGGER_NAME;
+
+ BURP_verbose(157, name.toQuotedString().c_str());
// msg 157 writing trigger message for %s
+
put_int32 (att_trigmsg_number, X.RDB$MESSAGE_NUMBER);
PUT_MESSAGE (att_trigmsg_text, att_end, X.RDB$MESSAGE);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
END_ERROR;
@@ -4439,6 +4696,7 @@ void write_types()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$TYPES WITH X.RDB$SYSTEM_FLAG NE 1 OR
X.RDB$SYSTEM_FLAG MISSING
+ {
put(tdgbl, rec_system_type);
PUT_TEXT (att_type_name, X.RDB$TYPE_NAME);
PUT_TEXT (att_type_field_name, X.RDB$FIELD_NAME);
@@ -4449,10 +4707,11 @@ void write_types()
if (X.RDB$SYSTEM_FLAG)
put_int32 (att_type_system_flag, X.RDB$SYSTEM_FLAG);
put(tdgbl, att_end);
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
}
@@ -4471,7 +4730,7 @@ void write_user_privileges()
* each user privilege.
*
**************************************/
- TEXT temp[GDS_NAME_LEN];
+ QualifiedMetaString user;
Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -4479,21 +4738,36 @@ void write_user_privileges()
FOR (REQUEST_HANDLE req_handle1)
X IN RDB$USER_PRIVILEGES
WITH X.RDB$GRANTOR NOT MISSING
+ {
put(tdgbl, rec_user_privilege);
- const SSHORT l = PUT_TEXT (att_priv_user, X.RDB$USER);
- MISC_terminate (X.RDB$USER, temp, l, sizeof(temp));
- BURP_verbose (152, temp);
+
+ if (!X.RDB$USER_SCHEMA_NAME.NULL)
+ {
+ PUT_TEXT(att_priv_user_schema_name, X.RDB$USER_SCHEMA_NAME);
+ user.schema = X.RDB$USER_SCHEMA_NAME;
+ }
+
+ PUT_TEXT(att_priv_user, X.RDB$USER);
+ user.object = X.RDB$USER;
+ BURP_verbose(152, user.toQuotedString().c_str());
// msg 152 writing privilege for user %s
+
PUT_TEXT (att_priv_grantor, X.RDB$GRANTOR);
PUT_TEXT (att_priv_privilege, X.RDB$PRIVILEGE);
if (!X.RDB$GRANT_OPTION.NULL)
put_int32 (att_priv_grant_option, X.RDB$GRANT_OPTION);
- PUT_TEXT (att_priv_object_name, X.RDB$RELATION_NAME);
+
+ if (!X.RDB$RELATION_SCHEMA_NAME.NULL)
+ PUT_TEXT(att_priv_object_schema_name, X.RDB$RELATION_SCHEMA_NAME);
+
+ PUT_TEXT(att_priv_object_name, X.RDB$RELATION_NAME);
+
if (!X.RDB$FIELD_NAME.NULL)
PUT_TEXT (att_priv_field_name, X.RDB$FIELD_NAME);
put_int32 (att_priv_user_type, X.RDB$USER_TYPE);
put_int32 (att_priv_obj_type, X.RDB$OBJECT_TYPE);
put(tdgbl, att_end);
+ }
END_FOR
ON_ERROR
general_on_error();
diff --git a/src/burp/burp.cpp b/src/burp/burp.cpp
index 9db13af103..1ccc04f40c 100644
--- a/src/burp/burp.cpp
+++ b/src/burp/burp.cpp
@@ -765,13 +765,35 @@ int gbak(Firebird::UtilSvc* uSvc)
}
tdgbl->gbl_sw_user = argv[itr];
break;
+ case IN_SW_BURP_SKIP_SCHEMA_DATA:
+ if (++itr >= argc)
+ {
+ BURP_error(417, true);
+ // missing regular expression to skip tables
+ }
+
+ tdgbl->setupSkipIncludePattern(argv[itr], 419, tdgbl->skipSchemaDataMatcher);
+ // msg 419 regular expression to skip schemas was already set
+ break;
case IN_SW_BURP_SKIP_DATA:
if (++itr >= argc)
{
BURP_error(354, true);
// missing regular expression to skip tables
}
- tdgbl->setupSkipData(argv[itr]);
+
+ tdgbl->setupSkipIncludePattern(argv[itr], 356, tdgbl->skipDataMatcher);
+ // msg 356 regular expression to skip tables was already set
+ break;
+ case IN_SW_BURP_INCLUDE_SCHEMA_DATA:
+ if (++itr >= argc)
+ {
+ BURP_error(418, true);
+ // missing regular expression to include tables
+ }
+
+ tdgbl->setupSkipIncludePattern(argv[itr], 420, tdgbl->includeSchemaDataMatcher);
+ // msg 420 regular expression to include schemas was already set
break;
case IN_SW_BURP_INCLUDE_DATA:
if (++itr >= argc)
@@ -779,7 +801,9 @@ int gbak(Firebird::UtilSvc* uSvc)
BURP_error(389, true);
// missing regular expression to include tables
}
- tdgbl->setupIncludeData(argv[itr]);
+
+ tdgbl->setupSkipIncludePattern(argv[itr], 390, tdgbl->includeDataMatcher);
+ // msg 390 regular expression to include tables was already set
break;
case IN_SW_BURP_ROLE:
if (++itr >= argc)
@@ -1153,6 +1177,8 @@ int gbak(Firebird::UtilSvc* uSvc)
dpb.insertBytes(isc_dpb_auth_block, authBlock, authSize);
}
+ dpb.insertString(isc_dpb_search_path, SYSTEM_SCHEMA, fb_strlen(SYSTEM_SCHEMA));
+
// We call getTableMod() because we are interested in the items that were activated previously,
// not in the original, unchanged table that "switches" took as parameter in the constructor.
for (const Switches::in_sw_tab_t* in_sw_tab = switches.getTableMod();
@@ -2664,59 +2690,25 @@ void close_platf(DESC file)
#endif // WIN_NT
-void BurpGlobals::setupSkipData(const Firebird::string& regexp)
+void BurpGlobals::setupSkipIncludePattern(const string& regexp, USHORT alreadySetErrorCode,
+ AutoPtr& matcher)
{
- if (skipDataMatcher)
- {
- BURP_error(356, true);
- // msg 356 regular expression to skip tables was already set
- }
+ if (matcher)
+ BURP_error(alreadySetErrorCode, true);
- // Compile skip relation expressions
+ // Compile expressions
try
{
if (regexp.hasData())
{
- Firebird::string filter(regexp);
+ string filter(regexp);
if (!uSvc->utf8FileNames())
ISC_systemToUtf8(filter);
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
- skipDataMatcher.reset(FB_NEW_POOL(tdgbl->getPool()) Firebird::SimilarToRegex(
- tdgbl->getPool(), Firebird::SimilarToFlag::CASE_INSENSITIVE,
- filter.c_str(), filter.length(),
- "\\", 1));
- }
- }
- catch (const Firebird::Exception&)
- {
- Firebird::fatal_exception::raiseFmt(
- "error while compiling regular expression \"%s\"", regexp.c_str());
- }
-}
-
-void BurpGlobals::setupIncludeData(const Firebird::string& regexp)
-{
- if (includeDataMatcher)
- {
- BURP_error(390, true);
- // msg 390 regular expression to include tables was already set
- }
-
- // Compile include relation expressions
- try
- {
- if (regexp.hasData())
- {
- Firebird::string filter(regexp);
- if (!uSvc->utf8FileNames())
- ISC_systemToUtf8(filter);
-
- BurpGlobals* tdgbl = BurpGlobals::getSpecific();
-
- includeDataMatcher.reset(FB_NEW_POOL(tdgbl->getPool()) Firebird::SimilarToRegex(
- tdgbl->getPool(), Firebird::SimilarToFlag::CASE_INSENSITIVE,
+ matcher.reset(FB_NEW_POOL(tdgbl->getPool()) SimilarToRegex(
+ tdgbl->getPool(), SimilarToFlag::CASE_INSENSITIVE,
filter.c_str(), filter.length(),
"\\", 1));
}
@@ -2750,7 +2742,7 @@ namespace // for local symbols
}
}
-bool BurpGlobals::skipRelation(const char* name)
+bool BurpGlobals::skipRelation(const QualifiedMetaString& name)
{
if (gbl_sw_meta)
return true;
@@ -2764,10 +2756,12 @@ bool BurpGlobals::skipRelation(const char* name)
{ false, false, true} // NM p
};
- const enum Pattern res1 = checkPattern(skipDataMatcher, name);
- const enum Pattern res2 = checkPattern(includeDataMatcher, name);
+ const enum Pattern res1sch = checkPattern(skipSchemaDataMatcher, name.schema.c_str());
+ const enum Pattern res1obj = checkPattern(skipDataMatcher, name.object.c_str());
+ const enum Pattern res2sch = checkPattern(includeSchemaDataMatcher, name.schema.c_str());
+ const enum Pattern res2obj = checkPattern(includeDataMatcher, name.object.c_str());
- return result[res1][res2];
+ return result[res1sch][res2sch] && result[res1obj][res2obj];
}
void BurpGlobals::read_stats(SINT64* stats)
@@ -2888,24 +2882,6 @@ void BurpGlobals::print_stats_header()
burp_output(false, "\n");
}
-void BURP_makeSymbol(BurpGlobals* tdgbl, Firebird::string& name) // add double quotes to string
-{
- if (tdgbl->gbl_dialect < SQL_DIALECT_V6)
- return;
-
- const char dq = '"';
- for (unsigned p = 0; p < name.length(); ++p)
- {
- if (name[p] == dq)
- {
- name.insert(p, 1, dq);
- ++p;
- }
- }
- name.insert(0u, 1, dq);
- name += dq;
-}
-
static void processFetchPass(const SCHAR*& password, int& itr, const int argc, Firebird::UtilSvc::ArgvType& argv)
{
if (++itr >= argc)
diff --git a/src/burp/burp.h b/src/burp/burp.h
index cb791efa7e..30541eb080 100644
--- a/src/burp/burp.h
+++ b/src/burp/burp.h
@@ -42,7 +42,9 @@
#include "../common/UtilSvc.h"
#include "../common/classes/array.h"
#include "../common/classes/fb_pair.h"
+#include "../common/classes/GenericMap.h"
#include "../common/classes/MetaString.h"
+#include "../common/classes/QualifiedMetaString.h"
#include "../common/SimilarToRegex.h"
#include "../common/status.h"
#include "../common/sha.h"
@@ -120,7 +122,8 @@ enum rec_type {
rec_package, // Package
rec_db_creator, // Database creator
rec_publication, // Publication
- rec_pub_table // Publication table
+ rec_pub_table, // Publication table
+ rec_schema // Schema
};
@@ -205,9 +208,12 @@ Version 10: FB3.0.
Version 11: FB4.0.
SQL SECURITY feature, tables RDB$PUBLICATIONS/RDB$PUBLICATION_TABLES.
+
+Version 12: FB6.0.
+ Schemas.
*/
-const int ATT_BACKUP_FORMAT = 11;
+const int ATT_BACKUP_FORMAT = 12;
// max array dimension
@@ -259,6 +265,7 @@ enum att_type {
att_database_sql_security, // default sql security value
att_default_pub_active, // default publication status
att_default_pub_auto_enable,
+ att_database_dfl_charset_schema_name, // default character set schema name
// Relation attributes
@@ -282,6 +289,7 @@ enum att_type {
att_relation_type,
att_relation_sql_security_deprecated, // can be removed later
att_relation_sql_security,
+ att_relation_schema_name,
// Field attributes (used for both global and local fields)
@@ -341,6 +349,7 @@ enum att_type {
att_field_owner_name, // FB3.0, ODS12_0,
att_field_generator_name,
att_field_identity_type,
+ att_field_schema_name,
// Index attributes
@@ -357,6 +366,7 @@ enum att_type {
att_index_expression_blr,
att_index_condition_source,
att_index_condition_blr,
+ att_index_foreign_key_schema_name,
// Data record
@@ -381,6 +391,7 @@ enum att_type {
// Security class attributes
+ // FIXME: SERIES + ... ?
att_class_security_class = SERIES + 10,
att_class_acl,
att_class_description,
@@ -396,7 +407,9 @@ enum att_type {
att_xdr_length = SERIES + 16,
att_xdr_array,
+
att_class_description2,
+ att_view_relation_schema_name,
// Trigger attributes
@@ -419,6 +432,7 @@ enum att_type {
att_trig_type2,
att_trig_sql_security_deprecated, // can be removed later
att_trig_sql_security,
+ att_trig_schema_name,
// Function attributes
@@ -444,6 +458,7 @@ enum att_type {
att_function_deterministic_flag,
att_function_sql_security_deprecated, // can be removed later
att_function_sql_security,
+ att_function_schema_name,
// Function argument attributes
@@ -467,6 +482,9 @@ enum att_type {
att_functionarg_field_name,
att_functionarg_relation_name,
att_functionarg_description,
+ att_functionarg_schema_name,
+ att_functionarg_field_source_schema_name,
+ att_functionarg_relation_schema_name,
// TYPE relation attributes
att_type_name = SERIES,
@@ -490,6 +508,7 @@ enum att_type {
att_trigmsg_name = SERIES,
att_trigmsg_number,
att_trigmsg_text,
+ att_trigmsg_schema_name,
// User privilege attributes
att_priv_user = SERIES,
@@ -500,6 +519,8 @@ enum att_type {
att_priv_field_name,
att_priv_user_type,
att_priv_obj_type,
+ att_priv_user_schema_name,
+ att_priv_object_schema_name,
// files for shadowing purposes
att_file_filename = SERIES,
@@ -519,6 +540,7 @@ enum att_type {
att_gen_sysflag,
att_gen_init_val,
att_gen_id_increment,
+ att_gen_schema_name,
// Stored procedure attributes
@@ -541,6 +563,7 @@ enum att_type {
att_procedure_private_flag,
att_procedure_sql_security_deprecated, // can be removed later
att_procedure_sql_security,
+ att_procedure_schema_name,
// Stored procedure parameter attributes
@@ -557,6 +580,8 @@ enum att_type {
att_procedureprm_mechanism,
att_procedureprm_field_name,
att_procedureprm_relation_name,
+ att_procedureprm_field_source_schema_name,
+ att_procedureprm_relation_schema_name,
// Exception attributes
@@ -567,6 +592,7 @@ enum att_type {
att_exception_msg2,
att_exception_security_class, // FB3.0, ODS12_0
att_exception_owner_name,
+ att_exception_schema_name, // FB6.0, ODS14_0
// Relation constraints attributes
@@ -576,6 +602,7 @@ enum att_type {
att_rel_constraint_defer,
att_rel_constraint_init,
att_rel_constraint_index,
+ att_rel_constraint_schema_name,
// Referential constraints attributes
@@ -584,6 +611,8 @@ enum att_type {
att_ref_match_option,
att_ref_update_rule,
att_ref_delete_rule,
+ att_ref_schema_name,
+ att_ref_unique_const_schema_name,
// SQL roles attributes
att_role_name = SERIES,
@@ -594,6 +623,7 @@ enum att_type {
// Check constraints attributes
att_chk_constraint_name = SERIES,
att_chk_trigger_name,
+ att_chk_schema_name,
// Character Set attributes
att_charset_name = SERIES,
@@ -607,6 +637,8 @@ enum att_type {
att_charset_bytes_char,
att_charset_security_class, // FB3.0, ODS12_0
att_charset_owner_name,
+ att_charset_schema_name,
+ att_charset_coll_schema_name,
att_coll_name = SERIES,
att_coll_id,
@@ -620,6 +652,7 @@ enum att_type {
att_coll_specific_attr,
att_coll_security_class, // FB3.0, ODS12_0
att_coll_owner_name,
+ att_coll_schema_name,
// Names mapping
att_map_name = SERIES,
@@ -643,6 +676,7 @@ enum att_type {
att_package_description,
att_package_sql_security_deprecated, // can be removed later
att_package_sql_security,
+ att_package_schema_name,
// Database creators
att_dbc_user = SERIES,
@@ -656,7 +690,16 @@ enum att_type {
// Publication tables
att_ptab_pub_name = SERIES,
- att_ptab_table_name
+ att_ptab_table_name,
+ att_ptab_table_schema_name,
+
+ // Schema attributes
+ att_schema_name = SERIES,
+ att_schema_charset_schema_name,
+ att_schema_charset_name,
+ att_schema_security_class,
+ att_schema_owner_name,
+ att_schema_description,
};
@@ -703,7 +746,7 @@ struct burp_fld
SSHORT fld_system_flag;
SSHORT fld_name_length;
TEXT fld_name [GDS_NAME_LEN];
- TEXT fld_source [GDS_NAME_LEN];
+ Firebird::QualifiedMetaString fld_source;
TEXT fld_base [GDS_NAME_LEN];
TEXT fld_query_name [GDS_NAME_LEN];
TEXT fld_security_class [GDS_NAME_LEN];
@@ -748,8 +791,7 @@ struct burp_rel
burp_fld* rel_fields;
SSHORT rel_flags;
SSHORT rel_id;
- SSHORT rel_name_length;
- GDS_NAME rel_name;
+ Firebird::QualifiedMetaString rel_name;
GDS_NAME rel_owner; // relation owner, if not us
ULONG rel_max_pp; // max pointer page sequence number
};
@@ -763,7 +805,7 @@ enum burp_rel_flags_vals {
struct burp_pkg
{
burp_pkg* pkg_next;
- GDS_NAME pkg_name;
+ Firebird::QualifiedMetaString pkg_name;
GDS_NAME pkg_owner;
};
@@ -772,16 +814,14 @@ struct burp_pkg
struct burp_prc
{
burp_prc* prc_next;
- //SSHORT prc_name_length; // Currently useless, but didn't want to delete it.
- GDS_NAME prc_package;
- GDS_NAME prc_name;
+ Firebird::QualifiedMetaString prc_name;
GDS_NAME prc_owner; // relation owner, if not us
};
struct gfld
{
- TEXT gfld_name [GDS_NAME_LEN];
+ Firebird::QualifiedMetaString gfld_name;
ISC_QUAD gfld_vb;
ISC_QUAD gfld_vs;
ISC_QUAD gfld_vs2;
@@ -806,7 +846,7 @@ struct burp_meta_obj
{
burp_meta_obj* obj_next;
USHORT obj_type;
- GDS_NAME obj_name;
+ Firebird::QualifiedMetaString obj_name;
bool obj_class;
};
@@ -1144,6 +1184,7 @@ public:
Firebird::IRequest* handles_get_ref_constraint_req_handle1;
Firebird::IRequest* handles_get_rel_constraint_req_handle1;
Firebird::IRequest* handles_get_relation_req_handle1;
+ Firebird::IRequest* handles_get_schema_req_handle1;
Firebird::IRequest* handles_get_security_class_req_handle1;
Firebird::IRequest* handles_get_sql_roles_req_handle1;
Firebird::IRequest* handles_get_trigger_message_req_handle1;
@@ -1189,9 +1230,9 @@ public:
{
ThreadData::restoreSpecific();
}
- void setupSkipData(const Firebird::string& regexp);
- void setupIncludeData(const Firebird::string& regexp);
- bool skipRelation(const char* name);
+ void setupSkipIncludePattern(const Firebird::string& regexp, USHORT alreadySetErrorCode,
+ Firebird::AutoPtr& matcher);
+ bool skipRelation(const Firebird::QualifiedMetaString& name);
char veryEnd;
//starting after this members must be initialized in constructor explicitly
@@ -1199,9 +1240,8 @@ public:
Firebird::FbLocalStatus status_vector;
Firebird::ThrowLocalStatus throwStatus;
- Firebird::Array > >
- defaultCollations;
- Firebird::SortedArray systemFields;
+ Firebird::NonPooledMap defaultCollations;
+ Firebird::SortedArray systemFields;
Firebird::Array gbl_dpb_data;
Firebird::UtilSvc* uSvc;
bool master; // set for master thread only
@@ -1211,7 +1251,9 @@ public:
bool firstMap; // this is the first time we entered get_mapping()
bool firstDbc; // this is the first time we entered get_db_creators()
bool stdIoMode; // stdin or stdout is used as backup file
+ Firebird::AutoPtr skipSchemaDataMatcher;
Firebird::AutoPtr skipDataMatcher;
+ Firebird::AutoPtr includeSchemaDataMatcher;
Firebird::AutoPtr includeDataMatcher;
public:
diff --git a/src/burp/burp_proto.h b/src/burp/burp_proto.h
index 393da083cc..2b692d5234 100644
--- a/src/burp/burp_proto.h
+++ b/src/burp/burp_proto.h
@@ -38,7 +38,6 @@ void BURP_abort(Firebird::IStatus* status = nullptr);
void BURP_error(USHORT, bool, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_error(USHORT, bool, const char* str);
void BURP_error_redirect(Firebird::IStatus*, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
-void BURP_makeSymbol(BurpGlobals*, Firebird::string&);
void BURP_msg_partial(bool, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_msg_put(bool, USHORT, const MsgFormat::SafeArg& arg);
const int BURP_MSG_GET_SIZE = 128; // Use it for buffers passed to this function.
diff --git a/src/burp/burpswi.h b/src/burp/burpswi.h
index 609f928614..57da4f4a1b 100644
--- a/src/burp/burpswi.h
+++ b/src/burp/burpswi.h
@@ -102,6 +102,9 @@ const int IN_SW_BURP_REPLICA = 53; // replica mode
const int IN_SW_BURP_PARALLEL_WORKERS = 54; // parallel workers
const int IN_SW_BURP_DIRECT_IO = 55; // direct IO for backup files
+const int IN_SW_BURP_SKIP_SCHEMA_DATA = 56; // skip data from schema
+const int IN_SW_BURP_INCLUDE_SCHEMA_DATA = 57; // backup data from schemas
+
/**************************************************************************/
static const char* const BURP_SW_MODE_NONE = "NONE";
@@ -186,8 +189,12 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
{IN_SW_BURP_S, 0, "SKIP_BAD_DATA", 0, 0, 0, false, false, 0, 4, NULL, boRestore},
{IN_SW_BURP_SE, 0, "SERVICE", 0, 0, 0, false, false, 277, 2, NULL, boGeneral},
// msg 277: @1SE(RVICE) use services manager
+ {IN_SW_BURP_SKIP_SCHEMA_DATA, isc_spb_res_skip_schema_data, "SKIP_SCHEMA_DATA", 0, 0, 0, false, false, 415, 13, NULL, boGeneral},
+ // msg 415: @1SKIP_SCHEMA_DATA skip data for schema
{IN_SW_BURP_SKIP_DATA, isc_spb_res_skip_data, "SKIP_DATA", 0, 0, 0, false, false, 355, 6, NULL, boGeneral},
// msg 355: @1SKIP_DATA skip data for table
+ {IN_SW_BURP_INCLUDE_SCHEMA_DATA, isc_spb_res_include_schema_data, "INCLUDE_SCHEMA_DATA", 0, 0, 0, false, false, 416, 16, NULL, boGeneral},
+ // msg 416: @1INCLUDE_SCHEMA_D(ATA) backup data of schemas(s)
{IN_SW_BURP_INCLUDE_DATA, isc_spb_res_include_data, "INCLUDE_DATA", 0, 0, 0, false, false, 388, 7, NULL, boGeneral},
// msg 388: @1INCLUDE(_DATA) backup data of table(s)
{IN_SW_BURP_STATS, isc_spb_bkp_stat, "STATISTICS", 0, 0, 0, false, false, 361, 2, NULL, boGeneral},
diff --git a/src/burp/restore.epp b/src/burp/restore.epp
index bdd59a7a19..4b7682cf4f 100644
--- a/src/burp/restore.epp
+++ b/src/burp/restore.epp
@@ -116,7 +116,7 @@ void decompress(BurpGlobals* tdgbl, UCHAR*, ULONG);
void eat_blob(BurpGlobals* tdgbl);
void eat_text(BurpGlobals* tdgbl);
void eat_text2(BurpGlobals* tdgbl);
-burp_rel* find_relation(BurpGlobals* tdgbl, const TEXT*);
+burp_rel* find_relation(BurpGlobals* tdgbl, const QualifiedMetaString&);
void fix_security_class_name(BurpGlobals* tdgbl, TEXT* sec_class, bool is_field);
// CVC: when do these functions return false indeed???
// get_acl and get_index are the only exceptions but ironically their
@@ -145,13 +145,14 @@ SLONG get_int32(BurpGlobals* tdgbl);
SINT64 get_int64(BurpGlobals* tdgbl);
bool get_package(BurpGlobals* tdgbl);
bool get_procedure(BurpGlobals* tdgbl);
-bool get_procedure_prm(BurpGlobals* tdgbl, GDS_NAME, GDS_NAME);
+bool get_procedure_prm(BurpGlobals* tdgbl, const QualifiedMetaString&);
bool get_publication(BurpGlobals* tdgbl);
bool get_pub_table(BurpGlobals* tdgbl);
bool get_ref_constraint(BurpGlobals* tdgbl);
bool get_rel_constraint(BurpGlobals* tdgbl);
bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* task);
bool get_relation_data(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* task);
+bool get_schema(BurpGlobals* tdgbl);
bool get_sql_roles(BurpGlobals* tdgbl);
bool get_mapping(BurpGlobals* tdgbl);
bool get_db_creator(BurpGlobals* tdgbl);
@@ -174,8 +175,8 @@ USHORT recompute_length(BurpGlobals* tdgbl, burp_rel*);
#endif
bool restore(BurpGlobals* tdgbl, Firebird::IProvider*, const TEXT*, const TEXT*);
void restore_security_class(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
-USHORT get_view_base_relation_count(BurpGlobals* tdgbl, const TEXT*, USHORT, bool* error);
-void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SINT64 initial_value,
+USHORT get_view_base_relation_count(BurpGlobals* tdgbl, const QualifiedMetaString&, USHORT, bool* error);
+void store_blr_gen_id(BurpGlobals* tdgbl, const QualifiedMetaString& gen_name, SINT64 value, SINT64 initial_value,
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername, fb_sysflag sysFlag,
SLONG increment);
void update_global_field(BurpGlobals* tdgbl);
@@ -264,21 +265,22 @@ const int USER_PRIV_FIELD_NAME = 32;
const int USER_PRIV_USER_TYPE = 64;
const int USER_PRIV_OBJECT_TYPE = 128;
-static inline void collect_missing_privs(BurpGlobals* tdgbl, USHORT type, const GDS_NAME name, bool hasSecClass)
+static inline void collect_missing_privs(BurpGlobals* tdgbl, USHORT type, const QualifiedMetaString& name,
+ bool hasSecClass)
{
burp_meta_obj* object = (burp_meta_obj*) BURP_alloc_zero(sizeof(burp_meta_obj));
object->obj_next = tdgbl->miss_privs;
object->obj_type = type;
- strcpy(object->obj_name, name);
+ object->obj_name = name;
object->obj_class = hasSecClass;
tdgbl->miss_privs = object;
}
} // namespace
-void activateIndex(BurpGlobals* tdgbl, const char* index_name)
+void activateIndex(BurpGlobals* tdgbl, const QualifiedMetaString& indexName)
{
- BURP_verbose(285, index_name);
+ BURP_verbose(285, indexName.toQuotedString().c_str());
// activating and creating deferred index %s
bool fError = false;
@@ -288,16 +290,19 @@ void activateIndex(BurpGlobals* tdgbl, const char* index_name)
START_TRANSACTION activateIndexTran;
FOR (TRANSACTION_HANDLE activateIndexTran REQUEST_HANDLE tdgbl->handles_activateIndex_req_handle1)
- IND1 IN RDB$INDICES WITH IND1.RDB$INDEX_NAME EQ index_name
+ IND1 IN RDB$INDICES
+ WITH IND1.RDB$SCHEMA_NAME EQUIV NULLIF(indexName.schema.c_str(), '') AND
+ IND1.RDB$INDEX_NAME EQ indexName.object.c_str()
+ {
MODIFY IND1 USING
IND1.RDB$INDEX_INACTIVE = FALSE;
- END_MODIFY;
- END_FOR;
-
+ END_MODIFY
+ }
+ END_FOR
ON_ERROR
fError = true;
fb_utils::copyStatus(&local_status_vector, isc_status);
- END_ERROR;
+ END_ERROR
if (!fError)
{
@@ -305,19 +310,19 @@ void activateIndex(BurpGlobals* tdgbl, const char* index_name)
ON_ERROR
fError = true;
fb_utils::copyStatus(&local_status_vector, isc_status);
- END_ERROR;
+ END_ERROR
}
if (fError)
{
- BURP_print(false, 173, index_name);
+ BURP_print(false, 173, indexName.toQuotedString().c_str());
BURP_print_status(false, &local_status_vector);
tdgbl->flag_on_line = false;
ROLLBACK activateIndexTran;
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
}
@@ -335,7 +340,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
**************************************/
Firebird::IRequest* req_handle1 = nullptr;
Firebird::IRequest* req_handle3 = nullptr;
- BASED_ON RDB$INDICES.RDB$INDEX_NAME index_name;
+ QualifiedMetaString indexName;
Firebird::DispatcherPtr provider;
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@@ -349,6 +354,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
COMMIT;
ON_ERROR
+ {
// Fix for bug_no 8055:
// don't throw away the database just because an index
// could not be made
@@ -359,18 +365,21 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
{
case isc_sort_mem_err:
case isc_no_dup:
- strcpy(index_name, (TEXT *)tdgbl->status_vector[3]);
+ indexName = QualifiedMetaString::parseSchemaObject((TEXT*) tdgbl->status_vector[3]);
BURP_print_status(false, &tdgbl->status_vector);
FOR (REQUEST_HANDLE req_handle3)
- IDX IN RDB$INDICES WITH IDX.RDB$INDEX_NAME EQ index_name
-
- BURP_verbose(243, index_name);
+ IDX IN RDB$INDICES
+ WITH IDX.RDB$SCHEMA_NAME EQUIV NULLIF(indexName.schema.c_str(), '') AND
+ IDX.RDB$INDEX_NAME EQ indexName.object.c_str()
+ {
+ BURP_verbose(243, indexName.toQuotedString().c_str());
MODIFY IDX USING
IDX.RDB$INDEX_INACTIVE = TRUE;
END_MODIFY;
- BURP_print(false, 240, index_name);
+ BURP_print(false, 240, indexName.toQuotedString().c_str());
// msg 240 Index \"%s\" failed to activate because:
- if ( error_code == isc_no_dup )
+
+ if (error_code == isc_no_dup)
{
BURP_print(false, 241);
// msg 241 The unique index has duplicate values or NULLs
@@ -384,12 +393,16 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
BURP_print(false, 245);
// msg 245 Set the TMP environment variable to a directory on a filesystem that does have enough space, and activate index with
}
- BURP_print(false, 243, index_name);
+
+ BURP_print(false, 243, indexName.toQuotedString().c_str());
// msg 243 ALTER INDEX \"%s\" ACTIVE;
- END_FOR;
+ }
+ END_FOR
+
// don't bring the database on-line
tdgbl->flag_on_line = false;
break;
+
default:
general_on_error ();
break;
@@ -399,7 +412,8 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
continue;
END_ERROR
}
- END_ERROR;
+ }
+ END_ERROR
if (tdgbl->global_trans)
{
@@ -430,21 +444,25 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
FOR (REQUEST_HANDLE req_handle1) IDS IN RDB$INDICES WITH
IDS.RDB$INDEX_INACTIVE EQ DEFERRED_ACTIVE AND
IDS.RDB$FOREIGN_KEY MISSING
+ {
+ if (!IDS.RDB$SCHEMA_NAME.NULL)
+ indexName.schema = IDS.RDB$SCHEMA_NAME;
- MISC_terminate(IDS.RDB$INDEX_NAME, index_name,
- (ULONG)MISC_symbol_length(IDS.RDB$INDEX_NAME, sizeof(IDS.RDB$INDEX_NAME)),
- sizeof(index_name));
+ indexName.object = IDS.RDB$INDEX_NAME;
- activateIndex(tdgbl, index_name);
- END_FOR;
+ activateIndex(tdgbl, indexName);
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
+
MISC_release_request_silent(req_handle1);
+
COMMIT;
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
EXEC SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED NO_AUTO_UNDO;
if (gds_status->hasData())
@@ -463,23 +481,27 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
CNST IN RDB$RELATION_CONSTRAINTS
CROSS IDS IN RDB$INDICES WITH
CNST.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY AND
+ CNST.RDB$SCHEMA_NAME EQUIV IDS.RDB$SCHEMA_NAME AND
CNST.RDB$INDEX_NAME EQ IDS.RDB$INDEX_NAME AND
IDS.RDB$INDEX_INACTIVE EQ DEFERRED_ACTIVE
+ {
+ if (!IDS.RDB$SCHEMA_NAME.NULL)
+ indexName.schema = IDS.RDB$SCHEMA_NAME;
- MISC_terminate(IDS.RDB$INDEX_NAME, index_name,
- (ULONG) MISC_symbol_length(IDS.RDB$INDEX_NAME, sizeof(IDS.RDB$INDEX_NAME)),
- sizeof(index_name));
+ indexName.object = IDS.RDB$INDEX_NAME;
- activateIndex(tdgbl, index_name);
- END_FOR;
+ activateIndex(tdgbl, indexName);
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
+
COMMIT;
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
EXEC SQL SET TRANSACTION ISOLATION LEVEL READ COMMITTED NO_AUTO_UNDO;
@@ -989,6 +1011,9 @@ void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TE
dpb.insertInt(isc_dpb_page_size, page_size & 0xff00);
dpb.insertString(isc_dpb_gbak_attach, FB_VERSION, fb_strlen(FB_VERSION));
+ if (tdgbl->RESTORE_format >= 12)
+ dpb.insertTag(isc_dpb_gbak_restore_has_schema);
+
if (sweep_interval != MAX_ULONG)
{
dpb.insertInt(isc_dpb_sweep_interval, sweep_interval);
@@ -1044,10 +1069,11 @@ void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TE
dpb.insertInt(isc_dpb_parallel_workers, tdgbl->gbl_sw_par_workers);
dpb.insertByte(isc_dpb_shutdown, isc_dpb_shut_multi);
}
+
dpb.insertInt(isc_dpb_shutdown_delay, 0);
dpb.insertInt(isc_dpb_overwrite, tdgbl->gbl_sw_overwrite);
-
dpb.insertByte(isc_dpb_no_db_triggers, 1);
+ dpb.insertString(isc_dpb_search_path, SYSTEM_SCHEMA, fb_strlen(SYSTEM_SCHEMA));
FbLocalStatus status_vector;
@@ -1356,7 +1382,7 @@ void eat_text2(BurpGlobals* tdgbl)
MVOL_skip_block(tdgbl, len);
}
-burp_rel* find_relation(BurpGlobals* tdgbl, const TEXT* name)
+burp_rel* find_relation(BurpGlobals* tdgbl, const QualifiedMetaString& name)
{
/**************************************
*
@@ -1373,14 +1399,11 @@ burp_rel* find_relation(BurpGlobals* tdgbl, const TEXT* name)
// Why isn't strcmp used here?
for (burp_rel* relation = tdgbl->relations; relation; relation = relation->rel_next)
{
- for (const TEXT* p = relation->rel_name, *q = name; *p == *q; p++, q++)
- {
- if (!*p)
- return relation;
- }
+ if (relation->rel_name == name)
+ return relation;
}
- BURP_error_redirect(NULL, 35, SafeArg() << name);
+ BURP_error_redirect(NULL, 35, SafeArg() << name.toQuotedString().c_str());
// msg 35 can't find relation %s
return NULL;
@@ -1434,8 +1457,18 @@ void fix_security_class_name(BurpGlobals* tdgbl, TEXT* sec_class, bool is_field)
add_byte(blr, blr_begin);
add_byte(blr, blr_assignment);
- add_byte(blr, blr_gen_id);
- add_string(blr, SQL_SECCLASS_GENERATOR);
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ {
+ add_byte(blr, blr_gen_id3);
+ add_string(blr, SYSTEM_SCHEMA);
+ add_string(blr, SQL_SECCLASS_GENERATOR);
+ add_byte(blr, 1);
+ }
+ else
+ {
+ add_byte(blr, blr_gen_id);
+ add_string(blr, SQL_SECCLASS_GENERATOR);
+ }
add_byte(blr, blr_literal);
add_byte(blr, blr_int64);
@@ -1884,8 +1917,15 @@ void get_array(BurpGlobals* tdgbl, burp_rel* relation, UCHAR* record_buffer)
add_byte(blr, field->fld_type);
}
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ {
+ add_byte(blr, isc_sdl_schema);
+ add_string(blr,
+ (relation->rel_name.schema.hasData() ? relation->rel_name.schema.c_str() : PUBLIC_SCHEMA));
+ }
+
add_byte(blr, isc_sdl_relation);
- add_string(blr, relation->rel_name);
+ add_string(blr, relation->rel_name.object.c_str());
add_byte(blr, isc_sdl_field);
add_string(blr, field->fld_name);
@@ -2119,8 +2159,14 @@ void get_array(BurpGlobals* tdgbl, burp_rel* relation, UCHAR* record_buffer)
add_byte(blr, field->fld_type);
}
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ {
+ add_byte(blr, isc_sdl_schema);
+ add_string(blr, (relation->rel_name.schema.hasData() ? relation->rel_name.schema.c_str() : PUBLIC_SCHEMA));
+ }
+
add_byte(blr, isc_sdl_relation);
- add_string(blr, relation->rel_name);
+ add_string(blr, relation->rel_name.object.c_str());
add_byte(blr, isc_sdl_field);
add_string(blr, field->fld_name);
@@ -2432,6 +2478,7 @@ bool get_character_set(BurpGlobals* tdgbl)
{
};
+ QualifiedMetaString name;
att_type attribute;
scan_attr_t scan_next_attr;
@@ -2439,14 +2486,19 @@ bool get_character_set(BurpGlobals* tdgbl)
{
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
- GDS_NAME charset_name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
bool securityClass = false;
STORE (REQUEST_HANDLE tdgbl->handles_get_character_sets_req_handle1)
X IN RDB$CHARACTER_SETS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$CHARACTER_SET_NAME.NULL = TRUE;
X.RDB$FORM_OF_USE.NULL = TRUE;
X.RDB$NUMBER_OF_CHARACTERS.NULL = TRUE;
+ X.RDB$DEFAULT_COLLATE_SCHEMA_NAME.NULL = TRUE;
X.RDB$DEFAULT_COLLATE_NAME.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
@@ -2462,10 +2514,17 @@ bool get_character_set(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_charset_schema_name:
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_charset_name:
X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
GET_TEXT(X.RDB$CHARACTER_SET_NAME);
- BURP_verbose (msgVerbose_restore_charset, X.RDB$CHARACTER_SET_NAME);
+ name.object = X.RDB$CHARACTER_SET_NAME;
+ BURP_verbose(msgVerbose_restore_charset, name.toQuotedString().c_str());
break;
case att_charset_form:
@@ -2478,6 +2537,11 @@ bool get_character_set(BurpGlobals* tdgbl)
X.RDB$NUMBER_OF_CHARACTERS = (USHORT) get_int32(tdgbl);
break;
+ case att_charset_coll_schema_name:
+ X.RDB$DEFAULT_COLLATE_SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$DEFAULT_COLLATE_SCHEMA_NAME);
+ break;
+
case att_charset_coll:
X.RDB$DEFAULT_COLLATE_NAME.NULL = FALSE;
GET_TEXT(X.RDB$DEFAULT_COLLATE_NAME);
@@ -2540,20 +2604,19 @@ bool get_character_set(BurpGlobals* tdgbl)
if (X.RDB$CHARACTER_SET_ID.NULL && !X.RDB$DEFAULT_COLLATE_NAME.NULL &&
!X.RDB$CHARACTER_SET_NAME.NULL)
{
- tdgbl->defaultCollations.add(
- Firebird::Pair >(
- X.RDB$CHARACTER_SET_NAME, X.RDB$DEFAULT_COLLATE_NAME));
+ tdgbl->defaultCollations.put(
+ QualifiedMetaString(X.RDB$CHARACTER_SET_NAME, X.RDB$SCHEMA_NAME),
+ QualifiedMetaString(X.RDB$DEFAULT_COLLATE_NAME, X.RDB$DEFAULT_COLLATE_SCHEMA_NAME));
+
throw AbortException(); // prevent the STORE
}
-
- strcpy(charset_name, X.RDB$CHARACTER_SET_NAME);
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
- collect_missing_privs(tdgbl, obj_charset, charset_name, securityClass);
+ collect_missing_privs(tdgbl, obj_charset, name, securityClass);
}
else
{
@@ -2578,7 +2641,8 @@ bool get_character_set(BurpGlobals* tdgbl)
case att_charset_name:
X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
GET_TEXT(X.RDB$CHARACTER_SET_NAME);
- BURP_verbose (msgVerbose_restore_charset, X.RDB$CHARACTER_SET_NAME);
+ name.object = X.RDB$CHARACTER_SET_NAME;
+ BURP_verbose(msgVerbose_restore_charset, name.toQuotedString().c_str());
break;
case att_charset_form:
@@ -2639,9 +2703,10 @@ bool get_character_set(BurpGlobals* tdgbl)
if (X.RDB$CHARACTER_SET_ID.NULL && !X.RDB$DEFAULT_COLLATE_NAME.NULL &&
!X.RDB$CHARACTER_SET_NAME.NULL)
{
- tdgbl->defaultCollations.add(
- Firebird::Pair >(
- X.RDB$CHARACTER_SET_NAME, X.RDB$DEFAULT_COLLATE_NAME));
+ tdgbl->defaultCollations.put(
+ QualifiedMetaString(X.RDB$CHARACTER_SET_NAME),
+ QualifiedMetaString(X.RDB$DEFAULT_COLLATE_NAME));
+
throw AbortException(); // prevent the STORE
}
@@ -2675,6 +2740,8 @@ bool get_chk_constraint(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_chk_constraint_req_handle1)
X IN RDB$CHECK_CONSTRAINTS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$CONSTRAINT_NAME.NULL = TRUE;
X.RDB$TRIGGER_NAME.NULL = TRUE;
@@ -2683,6 +2750,11 @@ bool get_chk_constraint(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_chk_schema_name:
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ break;
+
case att_chk_constraint_name:
X.RDB$CONSTRAINT_NAME.NULL = FALSE;
GET_TEXT(X.RDB$CONSTRAINT_NAME);
@@ -2699,10 +2771,11 @@ bool get_chk_constraint(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
return true;
}
@@ -2719,16 +2792,18 @@ bool get_collation(BurpGlobals* tdgbl)
* Restore data for user defined collations
*
**************************************/
+ QualifiedMetaString name;
att_type attribute;
scan_attr_t scan_next_attr;
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
- GDS_NAME coll_name;
bool securityClass = false;
STORE (REQUEST_HANDLE tdgbl->handles_get_collation_req_handle1)
X IN RDB$COLLATIONS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$COLLATION_NAME.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
@@ -2747,11 +2822,17 @@ bool get_collation(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_coll_schema_name:
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
case att_coll_name:
X.RDB$COLLATION_NAME.NULL = FALSE;
GET_TEXT(X.RDB$COLLATION_NAME);
- BURP_verbose(msgVerbose_restore_collation, X.RDB$COLLATION_NAME);
+ name.object = X.RDB$COLLATION_NAME;
+ BURP_verbose(msgVerbose_restore_collation, name.toQuotedString().c_str());
break;
case att_coll_id:
@@ -2837,21 +2918,20 @@ bool get_collation(BurpGlobals* tdgbl)
break;
}
}
-
- strcpy(coll_name, X.RDB$COLLATION_NAME);
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
- collect_missing_privs(tdgbl, obj_collation, coll_name, securityClass);
+ collect_missing_privs(tdgbl, obj_collation, name, securityClass);
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL11)
{
// This includes DDL11_0 that doesn't know to ignore unknown system fields.
STORE (REQUEST_HANDLE tdgbl->handles_get_collation_req_handle1)
X IN RDB$COLLATIONS
+ {
X.RDB$COLLATION_NAME.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
@@ -2872,7 +2952,8 @@ bool get_collation(BurpGlobals* tdgbl)
case att_coll_name:
X.RDB$COLLATION_NAME.NULL = FALSE;
GET_TEXT(X.RDB$COLLATION_NAME);
- BURP_verbose(msgVerbose_restore_collation, X.RDB$COLLATION_NAME);
+ name.object = X.RDB$COLLATION_NAME;
+ BURP_verbose(msgVerbose_restore_collation, name.toQuotedString().c_str());
break;
case att_coll_id:
@@ -2944,15 +3025,17 @@ bool get_collation(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
STORE (REQUEST_HANDLE tdgbl->handles_get_collation_req_handle1)
X IN RDB$COLLATIONS
+ {
X.RDB$COLLATION_NAME.NULL = TRUE;
X.RDB$COLLATION_ID.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
@@ -2973,7 +3056,8 @@ bool get_collation(BurpGlobals* tdgbl)
case att_coll_name:
X.RDB$COLLATION_NAME.NULL = FALSE;
GET_TEXT(X.RDB$COLLATION_NAME);
- BURP_verbose(msgVerbose_restore_collation, X.RDB$COLLATION_NAME);
+ name.object = X.RDB$COLLATION_NAME;
+ BURP_verbose(msgVerbose_restore_collation, name.toQuotedString().c_str());
break;
case att_coll_id:
@@ -3039,10 +3123,11 @@ bool get_collation(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
return true;
@@ -3052,11 +3137,12 @@ bool get_collation(BurpGlobals* tdgbl)
static void check_data_error(BurpGlobals* tdgbl, IStatus* status_vector, const burp_rel* relation)
{
ISC_STATUS code = status_vector->getErrors()[1];
+
if (code == isc_not_valid)
{
if (tdgbl->gbl_sw_incremental)
{
- BURP_print(false, 138, relation->rel_name);
+ BURP_print(false, 138, relation->rel_name.toQuotedString().c_str());
// msg 138 validation error on field in relation %s
BURP_print_status (false, status_vector);
}
@@ -3069,7 +3155,7 @@ static void check_data_error(BurpGlobals* tdgbl, IStatus* status_vector, const b
if (tdgbl->gbl_sw_incremental)
{
// msg 114 restore failed for record in relation %s
- BURP_print(false, 114, relation->rel_name);
+ BURP_print(false, 114, relation->rel_name.toQuotedString().c_str());
BURP_print_status(false, status_vector, 342); // isc_gbak_invalid_data
}
@@ -3080,7 +3166,7 @@ static void check_data_error(BurpGlobals* tdgbl, IStatus* status_vector, const b
{
if (tdgbl->gbl_sw_incremental && isc_sqlcode(status_vector->getErrors()) != -902)
{
- BURP_print (false, 114, relation->rel_name);
+ BURP_print (false, 114, relation->rel_name.toQuotedString().c_str());
// msg 114 restore failed for record in relation %s
BURP_print_status(false, status_vector);
}
@@ -3092,12 +3178,12 @@ static void check_data_error(BurpGlobals* tdgbl, IStatus* status_vector, const b
static void commit_relation_data(BurpGlobals* tdgbl, burp_rel* relation)
{
- BURP_verbose(72, relation->rel_name);
+ BURP_verbose(72, relation->rel_name.toQuotedString().c_str());
// msg 72 committing data for relation %s
COMMIT
// existing ON_ERROR continues past error, beck
ON_ERROR
-
+ {
// Fix for bug_no 8055:
// don't throw away the database just because an index
// could not be made
@@ -3109,51 +3195,58 @@ static void commit_relation_data(BurpGlobals* tdgbl, burp_rel* relation)
while (error_code = tdgbl->status_vector[1])
{
Firebird::IRequest* req_handle = 0;
- BASED_ON RDB$INDICES.RDB$INDEX_NAME index_name;
+ QualifiedMetaString indexName;
switch (error_code)
{
case isc_sort_mem_err:
case isc_no_dup:
- strcpy(index_name, (TEXT *)tdgbl->status_vector[3]);
+ indexName = QualifiedMetaString::parseSchemaObject((TEXT*) tdgbl->status_vector[3]);
+ indexName.object = (TEXT*) tdgbl->status_vector[3];
BURP_print_status(false, &tdgbl->status_vector);
FOR(REQUEST_HANDLE req_handle)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ index_name
+ WITH IDX.RDB$SCHEMA_NAME EQUIV NULLIF(indexName.schema.c_str(), '') AND
+ IDX.RDB$INDEX_NAME EQ indexName.object.c_str()
{
MODIFY IDX USING
+ {
IDX.RDB$INDEX_INACTIVE = TRUE;
- BURP_print(false, 240, index_name);
- // msg 240 Index \"%s\" failed to activate because:
- if (error_code == isc_no_dup)
- {
- BURP_print(false, 241);
- // msg 241 The unique index has duplicate values or NULLs
- BURP_print(false, 242);
- // msg 242 Delete or Update duplicate values or NULLs, and activate index with
+ BURP_print(false, 240, indexName.toQuotedString().c_str());
+ // msg 240 Index \"%s\" failed to activate because:
+
+ if (error_code == isc_no_dup)
+ {
+ BURP_print(false, 241);
+ // msg 241 The unique index has duplicate values or NULLs
+ BURP_print(false, 242);
+ // msg 242 Delete or Update duplicate values or NULLs, and activate index with
+ }
+ else
+ {
+ BURP_print(false, 244);
+ // msg 244 Not enough disk space to create the sort file for an index
+ BURP_print(false, 245);
+ // msg 245 Set the TMP environment variable to a directory on a filesystem that does have enough space, and activate index with
+ }
+
+ BURP_print(false, 243, indexName.toQuotedString().c_str());
+ // msg 243 ALTER INDEX \"%s\" ACTIVE
}
- else
- {
- BURP_print(false, 244);
- // msg 244 Not enough disk space to create the sort file for an index
- BURP_print(false, 245);
- // msg 245 Set the TMP environment variable to a directory on a filesystem that does have enough space, and activate index with
- }
- BURP_print(false, 243, index_name);
- // msg 243 ALTER INDEX \"%s\" ACTIVE
- END_MODIFY;
+ END_MODIFY
}
- END_FOR;
+ END_FOR
// commit one more time
COMMIT
- ON_ERROR
+ ON_ERROR
continue;
END_ERROR
- break;
+ break;
+
default:
- BURP_print(false, 69, relation->rel_name);
+ BURP_print(false, 69, relation->rel_name.toQuotedString().c_str());
// msg 69 commit failed on relation %s
BURP_print_status(false, &tdgbl->status_vector);
ROLLBACK;
@@ -3163,13 +3256,14 @@ static void commit_relation_data(BurpGlobals* tdgbl, burp_rel* relation)
break;
} // end of switch
} // end of while
- END_ERROR;
+ }
+ END_ERROR
set_transaction(tdgbl);
}
// We have a corrupt backup, save the restore process from becoming useless.
-void fix_exception(BurpGlobals* tdgbl, const char* exc_name, scan_attr_t& scan_next_attr,
+void fix_exception(BurpGlobals* tdgbl, const QualifiedMetaString& name, scan_attr_t& scan_next_attr,
const att_type attribute, att_type& failed_attrib, UCHAR*& msg_ptr, ULONG& l2, bool& msg_seen)
{
if (msg_seen && (tdgbl->RESTORE_format == 7 || tdgbl->RESTORE_format == 8))
@@ -3177,7 +3271,7 @@ void fix_exception(BurpGlobals* tdgbl, const char* exc_name, scan_attr_t& scan_n
if (!failed_attrib)
{
failed_attrib = attribute;
- BURP_print(false, 313, SafeArg() << failed_attrib << exc_name);
+ BURP_print(false, 313, SafeArg() << failed_attrib << name.toQuotedString().c_str());
}
// Notice we use 1021 instead of 1023 because this is the maximum length
@@ -3230,7 +3324,7 @@ void get_data(BurpGlobals* tdgbl, burp_rel* relation, WriteRelationReq* req)
RCRD_LENGTH length = req->getDataLength();
UCHAR* buffer = req->getData();
- // BURP_verbose (124, relation->rel_name); // msg 124 restoring data for relation %s
+ // BURP_verbose (124, relation->rel_name.toQuotedString().c_str()); // msg 124 restoring data for relation %s
lstring data;
data.lstr_allocated = 0;
@@ -3395,18 +3489,22 @@ bool get_exception(BurpGlobals* tdgbl)
* Reconstruct a exception.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
- TEXT temp[GDS_NAME_LEN];
ULONG l2 = 0;
scan_attr_t scan_next_attr;
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
- GDS_NAME exception_name;
bool securityClass = false;
STORE (REQUEST_HANDLE tdgbl->handles_get_exception_req_handle1)
X IN RDB$EXCEPTIONS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$EXCEPTION_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$MESSAGE.NULL = TRUE;
@@ -3424,22 +3522,28 @@ bool get_exception(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_exception_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_exception_name:
if (!X.RDB$EXCEPTION_NAME.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
- const ULONG l = GET_TEXT(X.RDB$EXCEPTION_NAME);
+ GET_TEXT(X.RDB$EXCEPTION_NAME);
X.RDB$EXCEPTION_NAME.NULL = FALSE;
- MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (199, temp);
+ name.object = X.RDB$EXCEPTION_NAME;
+ BURP_verbose(199, name.toQuotedString().c_str());
// msg 199 restoring exception %s
}
break;
case att_exception_description:
if (!X.RDB$DESCRIPTION.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3450,7 +3554,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_description2:
if (!X.RDB$DESCRIPTION.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3461,11 +3565,11 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_msg:
if (msg_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else if (!X.RDB$MESSAGE.NULL)
{
msg_seen = true;
- BURP_print(false, 312, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_print(false, 312, SafeArg() << attribute << name.toQuotedString().c_str());
eat_text(tdgbl);
}
else
@@ -3479,10 +3583,10 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_msg2:
if (msg_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else if (!X.RDB$MESSAGE.NULL)
{
- BURP_print(false, 312, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_print(false, 312, SafeArg() << attribute << name.toQuotedString().c_str());
eat_text2(tdgbl);
}
else
@@ -3495,7 +3599,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_security_class:
if (!X.RDB$SECURITY_CLASS.NULL)
{
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
}
else
{
@@ -3509,7 +3613,7 @@ bool get_exception(BurpGlobals* tdgbl)
}
else
{
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
}
}
@@ -3518,7 +3622,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_owner_name:
if (!X.RDB$OWNER_NAME.NULL)
{
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
}
else
{
@@ -3530,7 +3634,7 @@ bool get_exception(BurpGlobals* tdgbl)
}
else
{
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
}
}
@@ -3538,20 +3642,18 @@ bool get_exception(BurpGlobals* tdgbl)
default:
// do we have a corrupt backup?
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
break;
}
}
-
- strcpy(exception_name, X.RDB$EXCEPTION_NAME);
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
END_ERROR;
- collect_missing_privs(tdgbl, obj_exception, exception_name, securityClass);
+ collect_missing_privs(tdgbl, obj_exception, name, securityClass);
}
else
{
@@ -3577,20 +3679,20 @@ bool get_exception(BurpGlobals* tdgbl)
{
case att_exception_name:
if (!X.RDB$EXCEPTION_NAME.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
- const ULONG l = GET_TEXT(X.RDB$EXCEPTION_NAME);
+ GET_TEXT(X.RDB$EXCEPTION_NAME);
X.RDB$EXCEPTION_NAME.NULL = FALSE;
- MISC_terminate (X.RDB$EXCEPTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (199, temp);
+ name.object = X.RDB$EXCEPTION_NAME;
+ BURP_verbose(199, name.toQuotedString().c_str());
// msg 199 restoring exception %s
}
break;
case att_exception_description:
if (!X.RDB$DESCRIPTION.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3601,7 +3703,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_description2:
if (!X.RDB$DESCRIPTION.NULL)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3612,11 +3714,11 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_msg:
if (msg_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else if (!X.RDB$MESSAGE.NULL)
{
msg_seen = true;
- BURP_print(false, 312, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_print(false, 312, SafeArg() << attribute << name.toQuotedString().c_str());
eat_text(tdgbl);
}
else
@@ -3630,10 +3732,10 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_msg2:
if (msg_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else if (!X.RDB$MESSAGE.NULL)
{
- BURP_print(false, 312, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_print(false, 312, SafeArg() << attribute << name.toQuotedString().c_str());
eat_text2(tdgbl);
}
else
@@ -3645,7 +3747,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_security_class:
if (secclass_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3656,7 +3758,7 @@ bool get_exception(BurpGlobals* tdgbl)
}
else
{
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
}
}
@@ -3664,7 +3766,7 @@ bool get_exception(BurpGlobals* tdgbl)
case att_exception_owner_name:
if (ownername_seen)
- BURP_error(311, true, SafeArg() << attribute << X.RDB$EXCEPTION_NAME);
+ BURP_error(311, true, SafeArg() << attribute << name.toQuotedString().c_str());
else
{
msg_seen = false;
@@ -3675,7 +3777,7 @@ bool get_exception(BurpGlobals* tdgbl)
}
else
{
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
}
}
@@ -3683,7 +3785,7 @@ bool get_exception(BurpGlobals* tdgbl)
default:
// do we have a corrupt backup?
- fix_exception(tdgbl, X.RDB$EXCEPTION_NAME, scan_next_attr, attribute,
+ fix_exception(tdgbl, name, scan_next_attr, attribute,
failed_attrib, msg_ptr, l2, msg_seen);
break;
}
@@ -3738,7 +3840,8 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_field_req_handle1)
X IN RDB$RELATION_FIELDS
{
- strcpy (X.RDB$RELATION_NAME, relation->rel_name);
+ strcpy(X.RDB$RELATION_NAME, relation->rel_name.object.c_str());
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$FIELD_POSITION = 0;
X.RDB$VIEW_CONTEXT.NULL = TRUE;
X.RDB$BASE_FIELD.NULL = TRUE;
@@ -3759,6 +3862,14 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
// ODS 12
X.RDB$GENERATOR_NAME.NULL = TRUE;
X.RDB$IDENTITY_TYPE.NULL = TRUE;
+ // ODS 14
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = TRUE;
+
+ if (relation->rel_name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, relation->rel_name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
skip_init(&scan_next_attr);
while (get_attribute(&attribute, tdgbl) != att_end)
@@ -3767,14 +3878,23 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
{
case att_field_name:
field->fld_name_length = GET_TEXT(field->fld_name);
- BURP_verbose (115, field->fld_name);
+ BURP_verbose(115, MetaString(field->fld_name).toQuotedString().c_str());
// msg 115 restoring field %s
strcpy (X.RDB$FIELD_NAME, field->fld_name);
break;
+ case att_field_schema_name:
+ GET_TEXT(X.RDB$FIELD_SOURCE_SCHEMA_NAME);
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ field->fld_source.schema = X.RDB$FIELD_SOURCE_SCHEMA_NAME;
+
+ if (field->fld_source.schema.isEmpty() && tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ field->fld_source.schema = PUBLIC_SCHEMA;
+ break;
+
case att_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
- strcpy(field->fld_source, X.RDB$FIELD_SOURCE);
+ field->fld_source.object = X.RDB$FIELD_SOURCE;
break;
case att_field_security_class:
@@ -3945,7 +4065,7 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_field_req_handle1)
X IN RDB$RELATION_FIELDS
{
- strcpy (X.RDB$RELATION_NAME, relation->rel_name);
+ strcpy (X.RDB$RELATION_NAME, relation->rel_name.object.c_str());
X.RDB$FIELD_POSITION = 0;
X.RDB$VIEW_CONTEXT.NULL = TRUE;
X.RDB$BASE_FIELD.NULL = TRUE;
@@ -3971,14 +4091,14 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
{
case att_field_name:
field->fld_name_length = GET_TEXT(field->fld_name);
- BURP_verbose (115, field->fld_name);
+ BURP_verbose(115, MetaString(field->fld_name).toQuotedString().c_str());
// msg 115 restoring field %s
strcpy (X.RDB$FIELD_NAME, field->fld_name);
break;
case att_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
- strcpy(field->fld_source, X.RDB$FIELD_SOURCE);
+ field->fld_source.object = X.RDB$FIELD_SOURCE;
break;
case att_field_security_class:
@@ -4152,12 +4272,19 @@ bool get_field_dimensions(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_field_dimensions_req_handle1)
X IN RDB$FIELD_DIMENSIONS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
switch (attribute)
{
+ case att_field_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ break;
+
case att_field_name:
GET_TEXT(X.RDB$FIELD_NAME);
break;
@@ -4180,10 +4307,11 @@ bool get_field_dimensions(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
return true;
}
@@ -4315,7 +4443,7 @@ bool get_filter(BurpGlobals* tdgbl)
{
case att_filter_name:
GET_TEXT(X.RDB$FUNCTION_NAME);
- BURP_verbose (117, X.RDB$FUNCTION_NAME);
+ BURP_verbose(117, MetaString(X.RDB$FUNCTION_NAME).toQuotedString().c_str());
// msg 117 restoring filter %s
break;
@@ -4371,9 +4499,11 @@ bool get_function(BurpGlobals* tdgbl)
* Reconstruct a function.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
- TEXT temp[GDS_NAME_LEN * 2];
- SSHORT l;
scan_attr_t scan_next_attr;
bool existFlag = false;
@@ -4382,14 +4512,15 @@ bool get_function(BurpGlobals* tdgbl)
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
- GDS_NAME function_name;
bool securityClass = false;
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_function_req_handle1)
X IN RDB$FUNCTIONS
+ {
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$ENGINE_NAME.NULL = TRUE;
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$PACKAGE_NAME.NULL = TRUE;
X.RDB$PRIVATE_FLAG.NULL = TRUE;
X.RDB$FUNCTION_BLR.NULL = TRUE;
@@ -4419,22 +4550,11 @@ bool get_function(BurpGlobals* tdgbl)
switch (attribute)
{
case att_function_name:
- {
- SSHORT prefixLen = 0;
- if (!X.RDB$PACKAGE_NAME.NULL)
- {
- prefixLen = static_cast(strlen(X.RDB$PACKAGE_NAME));
- memcpy(temp, X.RDB$PACKAGE_NAME, prefixLen);
- temp[prefixLen++] = '.';
- }
-
- l = GET_TEXT(X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp + prefixLen, l,
- sizeof(temp) - prefixLen);
- BURP_verbose (118, temp);
+ GET_TEXT(X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(118, name.toQuotedString().c_str());
// msg 118 restoring function %s
break;
- }
case att_function_description:
X.RDB$DESCRIPTION.NULL = FALSE;
@@ -4479,12 +4599,18 @@ bool get_function(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 89);
break;
+ case att_function_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_function_package_name:
if (tdgbl->RESTORE_format >= 10)
{
GET_TEXT(X.RDB$PACKAGE_NAME);
- fb_utils::exact_name(X.RDB$PACKAGE_NAME);
X.RDB$PACKAGE_NAME.NULL = FALSE;
+ name.package = X.RDB$PACKAGE_NAME;
securityClass = true; // prevent creation of security class for packaged function
}
else
@@ -4600,23 +4726,23 @@ bool get_function(BurpGlobals* tdgbl)
break;
}
}
-
- strcpy(function_name, X.RDB$FUNCTION_NAME);
- END_STORE;
+ }
+ END_STORE
ON_ERROR
if (gds_status->getErrors()[1] != isc_no_dup)
general_on_error ();
else
existFlag = true;
- END_ERROR;
+ END_ERROR
- collect_missing_privs(tdgbl, obj_udf, function_name, securityClass);
+ collect_missing_privs(tdgbl, obj_udf, name, securityClass);
}
else
{
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_function_req_handle1)
X IN RDB$FUNCTIONS
+ {
X.RDB$RETURN_ARGUMENT.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
@@ -4628,9 +4754,9 @@ bool get_function(BurpGlobals* tdgbl)
switch (attribute)
{
case att_function_name:
- l = GET_TEXT(X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (118, temp);
+ GET_TEXT(X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(118, name.toQuotedString().c_str());
// msg 118 restoring function %s
break;
@@ -4732,14 +4858,14 @@ bool get_function(BurpGlobals* tdgbl)
break;
}
}
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
if (gds_status->getErrors()[1] != isc_no_dup)
general_on_error ();
else
existFlag = true;
- END_ERROR;
+ END_ERROR
}
// at the end of args for a function is the rec_function_end marker
@@ -4761,6 +4887,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
* Reconstruct function argument.
*
**************************************/
+ QualifiedMetaString name;
att_type attribute;
scan_attr_t scan_next_attr;
@@ -4773,6 +4900,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
{
switch (attribute)
{
+ case att_functionarg_schema_name:
case att_functionarg_name:
eat_text(tdgbl);
break;
@@ -4814,6 +4942,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
case att_functionarg_package_name:
case att_functionarg_arg_name:
+ case att_functionarg_field_source_schema_name:
case att_functionarg_field_source:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -4839,6 +4968,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
break;
case att_functionarg_field_name:
+ case att_functionarg_relation_schema_name:
case att_functionarg_relation_name:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -4862,21 +4992,21 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
return;
}
- SSHORT l;
- TEXT temp[GDS_NAME_LEN * 2];
-
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
// with RDB$FIELD_PRECISION
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_function_arg_req_handle1)
X IN RDB$FUNCTION_ARGUMENTS
+ {
X.RDB$ARGUMENT_POSITION.NULL = TRUE;
X.RDB$FIELD_SUB_TYPE.NULL = TRUE;
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
X.RDB$FIELD_PRECISION.NULL = TRUE;
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$PACKAGE_NAME.NULL = TRUE;
X.RDB$ARGUMENT_NAME.NULL = TRUE;
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = TRUE;
X.RDB$FIELD_SOURCE.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
X.RDB$DEFAULT_SOURCE.NULL = TRUE;
@@ -4884,6 +5014,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
X.RDB$NULL_FLAG.NULL = TRUE;
X.RDB$ARGUMENT_MECHANISM.NULL = TRUE;
X.RDB$FIELD_NAME.NULL = TRUE;
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
X.RDB$RELATION_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
@@ -4896,22 +5027,10 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
switch (attribute)
{
case att_functionarg_name:
- {
- SSHORT prefixLen = 0;
- if (!X.RDB$PACKAGE_NAME.NULL)
- {
- prefixLen = static_cast(strlen(X.RDB$PACKAGE_NAME));
- memcpy(temp, X.RDB$PACKAGE_NAME, prefixLen);
- temp[prefixLen++] = '.';
- }
-
- l = GET_TEXT(X.RDB$FUNCTION_NAME);
- MISC_terminate(X.RDB$FUNCTION_NAME, temp + prefixLen, l,
- sizeof(temp) - prefixLen);
-
- // msg 119 restoring argument for function %s
- BURP_verbose(119, temp);
- }
+ GET_TEXT(X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(119, name.toQuotedString().c_str());
+ // msg 119 restoring argument for function %s
break;
case att_functionarg_position:
@@ -4955,12 +5074,18 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
bad_attribute(scan_next_attr, attribute, 90);
break;
+ case att_functionarg_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_functionarg_package_name:
if (tdgbl->RESTORE_format >= 10)
{
GET_TEXT(X.RDB$PACKAGE_NAME);
X.RDB$PACKAGE_NAME.NULL = FALSE;
- fb_utils::exact_name(X.RDB$PACKAGE_NAME);
+ name.package = X.RDB$PACKAGE_NAME;
}
else
bad_attribute(scan_next_attr, attribute, 90);
@@ -4976,6 +5101,16 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
bad_attribute(scan_next_attr, attribute, 90);
break;
+ case att_functionarg_field_source_schema_name:
+ if (tdgbl->RESTORE_format >= 10)
+ {
+ GET_TEXT(X.RDB$FIELD_SOURCE_SCHEMA_NAME);
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ bad_attribute(scan_next_attr, attribute, 90);
+ break;
+
case att_functionarg_field_source:
if (tdgbl->RESTORE_format >= 10)
{
@@ -5046,6 +5181,16 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
bad_attribute(scan_next_attr, attribute, 90);
break;
+ case att_functionarg_relation_schema_name:
+ if (tdgbl->RESTORE_format >= 10)
+ {
+ GET_TEXT(X.RDB$RELATION_SCHEMA_NAME);
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ bad_attribute(scan_next_attr, attribute, 90);
+ break;
+
case att_functionarg_relation_name:
if (tdgbl->RESTORE_format >= 10)
{
@@ -5072,7 +5217,8 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
END_ERROR;
@@ -5094,9 +5240,9 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
switch (attribute)
{
case att_functionarg_name:
- l = GET_TEXT(X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (119, temp);
+ GET_TEXT(X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(119, name.toQuotedString().c_str());
// msg 119 restoring argument for function %s
break;
@@ -5143,6 +5289,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
case att_functionarg_package_name:
case att_functionarg_arg_name:
+ case att_functionarg_field_source_schema_name:
case att_functionarg_field_source:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -5168,6 +5315,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
break;
case att_functionarg_field_name:
+ case att_functionarg_relation_schema_name:
case att_functionarg_relation_name:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -5209,9 +5357,9 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
switch (attribute)
{
case att_functionarg_name:
- l = GET_TEXT(X.RDB$FUNCTION_NAME);
- MISC_terminate (X.RDB$FUNCTION_NAME, temp, l, sizeof(temp));
- BURP_verbose (119, temp);
+ GET_TEXT(X.RDB$FUNCTION_NAME);
+ name.object = X.RDB$FUNCTION_NAME;
+ BURP_verbose(119, name.toQuotedString().c_str());
// msg 119 restoring argument for function %s
break;
@@ -5255,6 +5403,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
case att_functionarg_package_name:
case att_functionarg_arg_name:
+ case att_functionarg_field_source_schema_name:
case att_functionarg_field_source:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -5280,6 +5429,7 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
break;
case att_functionarg_field_name:
+ case att_functionarg_relation_schema_name:
case att_functionarg_relation_name:
if (tdgbl->RESTORE_format >= 10)
eat_text(tdgbl);
@@ -5324,7 +5474,11 @@ bool get_generator(BurpGlobals* tdgbl)
**************************************/
SINT64 value = 0, initial_value = 0;
- BASED_ON RDB$GENERATORS.RDB$GENERATOR_NAME name = "";
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
+ BASED_ON RDB$GENERATORS.RDB$GENERATOR_NAME temp = "";
BASED_ON RDB$GENERATORS.RDB$SECURITY_CLASS secclass = "";
BASED_ON RDB$GENERATORS.RDB$OWNER_NAME ownername = "";
BASED_ON RDB$GENERATORS.RDB$GENERATOR_INCREMENT increment = 1;
@@ -5343,8 +5497,14 @@ bool get_generator(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_gen_schema_name:
+ GET_TEXT(temp);
+ name.schema = temp;
+ break;
+
case att_gen_generator:
- GET_TEXT(name);
+ GET_TEXT(temp);
+ name.object = temp;
break;
case att_gen_value:
@@ -5435,22 +5595,24 @@ bool get_global_field(BurpGlobals* tdgbl)
* Reconstruct a global field.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
- TEXT temp[GDS_NAME_LEN];
- SSHORT l;
scan_attr_t scan_next_attr;
gfld* gfield = NULL;
if (tdgbl->runtimeODS >= DB_VERSION_DDL12)
{
- GDS_NAME field_name;
bool securityClass = false;
// with rdb$field_precision, rdb$security_class and rdb$owner_name.
STORE (REQUEST_HANDLE tdgbl->handles_get_global_field_req_handle1)
X IN RDB$FIELDS
-
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$FIELD_SCALE = X.RDB$SEGMENT_LENGTH = 0;
X.RDB$CHARACTER_SET_ID = X.RDB$COLLATION_ID = 0;
X.RDB$FIELD_SUB_TYPE = 0;
@@ -5488,10 +5650,16 @@ bool get_global_field(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_field_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_field_name:
- l = GET_TEXT(X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (121, temp);
+ GET_TEXT(X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+ BURP_verbose(121, name.toQuotedString().c_str());
// msg 121 restoring global field %s
break;
@@ -5785,15 +5953,13 @@ bool get_global_field(BurpGlobals* tdgbl)
if (X.RDB$FIELD_TYPE <= DTYPE_BLR_MAX)
{
- l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
+ SSHORT l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
if (l = type_lengths[l])
X.RDB$FIELD_LENGTH = l;
}
- strcpy(field_name, X.RDB$FIELD_NAME);
-
if (gfield)
- strcpy(gfield->gfld_name, field_name);
+ gfield->gfld_name = name;
if (tdgbl->gbl_sw_fix_fss_data && tdgbl->gbl_sw_fix_fss_data_id == 0 &&
!X.RDB$CHARACTER_SET_ID.NULL && X.RDB$CHARACTER_SET_ID == CS_UNICODE_FSS &&
@@ -5807,20 +5973,20 @@ bool get_global_field(BurpGlobals* tdgbl)
X.RDB$CHARACTER_SET_ID = CS_NONE;
X.RDB$COLLATION_ID = 0;
}
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
- collect_missing_privs(tdgbl, obj_field, field_name, securityClass);
+ collect_missing_privs(tdgbl, obj_field, name, securityClass);
}
else if (tdgbl->runtimeODS >= DB_VERSION_DDL10)
{
// with rdb$field_precision
STORE (REQUEST_HANDLE tdgbl->handles_get_global_field_req_handle1)
X IN RDB$FIELDS
-
+ {
X.RDB$FIELD_SCALE = X.RDB$SEGMENT_LENGTH = 0;
X.RDB$CHARACTER_SET_ID = X.RDB$COLLATION_ID = 0;
X.RDB$FIELD_SUB_TYPE = 0;
@@ -5856,9 +6022,9 @@ bool get_global_field(BurpGlobals* tdgbl)
switch (attribute)
{
case att_field_name:
- l = GET_TEXT(X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (121, temp);
+ GET_TEXT(X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+ BURP_verbose(121, name.toQuotedString().c_str());
// msg 121 restoring global field %s
break;
@@ -6138,13 +6304,13 @@ bool get_global_field(BurpGlobals* tdgbl)
if (X.RDB$FIELD_TYPE <= DTYPE_BLR_MAX)
{
- l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
+ SSHORT l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
if (l = type_lengths[l])
X.RDB$FIELD_LENGTH = l;
}
if (gfield)
- strcpy (gfield->gfld_name, X.RDB$FIELD_NAME);
+ gfield->gfld_name = name;
if (tdgbl->gbl_sw_fix_fss_data && tdgbl->gbl_sw_fix_fss_data_id == 0 &&
!X.RDB$CHARACTER_SET_ID.NULL && X.RDB$CHARACTER_SET_ID == CS_UNICODE_FSS &&
@@ -6158,12 +6324,11 @@ bool get_global_field(BurpGlobals* tdgbl)
X.RDB$CHARACTER_SET_ID = CS_NONE;
X.RDB$COLLATION_ID = 0;
}
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
-
+ END_ERROR
}
else // runtimeODS < DB_VERSION_DDL10
{
@@ -6171,7 +6336,7 @@ bool get_global_field(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_global_field_req_handle1)
X IN RDB$FIELDS
-
+ {
X.RDB$FIELD_SCALE = X.RDB$SEGMENT_LENGTH = 0;
X.RDB$CHARACTER_SET_ID = X.RDB$COLLATION_ID = 0;
X.RDB$FIELD_SUB_TYPE = 0;
@@ -6206,9 +6371,9 @@ bool get_global_field(BurpGlobals* tdgbl)
switch (attribute)
{
case att_field_name:
- l = GET_TEXT(X.RDB$FIELD_NAME);
- MISC_terminate (X.RDB$FIELD_NAME, temp, l, sizeof(temp));
- BURP_verbose (121, temp);
+ GET_TEXT(X.RDB$FIELD_NAME);
+ name.object = X.RDB$FIELD_NAME;
+ BURP_verbose(121, name.toQuotedString().c_str());
// msg 121 restoring global field %s
break;
@@ -6485,13 +6650,13 @@ bool get_global_field(BurpGlobals* tdgbl)
if (X.RDB$FIELD_TYPE <= DTYPE_BLR_MAX)
{
- l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
+ SSHORT l = gds_cvt_blr_dtype[X.RDB$FIELD_TYPE];
if (l = type_lengths[l])
X.RDB$FIELD_LENGTH = l;
}
if (gfield)
- strcpy (gfield->gfld_name, X.RDB$FIELD_NAME);
+ gfield->gfld_name = name;
if (tdgbl->gbl_sw_fix_fss_data && tdgbl->gbl_sw_fix_fss_data_id == 0 &&
!X.RDB$CHARACTER_SET_ID.NULL && X.RDB$CHARACTER_SET_ID == CS_UNICODE_FSS &&
@@ -6505,12 +6670,11 @@ bool get_global_field(BurpGlobals* tdgbl)
X.RDB$CHARACTER_SET_ID = CS_NONE;
X.RDB$COLLATION_ID = 0;
}
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
-
+ END_ERROR
}
if (gfield)
@@ -6547,14 +6711,18 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
STORE (REQUEST_HANDLE tdgbl->handles_get_index_req_handle1)
X IN RDB$INDICES
- strcpy (X.RDB$RELATION_NAME, relation->rel_name);
+ {
+ strcpy (X.RDB$RELATION_NAME, relation->rel_name.object.c_str());
X.RDB$UNIQUE_FLAG = 0;
if (!tdgbl->gbl_sw_deactivate_indexes)
X.RDB$INDEX_INACTIVE = FALSE;
else
X.RDB$INDEX_INACTIVE = TRUE;
+
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$INDEX_TYPE.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
+ X.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL = TRUE;
X.RDB$FOREIGN_KEY.NULL = TRUE;
X.RDB$EXPRESSION_SOURCE.NULL = TRUE;
X.RDB$EXPRESSION_BLR.NULL = TRUE;
@@ -6563,6 +6731,12 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
+ if (relation->rel_name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, relation->rel_name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
{
@@ -6570,8 +6744,8 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
{
case att_index_name:
GET_TEXT(X.RDB$INDEX_NAME);
- strcpy (index_name, X.RDB$INDEX_NAME);
- BURP_verbose (122, X.RDB$INDEX_NAME);
+ strcpy(index_name, X.RDB$INDEX_NAME);
+ BURP_verbose(122, QualifiedMetaString(X.RDB$INDEX_NAME, relation->rel_name.schema).toQuotedString().c_str());
break;
case att_segment_count:
@@ -6608,13 +6782,19 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
case att_index_field_name:
STORE (REQUEST_HANDLE tdgbl->handles_get_index_req_handle2)
Y IN RDB$INDEX_SEGMENTS
+ {
GET_TEXT(Y.RDB$FIELD_NAME);
- strcpy (Y.RDB$INDEX_NAME, X.RDB$INDEX_NAME);
+ strcpy(Y.RDB$INDEX_NAME, X.RDB$INDEX_NAME);
Y.RDB$FIELD_POSITION = count++;
- END_STORE;
+
+ Y.RDB$SCHEMA_NAME.NULL = X.RDB$SCHEMA_NAME.NULL;
+ if (!X.RDB$SCHEMA_NAME.NULL)
+ strcpy(Y.RDB$SCHEMA_NAME, X.RDB$SCHEMA_NAME);
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
break;
case att_index_description:
@@ -6663,6 +6843,11 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
bad_attribute(scan_next_attr, attribute, 93);
break;
+ case att_index_foreign_key_schema_name:
+ X.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$FOREIGN_KEY_SCHEMA_NAME);
+ break;
+
case att_index_foreign_key:
foreign_index = true;
// Defer foreign key index activation
@@ -6683,33 +6868,45 @@ bool get_index(BurpGlobals* tdgbl, const burp_rel* relation)
count = 0;
FOR (REQUEST_HANDLE tdgbl->handles_get_index_req_handle3)
- RFR IN RDB$RELATION_FIELDS CROSS I_S IN RDB$INDEX_SEGMENTS
- OVER RDB$FIELD_NAME WITH I_S.RDB$INDEX_NAME = index_name AND
- RFR.RDB$RELATION_NAME = relation->rel_name
+ RFR IN RDB$RELATION_FIELDS
+ CROSS IDS IN RDB$INDEX_SEGMENTS
+ WITH RFR.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ RFR.RDB$RELATION_NAME = relation->rel_name.object.c_str() AND
+ IDS.RDB$SCHEMA_NAME EQUIV RFR.RDB$SCHEMA_NAME AND
+ IDS.RDB$FIELD_NAME = RFR.RDB$FIELD_NAME AND
+ IDS.RDB$INDEX_NAME = index_name
+ {
count++;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
if (count != segments)
{
FOR (REQUEST_HANDLE tdgbl->handles_get_index_req_handle4)
- I_S IN RDB$INDEX_SEGMENTS WITH I_S.RDB$INDEX_NAME = index_name
- ERASE I_S;
+ IDS IN RDB$INDEX_SEGMENTS
+ WITH IDS.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ IDS.RDB$INDEX_NAME = index_name
+ {
+ ERASE IDS;
ON_ERROR
general_on_error ();
- END_ERROR;
- END_FOR;
+ END_ERROR
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+
+ END_ERROR
return false;
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
return true;
}
@@ -6825,8 +7022,6 @@ bool get_package(BurpGlobals* tdgbl)
*
**************************************/
att_type attribute;
- TEXT temp[GDS_NAME_LEN];
- SSHORT len;
scan_attr_t scan_next_attr;
if (tdgbl->RESTORE_format < 10)
@@ -6835,12 +7030,16 @@ bool get_package(BurpGlobals* tdgbl)
Firebird::ITransaction* local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
burp_pkg* package = (burp_pkg*) BURP_alloc_zero(sizeof(burp_pkg));
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ package->pkg_name.schema = PUBLIC_SCHEMA;
+
package->pkg_next = tdgbl->packages;
tdgbl->packages = package;
STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_package_req_handle1)
X IN RDB$PACKAGES
{
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$PACKAGE_HEADER_SOURCE.NULL = TRUE;
X.RDB$PACKAGE_BODY_SOURCE.NULL = TRUE;
X.RDB$VALID_BODY_FLAG.NULL = TRUE;
@@ -6856,11 +7055,16 @@ bool get_package(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_package_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ package->pkg_name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_package_name:
- len = GET_TEXT(X.RDB$PACKAGE_NAME);
- strcpy(package->pkg_name, X.RDB$PACKAGE_NAME);
- MISC_terminate(X.RDB$PACKAGE_NAME, temp, len, sizeof(temp));
- BURP_verbose(337, temp); // msg 337 restoring package %s
+ GET_TEXT(X.RDB$PACKAGE_NAME);
+ package->pkg_name.object = X.RDB$PACKAGE_NAME;
+ BURP_verbose(337, package->pkg_name.toQuotedString().c_str()); // msg 337 restoring package %s
break;
case att_package_header_source:
@@ -6934,15 +7138,14 @@ bool get_procedure(BurpGlobals* tdgbl)
*
**************************************/
att_type attribute;
- GDS_NAME package_name = "";
- GDS_NAME procedure_name = "";
- TEXT temp[GDS_NAME_LEN * 2];
- SSHORT l;
scan_attr_t scan_next_attr;
Firebird::ITransaction* local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
burp_prc* procedure = (burp_prc*) BURP_alloc_zero (sizeof(burp_prc));
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ procedure->prc_name.schema = PUBLIC_SCHEMA;
+
procedure->prc_next = tdgbl->procedures;
tdgbl->procedures = procedure;
@@ -6951,6 +7154,7 @@ bool get_procedure(BurpGlobals* tdgbl)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_procedure_req_handle1)
X IN RDB$PROCEDURES
+ {
X.RDB$PROCEDURE_SOURCE.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SECURITY_CLASS.NULL = TRUE;
@@ -6964,6 +7168,7 @@ bool get_procedure(BurpGlobals* tdgbl)
X.RDB$PROCEDURE_BLR.NULL = TRUE;
X.RDB$ENGINE_NAME.NULL = TRUE;
X.RDB$ENTRYPOINT.NULL = TRUE;
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$PACKAGE_NAME.NULL = TRUE;
X.RDB$PRIVATE_FLAG.NULL = TRUE;
X.RDB$SQL_SECURITY.NULL = TRUE;
@@ -6973,25 +7178,28 @@ bool get_procedure(BurpGlobals* tdgbl)
{
switch (attribute)
{
- case att_procedure_name:
+ case att_procedure_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ procedure->prc_name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
+ case att_procedure_package_name:
+ if (tdgbl->RESTORE_format >= 10)
{
- SSHORT prefixLen = 0;
- if (package_name[0])
- {
- prefixLen = static_cast(strlen(package_name));
- memcpy(temp, package_name, prefixLen);
- temp[prefixLen++] = '.';
- }
-
- l = GET_TEXT(X.RDB$PROCEDURE_NAME);
- //procedure->prc_name_length = l;
- strcpy (procedure->prc_name, X.RDB$PROCEDURE_NAME);
-
- MISC_terminate (X.RDB$PROCEDURE_NAME, temp + prefixLen, l,
- sizeof(temp) - prefixLen);
- BURP_verbose (195, temp);
- // msg 195 restoring stored procedure %s
+ GET_TEXT(X.RDB$PACKAGE_NAME);
+ X.RDB$PACKAGE_NAME.NULL = FALSE;
+ procedure->prc_name.package = X.RDB$PACKAGE_NAME;
}
+ else
+ bad_attribute(scan_next_attr, attribute, 290);
+ break;
+
+ case att_procedure_name:
+ GET_TEXT(X.RDB$PROCEDURE_NAME);
+ procedure->prc_name.object = X.RDB$PROCEDURE_NAME;
+ BURP_verbose(195, procedure->prc_name.toQuotedString().c_str());
+ // msg 195 restoring stored procedure %s
break;
case att_procedure_description:
@@ -7088,19 +7296,6 @@ bool get_procedure(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 290);
break;
- case att_procedure_package_name:
- if (tdgbl->RESTORE_format >= 10)
- {
- GET_TEXT(X.RDB$PACKAGE_NAME);
- X.RDB$PACKAGE_NAME.NULL = FALSE;
- strcpy(procedure->prc_package, X.RDB$PACKAGE_NAME);
- strcpy(package_name, X.RDB$PACKAGE_NAME);
- fb_utils::exact_name(package_name);
- }
- else
- bad_attribute(scan_next_attr, attribute, 290);
- break;
-
case att_procedure_private_flag:
if (tdgbl->RESTORE_format >= 10)
{
@@ -7128,8 +7323,8 @@ bool get_procedure(BurpGlobals* tdgbl)
break;
}
}
- strcpy (procedure_name, X.RDB$PROCEDURE_NAME);
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
END_ERROR;
@@ -7139,6 +7334,7 @@ bool get_procedure(BurpGlobals* tdgbl)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_procedure_req_handle1)
X IN RDB$PROCEDURES
+ {
X.RDB$PROCEDURE_SOURCE.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SECURITY_CLASS.NULL = TRUE;
@@ -7152,11 +7348,9 @@ bool get_procedure(BurpGlobals* tdgbl)
switch (attribute)
{
case att_procedure_name:
- l = GET_TEXT(X.RDB$PROCEDURE_NAME);
- //procedure->prc_name_length = l;
- strcpy (procedure->prc_name, X.RDB$PROCEDURE_NAME);
- MISC_terminate (X.RDB$PROCEDURE_NAME, temp, l, sizeof(temp));
- BURP_verbose (195, temp);
+ GET_TEXT(X.RDB$PROCEDURE_NAME);
+ procedure->prc_name.object = X.RDB$PROCEDURE_NAME;
+ BURP_verbose(195, procedure->prc_name.toQuotedString().c_str());
// msg 195 restoring stored procedure %s
break;
@@ -7251,22 +7445,22 @@ bool get_procedure(BurpGlobals* tdgbl)
break;
}
}
- strcpy (procedure_name, X.RDB$PROCEDURE_NAME);
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
// at the end of prms for a procedure is the rec_procedure_end marker
while (get(tdgbl) == rec_procedure_prm)
- get_procedure_prm (tdgbl, package_name, procedure_name);
+ get_procedure_prm(tdgbl, procedure->prc_name);
return true;
}
-bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME procptr)
+bool get_procedure_prm(BurpGlobals* tdgbl, const QualifiedMetaString& name)
{
/**************************************
*
@@ -7282,8 +7476,6 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
*
**************************************/
att_type attribute;
- SSHORT l;
- TEXT temp[GDS_NAME_LEN];
scan_attr_t scan_next_attr;
Firebird::ITransaction* local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
@@ -7293,17 +7485,26 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_procedure_prm_req_handle1)
X IN RDB$PROCEDURE_PARAMETERS
+ {
+ strcpy(X.RDB$PROCEDURE_NAME, name.object.c_str());
- strcpy(X.RDB$PROCEDURE_NAME, procptr);
-
- if (package_name[0])
+ if (name.schema.hasData())
{
- strcpy(X.RDB$PACKAGE_NAME, package_name);
+ strcpy(X.RDB$SCHEMA_NAME, name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
+
+ if (name.package.hasData())
+ {
+ strcpy(X.RDB$PACKAGE_NAME, name.package.c_str());
X.RDB$PACKAGE_NAME.NULL = FALSE;
}
else
X.RDB$PACKAGE_NAME.NULL = TRUE;
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$DEFAULT_VALUE.NULL = TRUE;
X.RDB$DEFAULT_SOURCE.NULL = TRUE;
@@ -7318,8 +7519,8 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
X.RDB$PARAMETER_MECHANISM = prm_mech_normal;
X.RDB$PARAMETER_MECHANISM.NULL = FALSE;
- // DB_VERSION_DDL11_2
X.RDB$FIELD_NAME.NULL = TRUE;
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
X.RDB$RELATION_NAME.NULL = TRUE;
skip_init(&scan_next_attr);
@@ -7328,9 +7529,8 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
switch (attribute)
{
case att_procedureprm_name:
- l = GET_TEXT(X.RDB$PARAMETER_NAME);
- MISC_terminate (X.RDB$PARAMETER_NAME, temp, l, sizeof(temp));
- BURP_verbose (196, temp);
+ GET_TEXT(X.RDB$PARAMETER_NAME);
+ BURP_verbose(196, MetaString(X.RDB$PARAMETER_NAME).toQuotedString().c_str());
// msg 196 restoring parameter %s for stored procedure
break;
@@ -7342,6 +7542,11 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
X.RDB$PARAMETER_NUMBER= (USHORT) get_int32(tdgbl);
break;
+ case att_procedureprm_field_source_schema_name:
+ GET_TEXT(X.RDB$FIELD_SOURCE_SCHEMA_NAME);
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ break;
+
case att_procedureprm_field_source:
GET_TEXT(X.RDB$FIELD_SOURCE);
break;
@@ -7411,6 +7616,11 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
bad_attribute(scan_next_attr, attribute, 291);
break;
+ case att_procedureprm_relation_schema_name:
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$RELATION_SCHEMA_NAME);
+ break;
+
// DB_VERSION_DDL11_2
case att_procedureprm_relation_name:
if (tdgbl->RESTORE_format >= 9)
@@ -7428,18 +7638,20 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_procedure_prm_req_handle1)
X IN RDB$PROCEDURE_PARAMETERS
+ {
X.RDB$DESCRIPTION.NULL = TRUE;
- strcpy (X.RDB$PROCEDURE_NAME, procptr);
+ strcpy(X.RDB$PROCEDURE_NAME, name.object.c_str());
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
@@ -7449,9 +7661,8 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
switch (attribute)
{
case att_procedureprm_name:
- l = GET_TEXT(X.RDB$PARAMETER_NAME);
- MISC_terminate (X.RDB$PARAMETER_NAME, temp, l, sizeof(temp));
- BURP_verbose (196, temp);
+ GET_TEXT(X.RDB$PARAMETER_NAME);
+ BURP_verbose(196, MetaString(X.RDB$PARAMETER_NAME).toQuotedString().c_str());
// msg 196 restoring parameter %s for stored procedure
break;
@@ -7509,10 +7720,11 @@ bool get_procedure_prm (BurpGlobals* tdgbl, GDS_NAME package_name, GDS_NAME proc
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
return true;
@@ -7558,7 +7770,7 @@ bool get_publication(BurpGlobals* tdgbl)
case att_pub_name:
GET_TEXT(X.RDB$PUBLICATION_NAME);
X.RDB$PUBLICATION_NAME.NULL = FALSE;
- BURP_verbose(399, X.RDB$PUBLICATION_NAME);
+ BURP_verbose(399, MetaString(X.RDB$PUBLICATION_NAME).toQuotedString().c_str());
// msg 399 restoring publication %s
break;
@@ -7627,6 +7839,10 @@ bool get_pub_table(BurpGlobals* tdgbl)
* Reconstruct a publication table.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
scan_attr_t scan_next_attr;
@@ -7634,8 +7850,9 @@ bool get_pub_table(BurpGlobals* tdgbl)
{
STORE (REQUEST_HANDLE tdgbl->handles_get_pub_tab_req_handle1)
X IN RDB$PUBLICATION_TABLES
-
+ {
X.RDB$PUBLICATION_NAME.NULL = TRUE;
+ X.RDB$TABLE_SCHEMA_NAME.NULL = TRUE;
X.RDB$TABLE_NAME.NULL = TRUE;
skip_init(&scan_next_attr);
@@ -7648,10 +7865,17 @@ bool get_pub_table(BurpGlobals* tdgbl)
X.RDB$PUBLICATION_NAME.NULL = FALSE;
break;
+ case att_ptab_table_schema_name:
+ GET_TEXT(X.RDB$TABLE_SCHEMA_NAME);
+ name.schema = X.RDB$TABLE_SCHEMA_NAME;
+ X.RDB$TABLE_SCHEMA_NAME.NULL = FALSE;
+ break;
+
case att_ptab_table_name:
GET_TEXT(X.RDB$TABLE_NAME);
+ name.object = X.RDB$TABLE_NAME;
X.RDB$TABLE_NAME.NULL = FALSE;
- BURP_verbose(401, X.RDB$TABLE_NAME);
+ BURP_verbose(401, name.toQuotedString().c_str());
// msg 401 restoring publication for table %s
break;
@@ -7661,10 +7885,11 @@ bool get_pub_table(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
@@ -7675,6 +7900,7 @@ bool get_pub_table(BurpGlobals* tdgbl)
switch (attribute)
{
case att_ptab_pub_name:
+ case att_ptab_table_schema_name:
case att_ptab_table_name:
eat_text(tdgbl);
break;
@@ -7707,7 +7933,10 @@ bool get_ref_constraint(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_ref_constraint_req_handle1)
X IN RDB$REF_CONSTRAINTS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$CONSTRAINT_NAME.NULL = TRUE;
+ X.RDB$CONST_SCHEMA_NAME_UQ.NULL = TRUE;
X.RDB$CONST_NAME_UQ.NULL = TRUE;
X.RDB$MATCH_OPTION.NULL = TRUE;
X.RDB$UPDATE_RULE.NULL = TRUE;
@@ -7718,11 +7947,21 @@ bool get_ref_constraint(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_ref_schema_name:
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ break;
+
case att_ref_constraint_name:
X.RDB$CONSTRAINT_NAME.NULL = FALSE;
GET_TEXT(X.RDB$CONSTRAINT_NAME);
break;
+ case att_ref_unique_const_schema_name:
+ X.RDB$CONST_SCHEMA_NAME_UQ.NULL = FALSE;
+ GET_TEXT(X.RDB$CONST_SCHEMA_NAME_UQ);
+ break;
+
case att_ref_unique_const_name:
X.RDB$CONST_NAME_UQ.NULL = FALSE;
GET_TEXT(X.RDB$CONST_NAME_UQ);
@@ -7749,10 +7988,11 @@ bool get_ref_constraint(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
return true;
}
@@ -7812,24 +8052,13 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
// Pick up relation attributes
burp_rel* relation = (burp_rel*) BURP_alloc_zero (sizeof(burp_rel));
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ relation->rel_name.schema = PUBLIC_SCHEMA;
+
relation->rel_next = tdgbl->relations;
tdgbl->relations = relation;
- /*
- STORE (REQUEST_HANDLE tdgbl->handles_get_relation_req_handle1)
- X IN RDB$RELATIONS
- X.RDB$SYSTEM_FLAG = 0;
- X.RDB$SYSTEM_FLAG.NULL = FALSE;
- X.RDB$FLAGS.NULL = TRUE;
- X.RDB$SECURITY_CLASS.NULL = TRUE;
- X.RDB$VIEW_BLR.NULL = TRUE;
- X.RDB$VIEW_SOURCE.NULL = TRUE;
- X.RDB$DESCRIPTION.NULL = TRUE;
- X.RDB$RUNTIME.NULL = TRUE;
- X.RDB$EXTERNAL_DESCRIPTION.NULL = TRUE;
- */
-
- TEXT rel_name[GDS_NAME_LEN] = "";
+ TEXT temp[GDS_NAME_LEN];
att_type attribute;
scan_attr_t scan_next_attr;
skip_init(&scan_next_attr);
@@ -7838,12 +8067,16 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
{
switch (attribute)
{
+ case att_relation_schema_name:
+ GET_TEXT(temp);
+ relation->rel_name.schema = temp;
+ break;
+
case att_relation_name:
{
- const SSHORT l = GET_TEXT(relation->rel_name);
- relation->rel_name_length = l;
- MISC_terminate (relation->rel_name, rel_name, l, sizeof(rel_name));
- BURP_verbose(167, rel_name); // msg 167 restoring table @1
+ GET_TEXT(temp);
+ relation->rel_name.object = temp;
+ BURP_verbose(167, relation->rel_name.toQuotedString().c_str()); // msg 167 restoring table @1
}
break;
@@ -7857,8 +8090,8 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
view_blr_null = false;
get_blr_blob(tdgbl, view_blr, true);
relation->rel_flags |= REL_view;
- fb_assert(rel_name[0] != 0);
- BURP_verbose(346, rel_name); // msg 346 ' table @1 is a view'
+ fb_assert(relation->rel_name.object.hasData());
+ BURP_verbose(346, relation->rel_name.toQuotedString().c_str()); // msg 346 ' table @1 is a view'
break;
case att_relation_view_source:
@@ -7941,7 +8174,8 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_relation_req_handle1)
X IN RDB$RELATIONS
-
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$FLAGS.NULL = rel_flags_null;
X.RDB$SECURITY_CLASS.NULL = sec_class_null;
@@ -7961,24 +8195,30 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
X.RDB$DESCRIPTION = rel_desc;
X.RDB$EXTERNAL_DESCRIPTION = ext_desc;
+ if (relation->rel_name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, relation->rel_name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+
strcpy(X.RDB$SECURITY_CLASS, sec_class);
- strcpy(X.RDB$RELATION_NAME, relation->rel_name);
+ strcpy(X.RDB$RELATION_NAME, relation->rel_name.object.c_str());
strcpy(X.RDB$EXTERNAL_FILE, ext_file_name);
X.RDB$RELATION_TYPE = (USHORT) type;
X.RDB$SQL_SECURITY = (FB_BOOLEAN) sql_security;
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_relation_req_handle1)
X IN RDB$RELATIONS
-
+ {
X.RDB$SYSTEM_FLAG.NULL = FALSE;
X.RDB$FLAGS.NULL = rel_flags_null;
X.RDB$SECURITY_CLASS.NULL = sec_class_null;
@@ -7997,13 +8237,13 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
X.RDB$EXTERNAL_DESCRIPTION = ext_desc;
strcpy(X.RDB$SECURITY_CLASS, sec_class);
- strcpy(X.RDB$RELATION_NAME, relation->rel_name);
+ strcpy(X.RDB$RELATION_NAME, relation->rel_name.object.c_str());
strcpy(X.RDB$EXTERNAL_FILE, ext_file_name);
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
// Eat up misc. records
@@ -8018,12 +8258,12 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
case rec_relation_end:
if (tdgbl->gbl_sw_incremental)
{
- BURP_verbose (170, relation->rel_name);
+ BURP_verbose(170, relation->rel_name.toQuotedString().c_str());
// msg 170: committing metadata for relation %s
COMMIT
// existing ON_ERROR continues past error, beck
ON_ERROR
- BURP_print (false, 171, relation->rel_name);
+ BURP_print(false, 171, relation->rel_name.toQuotedString().c_str());
// msg 171: error committing metadata for relation %s
BURP_print_status (false, &tdgbl->status_vector);
ROLLBACK;
@@ -8071,7 +8311,7 @@ bool get_relation(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTask* t
// If we're only doing meta-data, ignore data records
- if (tdgbl->gbl_sw_meta || tdgbl->skipRelation(rel_name))
+ if (tdgbl->gbl_sw_meta || tdgbl->skipRelation(relation->rel_name))
ignore_data(tdgbl, relation);
else
{
@@ -8102,6 +8342,8 @@ bool get_rel_constraint(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_rel_constraint_req_handle1)
X IN RDB$RELATION_CONSTRAINTS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$CONSTRAINT_NAME.NULL = TRUE;
X.RDB$CONSTRAINT_TYPE.NULL = TRUE;
X.RDB$RELATION_NAME.NULL = TRUE;
@@ -8114,6 +8356,11 @@ bool get_rel_constraint(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_rel_constraint_schema_name:
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ break;
+
case att_rel_constraint_name:
X.RDB$CONSTRAINT_NAME.NULL = FALSE;
GET_TEXT(X.RDB$CONSTRAINT_NAME);
@@ -8150,10 +8397,11 @@ bool get_rel_constraint(BurpGlobals* tdgbl)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
return true;
}
@@ -8172,7 +8420,11 @@ bool get_relation_data(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTa
* find the relation named. If we can't find it, give up.
*
**************************************/
- BASED_ON RDB$RELATIONS.RDB$RELATION_NAME name;
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
+ TEXT temp[GDS_NAME_LEN];
att_type attribute;
scan_attr_t scan_next_attr;
@@ -8183,9 +8435,15 @@ bool get_relation_data(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTa
{
switch (attribute)
{
+ case att_relation_schema_name:
+ GET_TEXT(temp);
+ name.schema = temp;
+ break;
+
case att_relation_name:
- GET_TEXT(name);
- relation = find_relation (tdgbl, name);
+ GET_TEXT(temp);
+ name.object = temp;
+ relation = find_relation(tdgbl, name);
break;
default:
@@ -8257,6 +8515,118 @@ bool get_relation_data(BurpGlobals* tdgbl, Coordinator* coord, RestoreRelationTa
return true;
}
+// Reconstruct a schema.
+bool get_schema(BurpGlobals* tdgbl)
+{
+ att_type attribute;
+ scan_attr_t scan_next_attr;
+
+ if (tdgbl->runtimeODS < DB_VERSION_DDL14)
+ {
+ skip_init(&scan_next_attr);
+
+ while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
+ {
+ switch (attribute)
+ {
+ case att_schema_name:
+ eat_text(tdgbl);
+ break;
+
+ case att_schema_charset_schema_name:
+ eat_text(tdgbl);
+ break;
+
+ case att_schema_charset_name:
+ eat_text(tdgbl);
+ break;
+
+ case att_schema_security_class:
+ eat_text(tdgbl);
+ break;
+
+ case att_schema_owner_name:
+ eat_text(tdgbl);
+ break;
+
+ case att_schema_description:
+ eat_blob(tdgbl);
+ break;
+
+ default:
+ bad_attribute(scan_next_attr, attribute, 414); // msg 414 schema
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ ITransaction* local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
+
+ STORE (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_schema_req_handle1)
+ X IN RDB$SCHEMAS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
+ X.RDB$CHARACTER_SET_SCHEMA_NAME.NULL = TRUE;
+ X.RDB$CHARACTER_SET_NAME.NULL = TRUE;
+ X.RDB$SECURITY_CLASS.NULL = TRUE;
+ X.RDB$OWNER_NAME.NULL = TRUE;
+ X.RDB$DESCRIPTION.NULL = TRUE;
+ X.RDB$SYSTEM_FLAG = 0;
+
+ skip_init(&scan_next_attr);
+
+ while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
+ {
+ switch (attribute)
+ {
+ case att_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ BURP_verbose(413, MetaString(X.RDB$SCHEMA_NAME).toQuotedString().c_str()); // msg 413 restoring schema @1
+ break;
+
+ case att_schema_charset_schema_name:
+ GET_TEXT(X.RDB$CHARACTER_SET_SCHEMA_NAME);
+ X.RDB$CHARACTER_SET_SCHEMA_NAME.NULL = FALSE;
+ break;
+
+ case att_schema_charset_name:
+ GET_TEXT(X.RDB$CHARACTER_SET_NAME);
+ X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
+ break;
+
+ case att_schema_security_class:
+ GET_TEXT(X.RDB$SECURITY_CLASS);
+ fix_security_class_name(tdgbl, X.RDB$SECURITY_CLASS, false);
+ X.RDB$SECURITY_CLASS.NULL = FALSE;
+ break;
+
+ case att_schema_owner_name:
+ GET_TEXT(X.RDB$OWNER_NAME);
+ X.RDB$OWNER_NAME.NULL = FALSE;
+ break;
+
+ case att_schema_description:
+ get_source_blob(tdgbl, X.RDB$DESCRIPTION, true);
+ X.RDB$DESCRIPTION.NULL = FALSE;
+ break;
+
+ default:
+ bad_attribute(scan_next_attr, attribute, 414); // msg 414 schema
+ break;
+ }
+ }
+ }
+ END_STORE
+ ON_ERROR
+ general_on_error();
+ END_ERROR
+
+ return true;
+}
+
bool get_sql_roles(BurpGlobals* tdgbl)
{
/**************************************
@@ -8271,7 +8641,6 @@ bool get_sql_roles(BurpGlobals* tdgbl)
**************************************/
att_type attribute;
scan_attr_t scan_next_attr;
- TEXT temp[GDS_NAME_LEN];
SSHORT l;
if (tdgbl->runtimeODS >= DB_VERSION_DDL11)
@@ -8292,10 +8661,9 @@ bool get_sql_roles(BurpGlobals* tdgbl)
{
case att_role_name:
X.RDB$ROLE_NAME.NULL = FALSE;
- l = GET_TEXT(X.RDB$ROLE_NAME);
- MISC_terminate (X.RDB$ROLE_NAME, temp, l, sizeof(temp));
+ GET_TEXT(X.RDB$ROLE_NAME);
// msg 251, restoring SQL role: %s
- BURP_verbose (251, temp);
+ BURP_verbose(251, MetaString(X.RDB$ROLE_NAME).toQuotedString().c_str());
break;
case att_role_owner_name:
@@ -8353,10 +8721,9 @@ bool get_sql_roles(BurpGlobals* tdgbl)
{
case att_role_name:
X.RDB$ROLE_NAME.NULL = FALSE;
- l = GET_TEXT(X.RDB$ROLE_NAME);
- MISC_terminate (X.RDB$ROLE_NAME, temp, l, sizeof(temp));
+ GET_TEXT(X.RDB$ROLE_NAME);
// msg 251, restoring SQL role: %s
- BURP_verbose (251, temp);
+ BURP_verbose(251, MetaString(X.RDB$ROLE_NAME).toQuotedString().c_str());
break;
case att_role_owner_name:
@@ -8474,7 +8841,7 @@ bool get_mapping(BurpGlobals* tdgbl)
BURP_verbose(301);
// msg 301, restoring names mapping
- BURP_verbose (298, M.RDB$MAP_NAME);
+ BURP_verbose(298, MetaString(M.RDB$MAP_NAME).toQuotedString().c_str());
break;
case att_map_name:
@@ -8486,7 +8853,7 @@ bool get_mapping(BurpGlobals* tdgbl)
BURP_verbose(301);
// msg 301, restoring names mapping
}
- BURP_verbose (298, M.RDB$MAP_NAME);
+ BURP_verbose(298, MetaString(M.RDB$MAP_NAME).toQuotedString().c_str());
break;
case att_map_using:
@@ -8646,7 +9013,7 @@ bool get_mapping(BurpGlobals* tdgbl)
return true;
}
- BURP_verbose(298, ADMIN_ROLE);
+ BURP_verbose(298, MetaString(ADMIN_ROLE).toQuotedString().c_str());
// msg 298, restoring map @1
Firebird::string sql;
sql.printf("%s ('%s', %d) %s",
@@ -8721,7 +9088,7 @@ bool get_db_creator(BurpGlobals* tdgbl)
STORE (REQUEST_HANDLE tdgbl->handles_get_db_creators_req_handle1)
C IN RDB$DB_CREATORS
- BURP_verbose (393, usr);
+ BURP_verbose(393, MetaString(usr).toQuotedString().c_str());
if (strlen(usr) > sizeof(C.RDB$USER))
BURP_error_redirect(NULL, 46);
@@ -8778,9 +9145,8 @@ bool get_security_class(BurpGlobals* tdgbl)
* Restore a security class record including access control list.
*
**************************************/
+ MetaString name;
att_type attribute;
- TEXT temp[GDS_NAME_LEN];
- SSHORT l = 0;
scan_attr_t scan_next_attr;
bool is_valid_sec_class = false;
@@ -8795,7 +9161,8 @@ bool get_security_class(BurpGlobals* tdgbl)
switch (attribute)
{
case att_class_security_class:
- l = GET_TEXT(X.RDB$SECURITY_CLASS);
+ GET_TEXT(X.RDB$SECURITY_CLASS);
+ name = X.RDB$SECURITY_CLASS;
// Bug fix for bug_no 7299: There was a V3 bug that inserted
// garbage security class entry when doing GBAK. In order to
@@ -8804,17 +9171,15 @@ bool get_security_class(BurpGlobals* tdgbl)
// valid ASCII name. If not, skip this entry by setting
// 'is_valid_sec_class' to false.
- is_valid_sec_class = is_ascii_name(X.RDB$SECURITY_CLASS, l);
+ is_valid_sec_class = is_ascii_name(X.RDB$SECURITY_CLASS, name.length());
if (!is_valid_sec_class)
{
- MISC_terminate (X.RDB$SECURITY_CLASS, temp, l, sizeof(temp));
- BURP_print (false, 234, temp);
+ BURP_print(false, 234, name.toQuotedString().c_str());
// msg 234 Skipped bad security class entry: %s
break;
}
- MISC_terminate (X.RDB$SECURITY_CLASS, temp, l, sizeof(temp));
- BURP_verbose (125, temp);
+ BURP_verbose(125, name.toQuotedString().c_str());
// msg 125 restoring security class %s
break;
@@ -9056,7 +9421,7 @@ bool get_trigger_old (BurpGlobals* tdgbl, burp_rel* relation)
TEXT* p = X.RDB$TRIGGER_NAME;
const TEXT* const end = p + 31;
- const TEXT* q = relation->rel_name;
+ const TEXT* q = relation->rel_name.object.c_str();
while (*q) {
*p++ = *q++;
}
@@ -9085,9 +9450,9 @@ bool get_trigger_old (BurpGlobals* tdgbl, burp_rel* relation)
*p++ = *q++;
}
*p = 0;
- BURP_verbose (126, X.RDB$TRIGGER_NAME);
+ BURP_verbose(126, MetaString(X.RDB$TRIGGER_NAME).toQuotedString().c_str());
// msg 126 restoring trigger %s
- strncpy (X.RDB$RELATION_NAME, relation->rel_name, GDS_NAME_LEN);
+ strncpy (X.RDB$RELATION_NAME, relation->rel_name.object.c_str(), GDS_NAME_LEN);
strcpy (name, X.RDB$TRIGGER_NAME);
X.RDB$TRIGGER_SEQUENCE = TRIGGER_SEQUENCE_DEFAULT;
@@ -9128,8 +9493,11 @@ bool get_trigger(BurpGlobals* tdgbl)
* Get a trigger definition in rdb$triggers.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
- BASED_ON RDB$TRIGGERS.RDB$TRIGGER_NAME name;
BASED_ON RDB$TRIGGERS.RDB$RELATION_NAME relName;
scan_attr_t scan_next_attr;
bool skipTrig = false;
@@ -9141,7 +9509,8 @@ bool get_trigger(BurpGlobals* tdgbl)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_trigger_req_handle1)
X IN RDB$TRIGGERS
-
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
X.RDB$RELATION_NAME.NULL = TRUE;
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$TRIGGER_BLR.NULL = TRUE;
@@ -9191,10 +9560,16 @@ bool get_trigger(BurpGlobals* tdgbl)
get_source_blob (tdgbl, X.RDB$TRIGGER_SOURCE, true);
break;
+ case att_trig_schema_name:
+ GET_TEXT(X.RDB$SCHEMA_NAME);
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ name.schema = X.RDB$SCHEMA_NAME;
+ break;
+
case att_trig_name:
GET_TEXT(X.RDB$TRIGGER_NAME);
- strcpy (name, X.RDB$TRIGGER_NAME);
- BURP_verbose (126, X.RDB$TRIGGER_NAME);
+ name.object = X.RDB$TRIGGER_NAME;
+ BURP_verbose(126, name.toQuotedString().c_str());
// msg 126 restoring trigger %s
break;
@@ -9206,8 +9581,9 @@ bool get_trigger(BurpGlobals* tdgbl)
// Check for trigger on system relation
FOR (TRANSACTION_HANDLE local_trans REQUEST_HANDLE tdgbl->handles_get_trigger_req_handle2)
Y IN RDB$RELATIONS
- WITH Y.RDB$RELATION_NAME EQ relName
- AND Y.RDB$SYSTEM_FLAG EQ 1
+ WITH Y.RDB$SCHEMA_NAME EQUIV NULLIF(name.schema.c_str(), '') AND
+ Y.RDB$RELATION_NAME EQ relName AND
+ Y.RDB$SYSTEM_FLAG EQ 1
skipTrig = true;
END_FOR;
@@ -9297,14 +9673,14 @@ bool get_trigger(BurpGlobals* tdgbl)
// Skip trigger on system relation
if (skipTrig)
{
- BURP_message(387, SafeArg() << name << relName);
+ BURP_message(387, SafeArg() << name.toQuotedString().c_str() << relName);
return true;
}
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
@@ -9351,8 +9727,8 @@ bool get_trigger(BurpGlobals* tdgbl)
case att_trig_name:
GET_TEXT(X.RDB$TRIGGER_NAME);
- strcpy (name, X.RDB$TRIGGER_NAME);
- BURP_verbose (126, X.RDB$TRIGGER_NAME);
+ name.object = X.RDB$TRIGGER_NAME;
+ BURP_verbose(126, name.toQuotedString().c_str());
// msg 126 restoring trigger %s
break;
@@ -9441,7 +9817,7 @@ bool get_trigger(BurpGlobals* tdgbl)
// Skip trigger on system relation
if (skipTrig)
{
- BURP_message(387, SafeArg() << name << relName);
+ BURP_message(387, SafeArg() << name.toQuotedString().c_str() << relName);
return true;
}
@@ -9456,7 +9832,7 @@ bool get_trigger(BurpGlobals* tdgbl)
COMMIT
// existing ON_ERROR continues past error, beck
ON_ERROR
- BURP_print (false, 94, name);
+ BURP_print(false, 94, name.toQuotedString().c_str());
// msg 94 trigger %s is invalid
BURP_print_status(false, &tdgbl->status_vector);
ROLLBACK;
@@ -9483,10 +9859,13 @@ bool get_trigger_message(BurpGlobals* tdgbl)
* Get a trigger message text.
*
**************************************/
+ QualifiedMetaString name;
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ name.schema = PUBLIC_SCHEMA;
+
att_type attribute;
scan_attr_t scan_next_attr;
-
- BASED_ON RDB$TRIGGER_MESSAGES.RDB$TRIGGER_NAME name;
+ TEXT temp[GDS_NAME_LEN];
BASED_ON RDB$TRIGGER_MESSAGES.RDB$MESSAGE_NUMBER number = -1;
BASED_ON RDB$TRIGGER_MESSAGES.RDB$MESSAGE message;
@@ -9496,18 +9875,28 @@ bool get_trigger_message(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_trigmsg_schema_name:
+ GET_TEXT(temp);
+ name.schema = temp;
+ break;
+
case att_trigmsg_name:
- GET_TEXT(name);
+ GET_TEXT(temp);
+ name.object = temp;
sysflag = false;
FOR (REQUEST_HANDLE tdgbl->handles_get_trigger_message_req_handle1)
FIRST 1 X IN RDB$TRIGGERS WITH
- X.RDB$SYSTEM_FLAG EQ 1 AND X.RDB$TRIGGER_NAME EQ name
+ X.RDB$SYSTEM_FLAG = 1 AND
+ X.RDB$SCHEMA_NAME EQUIV NULLIF(name.schema.c_str(), '') AND
+ X.RDB$TRIGGER_NAME = name.object.c_str()
+ {
sysflag = true;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
- BURP_verbose (127, name);
+ END_ERROR
+ BURP_verbose(127, name.toQuotedString().c_str());
// msg 127 restoring trigger message for %s
break;
@@ -9538,20 +9927,30 @@ bool get_trigger_message(BurpGlobals* tdgbl)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_trigger_message_req_handle2)
X IN RDB$TRIGGER_MESSAGES
- strcpy (X.RDB$TRIGGER_NAME, name);
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
+
+ if (name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+
+ strcpy(X.RDB$TRIGGER_NAME, name.object.c_str());
X.RDB$MESSAGE_NUMBER = number;
- strcpy (X.RDB$MESSAGE, message);
- END_STORE;
+ strcpy(X.RDB$MESSAGE, message);
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
if (tdgbl->gbl_sw_incremental)
{
COMMIT
// existing ON_ERROR continues past error, beck
ON_ERROR
- BURP_print (false, 94, name);
+ BURP_print(false, 94, name.toQuotedString().c_str());
// msg 94 trigger %s is invalid
BURP_print_status(false, &tdgbl->status_vector);
ROLLBACK;
@@ -9630,7 +10029,7 @@ bool get_type(BurpGlobals* tdgbl)
}
MISC_terminate (X.RDB$TYPE_NAME, temp, len, sizeof(temp));
- BURP_verbose (128, SafeArg() << temp << X.RDB$FIELD_NAME);
+ BURP_verbose (128, SafeArg() << temp << MetaString(X.RDB$FIELD_NAME).toQuotedString().c_str());
// msg 128 restoring type %s for field %s
END_STORE;
@@ -9658,11 +10057,11 @@ bool get_user_privilege(BurpGlobals* tdgbl)
scan_attr_t scan_next_attr;
USHORT flags = 0;
- BASED_ON RDB$USER_PRIVILEGES.RDB$USER user;
+ QualifiedMetaString user, relation;
+ TEXT temp[GDS_NAME_LEN];
BASED_ON RDB$USER_PRIVILEGES.RDB$GRANTOR grantor;
BASED_ON RDB$USER_PRIVILEGES.RDB$PRIVILEGE privilege;
BASED_ON RDB$USER_PRIVILEGES.RDB$GRANT_OPTION grant_option = 0;
- BASED_ON RDB$USER_PRIVILEGES.RDB$RELATION_NAME relation_name;
BASED_ON RDB$USER_PRIVILEGES.RDB$FIELD_NAME field_name;
BASED_ON RDB$USER_PRIVILEGES.RDB$USER_TYPE user_type;
BASED_ON RDB$USER_PRIVILEGES.RDB$OBJECT_TYPE object_type;
@@ -9676,11 +10075,17 @@ bool get_user_privilege(BurpGlobals* tdgbl)
{
switch (attribute)
{
+ case att_priv_user_schema_name:
+ GET_TEXT(temp);
+ user.schema = temp;
+ break;
+
case att_priv_user:
// default USER_TYPE to USER
flags |= USER_PRIV_USER;
- GET_TEXT(user);
- BURP_verbose (123, user);
+ GET_TEXT(temp);
+ user.object = temp;
+ BURP_verbose(123, user.toQuotedString().c_str());
// msg 123 restoring privilege for user %s
break;
@@ -9699,10 +10104,16 @@ bool get_user_privilege(BurpGlobals* tdgbl)
grant_option = (USHORT) get_int32(tdgbl);
break;
+ case att_priv_object_schema_name:
+ GET_TEXT(temp);
+ relation.schema = temp;
+ break;
+
case att_priv_object_name:
flags |= USER_PRIV_OBJECT_NAME;
// default OBJECT_TYPE to RELATION
- GET_TEXT(relation_name);
+ GET_TEXT(temp);
+ relation.object = temp;
break;
case att_priv_field_name:
@@ -9738,9 +10149,9 @@ bool get_user_privilege(BurpGlobals* tdgbl)
switch (object_type)
{
case obj_package_header:
- {
for (const burp_pkg* pkg = tdgbl->packages; pkg; pkg = pkg->pkg_next)
- if (strcmp(pkg->pkg_name, relation_name) == 0)
+ {
+ if (pkg->pkg_name == relation)
{
exists = true;
local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
@@ -9750,9 +10161,9 @@ bool get_user_privilege(BurpGlobals* tdgbl)
break;
case obj_procedure:
- {
for (const burp_prc* proc = tdgbl->procedures; proc; proc = proc->prc_next)
- if (!proc->prc_package[0] && strcmp(proc->prc_name, relation_name) == 0)
+ {
+ if (proc->prc_name.package.isEmpty() && proc->prc_name == relation)
{
exists = true;
local_trans = tdgbl->global_trans ? tdgbl->global_trans : gds_trans;
@@ -9762,9 +10173,9 @@ bool get_user_privilege(BurpGlobals* tdgbl)
break;
case obj_relation:
- {
for (const burp_rel* rel = tdgbl->relations; rel; rel = rel->rel_next)
- if (strcmp(rel->rel_name, relation_name) == 0)
+ {
+ if (rel->rel_name == relation)
{
exists = true;
if (rel->rel_flags & REL_view)
@@ -9780,9 +10191,9 @@ bool get_user_privilege(BurpGlobals* tdgbl)
case obj_udf:
case obj_field:
case obj_generator:
- {
for (burp_meta_obj* object = tdgbl->miss_privs; object; object = object->obj_next)
- if (object->obj_type == object_type && strcmp(object->obj_name, relation_name) == 0)
+ {
+ if (object->obj_type == object_type && object->obj_name == relation)
{
if (object->obj_class)
exists = true;
@@ -9822,13 +10233,21 @@ bool get_user_privilege(BurpGlobals* tdgbl)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_user_privilege_req_handle1)
X IN RDB$USER_PRIVILEGES
-
+ {
+ X.RDB$USER_SCHEMA_NAME.NULL = TRUE;
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
X.RDB$FIELD_NAME.NULL = TRUE;
X.RDB$OBJECT_TYPE.NULL = TRUE;
X.RDB$GRANT_OPTION.NULL = TRUE;
+ if (user.schema.hasData())
+ {
+ strcpy(X.RDB$USER_SCHEMA_NAME, user.schema.c_str());
+ X.RDB$USER_SCHEMA_NAME.NULL = FALSE;
+ }
+
if (flags & USER_PRIV_USER)
- strcpy (X.RDB$USER, user);
+ strcpy(X.RDB$USER, user.object.c_str());
if (flags & USER_PRIV_GRANTOR)
strcpy (X.RDB$GRANTOR, grantor);
@@ -9842,8 +10261,14 @@ bool get_user_privilege(BurpGlobals* tdgbl)
X.RDB$GRANT_OPTION = grant_option;
}
+ if (relation.schema.hasData())
+ {
+ strcpy(X.RDB$RELATION_SCHEMA_NAME, relation.schema.c_str());
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ }
+
if (flags & USER_PRIV_OBJECT_NAME)
- strcpy (X.RDB$RELATION_NAME, relation_name);
+ strcpy(X.RDB$RELATION_NAME, relation.object.c_str());
if (flags & USER_PRIV_FIELD_NAME)
{
@@ -9871,7 +10296,7 @@ bool get_user_privilege(BurpGlobals* tdgbl)
// used at all. The following code should be uncommented
// in case we ever introduce obj_field to the picture.
-/***********************************************************
+ /***********************************************************
if ( !(flags & USER_PRIV_OBJECT_TYPE) )
{
if ( flags & USER_PRIV_FIELD_NAME )
@@ -9879,9 +10304,9 @@ bool get_user_privilege(BurpGlobals* tdgbl)
X.RDB$OBJECT_TYPE = obj_field;
}
}
-***********************************************************/
-
- END_STORE;
+ ***********************************************************/
+ }
+ END_STORE
ON_ERROR
if (tdgbl->status_vector->getErrors()[1] == isc_integ_fail)
{
@@ -9890,7 +10315,7 @@ bool get_user_privilege(BurpGlobals* tdgbl)
return true;
}
general_on_error ();
- END_ERROR;
+ END_ERROR
}
return true;
@@ -9920,8 +10345,17 @@ bool get_view(BurpGlobals* tdgbl, burp_rel* relation)
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_view_req_handle1)
X IN RDB$VIEW_RELATIONS
+ {
+ if (relation->rel_name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, relation->rel_name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
- strcpy (X.RDB$VIEW_NAME, relation->rel_name);
+ strcpy(X.RDB$VIEW_NAME, relation->rel_name.object.c_str());
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
X.RDB$CONTEXT_TYPE.NULL = TRUE;
X.RDB$PACKAGE_NAME.NULL = TRUE;
@@ -9930,6 +10364,11 @@ bool get_view(BurpGlobals* tdgbl, burp_rel* relation)
{
switch (attribute)
{
+ case att_view_relation_schema_name:
+ GET_TEXT(X.RDB$RELATION_SCHEMA_NAME);
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ break;
+
case att_view_relation_name:
GET_TEXT(X.RDB$RELATION_NAME);
break;
@@ -9973,18 +10412,19 @@ bool get_view(BurpGlobals* tdgbl, burp_rel* relation)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
STORE (TRANSACTION_HANDLE local_trans
REQUEST_HANDLE tdgbl->handles_get_view_req_handle1)
X IN RDB$VIEW_RELATIONS
-
- strcpy (X.RDB$VIEW_NAME, relation->rel_name);
+ {
+ strcpy(X.RDB$VIEW_NAME, relation->rel_name.object.c_str());
skip_init(&scan_next_attr);
while (skip_scan(&scan_next_attr), get_attribute(&attribute, tdgbl) != att_end)
@@ -10028,7 +10468,8 @@ bool get_view(BurpGlobals* tdgbl, burp_rel* relation)
break;
}
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
END_ERROR;
@@ -10435,6 +10876,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
Firebird::IRequest* req_handle3 = nullptr;
Firebird::IRequest* req_handle4 = nullptr;
Firebird::IRequest* req_handle5 = nullptr;
+ Firebird::IRequest* reqHandleDflCharSetSchema = nullptr;
// Collect system fields
{
@@ -10444,15 +10886,14 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
FOR(REQUEST_HANDLE req_handle)
X IN RDB$FIELDS WITH
X.RDB$SYSTEM_FLAG EQ 1
-
- const auto len = MISC_symbol_length(X.RDB$FIELD_NAME, sizeof(X.RDB$FIELD_NAME));
- MetaString name(X.RDB$FIELD_NAME, len);
+ {
+ const QualifiedMetaString name(X.RDB$FIELD_NAME, (X.RDB$SCHEMA_NAME.NULL ? "" : X.RDB$SCHEMA_NAME));
tdgbl->systemFields.add(name);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle);
tdgbl->systemFields.sort();
@@ -10474,6 +10915,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
case att_database_description2:
FOR (REQUEST_HANDLE req_handle2)
X IN RDB$DATABASE
+ {
MODIFY X USING
if (attribute == att_database_description2)
get_source_blob (tdgbl, X.RDB$DESCRIPTION, false);
@@ -10483,25 +10925,45 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
ON_ERROR
general_on_error ();
END_ERROR;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
+ break;
+
+ case att_database_dfl_charset_schema_name:
+ FOR (REQUEST_HANDLE reqHandleDflCharSetSchema)
+ X IN RDB$DATABASE
+ {
+ MODIFY X USING
+ GET_TEXT(X.RDB$CHARACTER_SET_SCHEMA_NAME);
+ END_MODIFY
+ ON_ERROR
+ general_on_error ();
+ END_ERROR
+ }
+ END_FOR
+ ON_ERROR
+ general_on_error ();
+ END_ERROR
break;
case att_database_dfl_charset:
FOR (REQUEST_HANDLE req_handle3)
X IN RDB$DATABASE
+ {
MODIFY X USING
GET_TEXT(X.RDB$CHARACTER_SET_NAME);
- END_MODIFY;
+ END_MODIFY
ON_ERROR
general_on_error ();
- END_ERROR;
- END_FOR;
+ END_ERROR
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
break;
case att_database_linger:
@@ -10511,16 +10973,18 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
{
FOR (REQUEST_HANDLE req_handle4)
X IN RDB$DATABASE
+ {
MODIFY X USING
X.RDB$LINGER = get_int32(tdgbl);
END_MODIFY;
ON_ERROR
general_on_error();
- END_ERROR;
- END_FOR;
+ END_ERROR
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
get_int32(tdgbl);
@@ -10541,16 +11005,18 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
{
FOR (REQUEST_HANDLE req_handle5)
X IN RDB$DATABASE
+ {
MODIFY X USING
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_database_sql_security_deprecated);
END_MODIFY;
ON_ERROR
general_on_error();
- END_ERROR;
- END_FOR;
+ END_ERROR
+ }
+ END_FOR
ON_ERROR
general_on_error();
- END_ERROR;
+ END_ERROR
}
else
get_boolean(tdgbl, attribute == att_database_sql_security_deprecated);
@@ -10610,15 +11076,16 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
FOR (REQUEST_HANDLE req_handle3)
X IN RDB$CHARACTER_SETS
- WITH X.RDB$CHARACTER_SET_NAME EQ name.c_str()
-
+ WITH (X.RDB$SCHEMA_NAME MISSING OR X.RDB$SCHEMA_NAME = SYSTEM_SCHEMA) AND
+ X.RDB$CHARACTER_SET_NAME EQ name.c_str()
+ {
tdgbl->gbl_sw_fix_fss_data_id = X.RDB$CHARACTER_SET_ID;
found = true;
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle3);
@@ -10636,15 +11103,16 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
FOR (REQUEST_HANDLE req_handle3)
X IN RDB$CHARACTER_SETS
- WITH X.RDB$CHARACTER_SET_NAME EQ name.c_str()
-
+ WITH (X.RDB$SCHEMA_NAME MISSING OR X.RDB$SCHEMA_NAME = SYSTEM_SCHEMA) AND
+ X.RDB$CHARACTER_SET_NAME EQ name.c_str()
+ {
tdgbl->gbl_sw_fix_fss_metadata_id = X.RDB$CHARACTER_SET_ID;
found = true;
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle3);
@@ -10778,6 +11246,12 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
return false;
break;
+ case rec_schema:
+ if (!get_schema(tdgbl))
+ return false;
+ flag = true;
+ break;
+
case rec_trigger: // new trigger type
if (!get_trigger(tdgbl))
return false;
@@ -10848,31 +11322,37 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
if (!task.finish())
return false;
- if (tdgbl->defaultCollations.getCount() > 0)
+ if (tdgbl->defaultCollations.hasData())
{
Firebird::IRequest* req_handle5 = nullptr;
FOR (REQUEST_HANDLE req_handle5)
CS IN RDB$CHARACTER_SETS
-
- for (FB_SIZE_T i = 0; i < tdgbl->defaultCollations.getCount(); ++i)
+ {
+ if (const auto collationName = tdgbl->defaultCollations.get(
+ QualifiedMetaString(CS.RDB$CHARACTER_SET_NAME, CS.RDB$SCHEMA_NAME)))
{
- if (tdgbl->defaultCollations[i].first == CS.RDB$CHARACTER_SET_NAME)
+ MODIFY CS
{
- MODIFY CS;
- CS.RDB$DEFAULT_COLLATE_NAME.NULL = FALSE;
- strcpy(CS.RDB$DEFAULT_COLLATE_NAME,
- tdgbl->defaultCollations[i].second.c_str());
- END_MODIFY;
- ON_ERROR
- general_on_error ();
- END_ERROR;
+ if (collationName->schema.hasData())
+ {
+ CS.RDB$DEFAULT_COLLATE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(CS.RDB$DEFAULT_COLLATE_SCHEMA_NAME, collationName->schema.c_str());
+ }
+
+ CS.RDB$DEFAULT_COLLATE_NAME.NULL = FALSE;
+ strcpy(CS.RDB$DEFAULT_COLLATE_NAME, collationName->object.c_str());
}
+ END_MODIFY
+ ON_ERROR
+ general_on_error ();
+ END_ERROR
}
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle5);
}
@@ -10927,6 +11407,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
FOR (REQUEST_HANDLE req_handle6)
IND IN RDB$INDICES WITH IND.RDB$SYSTEM_FLAG EQ 1
+ {
MODIFY IND
IND.RDB$STATISTICS.NULL = FALSE;
IND.RDB$STATISTICS = -1;
@@ -10934,10 +11415,11 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
ON_ERROR
general_on_error ();
END_ERROR;
- END_FOR;
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle6);
@@ -10988,7 +11470,7 @@ void restore_security_class(BurpGlobals* tdgbl, const TEXT* owner_nm, const TEXT
USHORT get_view_base_relation_count(BurpGlobals* tdgbl,
- const TEXT* current_view_name,
+ const QualifiedMetaString& current_view_name,
USHORT depth,
bool* error)
{
@@ -11021,9 +11503,11 @@ USHORT get_view_base_relation_count(BurpGlobals* tdgbl,
V IN RDB$VIEW_RELATIONS
CROSS R IN RDB$RELATIONS
WITH
- V.RDB$VIEW_NAME EQ current_view_name AND
+ V.RDB$SCHEMA_NAME EQUIV NULLIF(current_view_name.schema.c_str(), '') AND
+ V.RDB$VIEW_NAME EQ current_view_name.object.c_str() AND
+ R.RDB$SCHEMA_NAME EQUIV V.RDB$RELATION_SCHEMA_NAME AND
R.RDB$RELATION_NAME EQ V.RDB$RELATION_NAME
-
+ {
if (R.RDB$VIEW_BLR.NULL)
{
// This relation is a table, so increment count
@@ -11032,16 +11516,22 @@ USHORT get_view_base_relation_count(BurpGlobals* tdgbl,
else
{
// Call recursive for VIEWS that are referenced in VIEWS
- result += get_view_base_relation_count(tdgbl, V.RDB$RELATION_NAME, depth, error);
+ result += get_view_base_relation_count(tdgbl,
+ QualifiedMetaString(
+ V.RDB$RELATION_NAME,
+ (V.RDB$RELATION_SCHEMA_NAME.NULL ? "" : V.RDB$RELATION_SCHEMA_NAME)
+ ),
+ depth, error);
+
if (*error)
break;
}
- END_FOR;
-
+ }
+ END_FOR
ON_ERROR
MISC_release_request_silent(req_handle1);
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
@@ -11049,7 +11539,7 @@ USHORT get_view_base_relation_count(BurpGlobals* tdgbl,
}
-void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SINT64 initial_value,
+void store_blr_gen_id(BurpGlobals* tdgbl, const QualifiedMetaString& gen_name, SINT64 value, SINT64 initial_value,
const ISC_QUAD* gen_desc, const char* secclass, const char* ownername, fb_sysflag sysFlag,
SLONG increment)
{
@@ -11067,8 +11557,16 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
{
STORE (REQUEST_HANDLE tdgbl->handles_store_blr_gen_id_req_handle1)
X IN RDB$GENERATORS
+ {
+ X.RDB$SCHEMA_NAME.NULL = TRUE;
- strcpy (X.RDB$GENERATOR_NAME, gen_name);
+ if (gen_name.schema.hasData())
+ {
+ strcpy(X.RDB$SCHEMA_NAME, gen_name.schema.c_str());
+ X.RDB$SCHEMA_NAME.NULL = FALSE;
+ }
+
+ strcpy(X.RDB$GENERATOR_NAME, gen_name.object.c_str());
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = (SSHORT) sysFlag;
X.RDB$SECURITY_CLASS.NULL = TRUE;
@@ -11092,10 +11590,11 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
X.RDB$INITIAL_VALUE.NULL = FALSE;
X.RDB$INITIAL_VALUE = initial_value;
X.RDB$GENERATOR_INCREMENT = increment;
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
collect_missing_privs(tdgbl, obj_generator, gen_name, secclass);
}
@@ -11103,8 +11602,8 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
{
STORE (REQUEST_HANDLE tdgbl->handles_store_blr_gen_id_req_handle1)
X IN RDB$GENERATORS
-
- strcpy (X.RDB$GENERATOR_NAME, gen_name);
+ {
+ strcpy(X.RDB$GENERATOR_NAME, gen_name.object.c_str());
X.RDB$DESCRIPTION.NULL = TRUE;
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
@@ -11113,28 +11612,30 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
X.RDB$DESCRIPTION = *gen_desc;
X.RDB$DESCRIPTION.NULL = FALSE;
}
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
else
{
STORE (REQUEST_HANDLE tdgbl->handles_store_blr_gen_id_req_handle1)
X IN RDB$GENERATORS
-
- strcpy (X.RDB$GENERATOR_NAME, gen_name);
+ {
+ strcpy(X.RDB$GENERATOR_NAME, gen_name.object.c_str());
X.RDB$SYSTEM_FLAG = 0;
X.RDB$SYSTEM_FLAG.NULL = FALSE;
- END_STORE;
+ }
+ END_STORE
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
}
if (!value)
{
- BURP_verbose (185, SafeArg() << gen_name << 0);
+ BURP_verbose (185, SafeArg() << gen_name.toQuotedString().c_str() << 0);
// msg 185 restoring generator %s value: %ld
return;
}
@@ -11170,8 +11671,20 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
}
add_byte(blr, blr_begin);
add_byte(blr, blr_assignment);
- add_byte(blr, blr_gen_id);
- add_string(blr, gen_name);
+
+ if (tdgbl->runtimeODS >= DB_VERSION_DDL14)
+ {
+ add_byte(blr, blr_gen_id3);
+ add_string(blr, gen_name.schema.c_str());
+ add_string(blr, gen_name.object.c_str());
+ add_byte(blr, 1);
+ }
+ else
+ {
+ add_byte(blr, blr_gen_id);
+ add_string(blr, gen_name.object.c_str());
+ }
+
if (tdgbl->runtimeODS >= DB_VERSION_DDL10)
{
add_byte(blr, blr_literal);
@@ -11184,8 +11697,9 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
add_byte(blr, blr_literal);
add_byte(blr, blr_long);
add_byte(blr, 0);
- add_long(blr, (SLONG)value);
+ add_long(blr, (SLONG) value);
}
+
add_byte(blr, blr_variable);
add_word(blr, 0);
add_byte(blr, blr_end);
@@ -11211,7 +11725,7 @@ void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SI
BURP_error_redirect(&status_vector, 42); // msg 42 Failed in store_blr_gen_id
}
- BURP_verbose (185, SafeArg() << gen_name << value);
+ BURP_verbose (185, SafeArg() << gen_name.toQuotedString().c_str() << value);
// msg 185 restoring generator %s value: %ld
}
@@ -11234,9 +11748,12 @@ void update_global_field(BurpGlobals* tdgbl)
for (gfld* gfield = tdgbl->gbl_global_fields; gfield; )
{
FOR (TRANSACTION_HANDLE tdgbl->global_trans REQUEST_HANDLE req_handle1)
- X IN RDB$FIELDS WITH X.RDB$FIELD_NAME EQ gfield->gfld_name
+ X IN RDB$FIELDS
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(gfield->gfld_name.schema.c_str(), '') AND
+ X.RDB$FIELD_NAME EQ gfield->gfld_name.object.c_str()
+ {
MODIFY X
-
+ {
if (gfield->gfld_flags & GFLD_validation_blr)
{
X.RDB$VALIDATION_BLR.NULL = FALSE;
@@ -11272,16 +11789,16 @@ void update_global_field(BurpGlobals* tdgbl)
X.RDB$COMPUTED_SOURCE.NULL = FALSE;
memcpy(&X.RDB$COMPUTED_SOURCE, &gfield->gfld_computed_source2, sizeof(ISC_QUAD));
}
-
- END_MODIFY;
+ }
+ END_MODIFY
ON_ERROR
general_on_error ();
- END_ERROR;
-
- END_FOR;
+ END_ERROR
+ }
+ END_FOR
ON_ERROR
general_on_error ();
- END_ERROR;
+ END_ERROR
gfld* n_gfield = gfield->gfld_next;
BURP_free (gfield);
@@ -11309,15 +11826,16 @@ void update_ownership(BurpGlobals* tdgbl)
{
FOR (REQUEST_HANDLE req_handle6)
X IN RDB$PACKAGES
- WITH X.RDB$PACKAGE_NAME EQ package->pkg_name
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(package->pkg_name.schema.c_str(), '') AND
+ X.RDB$PACKAGE_NAME = package->pkg_name.object.c_str()
{
MODIFY X
strcpy(X.RDB$OWNER_NAME, package->pkg_owner);
- END_MODIFY;
+ END_MODIFY
ON_ERROR
MISC_release_request_silent(req_handle6);
general_on_error();
- END_ERROR;
+ END_ERROR
if (!X.RDB$SECURITY_CLASS.NULL)
restore_security_class(tdgbl, package->pkg_owner, X.RDB$SECURITY_CLASS);
@@ -11341,8 +11859,9 @@ void update_ownership(BurpGlobals* tdgbl)
{
FOR (REQUEST_HANDLE req_handle4)
X IN RDB$PROCEDURES
- WITH X.RDB$PROCEDURE_NAME EQ procedure->prc_name AND
- X.RDB$PACKAGE_NAME EQUIV NULLIF(procedure->prc_package, '')
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(procedure->prc_name.schema.c_str(), '') AND
+ X.RDB$PROCEDURE_NAME EQ procedure->prc_name.object.c_str() AND
+ X.RDB$PACKAGE_NAME EQUIV NULLIF(procedure->prc_name.package.c_str(), '')
{
MODIFY X
strcpy (X.RDB$OWNER_NAME, procedure->prc_owner);
@@ -11364,7 +11883,7 @@ void update_ownership(BurpGlobals* tdgbl)
else
{
FOR (REQUEST_HANDLE req_handle4)
- X IN RDB$PROCEDURES WITH X.RDB$PROCEDURE_NAME EQ procedure->prc_name
+ X IN RDB$PROCEDURES WITH X.RDB$PROCEDURE_NAME EQ procedure->prc_name.object.c_str()
{
MODIFY X
strcpy (X.RDB$OWNER_NAME, procedure->prc_owner);
@@ -11394,23 +11913,26 @@ void update_ownership(BurpGlobals* tdgbl)
if (relation->rel_owner[0])
{
FOR (REQUEST_HANDLE req_handle2)
- X IN RDB$RELATIONS WITH X.RDB$RELATION_NAME EQ relation->rel_name
+ X IN RDB$RELATIONS
+ WITH X.RDB$SCHEMA_NAME EQUIV NULLIF(relation->rel_name.schema.c_str(), '') AND
+ X.RDB$RELATION_NAME EQ relation->rel_name.object.c_str()
+ {
MODIFY X
strcpy (X.RDB$OWNER_NAME, relation->rel_owner);
- END_MODIFY;
+ END_MODIFY
ON_ERROR
MISC_release_request_silent(req_handle2);
general_on_error ();
- END_ERROR;
+ END_ERROR
restore_security_class(tdgbl, relation->rel_owner, X.RDB$SECURITY_CLASS);
restore_security_class(tdgbl, relation->rel_owner, X.RDB$DEFAULT_CLASS);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
MISC_release_request_silent(req_handle2);
general_on_error ();
- END_ERROR;
+ END_ERROR
}
}
@@ -11446,9 +11968,15 @@ void update_view_dbkey_lengths(BurpGlobals* tdgbl)
WITH
R.RDB$VIEW_BLR NOT MISSING AND
(R.RDB$SYSTEM_FLAG NE 1 OR R.RDB$SYSTEM_FLAG MISSING)
-
+ {
bool error = false;
- const USHORT result = get_view_base_relation_count(tdgbl, R.RDB$RELATION_NAME, 0, &error);
+ const USHORT result = get_view_base_relation_count(tdgbl,
+ QualifiedMetaString(
+ R.RDB$RELATION_NAME,
+ (R.RDB$SCHEMA_NAME.NULL ? "" : R.RDB$SCHEMA_NAME)
+ ),
+ 0, &error);
+
fb_utils::exact_name(R.RDB$RELATION_NAME);
if (error)
BURP_error(339, false, SafeArg() << MAX_UPDATE_DBKEY_RECURSION_DEPTH << R.RDB$RELATION_NAME);
@@ -11464,13 +11992,12 @@ void update_view_dbkey_lengths(BurpGlobals* tdgbl)
MISC_release_request_silent(req_handle2);
general_on_error();
END_ERROR;
-
- END_FOR;
-
+ }
+ END_FOR
ON_ERROR
MISC_release_request_silent(req_handle2);
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle2);
}
@@ -11487,14 +12014,14 @@ void fix_missing_privileges(BurpGlobals* tdgbl)
FOR (REQUEST_HANDLE req_handle1)
REL IN RDB$RELATIONS
WITH REL.RDB$RELATION_ID = 1
-
+ {
strcpy(owner_name, REL.RDB$OWNER_NAME);
-
- END_FOR;
+ }
+ END_FOR
ON_ERROR
MISC_release_request_silent(req_handle1);
general_on_error();
- END_ERROR;
+ END_ERROR
MISC_release_request_silent(req_handle1);
@@ -11509,7 +12036,7 @@ void fix_missing_privileges(BurpGlobals* tdgbl)
{
STORE (REQUEST_HANDLE req_handle2)
X IN RDB$USER_PRIVILEGES
-
+ {
X.RDB$FIELD_NAME.NULL = TRUE;
X.RDB$GRANTOR.NULL = TRUE;
@@ -11519,8 +12046,16 @@ void fix_missing_privileges(BurpGlobals* tdgbl)
X.RDB$USER.NULL = FALSE;
strcpy(X.RDB$USER, (i == 0) ? "PUBLIC" : owner_name);
+ if (object->obj_name.schema.hasData())
+ {
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ strcpy(X.RDB$RELATION_SCHEMA_NAME, object->obj_name.schema.c_str());
+ }
+ else
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
+
X.RDB$RELATION_NAME.NULL = FALSE;
- strcpy(X.RDB$RELATION_NAME, object->obj_name);
+ strcpy(X.RDB$RELATION_NAME, object->obj_name.object.c_str());
X.RDB$USER_TYPE.NULL = FALSE;
X.RDB$USER_TYPE = obj_user;
@@ -11530,12 +12065,12 @@ void fix_missing_privileges(BurpGlobals* tdgbl)
X.RDB$GRANT_OPTION.NULL = FALSE;
X.RDB$GRANT_OPTION = i;
-
- END_STORE;
+ }
+ END_STORE
ON_ERROR
MISC_release_request_silent(req_handle2);
general_on_error();
- END_ERROR;
+ END_ERROR
}
}
@@ -11578,7 +12113,7 @@ void fix_generator(BurpGlobals* tdgbl, const FixGenerator* g)
" "
" currentGen = gen_id(%s, 0); "
" IF (currentGen < maxInTable) THEN "
- " EXECUTE STATEMENT 'SET GENERATOR %s TO ' || maxInTable; "
+ " EXECUTE STATEMENT 'SET GENERATOR SYSTEM.%s TO ' || maxInTable; "
"END",
/* SELECT 1 */ g->field, start, g->table, g->field, start, g->field, g->prefix,
/* SELECT 2 */ g->name,
@@ -11841,7 +12376,7 @@ IBatch* WriteRelationMeta::createBatch(BurpGlobals* tdgbl, IAttachment* att)
if (m_batchOk)
return batch;
- BURP_verbose(371, m_relation->rel_name);
+ BURP_verbose(371, m_relation->rel_name.toQuotedString().c_str());
// msg 371 could not start batch when restoring table @1, trying old way
//BURP_print_status(false, fbStatus);
@@ -11870,10 +12405,7 @@ bool WriteRelationMeta::prepareBatch(BurpGlobals* tdgbl)
try
{
- string name(m_relation->rel_name);
- BURP_makeSymbol(tdgbl, name);
-
- m_sqlStatement.printf("insert into %s(", name.c_str());
+ m_sqlStatement.printf("insert into %s(", m_relation->rel_name.toQuotedString().c_str());
RefPtr builder(REF_NO_INCR,
MasterInterfacePtr()->getMetadataBuilder(fbStatus, count));
@@ -11933,9 +12465,7 @@ bool WriteRelationMeta::prepareBatch(BurpGlobals* tdgbl)
builder->setScale(&tdgbl->throwStatus, count, sqlScale);
builder->setCharSet(&tdgbl->throwStatus, count, characterSetId);
- name = field->fld_name;
- BURP_makeSymbol(tdgbl, name);
- m_sqlStatement += name;
+ m_sqlStatement += MetaString(field->fld_name).toQuotedString();
m_sqlStatement += ", ";
field->fld_parameter = count++;
@@ -12015,7 +12545,8 @@ void WriteRelationMeta::prepareRequest(BurpGlobals* tdgbl)
// Time to generate blr to store data. Whoppee.
- UCHAR* blr = m_blr.getBuffer(200 + length + count * 18);
+ UCHAR* blr = m_blr.getBuffer(200 + m_relation->rel_name.schema.length() + m_relation->rel_name.object.length() +
+ length + count * 18);
add_byte(blr, blr_version4);
add_byte(blr, blr_begin);
@@ -12162,8 +12693,19 @@ void WriteRelationMeta::prepareRequest(BurpGlobals* tdgbl)
add_byte(blr, 1);
add_byte(blr, 0x10); // must be Jrd::StatementNode::MARK_BULK_INSERT
- add_byte(blr, blr_relation);
- add_string(blr, m_relation->rel_name);
+ if (m_relation->rel_name.schema.hasData())
+ {
+ add_byte(blr, blr_relation3);
+ add_string(blr, m_relation->rel_name.schema.c_str());
+ add_string(blr, m_relation->rel_name.object.c_str());
+ add_string(blr, "");
+ }
+ else
+ {
+ add_byte(blr, blr_relation);
+ add_string(blr, m_relation->rel_name.object.c_str());
+ }
+
add_byte(blr, 0); // context variable
add_byte(blr, blr_begin);
@@ -12196,6 +12738,7 @@ void WriteRelationMeta::prepareRequest(BurpGlobals* tdgbl)
add_byte(blr, blr_end);
add_byte(blr, blr_eoc);
+ fb_assert(blr < m_blr.end());
const FB_SIZE_T blr_length = blr - m_blr.begin();
m_blr.shrink(blr_length);
}
@@ -12350,7 +12893,7 @@ bool RestoreRelationTask::fileReader(Item& item)
BurpGlobals* tdgbl = item.m_gbl;
fb_assert(tdgbl == m_masterGbl);
- BURP_verbose(124, m_relation->rel_name); // msg 124 restoring data for relation %s
+ BURP_verbose(124, m_relation->rel_name.toQuotedString().c_str()); // msg 124 restoring data for relation %s
const RCRD_LENGTH length = m_metadata.m_inMsgLen; // full record length
diff --git a/src/common/IntlParametersBlock.cpp b/src/common/IntlParametersBlock.cpp
index df92765bcc..bc2577b69b 100644
--- a/src/common/IntlParametersBlock.cpp
+++ b/src/common/IntlParametersBlock.cpp
@@ -195,6 +195,7 @@ IntlParametersBlock::TagType IntlDpb::checkTag(UCHAR tag, const char** tagName)
FB_IPB_TAG(isc_dpb_host_name);
FB_IPB_TAG(isc_dpb_os_user);
FB_IPB_TAG(isc_dpb_owner);
+ FB_IPB_TAG(isc_dpb_search_path);
return TAG_STRING;
}
@@ -324,6 +325,8 @@ IntlParametersBlock::TagType IntlSpbStart::checkTag(UCHAR tag, const char** tagN
case isc_action_svc_validate:
switch (tag)
{
+ FB_IPB_TAG(isc_spb_val_sch_incl);
+ FB_IPB_TAG(isc_spb_val_sch_excl);
FB_IPB_TAG(isc_spb_val_tab_incl);
FB_IPB_TAG(isc_spb_val_tab_excl);
FB_IPB_TAG(isc_spb_val_idx_incl);
diff --git a/src/common/MsgMetadata.cpp b/src/common/MsgMetadata.cpp
index fa428a7cda..657f4f2d01 100644
--- a/src/common/MsgMetadata.cpp
+++ b/src/common/MsgMetadata.cpp
@@ -149,6 +149,21 @@ void MetadataBuilder::setField(CheckStatusWrapper* status, unsigned index, const
}
}
+void MetadataBuilder::setSchema(CheckStatusWrapper* status, unsigned index, const char* schema)
+{
+ try
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ indexError(index, "setSchema");
+ msgMetadata->items[index].schema = schema;
+ }
+ catch (const Exception& ex)
+ {
+ ex.stuffException(status);
+ }
+}
+
void MetadataBuilder::setRelation(CheckStatusWrapper* status, unsigned index, const char* relation)
{
try
@@ -407,6 +422,9 @@ void MsgMetadata::assign(IMessageMetadata* from)
items[index].field = from->getField(&status, index);
check(&status);
+ items[index].schema = from->getSchema(&status, index);
+ check(&status);
+
items[index].relation = from->getRelation(&status, index);
check(&status);
diff --git a/src/common/MsgMetadata.h b/src/common/MsgMetadata.h
index f39307764e..cfd241daa9 100644
--- a/src/common/MsgMetadata.h
+++ b/src/common/MsgMetadata.h
@@ -50,6 +50,7 @@ public:
{
explicit Item(MemoryPool& pool)
: field(pool),
+ schema(pool),
relation(pool),
owner(pool),
alias(pool),
@@ -67,6 +68,7 @@ public:
Item(MemoryPool& pool, const Item& v)
: field(pool, v.field),
+ schema(pool, v.schema),
relation(pool, v.relation),
owner(pool, v.owner),
alias(pool, v.alias),
@@ -83,6 +85,7 @@ public:
}
string field;
+ string schema;
string relation;
string owner;
string alias;
@@ -165,6 +168,15 @@ public:
return NULL;
}
+ const char* getSchema(CheckStatusWrapper* status, unsigned index)
+ {
+ if (index < items.getCount())
+ return items[index].schema.c_str();
+
+ raiseIndexError(status, index, "getSchema");
+ return NULL;
+ }
+
const char* getRelation(CheckStatusWrapper* status, unsigned index)
{
if (index < items.getCount())
@@ -329,6 +341,7 @@ public:
unsigned addField(CheckStatusWrapper* status);
IMessageMetadata* getMetadata(CheckStatusWrapper* status);
void setField(CheckStatusWrapper* status, unsigned index, const char* field);
+ void setSchema(CheckStatusWrapper* status, unsigned index, const char* schema);
void setRelation(CheckStatusWrapper* status, unsigned index, const char* relation);
void setOwner(CheckStatusWrapper* status, unsigned index, const char* owner);
void setAlias(CheckStatusWrapper* status, unsigned index, const char* alias);
diff --git a/src/common/ParserTokens.h b/src/common/ParserTokens.h
index a45da1c81a..d1269cbf04 100644
--- a/src/common/ParserTokens.h
+++ b/src/common/ParserTokens.h
@@ -104,6 +104,7 @@ PARSER_TOKEN(TOK_BODY, "BODY", true)
PARSER_TOKEN(TOK_BOOLEAN, "BOOLEAN", false)
PARSER_TOKEN(TOK_BOTH, "BOTH", false)
PARSER_TOKEN(TOK_BREAK, "BREAK", true)
+PARSER_TOKEN(TOK_BTRIM, "BTRIM", false)
PARSER_TOKEN(TOK_BY, "BY", false)
PARSER_TOKEN(TOK_CALL, "CALL", false)
PARSER_TOKEN(TOK_CALLER, "CALLER", true)
@@ -157,6 +158,7 @@ PARSER_TOKEN(TOK_CURRENT, "CURRENT", false)
PARSER_TOKEN(TOK_CURRENT_CONNECTION, "CURRENT_CONNECTION", false)
PARSER_TOKEN(TOK_CURRENT_DATE, "CURRENT_DATE", false)
PARSER_TOKEN(TOK_CURRENT_ROLE, "CURRENT_ROLE", false)
+PARSER_TOKEN(TOK_CURRENT_SCHEMA, "CURRENT_SCHEMA", false)
PARSER_TOKEN(TOK_CURRENT_TIME, "CURRENT_TIME", false)
PARSER_TOKEN(TOK_CURRENT_TIMESTAMP, "CURRENT_TIMESTAMP", false)
PARSER_TOKEN(TOK_CURRENT_TRANSACTION, "CURRENT_TRANSACTION", false)
@@ -297,6 +299,7 @@ PARSER_TOKEN(TOK_LONG, "LONG", false)
PARSER_TOKEN(TOK_LOWER, "LOWER", false)
PARSER_TOKEN(TOK_LPAD, "LPAD", true)
PARSER_TOKEN(TOK_LPARAM, "LPARAM", true)
+PARSER_TOKEN(TOK_LTRIM, "LTRIM", false)
PARSER_TOKEN(TOK_MAKE_DBKEY, "MAKE_DBKEY", true)
PARSER_TOKEN(TOK_MANUAL, "MANUAL", true)
PARSER_TOKEN(TOK_MAPPING, "MAPPING", true)
@@ -440,11 +443,13 @@ PARSER_TOKEN(TOK_RSA_PRIVATE, "RSA_PRIVATE", true)
PARSER_TOKEN(TOK_RSA_PUBLIC, "RSA_PUBLIC", true)
PARSER_TOKEN(TOK_RSA_SIGN_HASH, "RSA_SIGN_HASH", true)
PARSER_TOKEN(TOK_RSA_VERIFY_HASH, "RSA_VERIFY_HASH", true)
+PARSER_TOKEN(TOK_RTRIM, "RTRIM", false)
PARSER_TOKEN(TOK_SALT_LENGTH, "SALT_LENGTH", true)
PARSER_TOKEN(TOK_SAVEPOINT, "SAVEPOINT", false)
PARSER_TOKEN(TOK_SCALAR_ARRAY, "SCALAR_ARRAY", true)
-PARSER_TOKEN(TOK_DATABASE, "SCHEMA", false) // Alias of DATABASE
+PARSER_TOKEN(TOK_SCHEMA, "SCHEMA", false)
PARSER_TOKEN(TOK_SCROLL, "SCROLL", false)
+PARSER_TOKEN(TOK_SEARCH_PATH, "SEARCH_PATH", true)
PARSER_TOKEN(TOK_SECOND, "SECOND", false)
PARSER_TOKEN(TOK_SECURITY, "SECURITY", true)
PARSER_TOKEN(TOK_SEGMENT, "SEGMENT", true)
@@ -509,9 +514,6 @@ PARSER_TOKEN(TOK_TRANSACTION, "TRANSACTION", true)
PARSER_TOKEN(TOK_TRAPS, "TRAPS", true)
PARSER_TOKEN(TOK_TRIGGER, "TRIGGER", false)
PARSER_TOKEN(TOK_TRIM, "TRIM", false)
-PARSER_TOKEN(TOK_BTRIM, "BTRIM", false)
-PARSER_TOKEN(TOK_LTRIM, "LTRIM", false)
-PARSER_TOKEN(TOK_RTRIM, "RTRIM", false)
PARSER_TOKEN(TOK_TRUE, "TRUE", false)
PARSER_TOKEN(TOK_TRUNC, "TRUNC", true)
PARSER_TOKEN(TOK_TRUSTED, "TRUSTED", true)
diff --git a/src/common/StatementMetadata.cpp b/src/common/StatementMetadata.cpp
index 11ddc467e7..2350d9bc07 100644
--- a/src/common/StatementMetadata.cpp
+++ b/src/common/StatementMetadata.cpp
@@ -43,6 +43,7 @@ static const UCHAR DESCRIBE_VARS[] =
isc_info_sql_scale,
isc_info_sql_length,
isc_info_sql_field,
+ isc_info_sql_relation_schema,
isc_info_sql_relation,
isc_info_sql_owner,
isc_info_sql_alias,
@@ -337,6 +338,10 @@ void StatementMetadata::parse(unsigned bufferLength, const UCHAR* buffer)
getStringInfo(&buffer, bufferEnd, ¶m->field);
break;
+ case isc_info_sql_relation_schema:
+ getStringInfo(&buffer, bufferEnd, ¶m->schema);
+ break;
+
case isc_info_sql_relation:
getStringInfo(&buffer, bufferEnd, ¶m->relation);
break;
diff --git a/src/common/TextType.h b/src/common/TextType.h
index 858b9fb5c8..420d3ed292 100644
--- a/src/common/TextType.h
+++ b/src/common/TextType.h
@@ -30,7 +30,7 @@
#ifndef COMMON_TEXTTYPE_H
#define COMMON_TEXTTYPE_H
-#include "../common/classes/MetaString.h"
+#include "../common/classes/QualifiedMetaString.h"
struct texttype;
@@ -96,7 +96,7 @@ public:
USHORT getFlags() const;
public:
- Firebird::MetaString name;
+ Firebird::QualifiedMetaString name;
protected:
texttype* tt;
diff --git a/src/common/classes/BlrReader.h b/src/common/classes/BlrReader.h
index 8a8f9b9eac..cc654220d2 100644
--- a/src/common/classes/BlrReader.h
+++ b/src/common/classes/BlrReader.h
@@ -33,6 +33,12 @@ namespace Firebird {
class BlrReader
{
+public:
+ struct Flags
+ {
+ bool searchSystemSchema = false;
+ };
+
public:
BlrReader(const UCHAR* buffer, unsigned maxLen)
: start(buffer),
@@ -121,6 +127,50 @@ public:
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
+ UCHAR parseHeader(Flags* flags = nullptr)
+ {
+ const auto version = getByte();
+
+ switch (version)
+ {
+ case blr_version4:
+ case blr_version5:
+ //case blr_version6:
+ break;
+
+ default:
+ status_exception::raise(
+ Arg::Gds(isc_metadata_corrupt) <<
+ Arg::Gds(isc_wroblrver2) << Arg::Num(blr_version4) << Arg::Num(blr_version5/*6*/) <<
+ Arg::Num(version));
+ }
+
+ auto code = getByte();
+
+ if (code == blr_flags)
+ {
+ while ((code = getByte()) != blr_end)
+ {
+ if (flags)
+ {
+ switch (code)
+ {
+ case blr_flags_search_system_schema:
+ flags->searchSystemSchema = true;
+ break;
+ }
+ }
+
+ const auto len = getWord();
+ seekForward(len);
+ }
+ }
+ else
+ seekBackward(1);
+
+ return version;
+ }
+
UCHAR checkByte(UCHAR expected)
{
UCHAR byte = getByte();
diff --git a/src/common/classes/ClumpletReader.cpp b/src/common/classes/ClumpletReader.cpp
index df1232e2cd..36cf84bc8b 100644
--- a/src/common/classes/ClumpletReader.cpp
+++ b/src/common/classes/ClumpletReader.cpp
@@ -490,6 +490,8 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
case isc_action_svc_validate:
switch (tag)
{
+ case isc_spb_val_sch_incl:
+ case isc_spb_val_sch_excl:
case isc_spb_val_tab_incl:
case isc_spb_val_tab_excl:
case isc_spb_val_idx_incl:
diff --git a/src/common/classes/MetaString.h b/src/common/classes/MetaString.h
index 6c954d3c07..38fc2c2d0b 100644
--- a/src/common/classes/MetaString.h
+++ b/src/common/classes/MetaString.h
@@ -31,7 +31,11 @@
#include "../common/classes/fb_string.h"
#include "../common/classes/fb_pair.h"
+#include "../common/classes/objects_array.h"
+#include "../common/StatusArg.h"
#include "../jrd/constants.h"
+#include
+#include
#ifdef SFIO
#include
@@ -68,6 +72,119 @@ public:
MetaString(MemoryPool&, const MetaString& m) { set(m); }
MetaString(MemoryPool&, const AbstractString& s) { assign(s.c_str(), s.length()); }
+public:
+ static void parseList(const string& str, ObjectsArray& list)
+ {
+ auto pos = str.begin();
+
+ const auto skipSpaces = [&pos, &str]
+ {
+ while (pos != str.end() && (*pos == ' ' || *pos == '\t' || *pos == '\f' || *pos == '\r' || *pos == '\n'))
+ ++pos;
+
+ return pos != str.end();
+ };
+
+ const auto isQuoted = [](const string& name) -> bool
+ {
+ return name.length() >= 2 && name[0] == '"' && name[name.length() - 1] == '"';
+ };
+
+ const auto unquote = [&](const string& name) -> string
+ {
+ if (!isQuoted(name))
+ return name;
+
+ string result;
+
+ for (size_t i = 1; i < name.length() - 1; ++i)
+ {
+ if (name[i] == '"')
+ {
+ if (i + 1 < name.length() - 1 && name[i + 1] == '"')
+ ++i;
+ else
+ (Arg::Gds(isc_invalid_unqualified_name_list) << str).raise();
+ }
+
+ result += name[i];
+ }
+
+ return result;
+ };
+
+ const auto validateUnquotedIdentifier = [&](const string& name)
+ {
+ bool first = true;
+
+ for (const auto c : name)
+ {
+ if (!((c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ c == '{' ||
+ c == '}' ||
+ (!first && c >= '0' && c <= '9') ||
+ (!first && c == '$') ||
+ (!first && c == '_')))
+ {
+ (Arg::Gds(isc_invalid_unqualified_name_list) << str).raise();
+ }
+
+ first = false;
+ }
+
+ return true;
+ };
+
+ list.clear();
+
+ if (!skipSpaces())
+ return;
+
+ do
+ {
+ const auto nameStart = pos;
+ auto nameEnd = pos;
+ bool inQuotes = false;
+
+ while (pos != str.end())
+ {
+ if (*pos == '"')
+ inQuotes = !inQuotes;
+ else if (*pos == ',' && !inQuotes)
+ break;
+
+ nameEnd = ++pos;
+ skipSpaces();
+ }
+
+ string name(nameStart, nameEnd);
+
+ if (isQuoted(name))
+ name = unquote(name);
+ else
+ {
+ validateUnquotedIdentifier(name);
+ std::transform(name.begin(), name.end(), name.begin(), ::toupper);
+ }
+
+ if (name.isEmpty())
+ (Arg::Gds(isc_invalid_unqualified_name_list) << str).raise();
+
+ list.add(name);
+
+ if (pos == str.end())
+ break;
+
+ if (*pos == ',')
+ {
+ ++pos;
+ skipSpaces();
+ }
+ } while(true);
+ }
+
+public:
MetaString& assign(const char* s, FB_SIZE_T l);
MetaString& assign(const char* s) { return assign(s, s ? fb_strlen(s) : 0); }
MetaString& clear() { return assign(nullptr, 0); }
diff --git a/src/common/classes/QualifiedMetaString.h b/src/common/classes/QualifiedMetaString.h
new file mode 100644
index 0000000000..f99777cc59
--- /dev/null
+++ b/src/common/classes/QualifiedMetaString.h
@@ -0,0 +1,272 @@
+/*
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights
+ * and limitations under the License.
+ *
+ * The Original Code was created by Adriano dos Santos Fernandes
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2024 Adriano dos Santos Fernandes
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#ifndef QUALIFIED_METASTRING_H
+#define QUALIFIED_METASTRING_H
+
+#include "../common/classes/MetaString.h"
+#include "../common/StatusArg.h"
+#include
+#include
+
+namespace Firebird {
+
+template
+class BaseQualifiedName
+{
+public:
+ explicit BaseQualifiedName(MemoryPool& p, const T& aObject,
+ const T& aSchema = {}, const T& aPackage = {})
+ : object(p, aObject),
+ schema(p, aSchema),
+ package(p, aPackage)
+ {
+ }
+
+ explicit BaseQualifiedName(const T& aObject, const T& aSchema = {}, const T& aPackage = {})
+ : object(aObject),
+ schema(aSchema),
+ package(aPackage)
+ {
+ }
+
+ BaseQualifiedName(MemoryPool& p, const BaseQualifiedName& src)
+ : object(p, src.object),
+ schema(p, src.schema),
+ package(p, src.package)
+ {
+ }
+
+ BaseQualifiedName(const BaseQualifiedName& src)
+ : object(src.object),
+ schema(src.schema),
+ package(src.package)
+ {
+ }
+
+ template
+ BaseQualifiedName(const BaseQualifiedName& src)
+ : object(src.object),
+ schema(src.schema),
+ package(src.package)
+ {
+ }
+
+ explicit BaseQualifiedName(MemoryPool& p)
+ : object(p),
+ schema(p),
+ package(p)
+ {
+ }
+
+ BaseQualifiedName()
+ {
+ }
+
+public:
+ static BaseQualifiedName parseSchemaObject(const string& str)
+ {
+ const auto isQuoted = [](const string& name) -> bool
+ {
+ return name.length() >= 2 && name[0] == '"' && name[name.length() - 1] == '"';
+ };
+
+ const auto unquote = [&](const string& name) -> string
+ {
+ if (!isQuoted(name))
+ return name;
+
+ string result;
+
+ for (size_t i = 1; i < name.length() - 1; ++i)
+ {
+ if (name[i] == '"')
+ {
+ if (i + 1 < name.length() - 1 && name[i + 1] == '"')
+ ++i;
+ else
+ (Arg::Gds(isc_invalid_name) << str).raise();
+ }
+
+ result += name[i];
+ }
+
+ return result;
+ };
+
+ const auto validateUnquotedIdentifier = [&](const string& name)
+ {
+ bool first = true;
+
+ for (const auto c : name)
+ {
+ if (!((c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ c == '{' ||
+ c == '}' ||
+ (!first && c >= '0' && c <= '9') ||
+ (!first && c == '$') ||
+ (!first && c == '_')))
+ {
+ (Arg::Gds(isc_invalid_name) << str).raise();
+ }
+
+ first = false;
+ }
+
+ return true;
+ };
+
+ BaseQualifiedName result;
+ string schema, object;
+
+ // Find the last unquoted dot to determine schema and object
+ bool inQuotes = false;
+ auto lastDotPos = string::npos;
+
+ for (size_t i = 0; i < str.size(); ++i)
+ {
+ if (str[i] == '"')
+ inQuotes = !inQuotes;
+ else if (str[i] == '.' && !inQuotes)
+ lastDotPos = i;
+ }
+
+ if (lastDotPos != string::npos)
+ {
+ schema = str.substr(0, lastDotPos);
+ object = str.substr(lastDotPos + 1);
+ }
+ else
+ object = str;
+
+ schema.trim(" \t\f\r\n");
+ object.trim(" \t\f\r\n");
+
+ // Process schema if it exists
+ if (schema.hasData())
+ {
+ if (isQuoted(schema))
+ result.schema = unquote(schema);
+ else
+ {
+ validateUnquotedIdentifier(schema);
+
+ std::transform(schema.begin(), schema.end(), schema.begin(), ::toupper);
+ result.schema = schema;
+ }
+ }
+
+ if (lastDotPos != string::npos && result.schema.isEmpty())
+ (Arg::Gds(isc_invalid_name) << str).raise();
+
+ // Process object
+ if (isQuoted(object))
+ result.object = unquote(object);
+ else
+ {
+ validateUnquotedIdentifier(object);
+
+ std::transform(object.begin(), object.end(), object.begin(), ::toupper);
+ result.object = object;
+ }
+
+ if (result.object.isEmpty())
+ (Arg::Gds(isc_invalid_name) << str).raise();
+
+ return result;
+ }
+
+public:
+ bool operator<(const BaseQualifiedName& m) const
+ {
+ return schema < m.schema ||
+ (schema == m.schema && object < m.object) ||
+ (schema == m.schema && object == m.object && package < m.package);
+ }
+
+ bool operator>(const BaseQualifiedName& m) const
+ {
+ return schema > m.schema ||
+ (schema == m.schema && object > m.object) ||
+ (schema == m.schema && object == m.object && package > m.package);
+ }
+
+ bool operator==(const BaseQualifiedName& m) const
+ {
+ return schema == m.schema && object == m.object && package == m.package;
+ }
+
+ bool operator!=(const BaseQualifiedName& m) const
+ {
+ return !(*this == m);
+ }
+
+public:
+ BaseQualifiedName getSchemaAndPackage() const
+ {
+ return BaseQualifiedName(package, schema);
+ }
+
+ void clear()
+ {
+ object = {};
+ schema = {};
+ package = {};
+ }
+
+ Firebird::string toQuotedString() const
+ {
+ Firebird::string s;
+
+ const auto appendName = [&s](const T& name) {
+ if (name.hasData())
+ {
+ s += name.toQuotedString();
+ return true;
+ }
+
+ return false;
+ };
+
+ if (appendName(schema))
+ s.append(".");
+
+ if (appendName(package))
+ s.append(".");
+
+ appendName(object);
+
+ return s;
+ }
+
+public:
+ T object;
+ T schema;
+ T package;
+};
+
+using QualifiedMetaString = Firebird::BaseQualifiedName;
+
+} // namespace Firebird
+
+#endif // QUALIFIED_METASTRING_H
diff --git a/src/common/classes/array.h b/src/common/classes/array.h
index 8b3ff24d9d..648fa7c1ff 100644
--- a/src/common/classes/array.h
+++ b/src/common/classes/array.h
@@ -145,6 +145,13 @@ public:
add(item);
}
+ Array(std::initializer_list items)
+ : Array()
+ {
+ for (auto& item : items)
+ add(item);
+ }
+
~Array()
{
freeData();
diff --git a/src/common/classes/objects_array.h b/src/common/classes/objects_array.h
index 449173d09b..c7fb9f58a6 100644
--- a/src/common/classes/objects_array.h
+++ b/src/common/classes/objects_array.h
@@ -306,12 +306,24 @@ namespace Firebird
return iterator(this, getCount());
}
+ const T& front() const
+ {
+ fb_assert(getCount() > 0);
+ return *begin();
+ }
+
T& front()
{
- fb_assert(getCount() > 0);
+ fb_assert(getCount() > 0);
return *begin();
}
+ const T& back() const
+ {
+ fb_assert(getCount() > 0);
+ return *iterator(this, getCount() - 1);
+ }
+
T& back()
{
fb_assert(getCount() > 0);
@@ -372,6 +384,13 @@ namespace Firebird
add(item);
}
+ ObjectsArray(std::initializer_list items)
+ : A()
+ {
+ for (auto& item : items)
+ add(item);
+ }
+
ObjectsArray() :
A()
{
diff --git a/src/common/classes/tests/MetaStringTest.cpp b/src/common/classes/tests/MetaStringTest.cpp
new file mode 100644
index 0000000000..d3cd101508
--- /dev/null
+++ b/src/common/classes/tests/MetaStringTest.cpp
@@ -0,0 +1,74 @@
+#include "boost/test/unit_test.hpp"
+#include "boost/test/data/test_case.hpp"
+#include "../common/classes/MetaString.h"
+#include "../common/classes/objects_array.h"
+#include
+#include
+#include
+
+using namespace Firebird;
+using std::make_tuple;
+
+
+BOOST_AUTO_TEST_SUITE(MetaStringSuite)
+BOOST_AUTO_TEST_SUITE(MetaStringTests)
+
+
+const auto parseTestData = boost::unit_test::data::make({
+ make_tuple("Object1", "\"OBJECT1\""),
+ make_tuple(" Object2 ", "\"OBJECT2\""),
+ make_tuple(" Object3 , Object4 ", "\"OBJECT3\", \"OBJECT4\""),
+ make_tuple(" \"Object5 \" , \" Object6 \" ", "\"Object5\", \" Object6\""),
+ make_tuple(" Object7 , \" Object8 \" ", "\"OBJECT7\", \" Object8\""),
+ make_tuple(" Object9 , Object10 ", "\"OBJECT9\", \"OBJECT10\""),
+});
+
+BOOST_DATA_TEST_CASE(ParseTest, parseTestData, input, formattedList)
+{
+ const auto parseAndFormatList = [](const char* input) -> std::string
+ {
+ ObjectsArray list;
+ MetaString::parseList(input, list);
+
+ if (list.hasData())
+ {
+ return std::accumulate(
+ std::next(list.begin()),
+ list.end(),
+ std::string(list[0].toQuotedString().c_str()),
+ [](const auto& a, const auto& b) {
+ return a + ", " + (b.hasData() ? b.toQuotedString().c_str() : "\" \"");
+ }
+ );
+ }
+ else
+ return {};
+ };
+
+ BOOST_TEST(parseAndFormatList(input) == formattedList);
+}
+
+
+const auto parseErrorTestData = boost::unit_test::data::make({
+ "1Object",
+ "_Object",
+ "$Object",
+ "\"\"name\"",
+ "Na me",
+ "Na.me",
+ "Name,"
+ "Name, "
+ ","
+ "Name,,Name",
+});
+
+BOOST_DATA_TEST_CASE(ParseErrorTest, parseErrorTestData, input)
+{
+ ObjectsArray array;
+ BOOST_CHECK_THROW(MetaString::parseList(input, array), status_exception);
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END() // MetaStringTests
+BOOST_AUTO_TEST_SUITE_END() // MetaStringSuite
diff --git a/src/common/classes/tests/QualifiedMetaStringTest.cpp b/src/common/classes/tests/QualifiedMetaStringTest.cpp
new file mode 100644
index 0000000000..47f8f76d13
--- /dev/null
+++ b/src/common/classes/tests/QualifiedMetaStringTest.cpp
@@ -0,0 +1,64 @@
+#include "boost/test/unit_test.hpp"
+#include "boost/test/data/test_case.hpp"
+#include "../common/classes/QualifiedMetaString.h"
+#include
+
+using namespace Firebird;
+using std::make_tuple;
+
+
+BOOST_AUTO_TEST_SUITE(QualifiedMetaStringSuite)
+BOOST_AUTO_TEST_SUITE(QualifiedMetaStringTests)
+
+
+const auto parseTestData = boost::unit_test::data::make({
+ make_tuple("Object", "", "OBJECT"),
+ make_tuple("Schema$_0.{Object}", "SCHEMA$_0", "{OBJECT}"),
+ make_tuple("Schema.Object", "SCHEMA", "OBJECT"),
+ make_tuple("\"A\"\"name\"", "", "A\"name"),
+ make_tuple("Schema.\"Name\"", "SCHEMA", "Name"),
+ make_tuple("\"Schema\".Name", "Schema", "NAME"),
+ make_tuple("\"Sche ma\".\"Na me\"", "Sche ma", "Na me"),
+ make_tuple(" x . y ", "X", "Y"),
+ make_tuple(" \" x \" . \" y \" ", " x ", " y "),
+ make_tuple(" \"x\" . \"y\" ", "x", "y"),
+ make_tuple(" \"Sch\"\"ma\" . \"Obj\"\"ect\" ", "Sch\"ma", "Obj\"ect"),
+});
+
+BOOST_DATA_TEST_CASE(ParseTest, parseTestData, input, expectedSchema, expectedObject)
+{
+ const auto name = QualifiedMetaString::parseSchemaObject(input);
+ BOOST_TEST(name.schema == MetaString(expectedSchema));
+ BOOST_TEST(name.object == MetaString(expectedObject));
+}
+
+
+const auto parseErrorTestData = boost::unit_test::data::make({
+ "1Object",
+ "_Object",
+ "$Object",
+ "\"\"name\"",
+ "Sche ma.Na me",
+ "Sch.ema.\"Na.me\"",
+ "a.b.c",
+ "a\"b\".c\"d\"",
+ "",
+ " ",
+ ".",
+ " . ",
+ "\"\"",
+ "\" \"",
+ "\"\".\"\"",
+ "\" \".\" \"",
+ "\" \" . \" \"",
+});
+
+BOOST_DATA_TEST_CASE(ParseErrorTest, parseErrorTestData, input)
+{
+ BOOST_CHECK_THROW(QualifiedMetaString::parseSchemaObject(input), status_exception);
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END() // QualifiedMetaStringTests
+BOOST_AUTO_TEST_SUITE_END() // QualifiedMetaStringSuite
diff --git a/src/common/pretty.cpp b/src/common/pretty.cpp
index d1a0e6956d..b744fb9547 100644
--- a/src/common/pretty.cpp
+++ b/src/common/pretty.cpp
@@ -815,6 +815,7 @@ static int print_sdl_verb( ctl* control, SSHORT level)
return 0;
case isc_sdl_field:
+ case isc_sdl_schema:
case isc_sdl_relation:
print_string(control, offset);
break;
diff --git a/src/common/sdl.cpp b/src/common/sdl.cpp
index 0059a6bda3..a730dad586 100644
--- a/src/common/sdl.cpp
+++ b/src/common/sdl.cpp
@@ -175,7 +175,8 @@ ISC_STATUS SDL_info(CheckStatusWrapper* status_vector,
const UCHAR* p = sdl;
info->sdl_info_fid = info->sdl_info_rid = 0;
- info->sdl_info_relation = info->sdl_info_field = "";
+ info->sdl_info_relation.clear();
+ info->sdl_info_field.clear();
if (*p++ != isc_sdl_version1)
return error(status_vector, Arg::Gds(isc_invalid_sdl) << Arg::Num(0));
@@ -207,9 +208,15 @@ ISC_STATUS SDL_info(CheckStatusWrapper* status_vector,
p += n;
break;
+ case isc_sdl_schema:
+ n = *p++;
+ info->sdl_info_relation.schema.assign(reinterpret_cast(p), n);
+ p += n;
+ break;
+
case isc_sdl_relation:
n = *p++;
- info->sdl_info_relation.assign(reinterpret_cast(p), n);
+ info->sdl_info_relation.object.assign(reinterpret_cast(p), n);
p += n;
break;
@@ -281,6 +288,7 @@ int SDL_walk(CheckStatusWrapper* status_vector,
break;
case isc_sdl_field:
+ case isc_sdl_schema:
case isc_sdl_relation:
n = *p++;
p += n;
diff --git a/src/common/sdl.h b/src/common/sdl.h
index ff8016a3a1..f3914f04a3 100644
--- a/src/common/sdl.h
+++ b/src/common/sdl.h
@@ -25,6 +25,7 @@
#define JRD_SDL_H
#include "../common/classes/MetaString.h"
+#include "../common/classes/QualifiedMetaString.h"
#include "../common/dsc.h"
struct sdl_info
@@ -32,7 +33,7 @@ struct sdl_info
USHORT sdl_info_fid;
USHORT sdl_info_rid;
Firebird::MetaString sdl_info_field;
- Firebird::MetaString sdl_info_relation;
+ Firebird::QualifiedMetaString sdl_info_relation;
dsc sdl_info_element;
USHORT sdl_info_dimensions;
SLONG sdl_info_lower[MAX_ARRAY_DIMENSIONS];
diff --git a/src/dbs/security.sql b/src/dbs/security.sql
index c184981707..8c3b908ac9 100644
--- a/src/dbs/security.sql
+++ b/src/dbs/security.sql
@@ -23,8 +23,8 @@
*/
/* Domain definitions */
-CREATE DOMAIN PLG$PASSWD AS VARBINARY(64);
-CREATE DOMAIN PLG$ID AS INTEGER;
+CREATE DOMAIN PUBLIC.PLG$PASSWD AS VARBINARY(64);
+CREATE DOMAIN PUBLIC.PLG$ID AS INTEGER;
COMMIT;
@@ -36,41 +36,41 @@ COMMIT;
/* Table: RDB$USERS */
-CREATE TABLE PLG$USERS (
- PLG$USER_NAME SEC$USER_NAME NOT NULL PRIMARY KEY,
- PLG$GROUP_NAME SEC$USER_NAME,
- PLG$UID PLG$ID,
- PLG$GID PLG$ID,
- PLG$PASSWD PLG$PASSWD NOT NULL,
- PLG$COMMENT RDB$DESCRIPTION,
- PLG$FIRST_NAME SEC$NAME_PART,
- PLG$MIDDLE_NAME SEC$NAME_PART,
- PLG$LAST_NAME SEC$NAME_PART);
+CREATE TABLE PUBLIC.PLG$USERS (
+ PLG$USER_NAME SYSTEM.SEC$USER_NAME NOT NULL PRIMARY KEY,
+ PLG$GROUP_NAME SYSTEM.SEC$USER_NAME,
+ PLG$UID PUBLIC.PLG$ID,
+ PLG$GID PUBLIC.PLG$ID,
+ PLG$PASSWD PUBLIC.PLG$PASSWD NOT NULL,
+ PLG$COMMENT SYSTEM.RDB$DESCRIPTION,
+ PLG$FIRST_NAME SYSTEM.SEC$NAME_PART,
+ PLG$MIDDLE_NAME SYSTEM.SEC$NAME_PART,
+ PLG$LAST_NAME SYSTEM.SEC$NAME_PART);
COMMIT;
/* VIEW: PLG$VIEW_USERS */
-CREATE VIEW PLG$VIEW_USERS (PLG$USER_NAME, PLG$GROUP_NAME, PLG$UID, PLG$GID, PLG$PASSWD,
+CREATE VIEW PUBLIC.PLG$VIEW_USERS (PLG$USER_NAME, PLG$GROUP_NAME, PLG$UID, PLG$GID, PLG$PASSWD,
PLG$COMMENT, PLG$FIRST_NAME, PLG$MIDDLE_NAME, PLG$LAST_NAME) AS
SELECT PLG$USER_NAME, PLG$GROUP_NAME, PLG$UID, PLG$GID, PLG$PASSWD,
PLG$COMMENT, PLG$FIRST_NAME, PLG$MIDDLE_NAME, PLG$LAST_NAME
- FROM PLG$USERS
+ FROM PUBLIC.PLG$USERS
WHERE CURRENT_USER = 'SYSDBA'
OR CURRENT_ROLE = 'RDB$ADMIN'
OR CURRENT_USER = PLG$USERS.PLG$USER_NAME;
/* Access rights */
-GRANT ALL ON PLG$USERS to VIEW PLG$VIEW_USERS;
-GRANT SELECT ON PLG$VIEW_USERS to PUBLIC;
+GRANT ALL ON PUBLIC.PLG$USERS to VIEW PUBLIC.PLG$VIEW_USERS;
+GRANT SELECT ON PUBLIC.PLG$VIEW_USERS to PUBLIC;
GRANT UPDATE(PLG$PASSWD, PLG$GROUP_NAME, PLG$UID, PLG$GID, PLG$FIRST_NAME, PLG$MIDDLE_NAME, PLG$LAST_NAME)
- ON PLG$VIEW_USERS TO PUBLIC;
+ ON PUBLIC.PLG$VIEW_USERS TO PUBLIC;
COMMIT;
/* Needed record - with PASSWD = random + SHA1 (random + 'SYSDBA' + crypt('masterke')) */
-INSERT INTO PLG$USERS(PLG$USER_NAME, PLG$PASSWD, PLG$FIRST_NAME, PLG$MIDDLE_NAME, PLG$LAST_NAME)
+INSERT INTO PUBLIC.PLG$USERS(PLG$USER_NAME, PLG$PASSWD, PLG$FIRST_NAME, PLG$MIDDLE_NAME, PLG$LAST_NAME)
VALUES ('SYSDBA', 'NLtwcs9LrxLMOYhG0uGM9i6KS7mf3QAKvFVpmRg=', 'Sql', 'Server', 'Administrator');
COMMIT;
diff --git a/src/dsql/BlrDebugWriter.cpp b/src/dsql/BlrDebugWriter.cpp
index 864264b066..a6b43aeaf0 100644
--- a/src/dsql/BlrDebugWriter.cpp
+++ b/src/dsql/BlrDebugWriter.cpp
@@ -142,7 +142,7 @@ void BlrDebugWriter::putDebugSubFunction(DeclareSubFuncNode* subFuncNode)
debugData.add(fb_dbg_subfunc);
dsql_udf* subFunc = subFuncNode->dsqlFunction;
- const MetaName& name = subFunc->udf_name.identifier;
+ const auto& name = subFunc->udf_name.object;
USHORT len = MIN(name.length(), MAX_UCHAR);
debugData.add(len);
@@ -162,7 +162,7 @@ void BlrDebugWriter::putDebugSubProcedure(DeclareSubProcNode* subProcNode)
debugData.add(fb_dbg_subproc);
dsql_prc* subProc = subProcNode->dsqlProcedure;
- const MetaName& name = subProc->prc_name.identifier;
+ const auto& name = subProc->prc_name.object;
USHORT len = MIN(name.length(), MAX_UCHAR);
debugData.add(len);
diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp
index 5a3cd5eed3..f4a93444f8 100644
--- a/src/dsql/DdlNodes.epp
+++ b/src/dsql/DdlNodes.epp
@@ -70,35 +70,35 @@ namespace Jrd {
using namespace Firebird;
static void checkForeignKeyTempScope(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& childRelName, const MetaName& masterIndexName);
+ const QualifiedName& childRelName, const QualifiedName& masterIndexName);
static void checkSpTrigDependency(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName);
+ const QualifiedName& relationName, const MetaName& fieldName);
static void checkViewDependency(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName);
+ const QualifiedName& relationName, const MetaName& fieldName);
static void clearPermanentField(dsql_rel* relation, bool permanent);
static void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relation,
dsql_fld* field, ValueSourceClause* clause, string& source, BlrDebugWriter::BlrData& value);
static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& constraintName, const MetaName& indexName);
-static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
+ const QualifiedName& relationName, const MetaName& constraintName, const MetaName& indexName);
+static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& relationName,
const MetaName& fieldName);
static bool isItSqlRole(thread_db* tdbb, jrd_tra* transaction, const MetaName& inputName,
MetaName& outputName);
static int getGrantorOption(thread_db* tdbb, jrd_tra* transaction, const MetaName& grantor,
int grantorType, const MetaName& roleName);
-static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& indexName, bool& systemIndex, bool silent = false);
+static QualifiedName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
+ const QualifiedName& indexName, bool& systemIndex, bool silent = false);
static const char* getRelationScopeName(const rel_t type);
-static void makeRelationScopeName(string& to, const MetaName& name, const rel_t type);
-static void checkRelationType(const rel_t type, const MetaName& name);
-static void checkFkPairTypes(const rel_t masterType, const MetaName& masterName,
- const rel_t childType, const MetaName& childName);
+static void makeRelationScopeName(string& to, const QualifiedName& name, const rel_t type);
+static void checkRelationType(const rel_t type, const QualifiedName& name);
+static void checkFkPairTypes(const rel_t masterType, const QualifiedName& masterName,
+ const rel_t childType, const QualifiedName& childName);
static void modifyLocalFieldPosition(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName, USHORT newPosition);
+ const QualifiedName& relationName, const MetaName& fieldName, USHORT newPosition);
static rel_t relationType(SSHORT relationTypeNull, SSHORT relationType);
static void saveField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, const MetaName& fieldName);
static void saveRelation(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- const MetaName& relationName, bool view, bool creating);
+ const QualifiedName& relationName, bool view, bool creating);
static void updateRdbFields(const TypeClause* type,
SSHORT& fieldType,
SSHORT& fieldLength,
@@ -180,10 +180,10 @@ void ExecInSecurityDb::executeInSecurityDb(jrd_tra* localTransaction)
// Check temporary table reference rules between given child relation and master
// relation (owner of given PK/UK index).
static void checkForeignKeyTempScope(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& childRelName, const MetaName& masterIndexName)
+ const QualifiedName& childRelName, const QualifiedName& masterIndexName)
{
AutoCacheRequest request(tdbb, drq_l_rel_info, DYN_REQUESTS);
- MetaName masterRelName;
+ QualifiedName masterRelName;
rel_t masterType, childType;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
@@ -192,20 +192,22 @@ static void checkForeignKeyTempScope(thread_db* tdbb, jrd_tra* transaction,
REL_M IN RDB$RELATIONS
WITH (RLC_M.RDB$CONSTRAINT_TYPE EQ UNIQUE_CNSTRT OR
RLC_M.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY) AND
- RLC_M.RDB$INDEX_NAME EQ masterIndexName.c_str() AND
- REL_C.RDB$RELATION_NAME EQ childRelName.c_str() AND
+ RLC_M.RDB$SCHEMA_NAME EQ masterIndexName.schema.c_str() AND
+ RLC_M.RDB$INDEX_NAME EQ masterIndexName.object.c_str() AND
+ REL_C.RDB$SCHEMA_NAME EQ childRelName.schema.c_str() AND
+ REL_C.RDB$RELATION_NAME EQ childRelName.object.c_str() AND
+ REL_M.RDB$SCHEMA_NAME EQ RLC_M.RDB$SCHEMA_NAME AND
REL_M.RDB$RELATION_NAME EQ RLC_M.RDB$RELATION_NAME
{
- fb_assert(masterRelName.isEmpty());
+ fb_assert(masterRelName.object.isEmpty());
- masterRelName = REL_M.RDB$RELATION_NAME;
+ masterRelName = QualifiedName(REL_M.RDB$RELATION_NAME, REL_M.RDB$SCHEMA_NAME);
masterType = relationType(REL_M.RDB$RELATION_TYPE.NULL, REL_M.RDB$RELATION_TYPE);
childType = relationType(REL_C.RDB$RELATION_TYPE.NULL, REL_C.RDB$RELATION_TYPE);
-
}
END_FOR
- if (masterRelName.hasData())
+ if (masterRelName.object.hasData())
{
checkRelationType(masterType, masterRelName);
checkRelationType(childType, childRelName);
@@ -216,7 +218,7 @@ static void checkForeignKeyTempScope(thread_db* tdbb, jrd_tra* transaction,
// Check temporary table reference rules between just created child relation and all
// its master relations.
static void checkRelationTempScope(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& childRelName, const rel_t childType)
+ const QualifiedName& childRelName, const rel_t childType)
{
if (childType != rel_persistent &&
childType != rel_global_temp_preserve &&
@@ -226,7 +228,7 @@ static void checkRelationTempScope(thread_db* tdbb, jrd_tra* transaction,
}
AutoCacheRequest request(tdbb, drq_l_rel_info2, DYN_REQUESTS);
- MetaName masterRelName;
+ QualifiedName masterRelName;
rel_t masterType;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
@@ -235,19 +237,23 @@ static void checkRelationTempScope(thread_db* tdbb, jrd_tra* transaction,
IND_M IN RDB$INDICES CROSS
REL_M IN RDB$RELATIONS
WITH RLC_C.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY AND
- RLC_C.RDB$RELATION_NAME EQ childRelName.c_str() AND
+ RLC_C.RDB$SCHEMA_NAME EQ childRelName.schema.c_str() AND
+ RLC_C.RDB$RELATION_NAME EQ childRelName.object.c_str() AND
+ IND_C.RDB$SCHEMA_NAME EQ RLC_C.RDB$SCHEMA_NAME AND
IND_C.RDB$INDEX_NAME EQ RLC_C.RDB$INDEX_NAME AND
+ IND_M.RDB$SCHEMA_NAME EQ IND_C.RDB$FOREIGN_KEY_SCHEMA_NAME AND
IND_M.RDB$INDEX_NAME EQ IND_C.RDB$FOREIGN_KEY AND
+ IND_M.RDB$SCHEMA_NAME EQ REL_M.RDB$SCHEMA_NAME AND
IND_M.RDB$RELATION_NAME EQ REL_M.RDB$RELATION_NAME
{
- fb_assert(masterRelName.isEmpty());
+ fb_assert(masterRelName.object.isEmpty());
masterType = relationType(REL_M.RDB$RELATION_TYPE.NULL, REL_M.RDB$RELATION_TYPE);
- masterRelName = REL_M.RDB$RELATION_NAME;
+ masterRelName = QualifiedName(REL_M.RDB$RELATION_NAME, REL_M.RDB$SCHEMA_NAME);
}
END_FOR
- if (masterRelName.hasData())
+ if (masterRelName.object.hasData())
{
checkRelationType(masterType, masterRelName);
checkFkPairTypes(masterType, masterRelName, childType, childRelName);
@@ -257,29 +263,30 @@ static void checkRelationTempScope(thread_db* tdbb, jrd_tra* transaction,
// Checks to see if the given field is referenced in a stored procedure or trigger.
// If the field is referenced, throw.
static void checkSpTrigDependency(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName)
+ const QualifiedName& relationName, const MetaName& fieldName)
{
AutoRequest request;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FIRST 1
DEP IN RDB$DEPENDENCIES
- WITH DEP.RDB$DEPENDED_ON_NAME EQ relationName.c_str() AND
+ WITH DEP.RDB$DEPENDED_ON_SCHEMA_NAME EQ relationName.schema.c_str() AND
+ DEP.RDB$DEPENDED_ON_NAME EQ relationName.object.c_str() AND
DEP.RDB$DEPENDED_ON_TYPE EQ obj_relation AND
DEP.RDB$FIELD_NAME EQ fieldName.c_str()
{
- MetaName depName(DEP.RDB$DEPENDENT_NAME);
+ const QualifiedName depName(DEP.RDB$DEPENDENT_NAME, DEP.RDB$DEPENDENT_SCHEMA_NAME);
// msg 206: Column %s from table %s is referenced in %s.
status_exception::raise(
- Arg::PrivateDyn(206) << fieldName << relationName << depName);
+ Arg::PrivateDyn(206) << fieldName << relationName.toQuotedString() << depName.toQuotedString());
}
END_FOR
}
// Checks to see if the given field is referenced in a view. If it is, throw.
static void checkViewDependency(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName)
+ const QualifiedName& relationName, const MetaName& fieldName)
{
AutoRequest request;
@@ -288,19 +295,23 @@ static void checkViewDependency(thread_db* tdbb, jrd_tra* transaction,
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$RELATION_FIELDS CROSS
Z IN RDB$VIEW_RELATIONS
- WITH X.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH X.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ relationName.object.c_str() AND
X.RDB$FIELD_NAME EQ fieldName.c_str() AND
X.RDB$FIELD_NAME EQ Y.RDB$BASE_FIELD AND
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME EQ Y.RDB$FIELD_SOURCE_SCHEMA_NAME AND
X.RDB$FIELD_SOURCE EQ Y.RDB$FIELD_SOURCE AND
+ Y.RDB$SCHEMA_NAME EQ Z.RDB$SCHEMA_NAME AND
Y.RDB$RELATION_NAME EQ Z.RDB$VIEW_NAME AND
+ X.RDB$SCHEMA_NAME EQ Z.RDB$RELATION_SCHEMA_NAME AND
X.RDB$RELATION_NAME EQ Z.RDB$RELATION_NAME AND
Y.RDB$VIEW_CONTEXT EQ Z.RDB$VIEW_CONTEXT
{
- MetaName viewName(Z.RDB$VIEW_NAME);
+ QualifiedName viewName(Z.RDB$VIEW_NAME, Z.RDB$SCHEMA_NAME);
// msg 206: Column %s from table %s is referenced in %s.
status_exception::raise(
- Arg::PrivateDyn(206) << fieldName << relationName << viewName);
+ Arg::PrivateDyn(206) << fieldName << relationName.toQuotedString() << viewName.toQuotedString());
}
END_FOR
}
@@ -312,8 +323,8 @@ static void clearPermanentField(dsql_rel* relation, bool permanent)
{
relation->rel_fields->fld_procedure = NULL;
relation->rel_fields->ranges = NULL;
- relation->rel_fields->charSet = NULL;
- relation->rel_fields->subTypeName = NULL;
+ relation->rel_fields->charSet.clear();
+ relation->rel_fields->subTypeName = nullptr;
relation->rel_fields->fld_relation = relation;
}
}
@@ -460,7 +471,7 @@ void definePartial(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relatio
// RDB$INDEX_SEGMENTS.RDB$INDEX_NAME =
// RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME
static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& constraintName, const MetaName& indexName)
+ const QualifiedName& relationName, const MetaName& constraintName, const MetaName& indexName)
{
SET_TDBB(tdbb);
@@ -471,7 +482,8 @@ static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
RC IN RDB$RELATION_CONSTRAINTS
WITH RC.RDB$CONSTRAINT_NAME EQ constraintName.c_str() AND
RC.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY AND
- RC.RDB$RELATION_NAME EQ relationName.c_str() AND
+ RC.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ RC.RDB$RELATION_NAME EQ relationName.object.c_str() AND
RC.RDB$INDEX_NAME EQ indexName.c_str()
{
found = true;
@@ -482,13 +494,12 @@ static void deleteKeyConstraint(thread_db* tdbb, jrd_tra* transaction,
if (!found)
{
// msg 130: "CONSTRAINT %s does not exist."
- status_exception::raise(
- Arg::PrivateDyn(130) << constraintName);
+ status_exception::raise(Arg::PrivateDyn(130) << constraintName);
}
}
// Checks to see if the given field already exists in a relation.
-static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& relationName,
+static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& relationName,
const MetaName& fieldName)
{
AutoRequest request;
@@ -496,7 +507,8 @@ static bool fieldExists(thread_db* tdbb, jrd_tra* transaction, const MetaName& r
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$RELATION_FIELDS
- WITH FLD.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH FLD.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ FLD.RDB$RELATION_NAME EQ relationName.object.c_str() AND
FLD.RDB$FIELD_NAME EQ fieldName.c_str()
{
found = true;
@@ -525,15 +537,15 @@ static bool isItSqlRole(thread_db* tdbb, jrd_tra* transaction, const MetaName& i
}
// Make string with relation name and type of its temporary scope.
-static void makeRelationScopeName(string& to, const MetaName& name, const rel_t type)
+static void makeRelationScopeName(string& to, const QualifiedName& name, const rel_t type)
{
const char* scope = getRelationScopeName(type);
- to.printf(scope, name.c_str());
+ to.printf(scope, name.toQuotedString().c_str());
}
// Get relation name of an index.
-static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& indexName, bool& systemIndex, bool silent)
+static QualifiedName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
+ const QualifiedName& indexName, bool& systemIndex, bool silent)
{
systemIndex = false;
@@ -541,10 +553,11 @@ static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ indexName.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ indexName.schema.c_str() AND
+ IDX.RDB$INDEX_NAME EQ indexName.object.c_str()
{
systemIndex = IDX.RDB$SYSTEM_FLAG == 1;
- return IDX.RDB$RELATION_NAME;
+ return QualifiedName(IDX.RDB$RELATION_NAME, IDX.RDB$SCHEMA_NAME);
}
END_FOR
@@ -558,20 +571,21 @@ static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
}
// Get relation name of an trigger.
-static MetaName getTriggerRelationName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& triggerName)
+static QualifiedName getTriggerRelationName(thread_db* tdbb, jrd_tra* transaction,
+ const QualifiedName& triggerName)
{
AutoCacheRequest request(tdbb, drq_l_trigger_relname, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGERS
- WITH X.RDB$TRIGGER_NAME EQ triggerName.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ triggerName.schema.c_str() AND
+ X.RDB$TRIGGER_NAME EQ triggerName.object.c_str()
{
- return X.RDB$RELATION_NAME;
+ return QualifiedName(X.RDB$RELATION_NAME, X.RDB$SCHEMA_NAME);
}
END_FOR
- return "";
+ return {};
}
// Get relation type name
@@ -595,7 +609,7 @@ static const char* getRelationScopeName(const rel_t type)
}
// Check, can relation of given type be used in FK?
-static void checkRelationType(const rel_t type, const MetaName& name)
+static void checkRelationType(const rel_t type, const QualifiedName& name)
{
if (type == rel_persistent ||
type == rel_global_temp_preserve ||
@@ -610,8 +624,8 @@ static void checkRelationType(const rel_t type, const MetaName& name)
}
// Check, can a pair of relations be used in FK
-static void checkFkPairTypes(const rel_t masterType, const MetaName& masterName,
- const rel_t childType, const MetaName& childName)
+static void checkFkPairTypes(const rel_t masterType, const QualifiedName& masterName,
+ const rel_t childType, const QualifiedName& childName)
{
if (masterType != childType &&
!(masterType == rel_global_temp_preserve && childType == rel_global_temp_delete))
@@ -644,7 +658,7 @@ static void checkFkPairTypes(const rel_t masterType, const MetaName& masterName,
//
// if new_position == original_position -- no_op
static void modifyLocalFieldPosition(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName, USHORT newPosition)
+ const QualifiedName& relationName, const MetaName& fieldName, USHORT newPosition)
{
USHORT existingPosition = 0;
bool found = false;
@@ -657,7 +671,8 @@ static void modifyLocalFieldPosition(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$RELATION_FIELDS
- WITH FLD.RDB$RELATION_NAME EQ relationName.c_str()
+ WITH FLD.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ FLD.RDB$RELATION_NAME EQ relationName.object.c_str()
SORTED BY ASCENDING FLD.RDB$FIELD_POSITION
{
if (FLD.RDB$FIELD_POSITION != newPos)
@@ -680,7 +695,7 @@ static void modifyLocalFieldPosition(thread_db* tdbb, jrd_tra* transaction,
if (!found)
{
// msg 176: "column %s does not exist in table/view %s"
- status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName);
+ status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName.toQuotedString());
}
// Find the position of the last field in the relation.
@@ -699,9 +714,10 @@ static void modifyLocalFieldPosition(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$RELATION_FIELDS
- WITH FLD.RDB$RELATION_NAME EQ relationName.c_str() AND
- FLD.RDB$FIELD_POSITION >= MIN(newPosition, existingPosition) AND
- FLD.RDB$FIELD_POSITION <= MAX(newPosition, existingPosition)
+ WITH FLD.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ FLD.RDB$RELATION_NAME EQ relationName.object.c_str() AND
+ FLD.RDB$FIELD_POSITION >= MIN(newPosition, existingPosition) AND
+ FLD.RDB$FIELD_POSITION <= MAX(newPosition, existingPosition)
{
MODIFY FLD USING
// If the field is the one we want, change the position, otherwise
@@ -747,7 +763,7 @@ static void saveField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, const M
MemoryPool& p = relation->rel_flags & REL_new_relation ?
*tdbb->getDefaultPool() : dsqlScratch->getAttachment()->dbb_pool;
dsql_fld* field = FB_NEW_POOL(p) dsql_fld(p);
- field->fld_name = fieldName.c_str();
+ field->fld_name = fieldName;
field->fld_next = relation->rel_fields;
relation->rel_fields = field;
}
@@ -755,7 +771,7 @@ static void saveField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, const M
// Save the name of the relation or view currently being defined. This is done to support definition
// of triggers which will depend on the metadata created in this statement.
static void saveRelation(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- const MetaName& relationName, bool view, bool creating)
+ const QualifiedName& relationName, bool view, bool creating)
{
if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_METADATA_SAVED)
return;
@@ -874,8 +890,7 @@ static void updateRdbFields(const TypeClause* type,
// Delete a security class.
-bool DdlNode::deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& secClass)
+bool DdlNode::deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction, const MetaName& secClass)
{
AutoCacheRequest request(tdbb, drq_e_class, DYN_REQUESTS);
bool found = false;
@@ -893,7 +908,7 @@ bool DdlNode::deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction,
}
void DdlNode::storePrivileges(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name, int type,
+ const QualifiedName& name, int type,
const char* privileges)
{
Attachment* const attachment = transaction->tra_attachment;
@@ -906,7 +921,22 @@ void DdlNode::storePrivileges(thread_db* tdbb, jrd_tra* transaction,
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$USER_PRIVILEGES
{
- strcpy(X.RDB$RELATION_NAME, name.c_str());
+ if (name.schema.hasData())
+ {
+ strcpy(X.RDB$RELATION_SCHEMA_NAME, name.schema.c_str());
+ X.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ X.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
+
+ if (name.object.hasData())
+ {
+ strcpy(X.RDB$RELATION_NAME, name.object.c_str());
+ X.RDB$RELATION_NAME.NULL = FALSE;
+ }
+ else
+ X.RDB$RELATION_NAME.NULL = TRUE;
+
strcpy(X.RDB$USER, ownerName.c_str());
X.RDB$USER_TYPE = obj_user;
X.RDB$OBJECT_TYPE = type;
@@ -919,13 +949,14 @@ void DdlNode::storePrivileges(thread_db* tdbb, jrd_tra* transaction,
}
void DdlNode::deletePrivilegesByRelName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name, int type)
+ const QualifiedName& name, int type)
{
AutoCacheRequest request(tdbb, drq_e_usr_prvs, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH PRIV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(name.schema.c_str(), '') AND
+ PRIV.RDB$RELATION_NAME EQ name.object.c_str() AND
PRIV.RDB$OBJECT_TYPE = type AND
PRIV.RDB$GRANTOR NOT MISSING
{
@@ -935,7 +966,7 @@ void DdlNode::deletePrivilegesByRelName(thread_db* tdbb, jrd_tra* transaction,
}
void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction, DdlTriggerWhen when,
- int action, const MetaName& objectName, const MetaName& oldNewObjectName, const string& sqlText)
+ int action, const QualifiedName& objectName, const QualifiedName& oldNewObjectName, const string& sqlText)
{
Attachment* const attachment = transaction->tra_attachment;
@@ -950,7 +981,7 @@ void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction, DdlTrigge
context.objectName = objectName;
context.sqlText = sqlText;
- if (oldNewObjectName.hasData())
+ if (oldNewObjectName.object.hasData())
{
context.oldObjectName = when == DTW_BEFORE ? objectName : oldNewObjectName;
context.newObjectName = when == DTW_BEFORE ? oldNewObjectName : objectName;
@@ -965,14 +996,14 @@ void DdlNode::executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction, DdlTrigge
}
void DdlNode::executeDdlTrigger(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction, DdlTriggerWhen when, int action, const MetaName& objectName,
- const MetaName& oldNewObjectName)
+ jrd_tra* transaction, DdlTriggerWhen when, int action, const QualifiedName& objectName,
+ const QualifiedName& oldNewObjectName)
{
executeDdlTrigger(tdbb, transaction, when, action, objectName, oldNewObjectName,
*dsqlScratch->getDsqlStatement()->getSqlText());
}
-void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
+void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, QualifiedName& name,
const TypeClause* field, const string& computedSource, const BlrDebugWriter::BlrData& computedValue)
{
Attachment* const attachment = transaction->tra_attachment;
@@ -988,7 +1019,7 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName&
Arg::Gds(isc_dsql_max_arr_dim_exceeded));
}
- if (name.isEmpty())
+ if (name.object.isEmpty())
DYN_UTIL_generate_field_name(tdbb, name);
AutoCacheRequest requestHandle(tdbb, drq_s_fld_src, DYN_REQUESTS);
@@ -997,7 +1028,8 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName&
FLD IN RDB$FIELDS
{
FLD.RDB$SYSTEM_FLAG = 0;
- strcpy(FLD.RDB$FIELD_NAME, name.c_str());
+ strcpy(FLD.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(FLD.RDB$FIELD_NAME, name.object.c_str());
FLD.RDB$OWNER_NAME.NULL = FALSE;
strcpy(FLD.RDB$OWNER_NAME, ownerName.c_str());
@@ -1064,7 +1096,8 @@ void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName&
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
DIM IN RDB$FIELD_DIMENSIONS
{
- strcpy(DIM.RDB$FIELD_NAME, name.c_str());
+ strcpy(DIM.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(DIM.RDB$FIELD_NAME, name.object.c_str());
DIM.RDB$DIMENSION = position;
DIM.RDB$UPPER_BOUND = hrange;
DIM.RDB$LOWER_BOUND = lrange;
@@ -1132,19 +1165,20 @@ void AlterCharSetNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR (REQUEST_HANDLE requestHandle1 TRANSACTION_HANDLE transaction)
CS IN RDB$CHARACTER_SETS
- WITH CS.RDB$CHARACTER_SET_NAME EQ charSet.c_str()
+ WITH CS.RDB$SCHEMA_NAME EQ charSet.schema.c_str() AND
+ CS.RDB$CHARACTER_SET_NAME EQ charSet.object.c_str()
{
charSetFound = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_CHARACTER_SET, charSet, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_CHARACTER_SET, charSet, {});
AutoCacheRequest requestHandle2(tdbb, drq_l_collation, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction)
COLL IN RDB$COLLATIONS
WITH COLL.RDB$CHARACTER_SET_ID EQ CS.RDB$CHARACTER_SET_ID AND
- COLL.RDB$COLLATION_NAME EQ defaultCollation.c_str()
+ COLL.RDB$SCHEMA_NAME EQ defaultCollation.schema.c_str() AND
+ COLL.RDB$COLLATION_NAME EQ defaultCollation.object.c_str()
{
collationFound = true;
}
@@ -1153,24 +1187,26 @@ void AlterCharSetNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
if (collationFound)
{
MODIFY CS
+ CS.RDB$DEFAULT_COLLATE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(CS.RDB$DEFAULT_COLLATE_SCHEMA_NAME, defaultCollation.schema.c_str());
+
CS.RDB$DEFAULT_COLLATE_NAME.NULL = FALSE;
- strcpy(CS.RDB$DEFAULT_COLLATE_NAME, defaultCollation.c_str());
+ strcpy(CS.RDB$DEFAULT_COLLATE_NAME, defaultCollation.object.c_str());
END_MODIFY
}
}
END_FOR
if (!charSetFound)
- status_exception::raise(Arg::Gds(isc_charset_not_found) << Arg::Str(charSet));
+ status_exception::raise(Arg::Gds(isc_charset_not_found) << charSet.toQuotedString());
if (!collationFound)
{
status_exception::raise(
- Arg::Gds(isc_collation_not_found) << Arg::Str(defaultCollation) << Arg::Str(charSet));
+ Arg::Gds(isc_collation_not_found) << defaultCollation.toQuotedString() << charSet.toQuotedString());
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_ALTER_CHARACTER_SET, charSet, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_CHARACTER_SET, charSet, {});
}
@@ -1270,7 +1306,7 @@ string CommentOnNode::internalPrint(NodePrinter& printer) const
DdlNode::internalPrint(printer);
NODE_PRINT(printer, objType);
- NODE_PRINT(printer, objName);
+ NODE_PRINT(printer, name);
NODE_PRINT(printer, subName);
NODE_PRINT(printer, text);
NODE_PRINT(printer, str);
@@ -1278,24 +1314,28 @@ string CommentOnNode::internalPrint(NodePrinter& printer) const
return "CommentOnNode";
}
-void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+DdlNode* CommentOnNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
- Attachment* const attachment = transaction->tra_attachment;
-
- Arg::StatusVector status;
- string objNameStr = objName.toString();
+ thread_db* tdbb = JRD_get_thread_data();
+ const auto transaction = dsqlScratch->getTransaction();
if (objType == obj_parameter)
{
fb_assert(subName.hasData());
- AutoRequest requestHandle;
+ auto nameCopy = name;
+ dsqlScratch->qualifyExistingName(nameCopy, obj_udf);
+
+ static const CachedRequestId funcCachedHandleId;
+ AutoCacheRequest requestHandle(tdbb, funcCachedHandleId);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS CROSS
ARG IN RDB$FUNCTION_ARGUMENTS
- WITH FUN.RDB$FUNCTION_NAME EQ objName.identifier.c_str() AND
- FUN.RDB$PACKAGE_NAME EQUIV NULLIF(objName.package.c_str(), '') AND
+ WITH FUN.RDB$SCHEMA_NAME EQ nameCopy.schema.c_str() AND
+ FUN.RDB$FUNCTION_NAME EQ nameCopy.object.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQUIV NULLIF(nameCopy.package.c_str(), '') AND
+ ARG.RDB$SCHEMA_NAME EQ FUN.RDB$SCHEMA_NAME AND
ARG.RDB$FUNCTION_NAME EQ FUN.RDB$FUNCTION_NAME AND
ARG.RDB$PACKAGE_NAME EQUIV FUN.RDB$PACKAGE_NAME AND
ARG.RDB$ARGUMENT_NAME EQ subName.c_str()
@@ -1304,13 +1344,19 @@ void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
}
END_FOR
- requestHandle.reset();
+ nameCopy = name;
+ dsqlScratch->qualifyExistingName(nameCopy, obj_procedure);
+
+ static const CachedRequestId procCachedHandleId;
+ requestHandle.reset(tdbb, procCachedHandleId);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRC IN RDB$PROCEDURES CROSS
PRM IN RDB$PROCEDURE_PARAMETERS
- WITH PRC.RDB$PROCEDURE_NAME EQ objName.identifier.c_str() AND
- PRC.RDB$PACKAGE_NAME EQUIV NULLIF(objName.package.c_str(), '') AND
+ WITH PRC.RDB$SCHEMA_NAME EQ nameCopy.schema.c_str() AND
+ PRC.RDB$PROCEDURE_NAME EQ nameCopy.object.c_str() AND
+ PRC.RDB$PACKAGE_NAME EQUIV NULLIF(nameCopy.package.c_str(), '') AND
+ PRM.RDB$SCHEMA_NAME EQ PRC.RDB$SCHEMA_NAME AND
PRM.RDB$PROCEDURE_NAME EQ PRC.RDB$PROCEDURE_NAME AND
PRM.RDB$PACKAGE_NAME EQUIV PRC.RDB$PACKAGE_NAME AND
PRM.RDB$PARAMETER_NAME EQ subName.c_str()
@@ -1320,7 +1366,7 @@ void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
else
{
status_exception::raise(Arg::Gds(isc_dyn_routine_param_ambiguous) <<
- Arg::Str(subName) << Arg::Str(objNameStr));
+ Arg::Str(subName) << name.toQuotedString());
}
}
END_FOR
@@ -1328,88 +1374,115 @@ void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
if (objType == obj_parameter)
{
status_exception::raise(Arg::Gds(isc_dyn_routine_param_not_found) <<
- Arg::Str(subName) << Arg::Str(objNameStr));
+ Arg::Str(subName) << name.toQuotedString());
}
+ else
+ name = nameCopy;
}
- dsc dscName;
- MetaName relationName;
+ dsqlScratch->ddlSchema = name.schema;
switch (objType)
{
case obj_database:
+ case obj_schema:
+ case obj_blob_filter:
+ case obj_sql_role:
+ fb_assert(name.schema.isEmpty());
+ break;
+
+ default:
+ dsqlScratch->qualifyExistingName(name, objType);
+ break;
+ }
+
+ return DdlNode::dsqlPass(dsqlScratch);
+}
+
+void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ Attachment* const attachment = transaction->tra_attachment;
+
+ Arg::StatusVector status;
+
+ switch (objType)
+ {
+ case obj_database:
+ fb_assert(name.schema.isEmpty());
SCL_check_database(tdbb, SCL_alter);
break;
+ case obj_schema:
+ fb_assert(name.schema.isEmpty());
+ SCL_check_schema(tdbb, name.object, SCL_alter);
+ break;
+
case obj_field:
- SCL_check_domain(tdbb, objName.identifier, SCL_alter);
+ SCL_check_domain(tdbb, name, SCL_alter);
break;
case obj_relation:
- dscName.makeText(objNameStr.length(), CS_METADATA, (UCHAR*) objName.identifier.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter);
+ SCL_check_relation(tdbb, name, SCL_alter);
break;
case obj_view:
- dscName.makeText(objNameStr.length(), CS_METADATA, (UCHAR*) objName.identifier.c_str());
- SCL_check_view(tdbb, &dscName, SCL_alter);
+ SCL_check_view(tdbb, name, SCL_alter);
break;
case obj_procedure:
- dscName.makeText(objNameStr.length(), CS_METADATA, (UCHAR*) objName.identifier.c_str());
- SCL_check_procedure(tdbb, &dscName, SCL_alter);
+ SCL_check_procedure(tdbb, name, SCL_alter);
break;
case obj_trigger:
- relationName = getTriggerRelationName(tdbb, transaction, objName.identifier);
- if (relationName.isEmpty())
+ {
+ const auto relationName = getTriggerRelationName(tdbb, transaction, name);
+ if (relationName.object.isEmpty())
SCL_check_database(tdbb, SCL_alter);
else
- {
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter);
- }
+ SCL_check_relation(tdbb, relationName, SCL_alter);
break;
+ }
case obj_udf:
- dscName.makeText(objName.identifier.length(), CS_METADATA, (UCHAR*) objName.identifier.c_str());
- SCL_check_function(tdbb, &dscName, SCL_alter);
+ SCL_check_function(tdbb, name, SCL_alter);
break;
case obj_blob_filter:
- SCL_check_filter(tdbb, objName.identifier, SCL_alter);
+ fb_assert(name.schema.isEmpty());
+ SCL_check_filter(tdbb, name.object, SCL_alter);
break;
case obj_exception:
- SCL_check_exception(tdbb, objName.identifier, SCL_alter);
+ SCL_check_exception(tdbb, name, SCL_alter);
break;
case obj_generator:
- SCL_check_generator(tdbb, objName.identifier, SCL_alter);
+ SCL_check_generator(tdbb, name, SCL_alter);
break;
case obj_index:
+ {
bool systemIndex;
- relationName = getIndexRelationName(tdbb, transaction, objName.identifier, systemIndex);
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
+ const auto relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
+ SCL_check_relation(tdbb, relationName, SCL_alter, systemIndex);
break;
+ }
case obj_sql_role:
- SCL_check_role(tdbb, objName.identifier, SCL_alter);
+ fb_assert(name.schema.isEmpty());
+ SCL_check_role(tdbb, name.object, SCL_alter);
break;
case obj_charset:
- SCL_check_charset(tdbb, objName.identifier, SCL_alter);
+ SCL_check_charset(tdbb, name, SCL_alter);
break;
case obj_collation:
- SCL_check_collation(tdbb, objName.identifier, SCL_alter);
+ SCL_check_collation(tdbb, name, SCL_alter);
break;
case obj_package_header:
- dscName.makeText(objName.identifier.length(), CS_METADATA, (UCHAR*) objName.identifier.c_str());
- SCL_check_package(tdbb, &dscName, SCL_alter);
+ SCL_check_package(tdbb, name, SCL_alter);
break;
default:
@@ -1426,12 +1499,13 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
{
Attachment* const attachment = transaction->tra_attachment;
- const char* tableClause = NULL;
- const char* columnClause = NULL;
- const char* subColumnClause = NULL;
- const char* addWhereClause = NULL;
+ const char* tableClause = nullptr;
+ const char* columnClause = nullptr;
+ const char* subColumnClause = nullptr;
+ const char* addWhereClause = nullptr;
+ bool useSchemaClause = true;
Arg::StatusVector status;
- string objNameStr = objName.toString();
+ const string objNameStr = name.toQuotedString();
fb_assert(objType != obj_parameter);
@@ -1439,6 +1513,14 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
{
case obj_database:
tableClause = "rdb$database";
+ useSchemaClause = false;
+ break;
+
+ case obj_schema:
+ tableClause = "rdb$schemas";
+ columnClause = "rdb$schema_name";
+ useSchemaClause = false;
+ status << Arg::Gds(isc_dyn_schema_not_found) << Arg::Str(objNameStr);
break;
case obj_field:
@@ -1538,6 +1620,7 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
case obj_sql_role:
tableClause = "rdb$roles";
columnClause = "rdb$role_name";
+ useSchemaClause = false;
status << Arg::Gds(isc_dyn_role_not_found) << Arg::Str(objNameStr);
break;
@@ -1569,18 +1652,21 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
description = text;
PreparedStatement::Builder sql;
- sql << "update" << tableClause << "set rdb$description =" << description << "where 1 = 1";
+ sql << "update system." << tableClause << "set rdb$description =" << description << "where 1 = 1";
+
+ if (useSchemaClause)
+ sql << "and rdb$schema_name = " << name.schema;
if (columnClause)
{
- sql << "and" << columnClause << "=" << objName.identifier;
+ sql << "and" << columnClause << "=" << name.object;
if (subColumnClause)
sql << "and" << subColumnClause << "=" << subName;
}
if (objType == obj_procedure || objType == obj_udf)
- sql << "and rdb$package_name is not distinct from nullif(" << objName.package << ", '')";
+ sql << "and rdb$package_name is not distinct from nullif(" << name.package << ", '')";
if (addWhereClause)
sql << "and" << addWhereClause;
@@ -1611,7 +1697,6 @@ string CreateAlterFunctionNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, body);
NODE_PRINT(printer, compiled);
NODE_PRINT(printer, invalid);
- NODE_PRINT(printer, package);
NODE_PRINT(printer, packageOwner);
NODE_PRINT(printer, privateScope);
NODE_PRINT(printer, udfReturnPos);
@@ -1621,6 +1706,14 @@ string CreateAlterFunctionNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_udf);
+
+ protectSystemSchema(name.schema, obj_udf);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_FUNCTION);
dsqlScratch->reserveInitialVarNumbers(1);
@@ -1656,7 +1749,7 @@ DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
returnType->type->resolve(dsqlScratch);
// check SQL SECURITY is not set if function declared in package
- if (package.hasData() && ssDefiner.has_value())
+ if (name.package.hasData() && ssDefiner.has_value())
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_invalid_clause) << Arg::Str("SQL SECURITY for functions is prohibit in packages"));
@@ -1667,19 +1760,16 @@ DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void CreateAlterFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (alter)
{
- if (SCL_check_function(tdbb, &dscName, SCL_alter) || !create)
+ if (SCL_check_function(tdbb, name, SCL_alter) || !create)
return;
}
- SCL_check_create_access(tdbb, obj_functions);
+ SCL_check_create_access(tdbb, obj_functions, name.schema);
}
-void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
fb_assert(create || alter);
@@ -1695,20 +1785,18 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql
if (executeAlterIndividualParameters(tdbb, dsqlScratch, transaction, false, true))
altered = true;
else
- status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << name.toQuotedString());
}
else if (alter)
{
if (executeAlter(tdbb, dsqlScratch, transaction, false, true))
- {
altered = true;
- }
else
{
if (create) // create or alter
executeCreate(tdbb, dsqlScratch, transaction);
else
- status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << name.toQuotedString());
}
}
else if (!executeCreate(tdbb, dsqlScratch, transaction))
@@ -1722,10 +1810,10 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql
else
executeAlter(tdbb, dsqlScratch, transaction, true, false);
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- (altered ? DDL_TRIGGER_ALTER_FUNCTION : DDL_TRIGGER_CREATE_FUNCTION), name, NULL);
+ (altered ? DDL_TRIGGER_ALTER_FUNCTION : DDL_TRIGGER_CREATE_FUNCTION), name, {});
}
savePoint.release(); // everything is ok
@@ -1733,24 +1821,23 @@ void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql
if (alter)
{
// Update DSQL cache
- METD_drop_function(transaction, QualifiedName(name, package));
- MET_dsql_cache_release(tdbb, SYM_udf, name, package);
+ METD_drop_function(transaction, name);
+ MET_dsql_cache_release(tdbb, SYM_udf, name);
}
}
-bool CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+bool CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
Attachment* const attachment = transaction->getAttachment();
const MetaString& ownerName = attachment->getEffectiveUserName();
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_udf))
return false;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_FUNCTION, name, NULL);
+ DDL_TRIGGER_CREATE_FUNCTION, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_udf);
}
@@ -1774,12 +1861,13 @@ bool CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
{
FUN.RDB$FUNCTION_ID = id;
FUN.RDB$SYSTEM_FLAG = 0;
- strcpy(FUN.RDB$FUNCTION_NAME, name.c_str());
+ strcpy(FUN.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(FUN.RDB$FUNCTION_NAME, name.object.c_str());
- if (package.hasData())
+ if (name.package.hasData())
{
FUN.RDB$PACKAGE_NAME.NULL = FALSE;
- strcpy(FUN.RDB$PACKAGE_NAME, package.c_str());
+ strcpy(FUN.RDB$PACKAGE_NAME, name.package.c_str());
FUN.RDB$PRIVATE_FLAG.NULL = FALSE;
FUN.RDB$PRIVATE_FLAG = privateScope;
@@ -1818,7 +1906,7 @@ bool CreateAlterFunctionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
}
}
- if (package.isEmpty())
+ if (name.package.isEmpty())
storePrivileges(tdbb, transaction, name, obj_udf, EXEC_PRIVILEGES);
executeAlter(tdbb, dsqlScratch, transaction, false, false);
@@ -1838,20 +1926,19 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$FUNCTION_NAME EQ name.c_str() AND
- FUN.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH FUN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FUN.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (FUN.RDB$SYSTEM_FLAG)
{
status_exception::raise(
- Arg::Gds(isc_dyn_cannot_mod_sysfunc) << MetaName(FUN.RDB$FUNCTION_NAME));
+ Arg::Gds(isc_dyn_cannot_mod_sysfunc) <<
+ name.toQuotedString());
}
- if (!secondPass && runTriggers && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_FUNCTION, name, NULL);
- }
+ if (!secondPass && runTriggers && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_FUNCTION, name, {});
MODIFY FUN
if (secondPass)
@@ -1866,7 +1953,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
FUN.RDB$ENTRYPOINT.NULL = TRUE;
FUN.RDB$VALID_BLR.NULL = TRUE;
- FUN.RDB$FUNCTION_SOURCE.NULL = !(source.hasData() && (external || package.isEmpty()));
+ FUN.RDB$FUNCTION_SOURCE.NULL = !(source.hasData() && (external || name.package.isEmpty()));
if (!FUN.RDB$FUNCTION_SOURCE.NULL)
attachment->storeMetaDataBlob(tdbb, transaction, &FUN.RDB$FUNCTION_SOURCE, source);
@@ -1998,7 +2085,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
}
}
- if (package.hasData())
+ if (name.package.hasData())
{
FUN.RDB$PRIVATE_FLAG.NULL = FALSE;
FUN.RDB$PRIVATE_FLAG = privateScope;
@@ -2018,7 +2105,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
collectParameters(tdbb, transaction, collectedParameters);
// delete all old arguments
- DropFunctionNode::dropArguments(tdbb, transaction, name, package);
+ DropFunctionNode::dropArguments(tdbb, transaction, name);
// and insert the new ones
@@ -2041,7 +2128,8 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
return modified;
}
-bool CreateAlterFunctionNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, bool secondPass, bool runTriggers)
+bool CreateAlterFunctionNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
+ jrd_tra* transaction, bool secondPass, bool runTriggers)
{
Attachment* const attachment = transaction->getAttachment();
@@ -2051,20 +2139,19 @@ bool CreateAlterFunctionNode::executeAlterIndividualParameters(thread_db* tdbb,
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$FUNCTION_NAME EQ name.c_str() AND
- FUN.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH FUN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FUN.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (FUN.RDB$SYSTEM_FLAG)
{
status_exception::raise(
- Arg::Gds(isc_dyn_cannot_mod_sysfunc) << MetaName(FUN.RDB$FUNCTION_NAME));
+ Arg::Gds(isc_dyn_cannot_mod_sysfunc) <<
+ name.toQuotedString());
}
- if (!secondPass && runTriggers && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_FUNCTION, name, NULL);
- }
+ if (!secondPass && runTriggers && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_FUNCTION, name, {});
MODIFY FUN
if (deterministic.isAssigned())
@@ -2103,14 +2190,14 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
ARG IN RDB$FUNCTION_ARGUMENTS
{
- ARG.RDB$FUNCTION_NAME.NULL = FALSE;
- strcpy(ARG.RDB$FUNCTION_NAME, name.c_str());
+ strcpy(ARG.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(ARG.RDB$FUNCTION_NAME, name.object.c_str());
ARG.RDB$ARGUMENT_NAME.NULL = (SSHORT) parameter->name.isEmpty();
strcpy(ARG.RDB$ARGUMENT_NAME, parameter->name.c_str());
- ARG.RDB$PACKAGE_NAME.NULL = (SSHORT) package.isEmpty();
- strcpy(ARG.RDB$PACKAGE_NAME, package.c_str());
+ ARG.RDB$PACKAGE_NAME.NULL = (SSHORT) name.package.isEmpty();
+ strcpy(ARG.RDB$PACKAGE_NAME, name.package.c_str());
ARG.RDB$SYSTEM_FLAG = 0;
ARG.RDB$SYSTEM_FLAG.NULL = FALSE;
@@ -2119,8 +2206,10 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
ARG.RDB$ARGUMENT_POSITION = pos;
ARG.RDB$NULL_FLAG.NULL = TRUE;
+ ARG.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
ARG.RDB$RELATION_NAME.NULL = TRUE;
ARG.RDB$FIELD_NAME.NULL = TRUE;
+ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = TRUE;
ARG.RDB$FIELD_SOURCE.NULL = TRUE;
ARG.RDB$DEFAULT_VALUE.NULL = TRUE;
ARG.RDB$DEFAULT_SOURCE.NULL = TRUE;
@@ -2139,7 +2228,7 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
if (!isUdf())
{
ARG.RDB$ARGUMENT_MECHANISM.NULL = FALSE;
- ARG.RDB$ARGUMENT_MECHANISM = (USHORT) (type->fullDomain || type->typeOfName.isEmpty() ?
+ ARG.RDB$ARGUMENT_MECHANISM = (USHORT) (type->fullDomain || type->typeOfName.object.isEmpty() ?
prm_mech_normal : prm_mech_type_of);
}
@@ -2149,12 +2238,15 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
ARG.RDB$NULL_FLAG = TRUE;
}
- if (type->typeOfTable.isEmpty())
+ if (type->typeOfTable.object.isEmpty())
{
- if (type->typeOfName.hasData())
+ if (type->typeOfName.object.hasData())
{
+ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(ARG.RDB$FIELD_SOURCE_SCHEMA_NAME, type->typeOfName.schema.c_str());
+
ARG.RDB$FIELD_SOURCE.NULL = FALSE;
- strcpy(ARG.RDB$FIELD_SOURCE, type->typeOfName.c_str());
+ strcpy(ARG.RDB$FIELD_SOURCE, type->typeOfName.object.c_str());
}
else
{
@@ -2177,30 +2269,39 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
}
else
{
- MetaName fieldName;
+ QualifiedName fieldName({}, name.schema);
storeGlobalField(tdbb, transaction, fieldName, type);
+ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(ARG.RDB$FIELD_SOURCE_SCHEMA_NAME, fieldName.schema.c_str());
+
ARG.RDB$FIELD_SOURCE.NULL = FALSE;
- strcpy(ARG.RDB$FIELD_SOURCE, fieldName.c_str());
+ strcpy(ARG.RDB$FIELD_SOURCE, fieldName.object.c_str());
}
}
}
else
{
+ ARG.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ strcpy(ARG.RDB$RELATION_SCHEMA_NAME, type->typeOfTable.schema.c_str());
+
ARG.RDB$RELATION_NAME.NULL = FALSE;
- strcpy(ARG.RDB$RELATION_NAME, type->typeOfTable.c_str());
+ strcpy(ARG.RDB$RELATION_NAME, type->typeOfTable.object.c_str());
ARG.RDB$FIELD_NAME.NULL = FALSE;
- strcpy(ARG.RDB$FIELD_NAME, type->typeOfName.c_str());
+ strcpy(ARG.RDB$FIELD_NAME, type->typeOfName.object.c_str());
+
+ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(ARG.RDB$FIELD_SOURCE_SCHEMA_NAME, type->fieldSource.schema.c_str());
ARG.RDB$FIELD_SOURCE.NULL = FALSE;
- strcpy(ARG.RDB$FIELD_SOURCE, type->fieldSource.c_str());
+ strcpy(ARG.RDB$FIELD_SOURCE, type->fieldSource.object.c_str());
}
// ASF: If we used a collate with a domain or table.column type, write it
// into RDB$FUNCTION_ARGUMENTS.
- if (type->collate.hasData() && type->typeOfName.hasData())
+ if (type->collate.object.hasData() && type->typeOfName.object.hasData())
{
ARG.RDB$COLLATION_ID.NULL = FALSE;
ARG.RDB$COLLATION_ID = type->collationId;
@@ -2216,8 +2317,8 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
{
status_exception::raise(
Arg::Gds(isc_dyn_defvaldecl_package_func) <<
- package.c_str() <<
- name.c_str());
+ name.getSchemaAndPackage().toQuotedString() <<
+ name.object);
}
ARG.RDB$DEFAULT_VALUE.NULL = FALSE;
@@ -2282,7 +2383,7 @@ void CreateAlterFunctionNode::storeArgument(thread_db* tdbb, DsqlCompilerScratch
void CreateAlterFunctionNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlScratch)
{
if (invalid)
- status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_func) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_func) << name.toQuotedString());
if (compiled)
return;
@@ -2332,7 +2433,7 @@ void CreateAlterFunctionNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
}
dsql_var* const variable = dsqlScratch->outputVariables[0];
- dsqlScratch->putLocalVariable(variable, nullptr, {});
+ dsqlScratch->putLocalVariable(variable);
// ASF: This is here to not change the old logic (proc_flag)
// of previous calls to PASS1_node and PASS1_statement.
@@ -2376,8 +2477,9 @@ void CreateAlterFunctionNode::collectParameters(thread_db* tdbb, jrd_tra* transa
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
ARG IN RDB$FUNCTION_ARGUMENTS
- WITH ARG.RDB$FUNCTION_NAME EQ name.c_str() AND
- ARG.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH ARG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ ARG.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ ARG.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
CollectedParameter parameter;
parameter.comment = ARG.RDB$DESCRIPTION;
@@ -2404,9 +2506,7 @@ string AlterExternalFunctionNode::internalPrint(NodePrinter& printer) const
void AlterExternalFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_function(tdbb, &dscName, SCL_alter);
+ SCL_check_function(tdbb, name, SCL_alter);
}
// Allow changing the entry point and/or the module name of a UDF.
@@ -2430,16 +2530,17 @@ void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* ds
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$FUNCTION_NAME EQ name.c_str() AND
+ WITH FUN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FUN.RDB$FUNCTION_NAME EQ name.object.c_str() AND
FUN.RDB$PACKAGE_NAME MISSING
{
found = true;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_FUNCTION,
- name, NULL);
+ name, {});
if (!FUN.RDB$ENGINE_NAME.NULL || !FUN.RDB$FUNCTION_BLR.NULL)
- status_exception::raise(Arg::Gds(isc_dyn_newfc_oldsyntax) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_newfc_oldsyntax) << name.toQuotedString());
MODIFY FUN
if (clauses.name.hasData())
@@ -2464,36 +2565,33 @@ void AlterExternalFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* ds
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_FUNCTION,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_FUNCTION, name, {});
else
{
// msg 41: "Function %s not found"
- status_exception::raise(Arg::PrivateDyn(41) << name);
+ status_exception::raise(Arg::PrivateDyn(41) << name.toQuotedString());
}
savePoint.release(); // everything is ok
// Update DSQL cache
- METD_drop_function(transaction, QualifiedName(name, ""));
- MET_dsql_cache_release(tdbb, SYM_udf, name, "");
+ METD_drop_function(transaction, name);
+ MET_dsql_cache_release(tdbb, SYM_udf, name);
}
//----------------------
-void DropFunctionNode::dropArguments(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& functionName, const MetaName& packageName)
+void DropFunctionNode::dropArguments(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& functionName)
{
AutoCacheRequest requestHandle(tdbb, drq_e_func_args, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
ARG IN RDB$FUNCTION_ARGUMENTS
- WITH ARG.RDB$FUNCTION_NAME EQ functionName.c_str() AND
- ARG.RDB$PACKAGE_NAME EQUIV NULLIF(packageName.c_str(), '')
+ WITH ARG.RDB$SCHEMA_NAME EQ functionName.schema.c_str() AND
+ ARG.RDB$FUNCTION_NAME EQ functionName.object.c_str() AND
+ ARG.RDB$PACKAGE_NAME EQUIV NULLIF(functionName.package.c_str(), '')
{
// get rid of arguments in rdb$fields
if (!ARG.RDB$FIELD_SOURCE.NULL && ARG.RDB$RELATION_NAME.NULL && ARG.RDB$FIELD_NAME.NULL)
@@ -2502,7 +2600,8 @@ void DropFunctionNode::dropArguments(thread_db* tdbb, jrd_tra* transaction,
FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE AND
+ WITH FLD.RDB$SCHEMA_NAME EQ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ FLD.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE AND
FLD.RDB$FIELD_NAME STARTING WITH IMPLICIT_DOMAIN_PREFIX AND
FLD.RDB$SYSTEM_FLAG EQ 0
{
@@ -2511,7 +2610,8 @@ void DropFunctionNode::dropArguments(thread_db* tdbb, jrd_tra* transaction,
if (!FLD.RDB$SECURITY_CLASS.NULL)
deleteSecurityClass(tdbb, transaction, FLD.RDB$SECURITY_CLASS);
- deletePrivilegesByRelName(tdbb, transaction, FLD.RDB$FIELD_NAME, obj_field);
+ deletePrivilegesByRelName(tdbb, transaction,
+ QualifiedName(FLD.RDB$FIELD_NAME, FLD.RDB$SCHEMA_NAME), obj_field);
}
END_FOR
}
@@ -2527,52 +2627,55 @@ string DropFunctionNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, name);
NODE_PRINT(printer, silent);
- NODE_PRINT(printer, package);
return "DropFunctionNode";
}
DdlNode* DropFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_exception);
+
+ protectSystemSchema(name.schema, obj_udf);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_FUNCTION);
+
return DdlNode::dsqlPass(dsqlScratch);
}
void DropFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_function(tdbb, &dscName, SCL_drop);
+ SCL_check_function(tdbb, name, SCL_drop);
}
-void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
bool found = false;
- dropArguments(tdbb, transaction, name, package);
+ dropArguments(tdbb, transaction, name);
AutoCacheRequest requestHandle(tdbb, drq_e_funcs, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$FUNCTION_NAME EQ name.c_str() AND
- FUN.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH FUN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FUN.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (FUN.RDB$SYSTEM_FLAG)
{
status_exception::raise(
Arg::Gds(isc_dyn_cannot_mod_sysfunc) <<
- MetaName(FUN.RDB$FUNCTION_NAME));
+ name.toQuotedString());
}
- if (package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_FUNCTION,
- name, NULL);
- }
+ if (name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_FUNCTION, name, {});
ERASE FUN;
@@ -2584,35 +2687,34 @@ void DropFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
END_FOR
if (!found && !silent)
- status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_func_not_found) << name.toQuotedString());
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
deletePrivilegesByRelName(tdbb, transaction, name, obj_udf);
requestHandle.reset(tdbb, drq_e_fun_prv, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
- PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$USER EQ name.c_str()
- AND PRIV.RDB$USER_TYPE = obj_udf
- AND PRIV.RDB$GRANTOR NOT MISSING
+ PRIV IN RDB$USER_PRIVILEGES
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$USER EQ name.object.c_str() AND
+ PRIV.RDB$USER_TYPE = obj_udf AND
+ PRIV.RDB$GRANTOR NOT MISSING
{
ERASE PRIV;
}
END_FOR
}
- if (found && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_FUNCTION,
- name, NULL);
- }
+ if (found && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_FUNCTION, name, {});
savePoint.release(); // everything is ok
// Update DSQL cache
- METD_drop_function(transaction, QualifiedName(name, package));
- MET_dsql_cache_release(tdbb, SYM_udf, name, package);
+ METD_drop_function(transaction, name);
+ MET_dsql_cache_release(tdbb, SYM_udf, name);
}
@@ -2634,7 +2736,6 @@ string CreateAlterProcedureNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, body);
NODE_PRINT(printer, compiled);
NODE_PRINT(printer, invalid);
- NODE_PRINT(printer, package);
NODE_PRINT(printer, packageOwner);
NODE_PRINT(printer, privateScope);
@@ -2643,6 +2744,14 @@ string CreateAlterProcedureNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_procedure);
+
+ protectSystemSchema(name.schema, obj_procedure);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_PROCEDURE);
dsqlScratch->reserveInitialVarNumbers(returns.getCount());
@@ -2678,7 +2787,7 @@ DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
returns[i]->type->resolve(dsqlScratch);
// check SQL SECURITY is not set if procedure declared in package
- if (package.hasData() && ssDefiner.has_value())
+ if (name.package.hasData() && ssDefiner.has_value())
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_invalid_clause) << Arg::Str("SQL SECURITY for procedures is prohibit in packages"));
@@ -2689,19 +2798,16 @@ DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void CreateAlterProcedureNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (alter)
{
- if (SCL_check_procedure(tdbb, &dscName, SCL_alter) || !create)
+ if (SCL_check_procedure(tdbb, name, SCL_alter) || !create)
return;
}
- SCL_check_create_access(tdbb, obj_procedures);
+ SCL_check_create_access(tdbb, obj_procedures, name.schema);
}
-void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
fb_assert(create || alter);
@@ -2717,7 +2823,7 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
if (executeAlterIndividualParameters(tdbb, dsqlScratch, transaction, false, true))
altered = true;
else
- status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << name.toQuotedString());
}
else if (alter)
{
@@ -2728,7 +2834,7 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
if (create) // create or alter
executeCreate(tdbb, dsqlScratch, transaction);
else
- status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << name.toQuotedString());
}
}
else if (!executeCreate(tdbb, dsqlScratch, transaction))
@@ -2742,10 +2848,10 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
else
executeAlter(tdbb, dsqlScratch, transaction, true, false);
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- (altered ? DDL_TRIGGER_ALTER_PROCEDURE : DDL_TRIGGER_CREATE_PROCEDURE), name, NULL);
+ (altered ? DDL_TRIGGER_ALTER_PROCEDURE : DDL_TRIGGER_CREATE_PROCEDURE), name, {});
}
savePoint.release(); // everything is ok
@@ -2753,8 +2859,8 @@ void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
if (alter)
{
// Update DSQL cache
- METD_drop_procedure(transaction, QualifiedName(name, package));
- MET_dsql_cache_release(tdbb, SYM_procedure, name, package);
+ METD_drop_procedure(transaction, name);
+ MET_dsql_cache_release(tdbb, SYM_procedure, name);
}
}
@@ -2764,13 +2870,12 @@ bool CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
Attachment* const attachment = transaction->getAttachment();
const MetaString& ownerName = attachment->getEffectiveUserName();
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_procedure))
return false;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_PROCEDURE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_PROCEDURE, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_procedure);
}
@@ -2794,12 +2899,13 @@ bool CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
{
P.RDB$PROCEDURE_ID = id;
P.RDB$SYSTEM_FLAG = 0;
- strcpy(P.RDB$PROCEDURE_NAME, name.c_str());
+ strcpy(P.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(P.RDB$PROCEDURE_NAME, name.object.c_str());
- if (package.hasData())
+ if (name.package.hasData())
{
P.RDB$PACKAGE_NAME.NULL = FALSE;
- strcpy(P.RDB$PACKAGE_NAME, package.c_str());
+ strcpy(P.RDB$PACKAGE_NAME, name.package.c_str());
P.RDB$PRIVATE_FLAG.NULL = FALSE;
P.RDB$PRIVATE_FLAG = privateScope;
@@ -2830,7 +2936,7 @@ bool CreateAlterProcedureNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
}
}
- if (package.isEmpty())
+ if (name.package.isEmpty())
storePrivileges(tdbb, transaction, name, obj_procedure, EXEC_PRIVILEGES);
executeAlter(tdbb, dsqlScratch, transaction, false, false);
@@ -2849,21 +2955,19 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
P IN RDB$PROCEDURES
- WITH P.RDB$PROCEDURE_NAME EQ name.c_str() AND
- P.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH P.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ P.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ P.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (P.RDB$SYSTEM_FLAG)
{
status_exception::raise(
Arg::Gds(isc_dyn_cannot_mod_sysproc) <<
- MetaName(P.RDB$PROCEDURE_NAME));
+ name.toQuotedString());
}
- if (!secondPass && runTriggers && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_PROCEDURE, name, NULL);
- }
+ if (!secondPass && runTriggers && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_PROCEDURE, name, {});
MODIFY P
if (secondPass)
@@ -2882,11 +2986,11 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
P.RDB$PROCEDURE_SOURCE.NULL = TRUE;
P.RDB$VALID_BLR.NULL = TRUE;
- P.RDB$PROCEDURE_SOURCE.NULL = !(source.hasData() && (external || package.isEmpty()));
+ P.RDB$PROCEDURE_SOURCE.NULL = !(source.hasData() && (external || name.package.isEmpty()));
if (!P.RDB$PROCEDURE_SOURCE.NULL)
attachment->storeMetaDataBlob(tdbb, transaction, &P.RDB$PROCEDURE_SOURCE, source);
- if (package.hasData())
+ if (name.package.hasData())
{
P.RDB$PRIVATE_FLAG.NULL = FALSE;
P.RDB$PRIVATE_FLAG = privateScope;
@@ -2956,7 +3060,7 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
collectParameters(tdbb, transaction, collectedParameters);
// Delete all old input and output parameters.
- DropProcedureNode::dropParameters(tdbb, transaction, name, package);
+ DropProcedureNode::dropParameters(tdbb, transaction, name);
// And insert the new ones.
@@ -2988,17 +3092,21 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
PRM IN RDB$PROCEDURE_PARAMETERS CROSS
RFR IN RDB$RELATION_FIELDS CROSS
VRL IN RDB$VIEW_RELATIONS
- WITH PRM.RDB$PROCEDURE_NAME EQ name.c_str() AND
- PRM.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '') AND
+ WITH PRM.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PRM.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ PRM.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '') AND
+ VRL.RDB$RELATION_SCHEMA_NAME EQ PRM.RDB$SCHEMA_NAME AND
VRL.RDB$RELATION_NAME EQ PRM.RDB$PROCEDURE_NAME AND
VRL.RDB$PACKAGE_NAME EQUIV PRM.RDB$PACKAGE_NAME AND
VRL.RDB$CONTEXT_TYPE EQ VCT_PROCEDURE AND
+ RFR.RDB$SCHEMA_NAME EQ VRL.RDB$SCHEMA_NAME AND
RFR.RDB$RELATION_NAME EQ VRL.RDB$VIEW_NAME AND
RFR.RDB$VIEW_CONTEXT EQ VRL.RDB$VIEW_CONTEXT AND
RFR.RDB$BASE_FIELD = PRM.RDB$PARAMETER_NAME
{
MODIFY RFR
{
+ strcpy(RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, PRM.RDB$FIELD_SOURCE_SCHEMA_NAME);
strcpy(RFR.RDB$FIELD_SOURCE, PRM.RDB$FIELD_SOURCE);
}
END_MODIFY
@@ -3009,7 +3117,8 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
return modified;
}
-bool CreateAlterProcedureNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction, bool secondPass, bool runTriggers)
+bool CreateAlterProcedureNode::executeAlterIndividualParameters(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
+ jrd_tra* transaction, bool secondPass, bool runTriggers)
{
Attachment* const attachment = transaction->getAttachment();
@@ -3019,21 +3128,19 @@ bool CreateAlterProcedureNode::executeAlterIndividualParameters(thread_db* tdbb,
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
P IN RDB$PROCEDURES
- WITH P.RDB$PROCEDURE_NAME EQ name.c_str() AND
- P.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH P.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ P.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ P.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (P.RDB$SYSTEM_FLAG)
{
status_exception::raise(
Arg::Gds(isc_dyn_cannot_mod_sysproc) <<
- MetaName(P.RDB$PROCEDURE_NAME));
+ name.toQuotedString());
}
- if (!secondPass && runTriggers && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_PROCEDURE, name, NULL);
- }
+ if (!secondPass && runTriggers && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_PROCEDURE, name, {});
MODIFY P
if (ssDefiner.has_value())
@@ -3067,16 +3174,15 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScrat
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRM IN RDB$PROCEDURE_PARAMETERS
{
- PRM.RDB$PARAMETER_NAME.NULL = FALSE;
strcpy(PRM.RDB$PARAMETER_NAME, parameter->name.c_str());
- PRM.RDB$PROCEDURE_NAME.NULL = FALSE;
- strcpy(PRM.RDB$PROCEDURE_NAME, name.c_str());
+ strcpy(PRM.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(PRM.RDB$PROCEDURE_NAME, name.object.c_str());
- if (package.hasData())
+ if (name.package.hasData())
{
PRM.RDB$PACKAGE_NAME.NULL = FALSE;
- strcpy(PRM.RDB$PACKAGE_NAME, package.c_str());
+ strcpy(PRM.RDB$PACKAGE_NAME, name.package.c_str());
}
else
PRM.RDB$PACKAGE_NAME.NULL = TRUE;
@@ -3091,39 +3197,45 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScrat
PRM.RDB$PARAMETER_TYPE = parameterType;
PRM.RDB$PARAMETER_MECHANISM.NULL = FALSE;
- PRM.RDB$PARAMETER_MECHANISM = (USHORT) (type->fullDomain || type->typeOfName.isEmpty() ?
+ PRM.RDB$PARAMETER_MECHANISM = (USHORT) (type->fullDomain || type->typeOfName.object.isEmpty() ?
prm_mech_normal : prm_mech_type_of);
PRM.RDB$NULL_FLAG.NULL = !type->notNull;
PRM.RDB$NULL_FLAG = type->notNull;
- PRM.RDB$RELATION_NAME.NULL = type->typeOfTable.isEmpty();
- PRM.RDB$FIELD_NAME.NULL = PRM.RDB$RELATION_NAME.NULL || type->typeOfName.isEmpty();
+ PRM.RDB$RELATION_SCHEMA_NAME.NULL = PRM.RDB$RELATION_NAME.NULL = type->typeOfTable.object.isEmpty();
+ PRM.RDB$FIELD_NAME.NULL = PRM.RDB$RELATION_NAME.NULL || type->typeOfName.object.isEmpty();
PRM.RDB$FIELD_SOURCE.NULL = FALSE;
if (PRM.RDB$RELATION_NAME.NULL)
{
- if (type->typeOfName.hasData())
- strcpy(PRM.RDB$FIELD_SOURCE, type->typeOfName.c_str());
+ if (type->typeOfName.object.hasData())
+ {
+ strcpy(PRM.RDB$FIELD_SOURCE_SCHEMA_NAME, type->typeOfName.schema.c_str());
+ strcpy(PRM.RDB$FIELD_SOURCE, type->typeOfName.object.c_str());
+ }
else
{
- MetaName fieldName;
+ QualifiedName fieldName({}, name.schema);
storeGlobalField(tdbb, transaction, fieldName, type);
- strcpy(PRM.RDB$FIELD_SOURCE, fieldName.c_str());
+ strcpy(PRM.RDB$FIELD_SOURCE_SCHEMA_NAME, fieldName.schema.c_str());
+ strcpy(PRM.RDB$FIELD_SOURCE, fieldName.object.c_str());
}
}
else
{
- strcpy(PRM.RDB$RELATION_NAME, type->typeOfTable.c_str());
- strcpy(PRM.RDB$FIELD_NAME, type->typeOfName.c_str());
- strcpy(PRM.RDB$FIELD_SOURCE, type->fieldSource.c_str());
+ strcpy(PRM.RDB$RELATION_SCHEMA_NAME, type->typeOfTable.schema.c_str());
+ strcpy(PRM.RDB$RELATION_NAME, type->typeOfTable.object.c_str());
+ strcpy(PRM.RDB$FIELD_NAME, type->typeOfName.object.c_str());
+ strcpy(PRM.RDB$FIELD_SOURCE_SCHEMA_NAME, type->fieldSource.schema.c_str());
+ strcpy(PRM.RDB$FIELD_SOURCE, type->fieldSource.object.c_str());
}
// ASF: If we used a collate with a domain or table.column type, write it
// in RDB$PROCEDURE_PARAMETERS.
- PRM.RDB$COLLATION_ID.NULL = !(type->collate.hasData() && type->typeOfName.hasData());
+ PRM.RDB$COLLATION_ID.NULL = !(type->collate.object.hasData() && type->typeOfName.object.hasData());
if (!PRM.RDB$COLLATION_ID.NULL)
PRM.RDB$COLLATION_ID = type->collationId;
@@ -3141,8 +3253,8 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScrat
{
status_exception::raise(
Arg::Gds(isc_dyn_defvaldecl_package_proc) <<
- package.c_str() <<
- name.c_str());
+ name.getSchemaAndPackage().toQuotedString() <<
+ name.object);
}
attachment->storeMetaDataBlob(tdbb, transaction, &PRM.RDB$DEFAULT_SOURCE,
@@ -3183,7 +3295,7 @@ void CreateAlterProcedureNode::storeParameter(thread_db* tdbb, DsqlCompilerScrat
void CreateAlterProcedureNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlScratch)
{
if (invalid)
- status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_proc) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_proc) << name.toQuotedString());
if (compiled)
return;
@@ -3236,7 +3348,7 @@ void CreateAlterProcedureNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
i != dsqlScratch->outputVariables.end();
++i)
{
- dsqlScratch->putLocalVariable(*i, nullptr, {});
+ dsqlScratch->putLocalVariable(*i);
}
// ASF: This is here to not change the old logic (proc_flag)
@@ -3280,8 +3392,9 @@ void CreateAlterProcedureNode::collectParameters(thread_db* tdbb, jrd_tra* trans
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRM IN RDB$PROCEDURE_PARAMETERS
- WITH PRM.RDB$PROCEDURE_NAME EQ name.c_str() AND
- PRM.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH PRM.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PRM.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ PRM.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
CollectedParameter parameter;
parameter.comment = PRM.RDB$DESCRIPTION;
@@ -3296,15 +3409,15 @@ void CreateAlterProcedureNode::collectParameters(thread_db* tdbb, jrd_tra* trans
//----------------------
-void DropProcedureNode::dropParameters(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& procedureName, const MetaName& packageName)
+void DropProcedureNode::dropParameters(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& procedureName)
{
AutoCacheRequest requestHandle(tdbb, drq_e_prms2, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRM IN RDB$PROCEDURE_PARAMETERS
- WITH PRM.RDB$PROCEDURE_NAME EQ procedureName.c_str() AND
- PRM.RDB$PACKAGE_NAME EQUIV NULLIF(packageName.c_str(), '')
+ WITH PRM.RDB$SCHEMA_NAME EQ procedureName.schema.c_str() AND
+ PRM.RDB$PROCEDURE_NAME EQ procedureName.object.c_str() AND
+ PRM.RDB$PACKAGE_NAME EQUIV NULLIF(procedureName.package.c_str(), '')
{
// get rid of parameters in rdb$fields
if (!PRM.RDB$FIELD_SOURCE.NULL && PRM.RDB$RELATION_NAME.NULL && PRM.RDB$FIELD_NAME.NULL)
@@ -3313,7 +3426,8 @@ void DropProcedureNode::dropParameters(thread_db* tdbb, jrd_tra* transaction,
FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE AND
+ WITH FLD.RDB$SCHEMA_NAME EQ PRM.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ FLD.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE AND
FLD.RDB$FIELD_NAME STARTING WITH IMPLICIT_DOMAIN_PREFIX AND
FLD.RDB$SYSTEM_FLAG EQ 0
{
@@ -3322,7 +3436,8 @@ void DropProcedureNode::dropParameters(thread_db* tdbb, jrd_tra* transaction,
if (!FLD.RDB$SECURITY_CLASS.NULL)
deleteSecurityClass(tdbb, transaction, FLD.RDB$SECURITY_CLASS);
- deletePrivilegesByRelName(tdbb, transaction, FLD.RDB$FIELD_NAME, obj_field);
+ deletePrivilegesByRelName(tdbb, transaction,
+ QualifiedName(FLD.RDB$FIELD_NAME, FLD.RDB$SCHEMA_NAME), obj_field);
}
END_FOR
}
@@ -3338,52 +3453,55 @@ string DropProcedureNode::internalPrint(NodePrinter& printer) const
NODE_PRINT(printer, name);
NODE_PRINT(printer, silent);
- NODE_PRINT(printer, package);
return "DropProcedureNode";
}
DdlNode* DropProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_exception);
+
+ protectSystemSchema(name.schema, obj_procedure);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_PROCEDURE);
+
return DdlNode::dsqlPass(dsqlScratch);
}
void DropProcedureNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_procedure(tdbb, &dscName, SCL_drop);
+ SCL_check_procedure(tdbb, name, SCL_drop);
}
-void DropProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
bool found = false;
- dropParameters(tdbb, transaction, name, package);
+ dropParameters(tdbb, transaction, name);
AutoCacheRequest requestHandle(tdbb, drq_e_prcs2, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRC IN RDB$PROCEDURES
- WITH PRC.RDB$PROCEDURE_NAME EQ name.c_str() AND
- PRC.RDB$PACKAGE_NAME EQUIV NULLIF(package.c_str(), '')
+ WITH PRC.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PRC.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ PRC.RDB$PACKAGE_NAME EQUIV NULLIF(name.package.c_str(), '')
{
if (PRC.RDB$SYSTEM_FLAG)
{
status_exception::raise(
Arg::Gds(isc_dyn_cannot_mod_sysproc) <<
- MetaName(PRC.RDB$PROCEDURE_NAME));
+ name.toQuotedString());
}
- if (package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_PROCEDURE, name, NULL);
- }
+ if (name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_PROCEDURE, name, {});
ERASE PRC;
@@ -3395,35 +3513,34 @@ void DropProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
END_FOR
if (!found && !silent)
- status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_proc_not_found) << name.toQuotedString());
- if (package.isEmpty())
+ if (name.package.isEmpty())
{
deletePrivilegesByRelName(tdbb, transaction, name, obj_procedure);
requestHandle.reset(tdbb, drq_e_prc_prv, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
- PRIV IN RDB$USER_PRIVILEGES WITH PRIV.RDB$USER EQ name.c_str()
- AND PRIV.RDB$USER_TYPE = obj_procedure
- AND PRIV.RDB$GRANTOR NOT MISSING
+ PRIV IN RDB$USER_PRIVILEGES
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$USER EQ name.object.c_str() AND
+ PRIV.RDB$USER_TYPE = obj_procedure AND
+ PRIV.RDB$GRANTOR NOT MISSING
{
ERASE PRIV;
}
END_FOR
}
- if (found && package.isEmpty())
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_PROCEDURE,
- name, NULL);
- }
+ if (found && name.package.isEmpty())
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_PROCEDURE, name, {});
savePoint.release(); // everything is ok
// Update DSQL cache
- METD_drop_procedure(transaction, QualifiedName(name, package));
- MET_dsql_cache_release(tdbb, SYM_procedure, name, package);
+ METD_drop_procedure(transaction, name);
+ MET_dsql_cache_release(tdbb, SYM_procedure, name);
}
@@ -3432,7 +3549,9 @@ void DropProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
void TriggerDefinition::store(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
- if (name.isEmpty())
+ fb_assert(relationName.object.isEmpty() || name.schema == relationName.schema);
+
+ if (name.object.isEmpty())
DYN_UTIL_generate_trigger_name(tdbb, transaction, name);
AutoCacheRequest requestHandle(tdbb, drq_s_triggers, DYN_REQUESTS);
@@ -3442,10 +3561,12 @@ void TriggerDefinition::store(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
{
TRG.RDB$SYSTEM_FLAG = SSHORT(systemFlag);
TRG.RDB$FLAGS = TRG_sql | (fkTrigger ? TRG_ignore_perm : 0);
- strcpy(TRG.RDB$TRIGGER_NAME, name.c_str());
- TRG.RDB$RELATION_NAME.NULL = relationName.isEmpty();
- strcpy(TRG.RDB$RELATION_NAME, relationName.c_str());
+ strcpy(TRG.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(TRG.RDB$TRIGGER_NAME, name.object.c_str());
+
+ TRG.RDB$RELATION_NAME.NULL = relationName.object.isEmpty();
+ strcpy(TRG.RDB$RELATION_NAME, relationName.object.c_str());
fb_assert(type.has_value());
TRG.RDB$TRIGGER_TYPE = type.value();
@@ -3458,8 +3579,7 @@ void TriggerDefinition::store(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
modify(tdbb, dsqlScratch, transaction);
}
-bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
Attachment* const attachment = transaction->getAttachment();
bool modified = false;
@@ -3468,7 +3588,8 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
TRG IN RDB$TRIGGERS
- WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
+ WITH TRG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ TRG.RDB$TRIGGER_NAME EQ name.object.c_str()
{
if (type.has_value() && type != (FB_UINT64) TRG.RDB$TRIGGER_TYPE &&
TRG.RDB$RELATION_NAME.NULL)
@@ -3489,8 +3610,8 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
break;
case fb_sysflag_system:
- status_exception::raise(
- Arg::Gds(isc_dyn_cannot_mod_systrig) << MetaName(TRG.RDB$TRIGGER_NAME));
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_mod_systrig) <<
+ QualifiedName(TRG.RDB$TRIGGER_NAME, TRG.RDB$SCHEMA_NAME).toQuotedString());
break;
default:
@@ -3513,9 +3634,10 @@ bool TriggerDefinition::modify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
TRG.RDB$VALID_BLR.NULL = TRUE;
}
- TRG.RDB$RELATION_NAME.NULL = relationName.isEmpty();
- if (relationName.hasData())
- strcpy(TRG.RDB$RELATION_NAME, relationName.c_str());
+ fb_assert(relationName.object.isEmpty() || name.schema == relationName.schema);
+ TRG.RDB$RELATION_NAME.NULL = relationName.object.isEmpty();
+ if (relationName.object.hasData())
+ strcpy(TRG.RDB$RELATION_NAME, relationName.object.c_str());
if (type.has_value())
TRG.RDB$TRIGGER_TYPE = type.value();
@@ -3600,14 +3722,40 @@ string CreateAlterTriggerNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ dsqlScratch->qualifyExistingName(relationName, obj_relation);
+
+ if (name.schema.isEmpty())
+ name.schema = relationName.schema;
+
+ if (relationName.object.isEmpty())
+ {
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_trigger);
+ }
+ else
+ {
+ if (name.schema != relationName.schema)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_dyn_trig_schema_must_match_table) <<
+ name.schema.toQuotedString() <<
+ relationName.schema.toQuotedString());
+ }
+ }
+
+ protectSystemSchema(name.schema, obj_trigger);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_TRIGGER);
if (type.has_value())
{
if (create && // ALTER TRIGGER doesn't accept table name
- ((relationName.hasData() &&
+ ((relationName.object.hasData() &&
(type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DML) ||
- (relationName.isEmpty() &&
+ (relationName.object.isEmpty() &&
(type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DB &&
(type.value() & (unsigned) TRIGGER_TYPE_MASK) != (unsigned) TRIGGER_TYPE_DDL)))
{
@@ -3631,26 +3779,23 @@ void CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transacti
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
TRG IN RDB$TRIGGERS
- WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
+ WITH TRG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ TRG.RDB$TRIGGER_NAME EQ name.object.c_str()
{
if (!type.has_value() && !TRG.RDB$TRIGGER_TYPE.NULL)
type = TRG.RDB$TRIGGER_TYPE;
- if (relationName.isEmpty() && !TRG.RDB$RELATION_NAME.NULL)
- relationName = TRG.RDB$RELATION_NAME;
+ if (relationName.object.isEmpty() && !TRG.RDB$RELATION_NAME.NULL)
+ relationName = QualifiedName(TRG.RDB$RELATION_NAME, TRG.RDB$SCHEMA_NAME);
}
END_FOR
if (!type.has_value())
- status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << name.toQuotedString());
}
- if (relationName.hasData())
- {
- dsc dscName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter);
- }
+ if (relationName.object.hasData())
+ SCL_check_relation(tdbb, relationName, SCL_alter);
else
SCL_check_database(tdbb, SCL_alter);
}
@@ -3679,7 +3824,7 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
if (create) // create or alter
executeCreate(tdbb, dsqlScratch, transaction);
else
- status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << name.toQuotedString());
}
}
else
@@ -3694,21 +3839,19 @@ void CreateAlterTriggerNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_trigger))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TRIGGER,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TRIGGER, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_trigger);
store(tdbb, dsqlScratch, transaction);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TRIGGER,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TRIGGER, name, {});
}
void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* dsqlScratch)
{
if (invalid)
- status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_trig) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_invalid_ddl_trig) << name.toQuotedString());
if (compiled)
return;
@@ -3728,12 +3871,12 @@ void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* d
if (dsqlScratch->contextNumber)
dsqlScratch->resetTriggerContextStack();
- if (relationName.hasData())
+ if (relationName.object.hasData())
{
RelationSourceNode* relationNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(
dsqlScratch->getPool(), relationName);
- const string temp = relationNode->alias; // always empty?
+ const auto temp = relationNode->alias; // always empty?
if (hasOldContext(type.value()))
{
@@ -3822,37 +3965,42 @@ string DropTriggerNode::internalPrint(NodePrinter& printer) const
DdlNode* DropTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_trigger);
+
+ protectSystemSchema(name.schema, obj_trigger);
+ dsqlScratch->ddlSchema = name.schema;
+
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_TRIGGER);
+
return DdlNode::dsqlPass(dsqlScratch);
}
void DropTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- MetaName relationName = getTriggerRelationName(tdbb, transaction, name);
+ const auto relationName = getTriggerRelationName(tdbb, transaction, name);
- if (relationName.isEmpty())
+ if (relationName.object.isEmpty())
SCL_check_database(tdbb, SCL_alter);
else
- {
- dsc dscName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter);
- }
+ SCL_check_relation(tdbb, relationName, SCL_alter);
}
-void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
bool found = false;
- MetaName relationName;
+ QualifiedName relationName;
AutoCacheRequest requestHandle(tdbb, drq_e_trigger3, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGERS
- WITH X.RDB$TRIGGER_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$TRIGGER_NAME EQ name.object.c_str()
{
switch (X.RDB$SYSTEM_FLAG)
{
@@ -3863,31 +4011,31 @@ void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
break;
case fb_sysflag_system:
- status_exception::raise(
- Arg::Gds(isc_dyn_cannot_mod_systrig) << MetaName(X.RDB$TRIGGER_NAME));
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_mod_systrig) <<
+ name.toQuotedString());
break;
default:
break;
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_TRIGGER,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_TRIGGER, name, {});
- relationName = X.RDB$RELATION_NAME;
+ relationName = QualifiedName(X.RDB$RELATION_NAME, X.RDB$SCHEMA_NAME);
ERASE X;
found = true;
}
END_FOR
if (!found && !silent)
- status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << name.toQuotedString());
requestHandle.reset(tdbb, drq_e_trg_msgs3, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
TM IN RDB$TRIGGER_MESSAGES
- WITH TM.RDB$TRIGGER_NAME EQ name.c_str()
+ WITH TM.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ TM.RDB$TRIGGER_NAME EQ name.object.c_str()
{
ERASE TM;
}
@@ -3897,7 +4045,8 @@ void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$USER EQ name.c_str() AND
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$USER EQ name.object.c_str() AND
PRIV.RDB$USER_TYPE = obj_trigger AND
PRIV.RDB$GRANTOR NOT MISSING
{
@@ -3905,44 +4054,48 @@ void DropTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
}
END_FOR
- // Clear the update flags on the fields if this is the last remaining
- // trigger that changes a view.
-
- bool viewFound = false;
- requestHandle.reset(tdbb, drq_e_trg_prv3, DYN_REQUESTS);
-
- FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
- FIRST 1 V IN RDB$VIEW_RELATIONS
- CROSS F IN RDB$RELATION_FIELDS
- CROSS T IN RDB$TRIGGERS
- WITH V.RDB$VIEW_NAME EQ relationName.c_str() AND
- F.RDB$RELATION_NAME EQ V.RDB$VIEW_NAME AND
- F.RDB$RELATION_NAME EQ T.RDB$RELATION_NAME
+ if (relationName.object.hasData())
{
- viewFound = true;
- }
- END_FOR
+ // Clear the update flags on the fields if this is the last remaining trigger that changes a view.
- if (!viewFound)
- {
- requestHandle.reset(tdbb, drq_m_rel_flds2, DYN_REQUESTS);
+ bool viewFound = false;
+
+ requestHandle.reset(tdbb, drq_e_trg_prv3, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
- F IN RDB$RELATION_FIELDS
- WITH F.RDB$RELATION_NAME EQ relationName.c_str()
+ FIRST 1 V IN RDB$VIEW_RELATIONS
+ CROSS F IN RDB$RELATION_FIELDS
+ CROSS T IN RDB$TRIGGERS
+ WITH V.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ V.RDB$VIEW_NAME EQ relationName.object.c_str() AND
+ F.RDB$SCHEMA_NAME EQ V.RDB$SCHEMA_NAME AND
+ F.RDB$RELATION_NAME EQ V.RDB$VIEW_NAME AND
+ T.RDB$SCHEMA_NAME EQ F.RDB$SCHEMA_NAME AND
+ T.RDB$RELATION_NAME EQ F.RDB$RELATION_NAME
{
- MODIFY F USING
- F.RDB$UPDATE_FLAG = FALSE;
- END_MODIFY
+ viewFound = true;
}
END_FOR
+
+ if (!viewFound)
+ {
+ requestHandle.reset(tdbb, drq_m_rel_flds2, DYN_REQUESTS);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ F IN RDB$RELATION_FIELDS
+ WITH F.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ F.RDB$RELATION_NAME EQ relationName.object.c_str()
+ {
+ MODIFY F USING
+ F.RDB$UPDATE_FLAG = FALSE;
+ END_MODIFY
+ }
+ END_FOR
+ }
}
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_TRIGGER,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_TRIGGER, name, {});
savePoint.release(); // everything is ok
}
@@ -3970,7 +4123,7 @@ string CreateCollationNode::internalPrint(NodePrinter& printer) const
void CreateCollationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- SCL_check_create_access(tdbb, obj_collations);
+ SCL_check_create_access(tdbb, obj_collations, name.schema);
}
void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -3985,8 +4138,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_collation))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_COLLATION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_COLLATION, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_collation);
@@ -3996,7 +4148,9 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
X IN RDB$COLLATIONS
{
X.RDB$CHARACTER_SET_ID = forCharSetId;
- strcpy(X.RDB$COLLATION_NAME, name.c_str());
+
+ strcpy(X.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(X.RDB$COLLATION_NAME, name.object.c_str());
X.RDB$SYSTEM_FLAG = 0;
X.RDB$OWNER_NAME.NULL = FALSE;
@@ -4008,7 +4162,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
CharSet* cs = INTL_charset_lookup(tdbb, forCharSetId);
SubtypeInfo info;
- if (fromName.hasData())
+ if (fromName.object.hasData())
{
if (MET_get_char_coll_subtype_info(tdbb,
INTL_CS_COLL_TO_TTYPE(forCharSetId, fromCollationId), &info) &&
@@ -4046,20 +4200,24 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
specificAttributes = temp;
}
- info.charsetName = forCharSet.c_str();
+ info.charsetName = forCharSet;
info.collationName = name;
+
if (X.RDB$BASE_COLLATION_NAME.NULL)
- info.baseCollationName = info.collationName;
+ info.baseCollationName = info.collationName.object.c_str();
else
+ {
info.baseCollationName = X.RDB$BASE_COLLATION_NAME;
+ info.baseCollationName.rtrim();
+ }
+
info.ignoreAttributes = false;
- if (!IntlManager::collationInstalled(info.baseCollationName.c_str(),
- info.charsetName.c_str()))
+ if (!IntlManager::collationInstalled(info.baseCollationName, info.charsetName))
{
// msg: 223: "Collation @1 not installed for character set @2"
status_exception::raise(
- Arg::PrivateDyn(223) << info.baseCollationName << info.charsetName);
+ Arg::PrivateDyn(223) << info.baseCollationName << info.charsetName.toQuotedString());
}
IntlUtil::SpecificAttributesMap map;
@@ -4077,7 +4235,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
string newSpecificAttributes;
if (!IntlManager::setupCollationAttributes(
- info.baseCollationName.c_str(), info.charsetName.c_str(), s,
+ info.baseCollationName, info.charsetName, s,
newSpecificAttributes))
{
// msg: 222: "Invalid collation attributes"
@@ -4117,7 +4275,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
FOR(REQUEST_HANDLE request2)
Y IN RDB$COLLATIONS
WITH Y.RDB$CHARACTER_SET_ID = forCharSetId AND
- Y.RDB$COLLATION_ID NOT MISSING
+ Y.RDB$COLLATION_ID NOT MISSING
SORTED BY DESCENDING Y.RDB$COLLATION_ID
{
if (Y.RDB$COLLATION_ID + 1 <= X.RDB$COLLATION_ID)
@@ -4137,8 +4295,7 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
storePrivileges(tdbb, transaction, name, obj_collation, USAGE_PRIVILEGES);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_CREATE_COLLATION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_COLLATION, name, {});
savePoint.release(); // everything is ok
@@ -4149,19 +4306,27 @@ void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
DdlNode* CreateCollationNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
- const dsql_intlsym* resolvedCharSet = METD_get_charset(
- dsqlScratch->getTransaction(), forCharSet.length(), forCharSet.c_str());
+ dsqlScratch->qualifyNewName(name);
+ protectSystemSchema(name.schema, obj_collation);
+ dsqlScratch->ddlSchema = name.schema;
+
+ dsqlScratch->qualifyExistingName(forCharSet, obj_charset);
+
+ if (fromName.object.hasData())
+ dsqlScratch->qualifyExistingName(fromName, obj_collation);
+
+ const dsql_intlsym* resolvedCharSet = METD_get_charset(dsqlScratch->getTransaction(), forCharSet);
if (!resolvedCharSet)
{
// specified character set not found
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
- Arg::Gds(isc_charset_not_found) << forCharSet);
+ Arg::Gds(isc_charset_not_found) << forCharSet.toQuotedString());
}
forCharSetId = resolvedCharSet->intlsym_charset_id;
- if (fromName.hasData())
+ if (fromName.object.hasData())
{
const dsql_intlsym* resolvedCollation = METD_get_collation(
dsqlScratch->getTransaction(), fromName, forCharSetId);
@@ -4170,7 +4335,7 @@ DdlNode* CreateCollationNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
// Specified collation not found
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
- Arg::Gds(isc_collation_not_found) << fromName << forCharSet);
+ Arg::Gds(isc_collation_not_found) << fromName.toQuotedString() << forCharSet.toQuotedString());
}
fromCollationId = resolvedCollation->intlsym_collate_id;
@@ -4197,8 +4362,7 @@ void DropCollationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
SCL_check_collation(tdbb, name, SCL_drop);
}
-void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
@@ -4209,24 +4373,22 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
COLL IN RDB$COLLATIONS
CROSS CS IN RDB$CHARACTER_SETS
- WITH COLL.RDB$COLLATION_NAME EQ name.c_str() AND
+ WITH COLL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ COLL.RDB$COLLATION_NAME EQ name.object.c_str() AND
CS.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_COLLATION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_COLLATION, name, {});
if (COLL.RDB$SYSTEM_FLAG)
status_exception::raise(Arg::Gds(isc_dyn_cannot_del_syscoll));
if (COLL.RDB$COLLATION_ID == 0 ||
(!CS.RDB$DEFAULT_COLLATE_NAME.NULL &&
- MetaName(COLL.RDB$COLLATION_NAME) == MetaName(CS.RDB$DEFAULT_COLLATE_NAME)))
+ name == QualifiedName(CS.RDB$DEFAULT_COLLATE_NAME, CS.RDB$DEFAULT_COLLATE_SCHEMA_NAME)))
{
- fb_utils::exact_name_limit(CS.RDB$CHARACTER_SET_NAME,
- sizeof(CS.RDB$CHARACTER_SET_NAME));
-
status_exception::raise(
- Arg::Gds(isc_dyn_cannot_del_def_coll) << CS.RDB$CHARACTER_SET_NAME);
+ Arg::Gds(isc_dyn_cannot_del_def_coll) <<
+ QualifiedName(CS.RDB$CHARACTER_SET_NAME, CS.RDB$SCHEMA_NAME).toQuotedString());
}
found = true;
@@ -4237,34 +4399,40 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RF IN RDB$RELATION_FIELDS
CROSS F IN RDB$FIELDS
- WITH RF.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND
- F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
- RF.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
+ WITH RF.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID AND
+ F.RDB$SCHEMA_NAME EQUIV RF.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ F.RDB$FIELD_NAME EQ RF.RDB$FIELD_SOURCE AND
+ F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID
+
{
- fb_utils::exact_name_limit(RF.RDB$RELATION_NAME, sizeof(RF.RDB$RELATION_NAME));
fb_utils::exact_name_limit(RF.RDB$FIELD_NAME, sizeof(RF.RDB$FIELD_NAME));
status_exception::raise(
- Arg::Gds(isc_dyn_coll_used_table) << COLL.RDB$COLLATION_NAME <<
- RF.RDB$RELATION_NAME << RF.RDB$FIELD_NAME);
+ Arg::Gds(isc_dyn_coll_used_table) <<
+ name.toQuotedString() <<
+ QualifiedName(RF.RDB$RELATION_NAME, RF.RDB$SCHEMA_NAME).toQuotedString() <<
+ RF.RDB$FIELD_NAME);
}
END_FOR
request2.reset(tdbb, drq_l_prm_coll, DYN_REQUESTS);
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
- PRM IN RDB$PROCEDURE_PARAMETERS CROSS F IN RDB$FIELDS
- WITH PRM.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND
- F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
- PRM.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
+ PRM IN RDB$PROCEDURE_PARAMETERS
+ CROSS F IN RDB$FIELDS
+ WITH PRM.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID AND
+ F.RDB$SCHEMA_NAME EQUIV PRM.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ F.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE AND
+ F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID
+
{
fb_utils::exact_name_limit(PRM.RDB$PARAMETER_NAME, sizeof(PRM.RDB$PARAMETER_NAME));
status_exception::raise(
Arg::Gds(isc_dyn_coll_used_procedure) <<
- COLL.RDB$COLLATION_NAME <<
- QualifiedName(PRM.RDB$PROCEDURE_NAME,
- (PRM.RDB$PACKAGE_NAME.NULL ? NULL : PRM.RDB$PACKAGE_NAME)).toString().c_str() <<
+ name.toQuotedString() <<
+ QualifiedName(PRM.RDB$PROCEDURE_NAME, PRM.RDB$SCHEMA_NAME,
+ (PRM.RDB$PACKAGE_NAME.NULL ? NULL : PRM.RDB$PACKAGE_NAME)).toQuotedString() <<
PRM.RDB$PARAMETER_NAME);
}
END_FOR
@@ -4272,18 +4440,21 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
request2.reset(tdbb, drq_l_arg_coll, DYN_REQUESTS);
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
- ARG IN RDB$FUNCTION_ARGUMENTS CROSS F IN RDB$FIELDS
- WITH ARG.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND
- F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND
- ARG.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID
+ ARG IN RDB$FUNCTION_ARGUMENTS
+ CROSS F IN RDB$FIELDS
+ WITH ARG.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID AND
+ F.RDB$SCHEMA_NAME EQUIV ARG.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ F.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE AND
+ F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID
+
{
fb_utils::exact_name_limit(ARG.RDB$ARGUMENT_NAME, sizeof(ARG.RDB$ARGUMENT_NAME));
status_exception::raise(
Arg::Gds(isc_dyn_coll_used_function) <<
- COLL.RDB$COLLATION_NAME <<
- QualifiedName(ARG.RDB$FUNCTION_NAME,
- (ARG.RDB$PACKAGE_NAME.NULL ? NULL : ARG.RDB$PACKAGE_NAME)).toString().c_str() <<
+ name.toQuotedString() <<
+ QualifiedName(ARG.RDB$FUNCTION_NAME, ARG.RDB$SCHEMA_NAME,
+ (ARG.RDB$PACKAGE_NAME.NULL ? NULL : ARG.RDB$PACKAGE_NAME)).toQuotedString() <<
ARG.RDB$ARGUMENT_NAME);
}
END_FOR
@@ -4298,7 +4469,9 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
fb_utils::exact_name_limit(F.RDB$FIELD_NAME, sizeof(F.RDB$FIELD_NAME));
status_exception::raise(
- Arg::Gds(isc_dyn_coll_used_domain) << COLL.RDB$COLLATION_NAME << F.RDB$FIELD_NAME);
+ Arg::Gds(isc_dyn_coll_used_domain) <<
+ name.toQuotedString() <<
+ F.RDB$FIELD_NAME);
}
END_FOR
@@ -4312,12 +4485,9 @@ void DropCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
deletePrivilegesByRelName(tdbb, transaction, name, obj_collation);
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_COLLATION,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_COLLATION, name, {});
else if (!silent)
- status_exception::raise(Arg::Gds(isc_dyn_collation_not_found) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_collation_not_found) << name.toQuotedString());
savePoint.release(); // everything is ok
@@ -4334,7 +4504,9 @@ string CreateDomainNode::internalPrint(NodePrinter& printer) const
{
DdlNode::internalPrint(printer);
- NODE_PRINT(printer, nameType);
+ NODE_PRINT(printer, name);
+ NODE_PRINT(printer, type);
+ NODE_PRINT(printer, defaultClause);
NODE_PRINT(printer, notNull);
NODE_PRINT(printer, check);
@@ -4343,31 +4515,29 @@ string CreateDomainNode::internalPrint(NodePrinter& printer) const
void CreateDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- SCL_check_create_access(tdbb, obj_domains);
+ SCL_check_create_access(tdbb, obj_domains, name.schema);
}
-void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
Attachment* const attachment = transaction->tra_attachment;
- dsql_fld* type = nameType->type;
// The commented line should be restored when implicit domains get their own sys flag.
- //if (fb_utils::implicit_domain(nameType->name.c_str()))
- if (strncmp(nameType->name.c_str(), IMPLICIT_DOMAIN_PREFIX, IMPLICIT_DOMAIN_PREFIX_LEN) == 0)
+ //if (fb_utils::implicit_domain(name.c_str()))
+ if (strncmp(name.object.c_str(), IMPLICIT_DOMAIN_PREFIX, IMPLICIT_DOMAIN_PREFIX_LEN) == 0)
{
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_implicit_domain_name) << nameType->name);
+ Arg::Gds(isc_dsql_implicit_domain_name) << name.toQuotedString());
}
const ValueListNode* elements = type->ranges;
const USHORT dims = elements ? elements->items.getCount() / 2 : 0;
- if (nameType->defaultClause && dims != 0)
+ if (defaultClause && dims != 0)
{
// Default value is not allowed for array type in domain %s
- status_exception::raise(Arg::PrivateDyn(226) << nameType->name);
+ status_exception::raise(Arg::PrivateDyn(226) << name.toQuotedString());
}
type->resolve(dsqlScratch);
@@ -4377,35 +4547,35 @@ void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
- if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, nameType->name, obj_field))
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_field))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_DOMAIN, nameType->name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_DOMAIN, name, {});
- DYN_UTIL_check_unique_name(tdbb, transaction, nameType->name, obj_field);
+ DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_field);
- storeGlobalField(tdbb, transaction, nameType->name, type);
+ storeGlobalField(tdbb, transaction, name, type);
- if (nameType->defaultClause || check || notNull)
+ if (defaultClause || check || notNull)
{
AutoCacheRequest request(tdbb, drq_m_fld, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ nameType->name.c_str()
+ WITH FLD.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FLD.RDB$FIELD_NAME EQ name.object.c_str()
{
MODIFY FLD
- if (nameType->defaultClause)
+ if (defaultClause)
{
FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
attachment->storeMetaDataBlob(tdbb, transaction, &FLD.RDB$DEFAULT_SOURCE,
- nameType->defaultClause->source);
+ defaultClause->source);
dsqlScratch->getBlrData().clear();
dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
- ValueExprNode* node = doDsqlPass(dsqlScratch, nameType->defaultClause->value);
+ ValueExprNode* node = doDsqlPass(dsqlScratch, defaultClause->value);
GEN_expr(dsqlScratch, node);
@@ -4454,8 +4624,7 @@ void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
END_FOR
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_CREATE_DOMAIN, nameType->name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_DOMAIN, name, {});
savePoint.release(); // everything is ok
}
@@ -4850,18 +5019,18 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
{
case isc_dyn_dtype_invalid:
// Cannot change datatype for column %s.The operation cannot be performed on DATE, BLOB, or ARRAY columns.
- status_exception::raise(Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str());
+ status_exception::raise(Arg::Gds(errorCode) << origFld.dyn_fld_name.toQuotedString());
break;
case isc_dyn_dtype_conv_invalid:
// Cannot convert column %s from character to non-character data.
- status_exception::raise(Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str());
+ status_exception::raise(Arg::Gds(errorCode) << origFld.dyn_fld_name.toQuotedString());
break;
case isc_dyn_char_fld_too_small:
// msg 208: New size specified for column %s must be at least %d characters.
status_exception::raise(
- Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str() << Arg::Num(origLen));
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.toQuotedString() << Arg::Num(origLen));
break;
case isc_dyn_scale_too_big:
@@ -4881,7 +5050,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
// scale_too_big: New scale specified for column @1 must be at most @2.
// precision_too_small: New precision specified for column @1 must be at least @2.
status_exception::raise(
- Arg::Gds(code) << origFld.dyn_fld_name.c_str() << Arg::Num(diff));
+ Arg::Gds(code) << origFld.dyn_fld_name.toQuotedString() << Arg::Num(diff));
}
break;
@@ -4894,7 +5063,7 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
// Cannot change datatype for @1. Conversion from base type @2 to @3 is not supported.
status_exception::raise(
- Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str() << orig_type << new_type);
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.toQuotedString() << orig_type << new_type);
}
break;
@@ -4934,7 +5103,8 @@ void AlterDomainNode::getDomainType(thread_db* tdbb, jrd_tra* transaction, dyn_f
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ dynFld.dyn_fld_source.c_str();
+ WITH FLD.RDB$SCHEMA_NAME EQ dynFld.dyn_fld_source.schema.c_str() AND
+ FLD.RDB$FIELD_NAME EQ dynFld.dyn_fld_source.object.c_str()
{
DSC_make_descriptor(&dynFld.dyn_dsc, FLD.RDB$FIELD_TYPE, FLD.RDB$FIELD_SCALE,
FLD.RDB$FIELD_LENGTH, FLD.RDB$FIELD_SUB_TYPE, FLD.RDB$CHARACTER_SET_ID,
@@ -4956,15 +5126,18 @@ void AlterDomainNode::getDomainType(thread_db* tdbb, jrd_tra* transaction, dyn_f
// Updates the field names in an index and forces the index to be rebuilt with the new field names.
void AlterDomainNode::modifyLocalFieldIndex(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName, const MetaName& newFieldName)
+ const QualifiedName& relationName, const MetaName& fieldName, const MetaName& newFieldName)
{
AutoRequest request;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- IDX IN RDB$INDICES CROSS IDXS IN RDB$INDEX_SEGMENTS WITH
- IDX.RDB$INDEX_NAME EQ IDXS.RDB$INDEX_NAME AND
- IDX.RDB$RELATION_NAME EQ relationName.c_str() AND
- IDXS.RDB$FIELD_NAME EQ fieldName.c_str()
+ IDX IN RDB$INDICES
+ CROSS IDXS IN RDB$INDEX_SEGMENTS
+ WITH IDXS.RDB$SCHEMA_NAME EQ IDX.RDB$SCHEMA_NAME AND
+ IDXS.RDB$INDEX_NAME EQ IDX.RDB$INDEX_NAME AND
+ IDX.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ IDX.RDB$RELATION_NAME EQ relationName.object.c_str() AND
+ IDXS.RDB$FIELD_NAME EQ fieldName.c_str()
{
// Change the name of the field in the index
MODIFY IDXS USING
@@ -5002,11 +5175,13 @@ void AlterDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
SCL_check_domain(tdbb, name, SCL_alter);
}
-void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
Attachment* const attachment = transaction->tra_attachment;
+ QualifiedName qualifiedRenameTo = renameTo.hasData() ?
+ QualifiedName(renameTo, name.schema) : QualifiedName();
+
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
@@ -5015,17 +5190,18 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ name.c_str()
+ WITH FLD.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FLD.RDB$FIELD_NAME EQ name.object.c_str()
{
found = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_DOMAIN, name, renameTo);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_DOMAIN,
+ name, qualifiedRenameTo);
if (FLD.RDB$SYSTEM_FLAG == fb_sysflag_system)
{
status_exception::raise(Arg::Gds(isc_dyn_cant_modify_sysobj) <<
- "domain" << Arg::Str(name));
+ "domain" << name.toQuotedString());
}
MODIFY FLD
@@ -5059,7 +5235,7 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_domain_not_found) << name);
+ Arg::Gds(isc_dsql_domain_not_found) << name.toQuotedString());
}
DsqlDescMaker::fromField(&dsqlScratch->domainValue, &localField);
@@ -5095,7 +5271,7 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
if (FLD.RDB$DIMENSIONS)
{
// msg 226: "Default value is not allowed for array type in domain %s"
- status_exception::raise(Arg::PrivateDyn(226) << name);
+ status_exception::raise(Arg::PrivateDyn(226) << name.toQuotedString());
}
FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
@@ -5130,17 +5306,21 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
IND IN RDB$INDICES CROSS
INDSEG IN RDB$INDEX_SEGMENTS CROSS
RELCON IN RDB$RELATION_CONSTRAINTS
- WITH RFL.RDB$FIELD_SOURCE EQ name.c_str() AND
+ WITH RFL.RDB$FIELD_SOURCE_SCHEMA_NAME EQ name.schema.c_str() AND
+ RFL.RDB$FIELD_SOURCE EQ name.object.c_str() AND
(RFL.RDB$NULL_FLAG MISSING OR RFL.RDB$NULL_FLAG EQ 0) AND
+ IND.RDB$SCHEMA_NAME EQ RFL.RDB$SCHEMA_NAME AND
IND.RDB$RELATION_NAME EQ RFL.RDB$RELATION_NAME AND
+ INDSEG.RDB$SCHEMA_NAME EQ IND.RDB$SCHEMA_NAME AND
INDSEG.RDB$INDEX_NAME EQ IND.RDB$INDEX_NAME AND
INDSEG.RDB$FIELD_NAME EQ RFL.RDB$FIELD_NAME AND
+ RELCON.RDB$SCHEMA_NAME EQ INDSEG.RDB$SCHEMA_NAME AND
RELCON.RDB$INDEX_NAME EQ INDSEG.RDB$INDEX_NAME AND
RELCON.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY
{
status_exception::raise(
Arg::Gds(isc_domain_primary_key_notnull) <<
- MetaName(RFL.RDB$RELATION_NAME));
+ QualifiedName(RFL.RDB$RELATION_NAME, RFL.RDB$SCHEMA_NAME).toQuotedString());
}
END_FOR
}
@@ -5208,12 +5388,13 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RFR IN RDB$RELATION_FIELDS
- WITH RFR.RDB$FIELD_SOURCE = FLD.RDB$FIELD_NAME AND
+ WITH RFR.RDB$FIELD_SOURCE_SCHEMA_NAME = FLD.RDB$SCHEMA_NAME AND
+ RFR.RDB$FIELD_SOURCE = FLD.RDB$FIELD_NAME AND
RFR.RDB$GENERATOR_NAME NOT MISSING
{
// Domain @1 must be of exact number type with zero scale because it's used
// in an identity column.
- status_exception::raise(Arg::PrivateDyn(276) << name);
+ status_exception::raise(Arg::PrivateDyn(276) << name.toQuotedString());
}
END_FOR
}
@@ -5224,9 +5405,11 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
DOM IN RDB$RELATION_FIELDS
- WITH DOM.RDB$FIELD_SOURCE EQ name.c_str()
+ WITH DOM.RDB$FIELD_SOURCE_SCHEMA_NAME = name.schema.c_str() AND
+ DOM.RDB$FIELD_SOURCE EQ name.object.c_str()
{
- modifyLocalFieldIndex(tdbb, transaction, DOM.RDB$RELATION_NAME,
+ modifyLocalFieldIndex(tdbb, transaction,
+ QualifiedName(DOM.RDB$RELATION_NAME, DOM.RDB$SCHEMA_NAME),
DOM.RDB$FIELD_NAME, DOM.RDB$FIELD_NAME);
}
END_FOR
@@ -5269,8 +5452,8 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
}
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_DOMAIN,
- (renameTo.hasData() ? renameTo : name),
- (renameTo.hasData() ? name : NULL));
+ (renameTo.hasData() ? qualifiedRenameTo : name),
+ (renameTo.hasData() ? name : QualifiedName()));
savePoint.release(); // everything is ok
}
@@ -5282,10 +5465,12 @@ void AlterDomainNode::rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimen
AutoRequest request;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ renameTo.c_str()
+ FLD IN RDB$FIELDS
+ WITH FLD.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FLD.RDB$FIELD_NAME EQ renameTo.c_str()
{
// msg 204: Cannot rename domain %s to %s. A domain with that name already exists.
- status_exception::raise(Arg::PrivateDyn(204) << name << renameTo);
+ status_exception::raise(Arg::PrivateDyn(204) << name.toQuotedString() << renameTo);
}
END_FOR
@@ -5296,7 +5481,8 @@ void AlterDomainNode::rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimen
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FDIM IN RDB$FIELD_DIMENSIONS
- WITH FDIM.RDB$FIELD_NAME EQ name.c_str()
+ WITH FDIM.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FDIM.RDB$FIELD_NAME EQ name.object.c_str()
{
MODIFY FDIM USING
strcpy(FDIM.RDB$FIELD_NAME, renameTo.c_str());
@@ -5309,13 +5495,15 @@ void AlterDomainNode::rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimen
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFLD IN RDB$RELATION_FIELDS
- WITH RFLD.RDB$FIELD_SOURCE EQ name.c_str()
+ WITH RFLD.RDB$FIELD_SOURCE_SCHEMA_NAME EQ name.schema.c_str() AND
+ RFLD.RDB$FIELD_SOURCE EQ name.object.c_str()
{
MODIFY RFLD USING
strcpy(RFLD.RDB$FIELD_SOURCE, renameTo.c_str());
END_MODIFY
- modifyLocalFieldIndex(tdbb, transaction, RFLD.RDB$RELATION_NAME,
+ modifyLocalFieldIndex(tdbb, transaction,
+ QualifiedName(RFLD.RDB$RELATION_NAME, RFLD.RDB$SCHEMA_NAME),
RFLD.RDB$FIELD_NAME, RFLD.RDB$FIELD_NAME);
}
END_FOR
@@ -5326,14 +5514,15 @@ void AlterDomainNode::rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimen
// Delete the records in RDB$FIELD_DIMENSIONS pertaining to a field.
-bool DropDomainNode::deleteDimensionRecords(thread_db* tdbb, jrd_tra* transaction, const MetaName& name)
+bool DropDomainNode::deleteDimensionRecords(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name)
{
AutoCacheRequest request(tdbb, drq_e_dims, DYN_REQUESTS);
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FIELD_DIMENSIONS
- WITH X.RDB$FIELD_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$FIELD_NAME EQ name.object.c_str()
{
found = true;
ERASE X;
@@ -5357,8 +5546,7 @@ void DropDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
SCL_check_domain(tdbb, name, SCL_drop);
}
-void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
@@ -5368,10 +5556,10 @@ void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FIELDS
- WITH X.RDB$FIELD_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$FIELD_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_DOMAIN, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_DOMAIN, name, {});
check(tdbb, transaction);
deleteDimensionRecords(tdbb, transaction, name);
@@ -5388,10 +5576,7 @@ void DropDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
deletePrivilegesByRelName(tdbb, transaction, name, obj_field);
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN, name, {});
else if (!silent)
{
// msg 89: "Domain not found"
@@ -5407,15 +5592,16 @@ void DropDomainNode::check(thread_db* tdbb, jrd_tra* transaction)
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
Y IN RDB$RELATION_FIELDS
- WITH Y.RDB$FIELD_SOURCE EQ name.c_str()
+ WITH Y.RDB$FIELD_SOURCE_SCHEMA_NAME EQ name.schema.c_str() AND
+ Y.RDB$FIELD_SOURCE EQ name.object.c_str()
{
- fb_utils::exact_name_limit(Y.RDB$FIELD_SOURCE, sizeof(Y.RDB$FIELD_SOURCE));
- fb_utils::exact_name_limit(Y.RDB$RELATION_NAME, sizeof(Y.RDB$RELATION_NAME));
fb_utils::exact_name_limit(Y.RDB$FIELD_NAME, sizeof(Y.RDB$FIELD_NAME));
// msg 43: "Domain %s is used in table %s (local name %s) and can not be dropped"
status_exception::raise(
- Arg::PrivateDyn(43) << Y.RDB$FIELD_SOURCE << Y.RDB$RELATION_NAME << Y.RDB$FIELD_NAME);
+ Arg::PrivateDyn(43) << name.toQuotedString() <<
+ QualifiedName(Y.RDB$RELATION_NAME, Y.RDB$SCHEMA_NAME).toQuotedString() <<
+ MetaName(Y.RDB$FIELD_NAME).toQuotedString());
}
END_FOR
@@ -5423,18 +5609,17 @@ void DropDomainNode::check(thread_db* tdbb, jrd_tra* transaction)
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$PROCEDURE_PARAMETERS
- WITH X.RDB$FIELD_SOURCE EQ name.c_str()
+ WITH X.RDB$FIELD_SOURCE_SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$FIELD_SOURCE EQ name.object.c_str()
{
- fb_utils::exact_name_limit(X.RDB$FIELD_SOURCE, sizeof(X.RDB$FIELD_SOURCE));
- fb_utils::exact_name_limit(X.RDB$PROCEDURE_NAME, sizeof(X.RDB$PROCEDURE_NAME));
fb_utils::exact_name_limit(X.RDB$PARAMETER_NAME, sizeof(X.RDB$PARAMETER_NAME));
// msg 239: "Domain %s is used in procedure %s (parameter name %s) and cannot be dropped"
status_exception::raise(
- Arg::PrivateDyn(239) << X.RDB$FIELD_SOURCE <<
- QualifiedName(X.RDB$PROCEDURE_NAME,
- (X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toString().c_str() <<
- X.RDB$PARAMETER_NAME);
+ Arg::PrivateDyn(239) << name.toQuotedString() <<
+ QualifiedName(X.RDB$PROCEDURE_NAME, X.RDB$SCHEMA_NAME,
+ (X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toQuotedString() <<
+ MetaName(X.RDB$PARAMETER_NAME).toQuotedString());
}
END_FOR
@@ -5442,18 +5627,17 @@ void DropDomainNode::check(thread_db* tdbb, jrd_tra* transaction)
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FUNCTION_ARGUMENTS
- WITH X.RDB$FIELD_SOURCE EQ name.c_str()
+ WITH X.RDB$FIELD_SOURCE_SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$FIELD_SOURCE EQ name.object.c_str()
{
- fb_utils::exact_name_limit(X.RDB$FIELD_SOURCE, sizeof(X.RDB$FIELD_SOURCE));
- fb_utils::exact_name_limit(X.RDB$FUNCTION_NAME, sizeof(X.RDB$FUNCTION_NAME));
fb_utils::exact_name_limit(X.RDB$ARGUMENT_NAME, sizeof(X.RDB$ARGUMENT_NAME));
// msg 239: "Domain %s is used in function %s (parameter name %s) and cannot be dropped"
status_exception::raise(
- Arg::Gds(isc_dyn_domain_used_function) << X.RDB$FIELD_SOURCE <<
- QualifiedName(X.RDB$FUNCTION_NAME,
- (X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toString().c_str() <<
- X.RDB$ARGUMENT_NAME);
+ Arg::Gds(isc_dyn_domain_used_function) << name.toQuotedString() <<
+ QualifiedName(X.RDB$FUNCTION_NAME, X.RDB$SCHEMA_NAME,
+ (X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toQuotedString() <<
+ MetaName(X.RDB$ARGUMENT_NAME).toQuotedString());
}
END_FOR
}
@@ -5482,11 +5666,10 @@ void CreateAlterExceptionNode::checkPermission(thread_db* tdbb, jrd_tra* transac
return;
}
- SCL_check_create_access(tdbb, obj_exceptions);
+ SCL_check_create_access(tdbb, obj_exceptions, name.schema);
}
-void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
fb_assert(create || alter);
@@ -5515,8 +5698,7 @@ void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsq
savePoint.release(); // everything is ok
}
-void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
Attachment* const attachment = transaction->getAttachment();
const MetaString& ownerName = attachment->getEffectiveUserName();
@@ -5524,8 +5706,7 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_exception))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_EXCEPTION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_EXCEPTION, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_exception);
@@ -5547,7 +5728,9 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
{
X.RDB$EXCEPTION_NUMBER = id;
X.RDB$SYSTEM_FLAG = 0;
- strcpy(X.RDB$EXCEPTION_NAME, name.c_str());
+
+ strcpy(X.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(X.RDB$EXCEPTION_NAME, name.object.c_str());
X.RDB$OWNER_NAME.NULL = FALSE;
strcpy(X.RDB$OWNER_NAME, ownerName.c_str());
@@ -5572,8 +5755,7 @@ void CreateAlterExceptionNode::executeCreate(thread_db* tdbb, DsqlCompilerScratc
storePrivileges(tdbb, transaction, name, obj_exception, USAGE_PRIVILEGES);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_EXCEPTION,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_EXCEPTION, name, {});
}
bool CreateAlterExceptionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -5584,10 +5766,10 @@ bool CreateAlterExceptionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$EXCEPTIONS
- WITH X.RDB$EXCEPTION_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$EXCEPTION_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_EXCEPTION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_EXCEPTION, name, {});
MODIFY X
strcpy(X.RDB$MESSAGE, message.c_str());
@@ -5598,10 +5780,7 @@ bool CreateAlterExceptionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
END_FOR
if (modified)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_EXCEPTION,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_EXCEPTION, name, {});
return modified;
}
@@ -5636,10 +5815,10 @@ void DropExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$EXCEPTIONS
- WITH X.RDB$EXCEPTION_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$EXCEPTION_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_EXCEPTION, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_EXCEPTION, name, {});
ERASE X;
if (!X.RDB$SECURITY_CLASS.NULL)
@@ -5652,10 +5831,7 @@ void DropExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
deletePrivilegesByRelName(tdbb, transaction, name, obj_exception);
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_EXCEPTION,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_EXCEPTION, name, {});
else if (!silent)
{
// msg 144: "Exception not found"
@@ -5692,7 +5868,7 @@ void CreateAlterSequenceNode::checkPermission(thread_db* tdbb, jrd_tra* transact
return;
}
- SCL_check_create_access(tdbb, obj_generators);
+ SCL_check_create_access(tdbb, obj_generators, name.schema);
}
void CreateAlterSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -5712,7 +5888,7 @@ void CreateAlterSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsql
else
{
// msg 214: "Sequence not found"
- status_exception::raise(Arg::PrivateDyn(214) << name);
+ status_exception::raise(Arg::PrivateDyn(214) << name.toQuotedString());
}
}
}
@@ -5745,7 +5921,7 @@ void CreateAlterSequenceNode::putErrorPrefix(Firebird::Arg::StatusVector& status
else
rc = isc_dsql_create_sequence_failed;
}
- statusVector << Firebird::Arg::Gds(rc) << name;
+ statusVector << Firebird::Arg::Gds(rc) << name.toQuotedString();
}
void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -5754,8 +5930,7 @@ void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_generator))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SEQUENCE, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_generator);
@@ -5765,13 +5940,12 @@ void CreateAlterSequenceNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch
{
initialStep = step.value();
if (initialStep == 0)
- status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << name.toQuotedString());
}
store(tdbb, transaction, name, fb_sysflag_user, val, initialStep);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SEQUENCE, name, {});
}
bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -5793,10 +5967,9 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
return false;
if (forbidden && !tdbb->getAttachment()->isRWGbak())
- status_exception::raise(Arg::Gds(isc_dyn_cant_modify_sysobj) << "generator" << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_cant_modify_sysobj) << "generator" << name.toQuotedString());
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE, name, {});
fb_assert(restartSpecified && value.has_value());
const SINT64 val = value.value_or(0);
@@ -5804,7 +5977,7 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
{
const SLONG newStep = step.value();
if (newStep == 0)
- status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << name.toQuotedString());
// Perhaps it's better to move this to DFW?
if (newStep != oldStep)
@@ -5812,12 +5985,13 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
}
transaction->getGenIdCache()->put(id, val);
- dsc desc;
- desc.makeText((USHORT) name.length(), ttype_metadata, (UCHAR*) name.c_str());
- DFW_post_work(transaction, dfw_set_generator, &desc, id);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_SEQUENCE,
- name, NULL);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText((USHORT) name.schema.length(), ttype_metadata, (UCHAR*) name.schema.c_str());
+ nameDesc.makeText((USHORT) name.object.length(), ttype_metadata, (UCHAR*) name.object.c_str());
+ DFW_post_work(transaction, dfw_set_generator, &nameDesc, &schemaDesc, id);
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_SEQUENCE, name, {});
return true;
}
@@ -5828,10 +6002,10 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$GENERATORS
- WITH X.RDB$GENERATOR_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$GENERATOR_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SEQUENCE, name, {});
if (X.RDB$SYSTEM_FLAG == fb_sysflag_system)
{
@@ -5845,7 +6019,7 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
{
const SLONG newStep = step.value();
if (newStep == 0)
- status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_increment) << name.toQuotedString());
if (newStep != X.RDB$GENERATOR_INCREMENT)
{
@@ -5864,24 +6038,24 @@ bool CreateAlterSequenceNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
newValue - (!X.RDB$GENERATOR_INCREMENT.NULL ? X.RDB$GENERATOR_INCREMENT : 1));
}
- dsc desc;
- desc.makeText((USHORT) name.length(), ttype_metadata, (UCHAR*) name.c_str());
- DFW_post_work(transaction, dfw_set_generator, &desc, id);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText((USHORT) name.schema.length(), ttype_metadata, (UCHAR*) name.schema.c_str());
+ nameDesc.makeText((USHORT) name.object.length(), ttype_metadata, (UCHAR*) name.object.c_str());
+ DFW_post_work(transaction, dfw_set_generator, &nameDesc, &schemaDesc, id);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_SEQUENCE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_SEQUENCE, name, {});
found = true;
}
END_FOR
if (forbidden)
- status_exception::raise(Arg::Gds(isc_dyn_cant_modify_sysobj) << "generator" << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_dyn_cant_modify_sysobj) << "generator" << name.toQuotedString());
return found;
}
-SSHORT CreateAlterSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const MetaName& name,
+SSHORT CreateAlterSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name,
fb_sysflag sysFlag, SINT64 val, SLONG step)
{
Attachment* const attachment = transaction->tra_attachment;
@@ -5908,7 +6082,9 @@ SSHORT CreateAlterSequenceNode::store(thread_db* tdbb, jrd_tra* transaction, con
{
X.RDB$GENERATOR_ID = id;
X.RDB$SYSTEM_FLAG = (SSHORT) sysFlag;
- strcpy(X.RDB$GENERATOR_NAME, name.c_str());
+
+ strcpy(X.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(X.RDB$GENERATOR_NAME, name.object.c_str());
X.RDB$OWNER_NAME.NULL = FALSE;
strcpy(X.RDB$OWNER_NAME, ownerName.c_str());
@@ -5973,16 +6149,16 @@ void DropSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
GEN IN RDB$GENERATORS
- WITH GEN.RDB$GENERATOR_NAME EQ name.c_str()
+ WITH GEN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ GEN.RDB$GENERATOR_NAME EQ name.object.c_str()
{
if (GEN.RDB$SYSTEM_FLAG != 0)
{
// msg 272: "Cannot delete system generator @1"
- status_exception::raise(Arg::PrivateDyn(272) << name);
+ status_exception::raise(Arg::PrivateDyn(272) << name.toQuotedString());
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_SEQUENCE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_SEQUENCE, name, {});
ERASE GEN;
@@ -5996,25 +6172,23 @@ void DropSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
deletePrivilegesByRelName(tdbb, transaction, name, obj_generator);
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_SEQUENCE,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_SEQUENCE, name, {});
else if (!silent)
- status_exception::raise(Arg::Gds(isc_gennotdef) << Arg::Str(name));
+ status_exception::raise(Arg::Gds(isc_gennotdef) << name.toQuotedString());
savePoint.release(); // everything is ok
}
// Delete a record from RDB$GENERATORS, without verifying RDB$SYSTEM_FLAG.
-void DropSequenceNode::deleteIdentity(thread_db* tdbb, jrd_tra* transaction, const MetaName& name)
+void DropSequenceNode::deleteIdentity(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name)
{
AutoCacheRequest request(tdbb, drq_e_ident_gens, DYN_REQUESTS);
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
GEN IN RDB$GENERATORS
- WITH GEN.RDB$GENERATOR_NAME EQ name.c_str()
+ WITH GEN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ GEN.RDB$GENERATOR_NAME EQ name.object.c_str()
{
ERASE GEN;
@@ -6044,13 +6218,15 @@ void RelationNode::FieldDefinition::modify(thread_db* tdbb, jrd_tra* transaction
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFR IN RDB$RELATION_FIELDS
- WITH RFR.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH RFR.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ RFR.RDB$RELATION_NAME EQ relationName.object.c_str() AND
RFR.RDB$FIELD_NAME EQ name.c_str()
{
// ASF: This is prepared only to modify view fields!
MODIFY RFR
- strcpy(RFR.RDB$FIELD_SOURCE, fieldSource.c_str());
+ strcpy(RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, fieldSource.schema.c_str());
+ strcpy(RFR.RDB$FIELD_SOURCE, fieldSource.object.c_str());
RFR.RDB$COLLATION_ID.NULL = TRUE;
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
@@ -6101,7 +6277,7 @@ void RelationNode::FieldDefinition::modify(thread_db* tdbb, jrd_tra* transaction
RFR.RDB$VIEW_CONTEXT = viewContext.value();
DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value(),
- baseField.c_str(), RFR.RDB$FIELD_SOURCE);
+ baseField.c_str(), RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, RFR.RDB$FIELD_SOURCE);
}
END_MODIFY
}
@@ -6118,8 +6294,10 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
RFR IN RDB$RELATION_FIELDS
{
strcpy(RFR.RDB$FIELD_NAME, name.c_str());
- strcpy(RFR.RDB$RELATION_NAME, relationName.c_str());
- strcpy(RFR.RDB$FIELD_SOURCE, fieldSource.c_str());
+ strcpy(RFR.RDB$SCHEMA_NAME, relationName.schema.c_str());
+ strcpy(RFR.RDB$RELATION_NAME, relationName.object.c_str());
+ strcpy(RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, fieldSource.schema.c_str());
+ strcpy(RFR.RDB$FIELD_SOURCE, fieldSource.object.c_str());
RFR.RDB$SYSTEM_FLAG = 0;
RFR.RDB$COLLATION_ID.NULL = TRUE;
@@ -6140,10 +6318,10 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
RFR.RDB$COLLATION_ID = collationId.value();
}
- if (identitySequence.hasData())
+ if (identitySequence.object.hasData())
{
RFR.RDB$GENERATOR_NAME.NULL = FALSE;
- strcpy(RFR.RDB$GENERATOR_NAME, identitySequence.c_str());
+ strcpy(RFR.RDB$GENERATOR_NAME, identitySequence.object.c_str());
RFR.RDB$IDENTITY_TYPE.NULL = FALSE;
RFR.RDB$IDENTITY_TYPE = identityType.value();
@@ -6199,12 +6377,73 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
RFR.RDB$VIEW_CONTEXT = viewContext.value();
DYN_UTIL_find_field_source(tdbb, transaction, relationName, viewContext.value(),
- baseField.c_str(), RFR.RDB$FIELD_SOURCE);
+ baseField.c_str(), RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, RFR.RDB$FIELD_SOURCE);
}
}
END_STORE
}
+DdlNode* RelationNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
+{
+ const auto processAddConstraint = [&dsqlScratch](AddConstraintClause* const constraintClause)
+ {
+ if (constraintClause->refRelation.object.hasData())
+ dsqlScratch->qualifyExistingName(constraintClause->refRelation, obj_relation);
+ };
+
+ for (auto clause : clauses)
+ {
+ switch (clause->type)
+ {
+ case Clause::TYPE_ADD_CONSTRAINT:
+ {
+ const auto constraintClause = static_cast(clause.getObject());
+ processAddConstraint(constraintClause);
+ break;
+ }
+
+ case Clause::TYPE_ADD_COLUMN:
+ {
+ const auto addColumnClause = static_cast(clause.getObject());
+
+ dsqlScratch->qualifyExistingName(addColumnClause->field->typeOfTable, obj_relation);
+ dsqlScratch->qualifyExistingName(addColumnClause->field->typeOfName, obj_field);
+ dsqlScratch->qualifyExistingName(addColumnClause->field->charSet, obj_charset);
+ dsqlScratch->qualifyExistingName(addColumnClause->field->collate, obj_collation);
+
+ for (auto& constraintClause : addColumnClause->constraints)
+ processAddConstraint(&constraintClause);
+
+ break;
+ }
+
+ case Clause::TYPE_ALTER_COL_TYPE:
+ {
+ const auto alterColTypeClause = static_cast(clause.getObject());
+ dsqlScratch->qualifyExistingName(alterColTypeClause->field->typeOfName, obj_field);
+ dsqlScratch->qualifyExistingName(alterColTypeClause->field->charSet, obj_field);
+ dsqlScratch->qualifyExistingName(alterColTypeClause->field->collate, obj_field);
+ break;
+ }
+
+ case Clause::TYPE_ALTER_COL_NAME:
+ case Clause::TYPE_ALTER_COL_NULL:
+ case Clause::TYPE_ALTER_COL_POS:
+ case Clause::TYPE_DROP_COLUMN:
+ case Clause::TYPE_DROP_CONSTRAINT:
+ case Clause::TYPE_ALTER_SQL_SECURITY:
+ case Clause::TYPE_ALTER_PUBLICATION:
+ break;
+
+ default:
+ fb_assert(false);
+ break;
+ }
+ }
+
+ return DdlNode::dsqlPass(dsqlScratch);
+}
+
// Delete local field.
//
// The rules for dropping a regular column:
@@ -6231,7 +6470,8 @@ void RelationNode::FieldDefinition::store(thread_db* tdbb, jrd_tra* transaction)
// done by code and system triggers. See the functional description of
// deleteKeyConstraint function for detail.
bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName, bool silent, std::function preChangeHandler)
+ const QualifiedName& relationName, const MetaName& fieldName, bool silent,
+ std::function preChangeHandler)
{
bool preChangeHandlerWasExecuted = false;
@@ -6253,11 +6493,15 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
X IN RDB$RELATION_FIELDS CROSS
Y IN RDB$RELATION_FIELDS CROSS
Z IN RDB$VIEW_RELATIONS
- WITH X.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH X.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ relationName.object.c_str() AND
X.RDB$FIELD_NAME EQ fieldName.c_str() AND
X.RDB$FIELD_NAME EQ Y.RDB$BASE_FIELD AND
+ X.RDB$FIELD_SOURCE_SCHEMA_NAME EQ Y.RDB$FIELD_SOURCE_SCHEMA_NAME AND
X.RDB$FIELD_SOURCE EQ Y.RDB$FIELD_SOURCE AND
+ Y.RDB$SCHEMA_NAME EQ Z.RDB$SCHEMA_NAME AND
Y.RDB$RELATION_NAME EQ Z.RDB$VIEW_NAME AND
+ X.RDB$SCHEMA_NAME EQ Z.RDB$RELATION_SCHEMA_NAME AND
X.RDB$RELATION_NAME EQ Z.RDB$RELATION_NAME AND
Y.RDB$VIEW_CONTEXT EQ Z.RDB$VIEW_CONTEXT
{
@@ -6265,7 +6509,10 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
// msg 52: "field %s from relation %s is referenced in view %s"
status_exception::raise(
- Arg::PrivateDyn(52) << fieldName << relationName << Y.RDB$RELATION_NAME);
+ Arg::PrivateDyn(52) <<
+ fieldName <<
+ relationName.toQuotedString() <<
+ QualifiedName(Y.RDB$RELATION_NAME, Y.RDB$SCHEMA_NAME).toQuotedString());
}
END_FOR
@@ -6280,25 +6527,26 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
IDX IN RDB$INDICES CROSS
IDX_SEG IN RDB$INDEX_SEGMENTS CROSS
REL_CONST IN RDB$RELATION_CONSTRAINTS
- WITH IDX.RDB$RELATION_NAME EQ relationName.c_str() AND
- REL_CONST.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH IDX.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ IDX.RDB$RELATION_NAME EQ relationName.object.c_str() AND
+ REL_CONST.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ REL_CONST.RDB$RELATION_NAME EQ relationName.object.c_str() AND
IDX_SEG.RDB$FIELD_NAME EQ fieldName.c_str() AND
+ IDX.RDB$SCHEMA_NAME EQ IDX_SEG.RDB$SCHEMA_NAME AND
IDX.RDB$INDEX_NAME EQ IDX_SEG.RDB$INDEX_NAME AND
+ IDX.RDB$SCHEMA_NAME EQ REL_CONST.RDB$SCHEMA_NAME AND
IDX.RDB$INDEX_NAME EQ REL_CONST.RDB$INDEX_NAME AND
REL_CONST.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY
{
executePreChangeHandler();
if (IDX.RDB$SEGMENT_COUNT == 1)
- {
- deleteKeyConstraint(tdbb, transaction, relationName,
- REL_CONST.RDB$CONSTRAINT_NAME, IDX.RDB$INDEX_NAME);
- }
+ deleteKeyConstraint(tdbb, transaction, relationName, REL_CONST.RDB$CONSTRAINT_NAME, IDX.RDB$INDEX_NAME);
else
{
// msg 187: "field %s from relation %s is referenced in index %s"
status_exception::raise(
- Arg::PrivateDyn(187) << fieldName << relationName << IDX.RDB$INDEX_NAME);
+ Arg::PrivateDyn(187) << fieldName << relationName.toQuotedString() << IDX.RDB$INDEX_NAME);
}
}
END_FOR
@@ -6314,11 +6562,14 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES CROSS
IDX_SEG IN RDB$INDEX_SEGMENTS
- WITH IDX.RDB$INDEX_NAME EQ IDX_SEG.RDB$INDEX_NAME AND
- IDX.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH IDX.RDB$SCHEMA_NAME EQ IDX_SEG.RDB$SCHEMA_NAME AND
+ IDX.RDB$INDEX_NAME EQ IDX_SEG.RDB$INDEX_NAME AND
+ IDX.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ IDX.RDB$RELATION_NAME EQ relationName.object.c_str() AND
IDX_SEG.RDB$FIELD_NAME EQ fieldName.c_str() AND
NOT ANY REL_CONST IN RDB$RELATION_CONSTRAINTS
- WITH REL_CONST.RDB$RELATION_NAME EQ IDX.RDB$RELATION_NAME AND
+ WITH REL_CONST.RDB$SCHEMA_NAME EQ IDX.RDB$SCHEMA_NAME AND
+ REL_CONST.RDB$RELATION_NAME EQ IDX.RDB$RELATION_NAME AND
REL_CONST.RDB$INDEX_NAME EQ IDX.RDB$INDEX_NAME
{
executePreChangeHandler();
@@ -6326,7 +6577,7 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
// msg 187: "field %s from relation %s is referenced in index %s"
status_exception::raise(
Arg::PrivateDyn(187) <<
- fieldName << relationName <<
+ fieldName << relationName.toQuotedString() <<
fb_utils::exact_name_limit(IDX.RDB$INDEX_NAME, sizeof(IDX.RDB$INDEX_NAME)));
}
END_FOR
@@ -6340,12 +6591,16 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFR IN RDB$RELATION_FIELDS
WITH RFR.RDB$FIELD_NAME EQ fieldName.c_str() AND
- RFR.RDB$RELATION_NAME EQ relationName.c_str()
+ RFR.RDB$SCHEMA_NAME EQ relationName.schema.c_str() AND
+ RFR.RDB$RELATION_NAME EQ relationName.object.c_str()
{
executePreChangeHandler();
if (!RFR.RDB$GENERATOR_NAME.NULL)
- DropSequenceNode::deleteIdentity(tdbb, transaction, RFR.RDB$GENERATOR_NAME);
+ {
+ DropSequenceNode::deleteIdentity(tdbb, transaction,
+ QualifiedName(RFR.RDB$GENERATOR_NAME, RFR.RDB$SCHEMA_NAME));
+ }
ERASE RFR;
@@ -6356,7 +6611,8 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
}
found = true;
- DropRelationNode::deleteGlobalField(tdbb, transaction, RFR.RDB$FIELD_SOURCE);
+ DropRelationNode::deleteGlobalField(tdbb, transaction,
+ QualifiedName(RFR.RDB$FIELD_SOURCE, RFR.RDB$SCHEMA_NAME));
}
END_FOR
@@ -6364,7 +6620,8 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$RELATION_NAME EQ relationName.c_str() AND
+ WITH PRIV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(relationName.schema.c_str(), '') AND
+ PRIV.RDB$RELATION_NAME EQ relationName.object.c_str() AND
PRIV.RDB$FIELD_NAME EQ fieldName.c_str() AND
PRIV.RDB$OBJECT_TYPE = obj_relation AND
PRIV.RDB$GRANTOR NOT MISSING
@@ -6378,7 +6635,7 @@ bool RelationNode::deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
if (!found && !silent)
{
// msg 176: "column %s does not exist in table/view %s"
- status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName);
+ status_exception::raise(Arg::PrivateDyn(176) << fieldName << relationName.toQuotedString());
}
return found;
@@ -6414,7 +6671,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
{
FieldDefinition fieldDefinition(*tdbb->getDefaultPool());
- if (field->typeOfName.hasData())
+ if (field->typeOfName.object.hasData())
{
// Get the domain information.
if (!METD_get_domain(transaction, field, field->typeOfName))
@@ -6423,7 +6680,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_domain_not_found) << field->typeOfName);
+ Arg::Gds(isc_dsql_domain_not_found) << field->typeOfName.toQuotedString());
}
fieldDefinition.fieldSource = field->typeOfName;
@@ -6447,7 +6704,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
// Let's see if the field appears in a "primary_key (a, b, c)" relation constraint.
for (FB_SIZE_T i = 0; !notNullFlag && i < pkCols->getCount(); ++i)
{
- if (field->fld_name == (*pkCols)[i].c_str())
+ if (field->fld_name == (*pkCols)[i])
notNullFlag = true;
}
}
@@ -6461,7 +6718,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
if (position >= 0)
fieldDefinition.position = position;
- if (field->typeOfName.isEmpty())
+ if (field->typeOfName.object.isEmpty())
{
string computedSource;
BlrDebugWriter::BlrData computedValue;
@@ -6477,13 +6734,17 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
field->resolve(dsqlScratch);
// Generate a domain.
+
+ if (fieldDefinition.fieldSource.schema.isEmpty())
+ fieldDefinition.fieldSource.schema = name.schema;
+
storeGlobalField(tdbb, transaction, fieldDefinition.fieldSource, field,
computedSource, computedValue);
}
else
{
// Resolve possible additional collation for domains. For plain types it is already resolved above.
- if (field->collate.hasData())
+ if (field->collate.object.hasData())
DDL_resolve_intl_type(dsqlScratch, field, field->collate);
}
@@ -6495,7 +6756,8 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_type_not_supp_ext_tab) << typeName << name << field->fld_name);
+ Arg::Gds(isc_dsql_type_not_supp_ext_tab) << typeName <<
+ name.toQuotedString() << field->fld_name.toQuotedString());
}
if (clause->identityOptions)
@@ -6504,7 +6766,7 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
{
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
Arg::Str(field->fld_name) <<
- Arg::Str(name));
+ name.toQuotedString());
}
dsc desc;
@@ -6513,9 +6775,10 @@ void RelationNode::defineField(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
if (!desc.isExact() || desc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
- status_exception::raise(Arg::PrivateDyn(273) << field->fld_name << name);
+ status_exception::raise(Arg::PrivateDyn(273) << field->fld_name << name.toQuotedString());
}
+ fieldDefinition.identitySequence.schema = fieldDefinition.relationName.schema;
DYN_UTIL_generate_generator_name(tdbb, fieldDefinition.identitySequence);
fieldDefinition.identityType = clause->identityOptions->type;
@@ -6620,8 +6883,10 @@ void RelationNode::makeConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
Constraint::TYPE_PK : Constraint::TYPE_UNIQUE;
constraint.name = clause->name;
constraint.create->index = clause->index;
+
if (constraint.create->index && constraint.create->index->name.isEmpty())
constraint.create->index->name = constraint.name;
+
constraint.create->columns = clause->columns;
break;
}
@@ -6677,6 +6942,7 @@ void RelationNode::makeConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
// Define the foreign key index and the triggers that may be needed
// for referential integrity action.
constraint.create->index = clause->index;
+
if (constraint.create->index && constraint.create->index->name.isEmpty())
constraint.create->index->name = constraint.name;
@@ -6761,10 +7027,14 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
jrd_tra* transaction, MetaName& constraintName, Constraint& constraint)
{
if (constraintName.isEmpty())
- DYN_UTIL_generate_constraint_name(tdbb, constraintName);
+ {
+ QualifiedName qualifiedConstraintName(constraintName, name.schema);
+ DYN_UTIL_generate_constraint_name(tdbb, qualifiedConstraintName);
+ constraintName = qualifiedConstraintName.object;
+ }
AutoCacheRequest request(tdbb, drq_s_rel_con, DYN_REQUESTS);
- MetaName referredIndexName;
+ QualifiedName referredIndexName;
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
CRT IN RDB$RELATION_CONSTRAINTS
@@ -6772,7 +7042,8 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
CRT.RDB$INDEX_NAME.NULL = TRUE;
strcpy(CRT.RDB$CONSTRAINT_NAME, constraintName.c_str());
- strcpy(CRT.RDB$RELATION_NAME, name.c_str());
+ strcpy(CRT.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(CRT.RDB$RELATION_NAME, name.object.c_str());
switch (constraint.type)
{
@@ -6820,16 +7091,18 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
definition.refRelation = constraint.refRelation;
definition.refColumns = constraint.refColumns;
- CreateIndexNode::store(tdbb, transaction, constraint.index->name,
- definition, &referredIndexName);
+ QualifiedName qualifiedIndexName(constraint.index->name, name.schema);
+ CreateIndexNode::store(tdbb, transaction, qualifiedIndexName, definition, &referredIndexName);
+ constraint.index->name = qualifiedIndexName.object;
CRT.RDB$INDEX_NAME.NULL = FALSE;
strcpy(CRT.RDB$INDEX_NAME, constraint.index->name.c_str());
checkForeignKeyTempScope(tdbb, transaction, name, referredIndexName);
- // Check that we have references permissions on the table and
+ // Check that we have references permissions on the schema, table and
// fields that the index:referredIndexName is on.
+ SCL_check_schema(tdbb, referredIndexName.schema, SCL_usage);
SCL_check_index(tdbb, referredIndexName, 0, SCL_references);
break;
@@ -6841,7 +7114,7 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (constraint.type == Constraint::TYPE_NOT_NULL)
{
fb_assert(constraint.columns.getCount() == 1);
- DYN_UTIL_store_check_constraints(tdbb, transaction, constraintName,
+ DYN_UTIL_store_check_constraints(tdbb, transaction, QualifiedName(constraintName, name.schema),
*constraint.columns.begin());
}
@@ -6852,7 +7125,8 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
++trigger)
{
trigger->store(tdbb, dsqlScratch, transaction);
- DYN_UTIL_store_check_constraints(tdbb, transaction, constraintName, trigger->name);
+ DYN_UTIL_store_check_constraints(tdbb, transaction, QualifiedName(constraintName, name.schema),
+ trigger->name.object);
}
if (constraint.type == Constraint::TYPE_NOT_NULL || constraint.type == Constraint::TYPE_CHECK)
@@ -6871,12 +7145,15 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
IDS IN RDB$INDEX_SEGMENTS CROSS
RFR IN RDB$RELATION_FIELDS CROSS
FLX IN RDB$FIELDS
- WITH IDS.RDB$INDEX_NAME EQ constraint.index->name.c_str() AND
- RFR.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH IDS.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDS.RDB$INDEX_NAME EQ constraint.index->name.c_str() AND
+ RFR.RDB$SCHEMA_NAME EQ IDS.RDB$SCHEMA_NAME AND
+ RFR.RDB$RELATION_NAME EQ name.object.c_str() AND
RFR.RDB$FIELD_NAME EQ IDS.RDB$FIELD_NAME AND
+ FLX.RDB$SCHEMA_NAME EQUIV RFR.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLX.RDB$FIELD_NAME EQ RFR.RDB$FIELD_SOURCE
- REDUCED TO IDS.RDB$FIELD_NAME, IDS.RDB$INDEX_NAME, FLX.RDB$NULL_FLAG
- SORTED BY ASCENDING IDS.RDB$FIELD_NAME
+ REDUCED TO RFR.RDB$SCHEMA_NAME, RFR.RDB$FIELD_NAME, IDS.RDB$INDEX_NAME, FLX.RDB$NULL_FLAG, RFR.RDB$NULL_FLAG
+ SORTED BY ASCENDING RFR.RDB$SCHEMA_NAME, RFR.RDB$FIELD_NAME
{
if ((FLX.RDB$NULL_FLAG.NULL || !FLX.RDB$NULL_FLAG) &&
(RFR.RDB$NULL_FLAG.NULL || !RFR.RDB$NULL_FLAG) &&
@@ -6884,11 +7161,12 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
{
// msg 123: "Field: %s not defined as NOT NULL - can't be used in PRIMARY KEY
// constraint definition"
- status_exception::raise(Arg::PrivateDyn(123) << MetaName(RFR.RDB$FIELD_NAME));
+ status_exception::raise(Arg::PrivateDyn(123) <<
+ QualifiedName(RFR.RDB$FIELD_NAME, RFR.RDB$SCHEMA_NAME).toQuotedString());
}
++uniqueCount;
- fieldList.add() = IDS.RDB$FIELD_NAME;
+ fieldList.add() = RFR.RDB$FIELD_NAME;
}
END_FOR
@@ -6896,7 +7174,8 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDS IN RDB$INDEX_SEGMENTS
- WITH IDS.RDB$INDEX_NAME EQ constraint.index->name.c_str()
+ WITH IDS.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDS.RDB$INDEX_NAME EQ constraint.index->name.c_str()
{
++allCount;
}
@@ -6919,12 +7198,16 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
CRT IN RDB$RELATION_CONSTRAINTS
- WITH CRT.RDB$INDEX_NAME EQ referredIndexName.c_str() AND
+ WITH CRT.RDB$SCHEMA_NAME EQ referredIndexName.schema.c_str() AND
+ CRT.RDB$INDEX_NAME EQ referredIndexName.object.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE = PRIMARY_KEY OR
CRT.RDB$CONSTRAINT_TYPE = UNIQUE_CNSTRT)
{
+ fb_utils::exact_name_limit(CRT.RDB$SCHEMA_NAME, sizeof(CRT.RDB$SCHEMA_NAME));
+ strcpy(REF.RDB$CONST_SCHEMA_NAME_UQ, CRT.RDB$SCHEMA_NAME);
fb_utils::exact_name_limit(CRT.RDB$CONSTRAINT_NAME, sizeof(CRT.RDB$CONSTRAINT_NAME));
strcpy(REF.RDB$CONST_NAME_UQ, CRT.RDB$CONSTRAINT_NAME);
+ strcpy(REF.RDB$SCHEMA_NAME, name.schema.c_str());
strcpy(REF.RDB$CONSTRAINT_NAME, constraintName.c_str());
REF.RDB$UPDATE_RULE.NULL = FALSE;
@@ -6944,20 +7227,21 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
request.reset(tdbb, drq_c_dup_con, DYN_REQUESTS);
- MetaName indexName;
+ QualifiedName indexName;
int listIndex = -1;
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
CRT IN RDB$RELATION_CONSTRAINTS CROSS
- IDS IN RDB$INDEX_SEGMENTS OVER RDB$INDEX_NAME
- WITH CRT.RDB$RELATION_NAME EQ name.c_str() AND
+ IDS IN RDB$INDEX_SEGMENTS OVER RDB$SCHEMA_NAME, RDB$INDEX_NAME
+ WITH CRT.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ CRT.RDB$RELATION_NAME EQ name.object.c_str() AND
CRT.RDB$CONSTRAINT_NAME NE constraintName.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY OR
CRT.RDB$CONSTRAINT_TYPE EQ UNIQUE_CNSTRT)
SORTED BY CRT.RDB$INDEX_NAME, DESCENDING IDS.RDB$FIELD_NAME
{
- if (indexName != CRT.RDB$INDEX_NAME)
+ if (indexName != QualifiedName(CRT.RDB$INDEX_NAME, CRT.RDB$SCHEMA_NAME))
{
if (listIndex >= 0)
found = false;
@@ -6966,7 +7250,7 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
break;
listIndex = fieldList.getCount() - 1;
- indexName = CRT.RDB$INDEX_NAME;
+ indexName = QualifiedName(CRT.RDB$INDEX_NAME, CRT.RDB$SCHEMA_NAME);
found = true;
}
@@ -7018,7 +7302,7 @@ void RelationNode::defineCheckConstraintTrigger(DsqlCompilerScratch* dsqlScratch
// Specify that the trigger should abort if the condition is not met.
NestConst actionNode = FB_NEW_POOL(pool) CompoundStmtNode(pool);
- ExceptionNode* exceptionNode = FB_NEW_POOL(pool) ExceptionNode(pool, CHECK_CONSTRAINT_EXCEPTION);
+ ExceptionNode* exceptionNode = FB_NEW_POOL(pool) ExceptionNode(pool, QualifiedName(CHECK_CONSTRAINT_EXCEPTION));
exceptionNode->exception->type = ExceptionItem::GDS_CODE;
actionNode->statements.add(exceptionNode);
@@ -7073,6 +7357,7 @@ void RelationNode::defineCheckConstraintTrigger(DsqlCompilerScratch* dsqlScratch
TriggerDefinition& trigger = constraint.triggers.add();
trigger.systemFlag = fb_sysflag_check_constraint;
trigger.relationName = name;
+ trigger.name.schema = name.schema;
trigger.type = triggerType;
trigger.source = clause->source;
trigger.blrData = blrWriter.getBlrData();
@@ -7106,18 +7391,42 @@ void RelationNode::defineSetDefaultTrigger(DsqlCompilerScratch* dsqlScratch,
blrWriter.appendUChar(blr_dcl_variable);
blrWriter.appendUShort(index);
- blrWriter.appendUChar(blr_column_name);
- blrWriter.appendUChar(blr_domain_type_of);
- blrWriter.appendNullString(0, name.c_str());
- blrWriter.appendNullString(0, column->c_str());
+ if (constraint.refRelation.schema != name.schema)
+ {
+ blrWriter.appendUChar(blr_column_name3);
+ blrWriter.appendUChar(blr_domain_type_of);
+ blrWriter.appendMetaString(name.schema.c_str());
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString(column->c_str());
+ blrWriter.appendUChar(0);
+ }
+ else
+ {
+ blrWriter.appendUChar(blr_column_name);
+ blrWriter.appendUChar(blr_domain_type_of);
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString(column->c_str());
+ }
blrWriter.appendUChar(blr_dcl_variable);
blrWriter.appendUShort(index + 1);
- blrWriter.appendUChar(blr_column_name);
- blrWriter.appendUChar(blr_domain_full);
- blrWriter.appendNullString(0, name.c_str());
- blrWriter.appendNullString(0, column->c_str());
+ if (constraint.refRelation.schema != name.schema)
+ {
+ blrWriter.appendUChar(blr_column_name3);
+ blrWriter.appendUChar(blr_domain_full);
+ blrWriter.appendMetaString(name.schema.c_str());
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString(column->c_str());
+ blrWriter.appendUChar(0);
+ }
+ else
+ {
+ blrWriter.appendUChar(blr_column_name);
+ blrWriter.appendUChar(blr_domain_full);
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString(column->c_str());
+ }
blrWriter.appendUChar(blr_assignment);
blrWriter.appendUChar(blr_null);
@@ -7164,7 +7473,7 @@ void RelationNode::defineSetDefaultTrigger(DsqlCompilerScratch* dsqlScratch,
// The context for the foreign key relation.
blrWriter.appendUChar(blr_field);
blrWriter.appendUChar(2);
- blrWriter.appendNullString(0, column->c_str());
+ blrWriter.appendMetaString(column->c_str());
}
blrWriter.appendUChar(blr_end);
@@ -7180,6 +7489,7 @@ void RelationNode::defineSetDefaultTrigger(DsqlCompilerScratch* dsqlScratch,
trigger.systemFlag = fb_sysflag_referential_constraint;
trigger.fkTrigger = true;
trigger.relationName = constraint.refRelation;
+ trigger.name.schema = constraint.refRelation.schema;
trigger.type = (onUpdate ? POST_MODIFY_TRIGGER : POST_ERASE_TRIGGER);
trigger.blrData = blrWriter.getBlrData();
}
@@ -7221,6 +7531,7 @@ void RelationNode::defineSetNullTrigger(DsqlCompilerScratch* dsqlScratch, Constr
trigger.systemFlag = fb_sysflag_referential_constraint;
trigger.fkTrigger = true;
trigger.relationName = constraint.refRelation;
+ trigger.name.schema = constraint.refRelation.schema;
trigger.type = (onUpdate ? POST_MODIFY_TRIGGER : POST_ERASE_TRIGGER);
trigger.blrData = blrWriter.getBlrData();
}
@@ -7237,11 +7548,21 @@ void RelationNode::defineDeleteCascadeTrigger(DsqlCompilerScratch* dsqlScratch,
blrWriter.appendUChar(blr_for);
blrWriter.appendUChar(blr_rse);
-
- // The context for the prim. key relation.
blrWriter.appendUChar(1);
- blrWriter.appendUChar(blr_relation);
- blrWriter.appendNullString(0, name.c_str());
+
+ if (constraint.refRelation.schema != name.schema)
+ {
+ blrWriter.appendUChar(blr_relation3);
+ blrWriter.appendMetaString(name.schema.c_str());
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString("");
+ }
+ else
+ {
+ blrWriter.appendUChar(blr_relation);
+ blrWriter.appendMetaString(name.object.c_str());
+ }
+
// The context for the foreign key relation.
blrWriter.appendUChar(2);
@@ -7257,6 +7578,7 @@ void RelationNode::defineDeleteCascadeTrigger(DsqlCompilerScratch* dsqlScratch,
trigger.systemFlag = fb_sysflag_referential_constraint;
trigger.fkTrigger = true;
trigger.relationName = constraint.refRelation;
+ trigger.name.schema = constraint.refRelation.schema;
trigger.type = POST_ERASE_TRIGGER;
trigger.blrData = blrWriter.getBlrData();
}
@@ -7296,6 +7618,7 @@ void RelationNode::defineUpdateCascadeTrigger(DsqlCompilerScratch* dsqlScratch,
trigger.systemFlag = fb_sysflag_referential_constraint;
trigger.fkTrigger = true;
trigger.relationName = constraint.refRelation;
+ trigger.name.schema = constraint.refRelation.schema;
trigger.type = POST_MODIFY_TRIGGER;
trigger.blrData = blrWriter.getBlrData();
}
@@ -7316,11 +7639,21 @@ void RelationNode::generateUnnamedTriggerBeginning(Constraint& constraint, bool
blrWriter.appendUChar(blr_for);
blrWriter.appendUChar(blr_rse);
-
- // The context for the prim. key relation.
blrWriter.appendUChar(1);
- blrWriter.appendUChar(blr_relation);
- blrWriter.appendNullString(0, name.c_str());
+
+ if (constraint.refRelation.schema != name.schema)
+ {
+ blrWriter.appendUChar(blr_relation3);
+ blrWriter.appendMetaString(name.schema.c_str());
+ blrWriter.appendMetaString(name.object.c_str());
+ blrWriter.appendMetaString("");
+ }
+ else
+ {
+ blrWriter.appendUChar(blr_relation);
+ blrWriter.appendMetaString(name.object.c_str());
+ }
+
// The context for the foreign key relation.
blrWriter.appendUChar(2);
@@ -7408,7 +7741,7 @@ void RelationNode::stuffTriggerFiringCondition(const Constraint& constraint, Blr
void RelationNode::addToPublication(thread_db* tdbb,
jrd_tra* transaction,
- const MetaName& tableName,
+ const QualifiedName& tableName,
const MetaName& pubName)
{
AutoCacheRequest request(tdbb, drq_s_pub_tab, DYN_REQUESTS);
@@ -7417,10 +7750,8 @@ void RelationNode::addToPublication(thread_db* tdbb,
PTAB IN RDB$PUBLICATION_TABLES
{
strcpy(PTAB.RDB$PUBLICATION_NAME, pubName.c_str());
- PTAB.RDB$PUBLICATION_NAME.NULL = FALSE;
-
- strcpy(PTAB.RDB$TABLE_NAME, tableName.c_str());
- PTAB.RDB$TABLE_NAME.NULL = FALSE;
+ strcpy(PTAB.RDB$TABLE_SCHEMA_NAME, tableName.schema.c_str());
+ strcpy(PTAB.RDB$TABLE_NAME, tableName.object.c_str());
}
END_STORE
}
@@ -7428,15 +7759,16 @@ void RelationNode::addToPublication(thread_db* tdbb,
void RelationNode::dropFromPublication(thread_db* tdbb,
jrd_tra* transaction,
- const MetaName& tableName,
+ const QualifiedName& tableName,
const MetaName& pubName)
{
AutoCacheRequest request(tdbb, drq_e_pub_tab, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PTAB IN RDB$PUBLICATION_TABLES
- WITH PTAB.RDB$PUBLICATION_NAME EQ pubName.c_str()
- AND PTAB.RDB$TABLE_NAME EQ tableName.c_str()
+ WITH PTAB.RDB$PUBLICATION_NAME EQ pubName.c_str() AND
+ PTAB.RDB$TABLE_SCHEMA_NAME EQ tableName.schema.c_str() AND
+ PTAB.RDB$TABLE_NAME EQ tableName.object.c_str()
{
ERASE PTAB;
}
@@ -7459,7 +7791,7 @@ string CreateRelationNode::internalPrint(NodePrinter& printer) const
void CreateRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- SCL_check_create_access(tdbb, obj_relations);
+ SCL_check_create_access(tdbb, obj_relations, name.schema);
}
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -7479,8 +7811,7 @@ void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScrat
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TABLE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_TABLE, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_relation);
@@ -7493,7 +7824,8 @@ void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScrat
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
REL IN RDB$RELATIONS
{
- strcpy(REL.RDB$RELATION_NAME, name.c_str());
+ strcpy(REL.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(REL.RDB$RELATION_NAME, name.object.c_str());
REL.RDB$SYSTEM_FLAG = 0;
REL.RDB$FLAGS = REL_sql;
REL.RDB$RELATION_TYPE = relationType.value();
@@ -7586,8 +7918,7 @@ void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScrat
dsqlScratch->relation->rel_flags &= ~REL_creating;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TABLE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_TABLE, name, {});
savePoint.release(); // everything is ok
@@ -7626,9 +7957,7 @@ string AlterRelationNode::internalPrint(NodePrinter& printer) const
void AlterRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter);
+ SCL_check_relation(tdbb, name, SCL_alter);
}
void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -7644,7 +7973,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_table_not_found) << name);
+ Arg::Gds(isc_dsql_table_not_found) << name.toQuotedString());
}
if (!dsqlScratch->relation)
@@ -7658,7 +7987,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_relation_err) <<
- Arg::Gds(isc_random) << name /***<<
+ Arg::Gds(isc_random) << name.toQuotedString() /***<<
Arg::Gds(isc_random) << linecol***/);
}
@@ -7669,7 +7998,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
if (!beforeTriggerWasExecuted)
{
beforeTriggerWasExecuted = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_TABLE, name, nullptr);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_TABLE, name, {});
}
};
@@ -7697,7 +8026,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFL IN RDB$RELATION_FIELDS
- WITH RFL.RDB$RELATION_NAME = relation->rel_name.c_str() AND
+ WITH RFL.RDB$SCHEMA_NAME = relation->rel_name.schema.c_str() AND
+ RFL.RDB$RELATION_NAME = relation->rel_name.object.c_str() AND
RFL.RDB$FIELD_NAME = addColumnClause->field->fld_name.c_str()
{
createColumn = false;
@@ -7732,7 +8062,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFL IN RDB$RELATION_FIELDS
WITH RFL.RDB$FIELD_NAME EQ clause->fromName.c_str() AND
- RFL.RDB$RELATION_NAME EQ name.c_str()
+ RFL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RFL.RDB$RELATION_NAME EQ name.object.c_str()
{
found = true;
@@ -7751,7 +8082,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
// msg 205: Cannot rename field %s to %s. A field with that name
// already exists in table %s.
status_exception::raise(
- Arg::PrivateDyn(205) << clause->fromName << clause->toName << name);
+ Arg::PrivateDyn(205) << clause->fromName << clause->toName << name.toQuotedString());
}
END_MODIFY
}
@@ -7760,7 +8091,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
if (!found)
{
// msg 176: "column %s does not exist in table/view %s"
- status_exception::raise(Arg::PrivateDyn(176) << clause->fromName << name);
+ status_exception::raise(Arg::PrivateDyn(176) << clause->fromName << name.toQuotedString());
}
AutoRequest request2;
@@ -7768,7 +8099,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RCL IN RDB$RELATION_CONSTRAINTS CROSS
CHK IN RDB$CHECK_CONSTRAINTS
- WITH RCL.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH RCL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RCL.RDB$RELATION_NAME EQ name.object.c_str() AND
RCL.RDB$CONSTRAINT_TYPE EQ NOT_NULL_CNSTRT AND
CHK.RDB$CONSTRAINT_NAME EQ RCL.RDB$CONSTRAINT_NAME AND
CHK.RDB$TRIGGER_NAME EQ clause->fromName.c_str()
@@ -7795,7 +8127,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFL IN RDB$RELATION_FIELDS
WITH RFL.RDB$FIELD_NAME EQ clause->name.c_str() AND
- RFL.RDB$RELATION_NAME EQ name.c_str()
+ RFL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RFL.RDB$RELATION_NAME EQ name.object.c_str()
{
found = true;
@@ -7804,7 +8137,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
if (!clause->notNullFlag && !RFL.RDB$GENERATOR_NAME.NULL)
{
// msg 274: Identity column @1 of table @2 cannot be changed to NULLable
- status_exception::raise(Arg::PrivateDyn(274) << clause->name << name);
+ status_exception::raise(Arg::PrivateDyn(274) << clause->name << name.toQuotedString());
}
if (clause->notNullFlag)
@@ -7828,8 +8161,10 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RCL IN RDB$RELATION_CONSTRAINTS CROSS
CHK IN RDB$CHECK_CONSTRAINTS
- WITH RCL.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH RCL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RCL.RDB$RELATION_NAME EQ name.object.c_str() AND
RCL.RDB$CONSTRAINT_TYPE EQ NOT_NULL_CNSTRT AND
+ CHK.RDB$SCHEMA_NAME EQ RCL.RDB$SCHEMA_NAME AND
CHK.RDB$CONSTRAINT_NAME EQ RCL.RDB$CONSTRAINT_NAME AND
CHK.RDB$TRIGGER_NAME EQ clause->name.c_str()
{
@@ -7847,7 +8182,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
if (!found)
{
// msg 176: "column %s does not exist in table/view %s"
- status_exception::raise(Arg::PrivateDyn(176) << clause->name << name);
+ status_exception::raise(Arg::PrivateDyn(176) << clause->name << name.toQuotedString());
}
break;
@@ -7911,7 +8246,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RC IN RDB$RELATION_CONSTRAINTS
WITH RC.RDB$CONSTRAINT_NAME EQ constraintName.c_str() AND
- RC.RDB$RELATION_NAME EQ name.c_str()
+ RC.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RC.RDB$RELATION_NAME EQ name.object.c_str()
{
found = true;
break;
@@ -7944,7 +8280,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
REL IN RDB$RELATIONS
- WITH REL.RDB$RELATION_NAME EQ name.c_str()
+ WITH REL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ REL.RDB$RELATION_NAME EQ name.object.c_str()
{
MODIFY REL
{
@@ -8021,7 +8358,8 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RC IN RDB$RELATION_CONSTRAINTS
WITH RC.RDB$CONSTRAINT_NAME EQ constraint->name.c_str() AND
- RC.RDB$RELATION_NAME EQ name.c_str()
+ RC.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RC.RDB$RELATION_NAME EQ name.object.c_str()
{
found = true;
ERASE RC;
@@ -8037,7 +8375,7 @@ void AlterRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
}
if (beforeTriggerWasExecuted)
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_TABLE, name, nullptr);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_TABLE, name, {});
savePoint.release(); // everything is ok
@@ -8116,10 +8454,13 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
RFR IN RDB$RELATION_FIELDS CROSS
REL IN RDB$RELATIONS CROSS
FLD IN RDB$FIELDS
- WITH REL.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
- FLD.RDB$FIELD_NAME = RFR.RDB$FIELD_SOURCE AND
- RFR.RDB$RELATION_NAME = name.c_str() AND
- RFR.RDB$FIELD_NAME = field->fld_name.c_str()
+ WITH RFR.RDB$SCHEMA_NAME = name.schema.c_str() AND
+ RFR.RDB$RELATION_NAME = name.object.c_str() AND
+ RFR.RDB$FIELD_NAME = field->fld_name.c_str() AND
+ REL.RDB$SCHEMA_NAME = RFR.RDB$SCHEMA_NAME AND
+ REL.RDB$RELATION_NAME = RFR.RDB$RELATION_NAME AND
+ FLD.RDB$SCHEMA_NAME EQUIV RFR.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ FLD.RDB$FIELD_NAME = RFR.RDB$FIELD_SOURCE
{
found = true;
@@ -8137,7 +8478,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FLD.RDB$FIELD_LENGTH, FLD.RDB$FIELD_SUB_TYPE, FLD.RDB$CHARACTER_SET_ID,
FLD.RDB$COLLATION_ID);
- origDom.dyn_fld_name = field->fld_name;
+ origDom.dyn_fld_name.object = field->fld_name;
origDom.dyn_charbytelen = FLD.RDB$FIELD_LENGTH;
origDom.dyn_dtype = FLD.RDB$FIELD_TYPE;
origDom.dyn_precision = FLD.RDB$FIELD_PRECISION;
@@ -8145,14 +8486,14 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
origDom.dyn_charlen = FLD.RDB$CHARACTER_LENGTH;
origDom.dyn_collation = FLD.RDB$COLLATION_ID;
origDom.dyn_null_flag = !FLD.RDB$NULL_FLAG.NULL && FLD.RDB$NULL_FLAG != 0;
- origDom.dyn_fld_source = RFR.RDB$FIELD_SOURCE;
+ origDom.dyn_fld_source = QualifiedName(RFR.RDB$FIELD_SOURCE, RFR.RDB$FIELD_SOURCE_SCHEMA_NAME);
// If the original field type is an array, force its blr type to blr_blob.
const bool hasDimensions = FLD.RDB$DIMENSIONS != 0;
if (hasDimensions)
origDom.dyn_dtype = blr_blob;
- const bool wasInternalDomain = fb_utils::implicit_domain(origDom.dyn_fld_source.c_str()) &&
+ const bool wasInternalDomain = fb_utils::implicit_domain(origDom.dyn_fld_source.object.c_str()) &&
RFR.RDB$BASE_FIELD.NULL;
string computedSource;
BlrDebugWriter::BlrData computedValue;
@@ -8171,7 +8512,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!RFR.RDB$GENERATOR_NAME.NULL)
{
// msg 275: Identity column @1 of table @2 cannot have default value
- status_exception::raise(Arg::PrivateDyn(275) << field->fld_name << name);
+ status_exception::raise(Arg::PrivateDyn(275) << field->fld_name << name.toQuotedString());
}
if (hasDimensions)
@@ -8216,7 +8557,8 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
// msg 230: "Local column %s default belongs to domain %s"
status_exception::raise(
Arg::PrivateDyn(230) <<
- field->fld_name << MetaName(FLD.RDB$FIELD_NAME));
+ field->fld_name <<
+ QualifiedName(FLD.RDB$FIELD_NAME, FLD.RDB$SCHEMA_NAME).toQuotedString());
}
}
else
@@ -8234,7 +8576,8 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
status_exception::raise(Arg::PrivateDyn(285) << field->fld_name);
}
- DropSequenceNode::deleteIdentity(tdbb, transaction, RFR.RDB$GENERATOR_NAME);
+ DropSequenceNode::deleteIdentity(tdbb, transaction,
+ QualifiedName(RFR.RDB$GENERATOR_NAME, name.schema));
MODIFY RFR
RFR.RDB$GENERATOR_NAME.NULL = TRUE;
@@ -8251,7 +8594,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
WITH GEN.RDB$GENERATOR_NAME EQ RFR.RDB$GENERATOR_NAME
{
const SLONG id = GEN.RDB$GENERATOR_ID;
- const MetaName genName(RFR.RDB$GENERATOR_NAME);
+ const QualifiedName genName(RFR.RDB$GENERATOR_NAME, RFR.RDB$SCHEMA_NAME);
if (clause->identityOptions->restart)
{
@@ -8277,17 +8620,17 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
{
status_exception::raise(Arg::Gds(isc_dyn_cant_use_zero_inc_ident) <<
Arg::Str(field->fld_name) <<
- Arg::Str(name));
+ name.toQuotedString());
}
MET_update_generator_increment(tdbb, id,
clause->identityOptions->increment.value());
}
- dsc desc;
- desc.makeText((USHORT) genName.length(), ttype_metadata,
- (UCHAR*) genName.c_str());
- DFW_post_work(transaction, dfw_set_generator, &desc, id);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText((USHORT) genName.schema.length(), ttype_metadata, (UCHAR*) genName.schema.c_str());
+ nameDesc.makeText((USHORT) genName.object.length(), ttype_metadata, (UCHAR*) genName.object.c_str());
+ DFW_post_work(transaction, dfw_set_generator, &nameDesc, &schemaDesc, id);
found = true;
}
@@ -8303,21 +8646,21 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
{
// We have the type. Default and type/domain are exclusive for now.
- MetaName newDomainName;
+ QualifiedName newDomainName;
dyn_fld newDom;
- if (field->typeOfName.hasData())
+ if (field->typeOfName.object.hasData())
{
// Case a1: Internal domain -> domain.
// Case a2: Domain -> domain.
newDomainName = field->typeOfName;
- if (fb_utils::implicit_domain(newDomainName.c_str()))
+ if (fb_utils::implicit_domain(newDomainName.object.c_str()))
{
// msg 224: "Cannot use the internal domain %s as new type for field %s".
status_exception::raise(
- Arg::PrivateDyn(224) << newDomainName << field->fld_name);
+ Arg::PrivateDyn(224) << newDomainName.toQuotedString() << field->fld_name);
}
// Get the domain information.
@@ -8327,10 +8670,11 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_domain_not_found) << newDomainName);
+ Arg::Gds(isc_dsql_domain_not_found) << newDomainName.toQuotedString());
}
- DDL_resolve_intl_type(dsqlScratch, field, NULL);
+ QualifiedName dummyCollationName;
+ DDL_resolve_intl_type(dsqlScratch, field, dummyCollationName);
// If the original definition was a base field type, remove the
// entries from RDB$FIELDS.
@@ -8345,6 +8689,8 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
// Case b1: Internal domain -> internal domain.
// Case b2: Domain -> internal domain.
+ newDomainName.schema = name.schema;
+
// If COMPUTED was specified but the type wasn't, we use the type of
// the computed expression.
if (clause->computed && field->dtype == dtype_unknown)
@@ -8402,7 +8748,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!clause->computed && !isView)
{
- if (newDomainName.hasData())
+ if (newDomainName.object.hasData())
newDom.dyn_fld_source = newDomainName;
AlterDomainNode::getDomainType(tdbb, transaction, newDom);
@@ -8413,16 +8759,19 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!newDom.dyn_dsc.isExact() || newDom.dyn_dsc.dsc_scale != 0)
{
// Identity column @1 of table @2 must be exact numeric with zero scale.
- status_exception::raise(Arg::PrivateDyn(273) << field->fld_name << name);
+ status_exception::raise(Arg::PrivateDyn(273) << field->fld_name << name.toQuotedString());
}
}
}
- if (newDomainName.hasData())
+ if (newDomainName.object.hasData())
{
MODIFY RFR USING
+ RFR.RDB$FIELD_SOURCE_SCHEMA_NAME.NULL = FALSE;
+ strcpy(RFR.RDB$FIELD_SOURCE_SCHEMA_NAME, newDomainName.schema.c_str());
+
RFR.RDB$FIELD_SOURCE.NULL = FALSE;
- strcpy(RFR.RDB$FIELD_SOURCE, newDomainName.c_str());
+ strcpy(RFR.RDB$FIELD_SOURCE, newDomainName.object.c_str());
if (clause->computed)
{
@@ -8458,10 +8807,12 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
PRM IN RDB$PROCEDURE_PARAMETERS
- WITH PRM.RDB$RELATION_NAME = name.c_str() AND
+ WITH PRM.RDB$SCHEMA_NAME = name.schema.c_str() AND
+ PRM.RDB$RELATION_NAME = name.object.c_str() AND
PRM.RDB$FIELD_NAME = field->fld_name.c_str()
{
MODIFY PRM USING
+ strcpy(PRM.RDB$FIELD_SOURCE_SCHEMA_NAME, RFR.RDB$FIELD_SOURCE_SCHEMA_NAME);
strcpy(PRM.RDB$FIELD_SOURCE, RFR.RDB$FIELD_SOURCE);
END_MODIFY
}
@@ -8471,10 +8822,12 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
ARG IN RDB$FUNCTION_ARGUMENTS
- WITH ARG.RDB$RELATION_NAME = name.c_str() AND
+ WITH ARG.RDB$SCHEMA_NAME = name.schema.c_str() AND
+ ARG.RDB$RELATION_NAME = name.object.c_str() AND
ARG.RDB$FIELD_NAME = field->fld_name.c_str()
{
MODIFY ARG USING
+ strcpy(ARG.RDB$FIELD_SOURCE_SCHEMA_NAME, RFR.RDB$FIELD_SOURCE_SCHEMA_NAME);
strcpy(ARG.RDB$FIELD_SOURCE, RFR.RDB$FIELD_SOURCE);
END_MODIFY
}
@@ -8485,9 +8838,11 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RFR2 IN RDB$RELATION_FIELDS CROSS
VRL IN RDB$VIEW_RELATIONS
- WITH VRL.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH VRL.RDB$RELATION_SCHEMA_NAME EQ name.schema.c_str() AND
+ VRL.RDB$RELATION_NAME EQ name.object.c_str() AND
VRL.RDB$PACKAGE_NAME MISSING AND
VRL.RDB$CONTEXT_TYPE EQ VCT_TABLE AND
+ RFR2.RDB$SCHEMA_NAME EQ VRL.RDB$SCHEMA_NAME AND
RFR2.RDB$RELATION_NAME EQ VRL.RDB$VIEW_NAME AND
RFR2.RDB$VIEW_CONTEXT EQ VRL.RDB$VIEW_CONTEXT AND
RFR2.RDB$BASE_FIELD = field->fld_name.c_str()
@@ -8505,7 +8860,7 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!found)
{
// msg 176: "column %s does not exist in table/view %s"
- status_exception::raise(Arg::PrivateDyn(176) << field->fld_name << name);
+ status_exception::raise(Arg::PrivateDyn(176) << field->fld_name << name.toQuotedString());
}
// Update any indices that exist.
@@ -8527,22 +8882,26 @@ void AlterRelationNode::modifyField(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
// Delete a global field if it's not used in others objects.
void DropRelationNode::deleteGlobalField(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& globalName)
+ const QualifiedName& globalName)
{
AutoCacheRequest request(tdbb, drq_e_l_gfld, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
FLD IN RDB$FIELDS
- WITH FLD.RDB$FIELD_NAME EQ globalName.c_str() AND
+ WITH FLD.RDB$SCHEMA_NAME EQ globalName.schema.c_str() AND
+ FLD.RDB$FIELD_NAME EQ globalName.object.c_str() AND
FLD.RDB$VALIDATION_SOURCE MISSING AND
FLD.RDB$NULL_FLAG MISSING AND
FLD.RDB$DEFAULT_SOURCE MISSING AND
FLD.RDB$FIELD_NAME STARTING WITH IMPLICIT_DOMAIN_PREFIX AND
(NOT ANY RFR IN RDB$RELATION_FIELDS WITH
+ RFR.RDB$FIELD_SOURCE_SCHEMA_NAME EQUIV FLD.RDB$SCHEMA_NAME AND
RFR.RDB$FIELD_SOURCE EQ FLD.RDB$FIELD_NAME) AND
(NOT ANY PRM IN RDB$PROCEDURE_PARAMETERS WITH
+ PRM.RDB$FIELD_SOURCE_SCHEMA_NAME EQUIV FLD.RDB$SCHEMA_NAME AND
PRM.RDB$FIELD_SOURCE EQ FLD.RDB$FIELD_NAME) AND
(NOT ANY ARG IN RDB$FUNCTION_ARGUMENTS WITH
+ ARG.RDB$FIELD_SOURCE_SCHEMA_NAME EQUIV FLD.RDB$SCHEMA_NAME AND
ARG.RDB$FIELD_SOURCE EQ FLD.RDB$FIELD_NAME)
{
DropDomainNode::deleteDimensionRecords(tdbb, transaction, globalName);
@@ -8564,12 +8923,10 @@ string DropRelationNode::internalPrint(NodePrinter& printer) const
void DropRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (view)
- SCL_check_view(tdbb, &dscName, SCL_drop);
+ SCL_check_view(tdbb, name, SCL_drop);
else
- SCL_check_relation(tdbb, &dscName, SCL_drop);
+ SCL_check_relation(tdbb, name, SCL_drop);
}
void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -8592,7 +8949,7 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_view_not_found) << name);
+ Arg::Gds(isc_dsql_view_not_found) << name.toQuotedString());
}
}
else
@@ -8602,7 +8959,7 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
status_exception::raise(
Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
Arg::Gds(isc_dsql_command_err) <<
- Arg::Gds(isc_dsql_table_not_found) << name);
+ Arg::Gds(isc_dsql_table_not_found) << name.toQuotedString());
}
}
@@ -8616,9 +8973,10 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
R IN RDB$RELATIONS
- WITH R.RDB$RELATION_NAME EQ name.c_str()
+ WITH R.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ R.RDB$RELATION_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name, {});
found = true;
}
END_FOR
@@ -8627,7 +8985,8 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
CRT IN RDB$RELATION_CONSTRAINTS
- WITH CRT.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH CRT.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ CRT.RDB$RELATION_NAME EQ name.object.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY OR
CRT.RDB$CONSTRAINT_TYPE EQ UNIQUE_CNSTRT OR
CRT.RDB$CONSTRAINT_TYPE EQ FOREIGN_KEY)
@@ -8641,9 +9000,10 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$RELATION_NAME EQ name.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDX.RDB$RELATION_NAME EQ name.object.c_str()
{
- DropIndexNode::deleteSegmentRecords(tdbb, transaction, IDX.RDB$INDEX_NAME);
+ DropIndexNode::deleteSegmentRecords(tdbb, transaction, QualifiedName(IDX.RDB$INDEX_NAME, name.schema));
ERASE IDX;
}
END_FOR
@@ -8653,7 +9013,9 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
TM IN RDB$TRIGGER_MESSAGES
CROSS T IN RDB$TRIGGERS
- WITH T.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH T.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ T.RDB$RELATION_NAME EQ name.object.c_str() AND
+ TM.RDB$SCHEMA_NAME EQ T.RDB$SCHEMA_NAME AND
TM.RDB$TRIGGER_NAME EQ T.RDB$TRIGGER_NAME
{
ERASE TM;
@@ -8665,7 +9027,8 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
CRT IN RDB$RELATION_CONSTRAINTS
- WITH CRT.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH CRT.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ CRT.RDB$RELATION_NAME EQ name.object.c_str() AND
(CRT.RDB$CONSTRAINT_TYPE EQ CHECK_CNSTRT OR
CRT.RDB$CONSTRAINT_TYPE EQ NOT_NULL_CNSTRT)
{
@@ -8677,10 +9040,14 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFR IN RDB$RELATION_FIELDS
- WITH RFR.RDB$RELATION_NAME EQ name.c_str()
+ WITH RFR.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RFR.RDB$RELATION_NAME EQ name.object.c_str()
{
if (!RFR.RDB$GENERATOR_NAME.NULL)
- DropSequenceNode::deleteIdentity(tdbb, transaction, RFR.RDB$GENERATOR_NAME);
+ {
+ DropSequenceNode::deleteIdentity(tdbb, transaction,
+ QualifiedName(RFR.RDB$GENERATOR_NAME, name.schema));
+ }
ERASE RFR;
@@ -8690,7 +9057,7 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
deleteSecurityClass(tdbb, transaction, RFR.RDB$SECURITY_CLASS);
}
- deleteGlobalField(tdbb, transaction, RFR.RDB$FIELD_SOURCE);
+ deleteGlobalField(tdbb, transaction, QualifiedName(RFR.RDB$FIELD_SOURCE, RFR.RDB$FIELD_SOURCE_SCHEMA_NAME));
}
END_FOR
@@ -8698,7 +9065,8 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
VR IN RDB$VIEW_RELATIONS
- WITH VR.RDB$VIEW_NAME EQ name.c_str()
+ WITH VR.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ VR.RDB$VIEW_NAME EQ name.object.c_str()
{
ERASE VR;
}
@@ -8708,7 +9076,8 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
R IN RDB$RELATIONS
- WITH R.RDB$RELATION_NAME EQ name.c_str()
+ WITH R.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ R.RDB$RELATION_NAME EQ name.object.c_str()
{
ERASE R;
@@ -8728,24 +9097,26 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
// Triggers must be deleted after check constraints
- MetaName triggerName;
+ QualifiedName triggerName;
request.reset(tdbb, drq_e_trigger2, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGERS
- WITH X.RDB$RELATION_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ name.object.c_str()
{
- triggerName = X.RDB$TRIGGER_NAME;
+ triggerName = QualifiedName(X.RDB$TRIGGER_NAME, X.RDB$SCHEMA_NAME);
ERASE X;
AutoCacheRequest request2(tdbb, drq_e_trg_prv, DYN_REQUESTS);
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$USER EQ triggerName.c_str() AND
- PRIV.RDB$USER_TYPE = obj_trigger AND
- PRIV.RDB$GRANTOR NOT MISSING
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQ triggerName.schema.c_str() AND
+ PRIV.RDB$USER EQ triggerName.object.c_str() AND
+ PRIV.RDB$USER_TYPE = obj_trigger AND
+ PRIV.RDB$GRANTOR NOT MISSING
{
ERASE PRIV;
}
@@ -8759,7 +9130,8 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$USER EQ name.c_str() AND
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$USER EQ name.object.c_str() AND
PRIV.RDB$USER_TYPE = obj_view AND
PRIV.RDB$GRANTOR NOT MISSING
{
@@ -8773,14 +9145,15 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PTAB IN RDB$PUBLICATION_TABLES
- WITH PTAB.RDB$TABLE_NAME EQ name.c_str()
+ WITH PTAB.RDB$TABLE_SCHEMA_NAME EQ name.schema.c_str() AND
+ PTAB.RDB$TABLE_NAME EQ name.object.c_str()
{
ERASE PTAB;
}
END_FOR
if (found)
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, {});
else
{
// msg 61: "Relation not found"
@@ -8789,7 +9162,7 @@ void DropRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
savePoint.release(); // everything is ok
- METD_drop_relation(transaction, name.c_str());
+ METD_drop_relation(transaction, name);
MET_dsql_cache_release(tdbb, SYM_relation, name);
}
@@ -8813,21 +9186,28 @@ string CreateAlterViewNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterViewNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_view);
+
+ protectSystemSchema(name.schema, obj_view);
+ dsqlScratch->ddlSchema = name.schema;
+
source.ltrim("\n\r\t ");
+
return DdlNode::dsqlPass(dsqlScratch);
}
void CreateAlterViewNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
if (alter)
{
- if (SCL_check_view(tdbb, &dscName, SCL_alter) || !create)
+ if (SCL_check_view(tdbb, name, SCL_alter) || !create)
return;
}
- SCL_check_create_access(tdbb, obj_views);
+ SCL_check_create_access(tdbb, obj_views, name.schema);
}
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@@ -8846,7 +9226,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
modifyingView = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch, name);
if (!modifyingView && !create)
- status_exception::raise(Arg::Gds(isc_dyn_view_not_found) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_view_not_found) << name.toQuotedString());
}
saveRelation(tdbb, dsqlScratch, name, true, modifyingView == NULL);
@@ -8856,7 +9236,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
const int ddlTriggerAction = (modifyingView ? DDL_TRIGGER_ALTER_VIEW : DDL_TRIGGER_CREATE_VIEW);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name, {});
if (!modifyingView)
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_relation);
@@ -8884,7 +9264,8 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
REL IN RDB$RELATIONS
- WITH REL.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH REL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ REL.RDB$RELATION_NAME EQ name.object.c_str() AND
REL.RDB$VIEW_BLR NOT MISSING
{
found = true;
@@ -8898,13 +9279,14 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
END_FOR
if (!found)
- status_exception::raise(Arg::Gds(isc_dyn_view_not_found) << name);
+ status_exception::raise(Arg::Gds(isc_dyn_view_not_found) << name.toQuotedString());
AutoRequest request2;
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
VR IN RDB$VIEW_RELATIONS
- WITH VR.RDB$VIEW_NAME EQ name.c_str()
+ WITH VR.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ VR.RDB$VIEW_NAME EQ name.object.c_str()
{
ERASE VR;
}
@@ -8914,7 +9296,8 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
TRG IN RDB$TRIGGERS
- WITH TRG.RDB$RELATION_NAME EQ name.c_str() AND
+ WITH TRG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ TRG.RDB$RELATION_NAME EQ name.object.c_str() AND
TRG.RDB$SYSTEM_FLAG EQ fb_sysflag_view_check
{
ERASE TRG;
@@ -8928,7 +9311,8 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
REL IN RDB$RELATIONS
{
- strcpy(REL.RDB$RELATION_NAME, name.c_str());
+ strcpy(REL.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(REL.RDB$RELATION_NAME, name.object.c_str());
REL.RDB$SYSTEM_FLAG = 0;
REL.RDB$FLAGS = REL_sql;
REL.RDB$RELATION_TYPE = SSHORT(rel_view);
@@ -8959,9 +9343,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (relation || procedure)
{
- const MetaName& refName = relation ? relation->rel_name : procedure->prc_name.identifier;
- const char* contextName = context->ctx_alias.hasData() ?
- context->ctx_alias.c_str() : refName.c_str();
+ const auto& refName = relation ? relation->rel_name : procedure->prc_name;
+ string contextName;
+
+ if (context->ctx_alias.hasData())
+ contextName = context->getConcatenatedAlias();
+ else
+ contextName = refName.toQuotedString();
ViewContextType ctxType;
if (relation)
@@ -8977,11 +9365,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
VRL IN RDB$VIEW_RELATIONS
{
- strcpy(VRL.RDB$VIEW_NAME, name.c_str());
- strcpy(VRL.RDB$RELATION_NAME, refName.c_str());
+ strcpy(VRL.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(VRL.RDB$VIEW_NAME, name.object.c_str());
+ strcpy(VRL.RDB$RELATION_SCHEMA_NAME, refName.schema.c_str());
+ strcpy(VRL.RDB$RELATION_NAME, refName.object.c_str());
VRL.RDB$CONTEXT_TYPE = SSHORT(ctxType);
VRL.RDB$VIEW_CONTEXT = context->ctx_context;
- strcpy(VRL.RDB$CONTEXT_NAME, contextName);
+ strcpy(VRL.RDB$CONTEXT_NAME, contextName.c_str());
if (procedure && procedure->prc_name.package.hasData())
{
@@ -9000,10 +9390,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
request.reset(tdbb, drq_l_view_rels, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- VRL IN RDB$VIEW_RELATIONS CROSS
- PREL IN RDB$RELATIONS OVER RDB$RELATION_NAME
+ VRL IN RDB$VIEW_RELATIONS
+ CROSS PREL IN RDB$RELATIONS
WITH VRL.RDB$PACKAGE_NAME MISSING AND
- VRL.RDB$VIEW_NAME EQ name.c_str()
+ VRL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ VRL.RDB$VIEW_NAME EQ name.object.c_str() AND
+ PREL.RDB$SCHEMA_NAME EQ VRL.RDB$RELATION_SCHEMA_NAME AND
+ PREL.RDB$RELATION_NAME EQ VRL.RDB$RELATION_NAME
{
// CVC: This never matches so it causes unnecessary calls to verify,
// so I included a call to strip trailing blanks.
@@ -9011,13 +9404,13 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (ownerName != PREL.RDB$OWNER_NAME)
{
- SecurityClass::flags_t priv;
+ // I think this should be the responsability of DFW or the user will find ways to circumvent DYN.
- // I think this should be the responsability of DFW or the user will find ways to
- // circumvent DYN.
- priv = SCL_get_mask(tdbb, PREL.RDB$RELATION_NAME, "");
+ SCL_check_schema(tdbb, PREL.RDB$SCHEMA_NAME, SCL_usage);
- if (!(priv & SCL_select))
+ if (auto priv = SCL_get_mask(tdbb, QualifiedName(PREL.RDB$RELATION_NAME, PREL.RDB$SCHEMA_NAME), "");
+ !(priv & SCL_select)
+ )
{
// msg 32: no permission for %s access to %s %s
status_exception::raise(
@@ -9025,7 +9418,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
// Remember, a view may be based on a view.
"TABLE/VIEW" << // Non-Translatable
// We want to print the name of the base table or view.
- MetaName(PREL.RDB$RELATION_NAME));
+ QualifiedName(PREL.RDB$RELATION_NAME, PREL.RDB$SCHEMA_NAME).toQuotedString());
}
}
}
@@ -9177,6 +9570,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
fieldDefinition.relationName = name;
fieldDefinition.name = fieldStr;
fieldDefinition.position = position;
+ fieldDefinition.fieldSource.schema = name.schema;
// CVC: Not sure if something should be done now that isc_dyn_view_context is used here,
// but if alter view is going to work, maybe we need here the context type and package, too.
@@ -9201,8 +9595,10 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
RFL IN RDB$RELATION_FIELDS CROSS
FLD IN RDB$FIELDS
WITH RFL.RDB$FIELD_NAME EQ fieldStr AND
- RFL.RDB$RELATION_NAME EQ name.c_str() AND
+ RFL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RFL.RDB$RELATION_NAME EQ name.object.c_str() AND
RFL.RDB$BASE_FIELD MISSING AND
+ FLD.RDB$SCHEMA_NAME EQ RFL.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ RFL.RDB$FIELD_SOURCE
{
bool wasInternalDomain = fb_utils::implicit_domain(FLD.RDB$FIELD_NAME);
@@ -9262,8 +9658,10 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
RFL IN RDB$RELATION_FIELDS CROSS
FLD IN RDB$FIELDS
WITH RFL.RDB$FIELD_NAME EQ fieldStr AND
- RFL.RDB$RELATION_NAME EQ name.c_str() AND
+ RFL.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ RFL.RDB$RELATION_NAME EQ name.object.c_str() AND
RFL.RDB$BASE_FIELD MISSING AND
+ FLD.RDB$SCHEMA_NAME EQ RFL.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ RFL.RDB$FIELD_SOURCE
{
bool wasInternalDomain = fb_utils::implicit_domain(FLD.RDB$FIELD_NAME);
@@ -9271,7 +9669,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (wasInternalDomain)
{
- fieldDefinition.fieldSource = FLD.RDB$FIELD_NAME;
+ fieldDefinition.fieldSource = QualifiedName(FLD.RDB$FIELD_NAME, FLD.RDB$SCHEMA_NAME);
MODIFY FLD
updateRdbFields(&newField,
@@ -9293,7 +9691,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
}
END_FOR
- if (fieldDefinition.fieldSource.isEmpty())
+ if (fieldDefinition.fieldSource.object.isEmpty())
{
storeGlobalField(tdbb, transaction, fieldDefinition.fieldSource, &newField,
"", dsqlScratch->getBlrData());
@@ -9388,7 +9786,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
dsqlScratch->resetContextStack();
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, {});
savePoint.release(); // everything is ok
@@ -9404,7 +9802,7 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
MemoryPool& pool = *tdbb->getDefaultPool();
// Specify that the trigger should abort if the condition is not met.
- ExceptionNode* exceptionNode = FB_NEW_POOL(pool) ExceptionNode(pool, CHECK_CONSTRAINT_EXCEPTION);
+ ExceptionNode* exceptionNode = FB_NEW_POOL(pool) ExceptionNode(pool, QualifiedName(CHECK_CONSTRAINT_EXCEPTION));
exceptionNode->exception->type = ExceptionItem::GDS_CODE;
AutoSetRestore autoCheckConstraintTrigger(&dsqlScratch->checkConstraintTrigger, true);
@@ -9430,8 +9828,7 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
{
dsqlScratch->contextNumber = 2;
- RelationSourceNode* baseRelation = FB_NEW_POOL(pool) RelationSourceNode(pool,
- sourceNode->dsqlName.identifier);
+ RelationSourceNode* baseRelation = FB_NEW_POOL(pool) RelationSourceNode(pool, sourceNode->dsqlName);
baseRelation->alias = sourceNode->alias;
dsqlScratch->appendUChar(blr_for);
@@ -9508,7 +9905,7 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
{
FieldNode* oldValueNode = FB_NEW_POOL(pool) FieldNode(pool);
oldValueNode->dsqlName = (aliasNode ? aliasNode->name : valueNode->dsqlName);
- oldValueNode->dsqlQualifier = OLD_CONTEXT_NAME;
+ oldValueNode->dsqlQualifier.object = OLD_CONTEXT_NAME;
valueNod = oldValueNode->dsqlPass(dsqlScratch);
fieldNod = fieldNode->dsqlPass(dsqlScratch);
@@ -9534,7 +9931,7 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
AutoSetRestore autoAlias(&relationNode->alias, sourceNode->alias);
if (relationNode->alias.isEmpty())
- relationNode->alias = sourceNode->dsqlName.identifier.c_str();
+ relationNode->alias = sourceNode->dsqlName.object.c_str();
newContext = PASS1_make_context(dsqlScratch, relationNode);
newContext->ctx_flags |= CTX_system;
@@ -9619,12 +10016,14 @@ void CreateAlterViewNode::createCheckTrigger(thread_db* tdbb, DsqlCompilerScratc
// Store an index.
-void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
- const Definition& definition, MetaName* referredIndexName)
+void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, QualifiedName& name,
+ const Definition& definition, QualifiedName* referredIndexName)
{
- if (name.isEmpty())
+ if (name.object.isEmpty())
DYN_UTIL_generate_index_name(tdbb, transaction, name, definition.type);
+ fb_assert(name.schema == definition.relation.schema);
+
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_index);
AutoCacheRequest request(tdbb, drq_s_indices, DYN_REQUESTS);
@@ -9637,14 +10036,14 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
IDX.RDB$UNIQUE_FLAG.NULL = TRUE;
IDX.RDB$INDEX_INACTIVE.NULL = TRUE;
IDX.RDB$INDEX_TYPE.NULL = TRUE;
+ IDX.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL = TRUE;
IDX.RDB$FOREIGN_KEY.NULL = TRUE;
IDX.RDB$EXPRESSION_SOURCE.NULL = TRUE;
IDX.RDB$EXPRESSION_BLR.NULL = TRUE;
- strcpy(IDX.RDB$INDEX_NAME, name.c_str());
- strcpy(IDX.RDB$RELATION_NAME, definition.relation.c_str());
- IDX.RDB$RELATION_NAME.NULL = FALSE;
+ strcpy(IDX.RDB$SCHEMA_NAME, name.schema.c_str());
+ strcpy(IDX.RDB$INDEX_NAME, name.object.c_str());
+ strcpy(IDX.RDB$RELATION_NAME, definition.relation.object.c_str());
IDX.RDB$SYSTEM_FLAG = 0;
- IDX.RDB$SYSTEM_FLAG.NULL = FALSE; // Probably redundant.
// Check if the table is actually a view.
@@ -9652,7 +10051,8 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
VREL IN RDB$RELATIONS
- WITH VREL.RDB$RELATION_NAME EQ IDX.RDB$RELATION_NAME
+ WITH VREL.RDB$SCHEMA_NAME EQ IDX.RDB$SCHEMA_NAME AND
+ VREL.RDB$RELATION_NAME EQ IDX.RDB$RELATION_NAME
{
if (!VREL.RDB$VIEW_BLR.NULL)
{
@@ -9699,8 +10099,10 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
F IN RDB$RELATION_FIELDS CROSS
GF IN RDB$FIELDS
- WITH GF.RDB$FIELD_NAME EQ F.RDB$FIELD_SOURCE AND
- F.RDB$FIELD_NAME EQ definition.columns[i].c_str() AND
+ WITH F.RDB$FIELD_NAME EQ definition.columns[i].c_str() AND
+ GF.RDB$SCHEMA_NAME EQUIV F.RDB$FIELD_SOURCE_SCHEMA_NAME AND
+ GF.RDB$FIELD_NAME EQ F.RDB$FIELD_SOURCE AND
+ IDX.RDB$SCHEMA_NAME EQ F.RDB$SCHEMA_NAME AND
IDX.RDB$RELATION_NAME EQ F.RDB$RELATION_NAME
{
ULONG length = 0;
@@ -9708,17 +10110,17 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
if (GF.RDB$FIELD_TYPE == blr_blob)
{
// msg 116 "attempt to index blob field in index %s"
- status_exception::raise(Arg::PrivateDyn(116) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(116) << name.toQuotedString());
}
else if (!GF.RDB$DIMENSIONS.NULL)
{
// msg 117 "attempt to index array field in index %s"
- status_exception::raise(Arg::PrivateDyn(117) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(117) << name.toQuotedString());
}
else if (!GF.RDB$COMPUTED_BLR.NULL)
{
// msg 179 "attempt to index COMPUTED BY field in index %s"
- status_exception::raise(Arg::PrivateDyn(179) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(179) << name.toQuotedString());
}
else if (GF.RDB$FIELD_TYPE == blr_varying || GF.RDB$FIELD_TYPE == blr_text)
{
@@ -9760,7 +10162,7 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
if (!found)
{
// msg 120 "Unknown columns in index %s"
- status_exception::raise(Arg::PrivateDyn(120) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(120) << name.toQuotedString());
}
}
@@ -9780,7 +10182,7 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
if (keyLength >= MAX_KEY)
{
// msg 118 "key size too big for index %s"
- status_exception::raise(Arg::PrivateDyn(118) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(118) << name.toQuotedString());
}
if (definition.columns.hasData())
@@ -9796,6 +10198,7 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
X IN RDB$INDEX_SEGMENTS
{
+ strcpy(X.RDB$SCHEMA_NAME, IDX.RDB$SCHEMA_NAME);
strcpy(X.RDB$INDEX_NAME, IDX.RDB$INDEX_NAME);
strcpy(X.RDB$FIELD_NAME, segment->c_str());
X.RDB$FIELD_POSITION = position++;
@@ -9806,7 +10209,7 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
else if (IDX.RDB$EXPRESSION_BLR.NULL)
{
// msg 119 "no keys for index %s"
- status_exception::raise(Arg::PrivateDyn(119) << IDX.RDB$INDEX_NAME);
+ status_exception::raise(Arg::PrivateDyn(119) << name.toQuotedString());
}
if (definition.refColumns.hasData())
@@ -9825,29 +10228,30 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
request2.reset(tdbb, drq_l_unq_idx, DYN_REQUESTS);
- MetaName indexName;
+ QualifiedName refIndexName;
int listIndex = -1;
bool found = false;
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RC IN RDB$RELATION_CONSTRAINTS CROSS
- IND IN RDB$INDICES OVER RDB$INDEX_NAME CROSS
- ISEG IN RDB$INDEX_SEGMENTS OVER RDB$INDEX_NAME
- WITH IND.RDB$RELATION_NAME EQ definition.refRelation.c_str() AND
+ IND IN RDB$INDICES OVER RDB$SCHEMA_NAME, RDB$INDEX_NAME CROSS
+ ISEG IN RDB$INDEX_SEGMENTS OVER RDB$SCHEMA_NAME, RDB$INDEX_NAME
+ WITH IND.RDB$SCHEMA_NAME EQ definition.refRelation.schema.c_str() AND
+ IND.RDB$RELATION_NAME EQ definition.refRelation.object.c_str() AND
IND.RDB$UNIQUE_FLAG NOT MISSING AND
(RC.RDB$CONSTRAINT_TYPE = PRIMARY_KEY OR
RC.RDB$CONSTRAINT_TYPE = UNIQUE_CNSTRT)
SORTED BY IND.RDB$INDEX_NAME,
DESCENDING ISEG.RDB$FIELD_POSITION
{
- if (indexName != IND.RDB$INDEX_NAME)
+ if (refIndexName != QualifiedName(IND.RDB$INDEX_NAME, IND.RDB$SCHEMA_NAME))
{
if (listIndex >= 0)
found = false;
if (found)
break;
listIndex = definition.refColumns.getCount() - 1;
- indexName = IND.RDB$INDEX_NAME;
+ refIndexName = QualifiedName(IND.RDB$INDEX_NAME, IND.RDB$SCHEMA_NAME);
found = true;
}
@@ -9870,11 +10274,14 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
if (found)
{
+ IDX.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL = FALSE;
+ strcpy(IDX.RDB$FOREIGN_KEY_SCHEMA_NAME, refIndexName.schema.c_str());
+
IDX.RDB$FOREIGN_KEY.NULL = FALSE;
- strcpy(IDX.RDB$FOREIGN_KEY, indexName.c_str());
+ strcpy(IDX.RDB$FOREIGN_KEY, refIndexName.object.c_str());
if (referredIndexName)
- *referredIndexName = indexName;
+ *referredIndexName = refIndexName;
}
else
{
@@ -9883,7 +10290,8 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
FOR(REQUEST_HANDLE request3 TRANSACTION_HANDLE transaction)
X IN RDB$RELATIONS
- WITH X.RDB$RELATION_NAME EQ definition.refRelation.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ definition.refRelation.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ definition.refRelation.object.c_str()
{
found = true;
isView = !X.RDB$VIEW_BLR.NULL;
@@ -9893,30 +10301,31 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
if (isView)
{
// msg 242: "attempt to reference a view (%s) in a foreign key"
- status_exception::raise(Arg::PrivateDyn(242) << definition.refRelation);
+ status_exception::raise(Arg::PrivateDyn(242) << definition.refRelation.toQuotedString());
}
if (found)
{
// msg 18: "could not find UNIQUE or PRIMARY KEY constraint in table %s with
// specified columns"
- status_exception::raise(Arg::PrivateDyn(18) << definition.refRelation);
+ status_exception::raise(Arg::PrivateDyn(18) << definition.refRelation.toQuotedString());
}
else
{
// msg 241: "Table %s not found"
- status_exception::raise(Arg::PrivateDyn(241) << definition.refRelation);
+ status_exception::raise(Arg::PrivateDyn(241) << definition.refRelation.toQuotedString());
}
}
}
- else if (definition.refRelation.hasData())
+ else if (definition.refRelation.object.hasData())
{
request2.reset(tdbb, drq_l_primary, DYN_REQUESTS);
FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
IND IN RDB$INDICES CROSS
- RC IN RDB$RELATION_CONSTRAINTS OVER RDB$INDEX_NAME
- WITH IND.RDB$RELATION_NAME EQ definition.refRelation.c_str() AND
+ RC IN RDB$RELATION_CONSTRAINTS OVER RDB$SCHEMA_NAME, RDB$INDEX_NAME
+ WITH IND.RDB$SCHEMA_NAME EQ definition.refRelation.schema.c_str() AND
+ IND.RDB$RELATION_NAME EQ definition.refRelation.object.c_str() AND
RC.RDB$CONSTRAINT_TYPE EQ PRIMARY_KEY
{
// Number of columns in referred index should be same as number
@@ -9930,20 +10339,24 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
status_exception::raise(Arg::PrivateDyn(133));
}
+ fb_utils::exact_name_limit(IND.RDB$SCHEMA_NAME, sizeof(IND.RDB$SCHEMA_NAME));
fb_utils::exact_name_limit(IND.RDB$INDEX_NAME, sizeof(IND.RDB$INDEX_NAME));
+ IDX.RDB$FOREIGN_KEY_SCHEMA_NAME.NULL = FALSE;
+ strcpy(IDX.RDB$FOREIGN_KEY_SCHEMA_NAME, IND.RDB$SCHEMA_NAME);
+
IDX.RDB$FOREIGN_KEY.NULL = FALSE;
strcpy(IDX.RDB$FOREIGN_KEY, IND.RDB$INDEX_NAME);
if (referredIndexName)
- *referredIndexName = IND.RDB$INDEX_NAME;
+ *referredIndexName = QualifiedName(IND.RDB$INDEX_NAME, IND.RDB$SCHEMA_NAME);
}
END_FOR
if (IDX.RDB$FOREIGN_KEY.NULL)
{
// msg 20: "could not find PRIMARY KEY index in specified table %s"
- status_exception::raise(Arg::PrivateDyn(20) << definition.refRelation);
+ status_exception::raise(Arg::PrivateDyn(20) << definition.refRelation.toQuotedString());
}
}
@@ -9957,7 +10370,8 @@ void CreateIndexNode::store(thread_db* tdbb, jrd_tra* transaction, MetaName& nam
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDX.RDB$INDEX_NAME EQ name.object.c_str()
{
MODIFY IDX
if (!definition.conditionBlr.isEmpty())
@@ -9994,10 +10408,7 @@ string CreateIndexNode::internalPrint(NodePrinter& printer) const
void CreateIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- const MetaName &relationName = relation->dsqlName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
- SCL_check_relation(tdbb, &dscName, SCL_alter, false);
+ SCL_check_relation(tdbb, relation->dsqlName, SCL_alter, false);
}
// Define an index.
@@ -10011,8 +10422,7 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_index))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_INDEX,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_INDEX, name, {});
CreateIndexNode::Definition definition;
definition.type = isc_dyn_def_idx;
@@ -10023,8 +10433,8 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
if (columns)
{
- const NestConst* ptr = columns->items.begin();
- const NestConst* const end = columns->items.end();
+ const NestConst* ptr = columns->items.begin();
+ const NestConst* const end = columns->items.end();
for (; ptr != end; ++ptr)
{
@@ -10061,12 +10471,31 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
store(tdbb, transaction, name, definition);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_INDEX,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_INDEX, name, {});
savePoint.release(); // everything is ok
}
+DdlNode* CreateIndexNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
+{
+ dsqlScratch->qualifyExistingName(relation->dsqlName, obj_relation);
+
+ if (name.schema.isEmpty())
+ name.schema = relation->dsqlName.schema;
+
+ if (name.schema != relation->dsqlName.schema)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_dyn_index_schema_must_match_table) <<
+ name.schema.toQuotedString() <<
+ relation->dsqlName.schema.toQuotedString());
+ }
+
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+}
+
//----------------------
@@ -10084,12 +10513,9 @@ string AlterIndexNode::internalPrint(NodePrinter& printer) const
void AlterIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
bool systemIndex;
- MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
+ const auto relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
- dsc dscName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
-
- SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
+ SCL_check_relation(tdbb, relationName, SCL_alter, systemIndex);
}
void AlterIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
@@ -10102,12 +10528,12 @@ void AlterIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDX.RDB$INDEX_NAME EQ name.object.c_str()
{
found = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_INDEX,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_INDEX, name, {});
MODIFY IDX
IDX.RDB$INDEX_INACTIVE.NULL = FALSE;
@@ -10117,10 +10543,7 @@ void AlterIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_INDEX,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_INDEX, name, {});
else
{
// msg 48: "Index not found"
@@ -10146,12 +10569,9 @@ string SetStatisticsNode::internalPrint(NodePrinter& printer) const
void SetStatisticsNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
bool systemIndex;
- MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
+ const auto relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
- dsc dscName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
-
- SCL_check_relation(tdbb, &dscName, SCL_alter, false);
+ SCL_check_relation(tdbb, relationName, SCL_alter, false);
}
void SetStatisticsNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
@@ -10164,12 +10584,12 @@ void SetStatisticsNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDX.RDB$INDEX_NAME EQ name.object.c_str()
{
found = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_INDEX,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_INDEX, name, {});
MODIFY IDX
// For V4 index selectivity can be set only to -1.
@@ -10180,10 +10600,7 @@ void SetStatisticsNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_INDEX,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_INDEX, name, {});
else
{
// msg 48: "Index not found"
@@ -10198,14 +10615,15 @@ void SetStatisticsNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
// Delete the records in RDB$INDEX_SEGMENTS pertaining to an index.
-bool DropIndexNode::deleteSegmentRecords(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name)
+bool DropIndexNode::deleteSegmentRecords(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name)
{
AutoCacheRequest request(tdbb, drq_e_idx_segs, DYN_REQUESTS);
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- IDXSEG IN RDB$INDEX_SEGMENTS WITH IDXSEG.RDB$INDEX_NAME EQ name.c_str()
+ IDXSEG IN RDB$INDEX_SEGMENTS
+ WITH IDXSEG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDXSEG.RDB$INDEX_NAME EQ name.object.c_str()
{
found = true;
ERASE IDXSEG;
@@ -10227,15 +10645,10 @@ string DropIndexNode::internalPrint(NodePrinter& printer) const
void DropIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
bool systemIndex;
- MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex, silent);
+ const auto relationName = getIndexRelationName(tdbb, transaction, name, systemIndex, silent);
- if (relationName.hasData())
- {
- dsc dscName;
- dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
-
- SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
- }
+ if (relationName.object.hasData())
+ SCL_check_relation(tdbb, relationName, SCL_alter, systemIndex);
}
void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
@@ -10248,10 +10661,10 @@ void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
- WITH IDX.RDB$INDEX_NAME EQ name.c_str()
+ WITH IDX.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ IDX.RDB$INDEX_NAME EQ name.object.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_INDEX, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_INDEX, name, {});
ERASE IDX;
@@ -10266,10 +10679,7 @@ void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_INDEX,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_INDEX, name, {});
else if (!silent)
{
// msg 48: "Index not found"
@@ -10298,7 +10708,7 @@ string CreateFilterNode::internalPrint(NodePrinter& printer) const
void CreateFilterNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- SCL_check_create_access(tdbb, obj_filters);
+ SCL_check_create_access(tdbb, obj_filters, {});
}
// Define a blob filter.
@@ -10310,10 +10720,7 @@ void CreateFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
// run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction);
- /***
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DECLARE_FILTER,
- name, NULL);
- ***/
+ /// executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DECLARE_FILTER, name, {});
AutoCacheRequest request(tdbb, drq_s_filters, DYN_REQUESTS);
@@ -10356,10 +10763,7 @@ void CreateFilterNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScrat
}
END_STORE
- /***
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DECLARE_FILTER,
- name, NULL);
- ***/
+ /// executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DECLARE_FILTER, name, {});
savePoint.release(); // everything is ok
}
@@ -10565,7 +10969,7 @@ string CreateAlterRoleNode::internalPrint(NodePrinter& printer) const
void CreateAlterRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
if (createFlag)
- SCL_check_create_access(tdbb, obj_roles);
+ SCL_check_create_access(tdbb, obj_roles, {});
else
SCL_check_role(tdbb, name, SCL_alter);
}
@@ -10589,7 +10993,7 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
return;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE, name, NULL);
+ (createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE), QualifiedName(name), {});
if (name == ownerName)
{
@@ -10638,7 +11042,7 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
if (createFlag)
{
PreparedStatement::Builder sql;
- sql << "insert into rdb$roles(rdb$role_name, rdb$owner_name, rdb$system_privileges, rdb$system_flag)"
+ sql << "insert into system.rdb$roles(rdb$role_name, rdb$owner_name, rdb$system_privileges, rdb$system_flag)"
<< "values(" << name << "," << ownerName << "," << p << ", 0)";
AutoPreparedStatement ps(attachment->prepareStatement(tdbb, transaction, sql));
@@ -10647,7 +11051,7 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
else if (privileges.hasData() || sysPrivDrop)
{
PreparedStatement::Builder sql;
- sql << "update rdb$roles set rdb$system_privileges =" << p << "where rdb$role_name =" << name;
+ sql << "update system.rdb$roles set rdb$system_privileges =" << p << "where rdb$role_name =" << name;
AutoPreparedStatement ps(attachment->prepareStatement(tdbb, transaction, sql));
if (ps->executeUpdate(tdbb, transaction) == 0)
@@ -10658,7 +11062,7 @@ void CreateAlterRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
}
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE, name, NULL);
+ (createFlag ? DDL_TRIGGER_CREATE_ROLE : DDL_TRIGGER_ALTER_ROLE), QualifiedName(name), {});
savePoint.release(); // everything is ok
}
@@ -10871,7 +11275,7 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
Message result;
Field cnt(result);
- const char* checkSql = "select count(*) from RDB$AUTH_MAPPING where RDB$MAP_NAME = ?";
+ const char* checkSql = "select count(*) from SYSTEM.RDB$AUTH_MAPPING where RDB$MAP_NAME = ?";
secDbContext->att->execute(&statusWrapper2, secDbContext->tra, 0, checkSql, SQL_DIALECT_V6,
msgCheck.getMetadata(), msgCheck.getBuffer(), result.getMetadata(), result.getBuffer());
@@ -10936,20 +11340,20 @@ void MappingNode::runInSecurityDb(SecDbContext* secDbContext)
switch(op)
{
case MAP_ADD:
- sql = "insert into RDB$AUTH_MAPPING(RDB$MAP_TO_TYPE, RDB$MAP_TO, RDB$MAP_USING, "
+ sql = "insert into SYSTEM.RDB$AUTH_MAPPING(RDB$MAP_TO_TYPE, RDB$MAP_TO, RDB$MAP_USING, "
"RDB$MAP_PLUGIN, RDB$MAP_DB, RDB$MAP_FROM_TYPE, RDB$MAP_FROM, RDB$MAP_NAME, RDB$SYSTEM_FLAG) "
"values (?, ?, ?, ?, ?, ?, ?, ?, 0)";
msg = &full;
break;
case MAP_MOD:
- sql = "update RDB$AUTH_MAPPING set RDB$MAP_TO_TYPE = ?, RDB$MAP_TO = ?, "
+ sql = "update SYSTEM.RDB$AUTH_MAPPING set RDB$MAP_TO_TYPE = ?, RDB$MAP_TO = ?, "
"RDB$MAP_USING = ?, RDB$MAP_PLUGIN = ?, RDB$MAP_DB = ?, "
"RDB$MAP_FROM_TYPE = ?, RDB$MAP_FROM = ? "
"where RDB$MAP_NAME = ?";
msg = &full;
break;
case MAP_COMMENT:
- sql = "update RDB$AUTH_MAPPING set RDB$DESCRIPTION = ? "
+ sql = "update SYSTEM.RDB$AUTH_MAPPING set RDB$DESCRIPTION = ? "
"where RDB$MAP_NAME = ?";
msg = &cmnt;
break;
@@ -11024,8 +11428,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
case MAP_MOD:
case MAP_RPL:
ddlTriggerAction = DDL_TRIGGER_ALTER_MAPPING;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, QualifiedName(name), {});
MODIFY M
if (to)
@@ -11066,8 +11469,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
case MAP_DROP:
ddlTriggerAction = DDL_TRIGGER_DROP_MAPPING;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, QualifiedName(name), {});
ERASE M;
break;
@@ -11092,7 +11494,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
break;
ddlTriggerAction = DDL_TRIGGER_CREATE_MAPPING;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlTriggerAction, QualifiedName(name), {});
STORE(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
M IN RDB$AUTH_MAPPING
@@ -11141,10 +11543,10 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
fb_assert(ddlTriggerAction > 0 || op == MAP_COMMENT || (op == MAP_DROP && silentDrop));
if (ddlTriggerAction > 0)
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlTriggerAction, QualifiedName(name), {});
if (op != MAP_COMMENT)
- DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::MAPPING_CACHE);
+ DFW_post_work(transaction, dfw_clear_cache, {}, {}, Mapping::MAPPING_CACHE);
savePoint.release(); // everything is ok
}
@@ -11179,8 +11581,8 @@ void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jr
ROL IN RDB$ROLES
WITH ROL.RDB$ROLE_NAME EQ name.c_str()
{
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_ROLE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_ROLE,
+ QualifiedName(name), {});
if (ROL.RDB$SYSTEM_FLAG != 0)
{
@@ -11222,10 +11624,7 @@ void DropRoleNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jr
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_ROLE,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_ROLE, QualifiedName(name), {});
else if (!silent)
{
// msg 155: "Role %s not found"
@@ -11399,13 +11798,13 @@ void CreateAlterUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
const int ddlAction = mode == USER_ADD ? DDL_TRIGGER_CREATE_USER : DDL_TRIGGER_ALTER_USER;
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, ddlAction,
- userData->user.get(), NULL);
+ QualifiedName(userData->user.get()), {});
const USHORT id = transaction->getUserManagement()->put(userData);
- DFW_post_work(transaction, dfw_user_management, NULL, id);
+ DFW_post_work(transaction, dfw_user_management, nullptr, nullptr, id);
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, ddlAction,
- userData->user.get(), NULL);
+ QualifiedName(userData->user.get()), {});
savePoint.release(); // everything is ok
}
@@ -11450,13 +11849,13 @@ void DropUserNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jr
check(&statusWrapper);
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_USER,
- userData->user.get(), NULL);
+ QualifiedName(userData->user.get()), {});
const USHORT id = transaction->getUserManagement()->put(userData);
- DFW_post_work(transaction, dfw_user_management, NULL, id);
+ DFW_post_work(transaction, dfw_user_management, nullptr, nullptr, id);
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_USER,
- userData->user.get(), NULL);
+ QualifiedName(userData->user.get()), {});
savePoint.release(); // everything is ok
}
@@ -11532,7 +11931,7 @@ void GrantRevokeNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
}
// Invalidate system privileges cache
- DFW_post_work(transaction, dfw_clear_cache, NULL, Mapping::SYSTEM_PRIVILEGES_CACHE);
+ DFW_post_work(transaction, dfw_clear_cache, {}, {}, Mapping::SYSTEM_PRIVILEGES_CACHE);
}
}
@@ -11559,7 +11958,7 @@ void GrantRevokeNode::runInSecurityDb(SecDbContext* secDbContext)
Field u(isRole, MAX_SQL_IDENTIFIER_LEN);
u = j.user.c_str();
- const char* isRoleSql = "select count(*) from RDB$ROLES where RDB$ROLE_NAME = ?";
+ const char* isRoleSql = "select count(*) from SYSTEM.RDB$ROLES where RDB$ROLE_NAME = ?";
secDbContext->att->execute(&statusWrapper, secDbContext->tra, 0, isRoleSql, SQL_DIALECT_V6,
isRole.getMetadata(), isRole.getBuffer(), result.getMetadata(), result.getBuffer());
check(&statusWrapper);
@@ -11578,7 +11977,7 @@ void GrantRevokeNode::runInSecurityDb(SecDbContext* secDbContext)
uType = j.userType;
u = j.user.c_str();
- const char* checkSql = "select count(*) from RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
+ const char* checkSql = "select count(*) from SYSTEM.RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
secDbContext->att->execute(&statusWrapper, secDbContext->tra, 0, checkSql, SQL_DIALECT_V6,
gr.getMetadata(), gr.getBuffer(), result.getMetadata(), result.getBuffer());
check(&statusWrapper);
@@ -11587,7 +11986,7 @@ void GrantRevokeNode::runInSecurityDb(SecDbContext* secDbContext)
{
if (!cnt)
{
- const char* insertSql = "insert into RDB$DB_CREATORS(RDB$USER_TYPE, RDB$USER) values(?, ?)";
+ const char* insertSql = "insert into SYSTEM.RDB$DB_CREATORS(RDB$USER_TYPE, RDB$USER) values(?, ?)";
secDbContext->att->execute(&statusWrapper, secDbContext->tra, 0, insertSql, SQL_DIALECT_V6,
gr.getMetadata(), gr.getBuffer(), NULL, NULL);
check(&statusWrapper);
@@ -11597,7 +11996,7 @@ void GrantRevokeNode::runInSecurityDb(SecDbContext* secDbContext)
{
if (cnt)
{
- const char* deleteSql = "delete from RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
+ const char* deleteSql = "delete from SYSTEM.RDB$DB_CREATORS where RDB$USER_TYPE = ? and RDB$USER = ?";
secDbContext->att->execute(&statusWrapper, secDbContext->tra, 0, deleteSql, SQL_DIALECT_V6,
gr.getMetadata(), gr.getBuffer(), NULL, NULL);
@@ -11645,13 +12044,8 @@ void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SS
{
char privs0[2] = {i->first, '\0'};
- ValueListNode* fields = i->second;
-
- for (NestConst* ptr = fields->items.begin(); ptr != fields->items.end(); ++ptr)
- {
- grantRevoke(tdbb, transaction, object, user, privs0,
- nodeAs(*ptr)->dsqlName, option);
- }
+ for (const auto& field : *i->second)
+ grantRevoke(tdbb, transaction, object, user, privs0, field, option);
}
else
privs += i->first;
@@ -11662,7 +12056,7 @@ void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SS
}
-static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaName& name, int type)
+static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name, int type)
{
bool rc = false;
@@ -11673,7 +12067,9 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_proc_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$PROCEDURES
- WITH X.RDB$PROCEDURE_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$PROCEDURE_NAME EQ name.object.c_str() AND
+ X.RDB$PACKAGE_NAME MISSING
{
rc = true;
}
@@ -11686,7 +12082,9 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_udf_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$FUNCTIONS
- WITH X.RDB$FUNCTION_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$FUNCTION_NAME EQ name.object.c_str() AND
+ X.RDB$PACKAGE_NAME MISSING
{
rc = true;
}
@@ -11699,7 +12097,25 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_package_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$PACKAGES
- WITH X.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$PACKAGE_NAME EQ name.object.c_str()
+ {
+ rc = true;
+ }
+ END_FOR
+ break;
+ }
+
+ case obj_schema:
+ {
+ fb_assert(name.object.hasData() && name.schema.isEmpty());
+
+ static const CachedRequestId requestId;
+ AutoCacheRequest request(tdbb, requestId);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ SCH IN RDB$SCHEMAS
+ WITH SCH.RDB$SCHEMA_NAME EQ name.object.c_str()
{
rc = true;
}
@@ -11712,7 +12128,8 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_trigger_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$TRIGGERS
- WITH X.RDB$TRIGGER_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$TRIGGER_NAME EQ name.object.c_str()
{
rc = true;
}
@@ -11726,7 +12143,8 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_rel_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$RELATIONS
- WITH X.RDB$RELATION_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ name.object.c_str()
{
rc = (type != obj_view) || !X.RDB$VIEW_BLR.NULL;
}
@@ -11739,7 +12157,8 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_exception_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$EXCEPTIONS
- WITH X.RDB$EXCEPTION_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$EXCEPTION_NAME EQ name.object.c_str()
{
rc = true;
}
@@ -11752,7 +12171,8 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
AutoCacheRequest request(tdbb, drq_generator_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$GENERATORS
- WITH X.RDB$GENERATOR_NAME EQ name.c_str()
+ WITH X.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ X.RDB$GENERATOR_NAME EQ name.object.c_str()
{
rc = true;
}
@@ -11764,14 +12184,16 @@ static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaNa
return rc;
}
-static bool checkFieldExist(thread_db* tdbb, jrd_tra* transaction, const MetaName& relation, const MetaName& field)
+static bool checkFieldExist(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& relation,
+ const MetaName& field)
{
bool rc = false;
AutoCacheRequest request(tdbb, drq_rel_field_exist, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
X IN RDB$RELATION_FIELDS
- WITH X.RDB$RELATION_NAME EQ relation.c_str() AND
+ WITH X.RDB$SCHEMA_NAME EQ relation.schema.c_str() AND
+ X.RDB$RELATION_NAME EQ relation.object.c_str() AND
X.RDB$FIELD_NAME EQ field.c_str()
{
rc = true;
@@ -11787,10 +12209,10 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
MetaName field, int options)
{
ObjectType userType = userNod->first;
- MetaName user(userNod->second);
+ QualifiedName user(userNod->second);
MetaName dummyName;
const ObjectType objType = object ? object->first : obj_type_MAX;
- const MetaName objName(object ? object->second : "");
+ const auto objName(object ? object->second : QualifiedName());
bool crdb = false;
AutoPtr privileges(FB_NEW char[MAX(strlen(ALL_PRIVILEGES), strlen(privs ? privs : "")) + 1]);
@@ -11825,13 +12247,13 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
{
case obj_user_or_role:
// This test may become obsolete as we now allow explicit ROLE keyword.
- if (isItSqlRole(tdbb, transaction, user, dummyName))
+ if (isItSqlRole(tdbb, transaction, user.object, dummyName))
{
userType = obj_sql_role;
- if (user == NULL_ROLE)
+ if (user.object == NULL_ROLE)
{
// msg 195: keyword NONE could not be used as SQL role name.
- status_exception::raise(Arg::PrivateDyn(195) << user.c_str());
+ status_exception::raise(Arg::PrivateDyn(195) << user.toQuotedString());
}
}
else
@@ -11844,49 +12266,53 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
case obj_udf:
if (!checkObjectExist(tdbb, transaction, user, userType))
- status_exception::raise(Arg::PrivateDyn(301) << user.c_str()); // Function @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(301) << user.toQuotedString()); // Function @1 does not exist
break;
case obj_procedure:
if (!checkObjectExist(tdbb, transaction, user, userType))
- status_exception::raise(Arg::PrivateDyn(302) << user.c_str()); // Procedure @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(302) << user.toQuotedString()); // Procedure @1 does not exist
break;
case obj_package_header:
if (!checkObjectExist(tdbb, transaction, user, userType))
- status_exception::raise(Arg::PrivateDyn(303) << user.c_str()); // Package @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(303) << user.toQuotedString()); // Package @1 does not exist
+ break;
+
+ case obj_schema:
+ if (!checkObjectExist(tdbb, transaction, user, userType))
+ status_exception::raise(Arg::Gds(isc_dyn_schema_not_found) << user.toQuotedString());
break;
case obj_trigger:
if (!checkObjectExist(tdbb, transaction, user, userType))
- status_exception::raise(Arg::PrivateDyn(304) << user.c_str()); // Trigger @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(304) << user.toQuotedString()); // Trigger @1 does not exist
break;
case obj_view:
if (!checkObjectExist(tdbb, transaction, user, userType))
- status_exception::raise(Arg::PrivateDyn(305) << user.c_str()); // View @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(305) << user.toQuotedString()); // View @1 does not exist
break;
case obj_sql_role:
- if (!crdb && (!isItSqlRole(tdbb, transaction, user, dummyName)))
+ if (!crdb && (!isItSqlRole(tdbb, transaction, user.object, dummyName)))
{
// msg 188: Role doesn't exist.
- status_exception::raise(Arg::PrivateDyn(188) << user.c_str());
+ status_exception::raise(Arg::PrivateDyn(188) << user.toQuotedString());
}
- if (user == NULL_ROLE)
+ if (user.object == NULL_ROLE)
{
// msg 195: keyword NONE could not be used as SQL role name.
- status_exception::raise(Arg::PrivateDyn(195) << user.c_str());
+ status_exception::raise(Arg::PrivateDyn(195) << user.toQuotedString());
}
break;
case obj_privilege: // Should convert symbolic privilege name to bit number
{
- USHORT p = convertPrivilegeFromString(tdbb, transaction, user);
- user.printf("%d", p);
+ USHORT p = convertPrivilegeFromString(tdbb, transaction, user.object);
+ user.object.printf("%d", p);
}
break;
-
}
// Check if grant subject exists
@@ -11894,52 +12320,70 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
{
case obj_view:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(305) << objName.c_str()); // View @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(305) << objName.toQuotedString()); // View @1 does not exist
break;
case obj_relation:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(306) << objName.c_str()); // Table @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(306) << objName.toQuotedString()); // Table @1 does not exist
if (field.hasData() && !checkFieldExist(tdbb, transaction, objName, field))
- status_exception::raise(Arg::PrivateDyn(309) << field.c_str() << objName.c_str()); // Field @1 of table @2 does not exist
+ status_exception::raise(Arg::PrivateDyn(309) << field.c_str() << objName.toQuotedString()); // Field @1 of table @2 does not exist
+ break;
+
+ case obj_schema:
+ if (!checkObjectExist(tdbb, transaction, objName, objType))
+ status_exception::raise(Arg::Gds(isc_dyn_schema_not_found) << objName.toQuotedString());
break;
case obj_trigger:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(304) << objName.c_str()); // Trigger @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(304) << objName.toQuotedString()); // Trigger @1 does not exist
break;
case obj_procedure:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(302) << objName.c_str()); // Procedure @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(302) << objName.toQuotedString()); // Procedure @1 does not exist
break;
case obj_exception:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(307) << objName.c_str()); // Exception @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(307) << objName.toQuotedString()); // Exception @1 does not exist
break;
case obj_generator:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(308) << objName.c_str()); // Generator/Sequence @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(308) << objName.toQuotedString()); // Generator/Sequence @1 does not exist
break;
case obj_udf:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(301) << objName.c_str()); // Function @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(301) << objName.toQuotedString()); // Function @1 does not exist
break;
case obj_package_header:
if (!checkObjectExist(tdbb, transaction, objName, objType))
- status_exception::raise(Arg::PrivateDyn(303) << objName.c_str()); // Package @1 does not exist
+ status_exception::raise(Arg::PrivateDyn(303) << objName.toQuotedString()); // Package @1 does not exist
break;
case obj_sql_role:
- if (!isItSqlRole(tdbb, transaction, objName, dummyName))
- status_exception::raise(Arg::PrivateDyn(188) << objName.c_str()); // Role doesn't exist.
+ if (!isItSqlRole(tdbb, transaction, objName.object, dummyName))
+ status_exception::raise(Arg::PrivateDyn(188) << objName.toQuotedString()); // Role doesn't exist.
break;
+ case obj_relations:
+ case obj_views:
+ case obj_procedures:
+ case obj_functions:
+ case obj_packages:
+ case obj_generators:
+ case obj_domains:
+ case obj_exceptions:
+ case obj_charsets:
+ case obj_collations:
+ if (!checkObjectExist(tdbb, transaction, QualifiedName(objName.schema), obj_schema))
+ status_exception::raise(Arg::Gds(isc_dyn_schema_not_found) << objName.toQuotedString());
+
default:
fb_assert(object == NULL || isDdlObject(objType));
}
@@ -11952,6 +12396,10 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("procedures"));
break;
+ case obj_schema:
+ ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("schemas"));
+ break;
+
case obj_trigger:
ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("triggers"));
break;
@@ -11995,13 +12443,14 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
if (!isGrant && !privs) // REVOKE ALL ON ALL
{
AutoCacheRequest request(tdbb, drq_e_grant3, DYN_REQUESTS);
- CreateDbJob all(userType, user);
+ CreateDbJob all(userType, user.object);
all.allOnAll = true;
all.revoker = grantorRevoker;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$USER = user.c_str() AND
+ WITH PRIV.RDB$USER_SCHEMA_NAME EQUIV NULLIF(user.schema.c_str(), '') AND
+ PRIV.RDB$USER = user.object.c_str() AND
PRIV.RDB$USER_TYPE = userType AND
PRIV.RDB$GRANTOR NOT MISSING
{
@@ -12021,12 +12470,12 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
return;
}
- if (objType == obj_sql_role && objName == NULL_ROLE)
+ if (objType == obj_sql_role && objName.object == NULL_ROLE)
{
if (isGrant)
{
// msg 195: keyword NONE could not be used as SQL role name.
- status_exception::raise(Arg::PrivateDyn(195) << objName.c_str());
+ status_exception::raise(Arg::PrivateDyn(195) << objName.object.c_str());
}
else
{
@@ -12037,7 +12486,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
if (crdb)
{
- CreateDbJob job(userType, user);
+ CreateDbJob job(userType, user.object);
createDbJobs.push(job);
if (!privileges[0])
@@ -12060,10 +12509,12 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$RELATION_NAME EQ objName.c_str() AND
+ WITH PRIV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(objName.schema.c_str(), '') AND
+ PRIV.RDB$RELATION_NAME EQUIV NULLIF(objName.object.c_str(), '') AND
PRIV.RDB$OBJECT_TYPE = objType AND
PRIV.RDB$PRIVILEGE EQ priv AND
- PRIV.RDB$USER = user.c_str() AND
+ PRIV.RDB$USER_SCHEMA_NAME EQUIV NULLIF(user.schema.c_str(), '') AND
+ PRIV.RDB$USER = user.object.c_str() AND
PRIV.RDB$USER_TYPE = userType AND
PRIV.RDB$GRANTOR EQ grantorRevoker.c_str() AND
(PRIV.RDB$FIELD_NAME EQUIV NULLIF(field.c_str(), '') OR
@@ -12079,10 +12530,10 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
const bool addDefaultRole = (objType == obj_sql_role && field == "D" && PRIV.RDB$FIELD_NAME.NULL);
if (addGrantOption && !addDefaultRole) // Save DEFAULT option for re-grant
- newField = PRIV.RDB$FIELD_NAME;
+ newField = PRIV.RDB$FIELD_NAME;
if (addDefaultRole && !addGrantOption) // Add grant option was requested
- newOptions = PRIV.RDB$GRANT_OPTION;
+ newOptions = PRIV.RDB$GRANT_OPTION;
duplicate = !addGrantOption && !addDefaultRole;
@@ -12096,18 +12547,18 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
if (objType == obj_sql_role)
{
- checkGrantorCanGrantRole(tdbb, transaction, grantorRevoker, objName);
+ checkGrantorCanGrantRole(tdbb, transaction, grantorRevoker, objName.object);
if (userType == obj_sql_role)
{
// Check for blocking cycles of role grants.
UserId grantedRoles;
- grantedRoles.setSqlRole(objName);
+ grantedRoles.setSqlRole(objName.object);
- if (grantedRoles.roleInUse(tdbb, user))
+ if (grantedRoles.roleInUse(tdbb, user.object))
{
// 292: role @1 can not be granted to role @2
- status_exception::raise(Arg::PrivateDyn(292) << objName.c_str() << user.c_str());
+ status_exception::raise(Arg::PrivateDyn(292) << objName.toQuotedString() << user.toQuotedString());
}
}
}
@@ -12139,6 +12590,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
case obj_exception:
case obj_generator:
case obj_package_header:
+ case obj_schema:
{
checkGrantorCanGrantObject(tdbb, transaction, currentUser.c_str(), priv, objName, objType);
break;
@@ -12161,24 +12613,25 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
const bool revokeDefaultRole = (objType == obj_sql_role) && field.hasData();
const bool revokeGrantOption = options;
- // This var must be identical for request (1) and if below (2)
const bool withField = field.hasData() && objType != obj_sql_role;
-
- AutoCacheRequest request(tdbb, (withField ? drq_e_grant1 : drq_e_grant2), DYN_REQUESTS); // (1)
+ static const CachedRequestId withFieldRequestHandleId, withoutFieldRequestHandleId;
+ AutoCacheRequest request(tdbb, (withField ? withFieldRequestHandleId : withoutFieldRequestHandleId));
for (const char* pr = privileges; (priv[0] = *pr); ++pr)
{
bool grantErased = false;
bool badGrantor = false;
- if (withField) // (2)
+ if (withField)
{
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH PRIV.RDB$RELATION_NAME EQ objName.c_str() AND
+ WITH PRIV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(objName.schema.c_str(), '') AND
+ PRIV.RDB$RELATION_NAME EQUIV NULLIF(objName.object.c_str(), '') AND
PRIV.RDB$OBJECT_TYPE = objType AND
PRIV.RDB$PRIVILEGE EQ priv AND
- PRIV.RDB$USER = user.c_str() AND
+ PRIV.RDB$USER_SCHEMA_NAME EQUIV NULLIF(user.schema.c_str(), '') AND
+ PRIV.RDB$USER = user.object.c_str() AND
PRIV.RDB$USER_TYPE = userType AND
PRIV.RDB$FIELD_NAME EQ field.c_str() AND
PRIV.RDB$GRANTOR NOT MISSING
@@ -12211,9 +12664,11 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
WITH PRIV.RDB$PRIVILEGE EQ priv AND
- PRIV.RDB$RELATION_NAME EQ objName.c_str() AND
+ PRIV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(objName.schema.c_str(), '') AND
+ PRIV.RDB$RELATION_NAME EQUIV NULLIF(objName.object.c_str(), '') AND
PRIV.RDB$OBJECT_TYPE = objType AND
- PRIV.RDB$USER EQ user.c_str() AND
+ PRIV.RDB$USER_SCHEMA_NAME EQUIV NULLIF(user.schema.c_str(), '') AND
+ PRIV.RDB$USER EQ user.object.c_str() AND
PRIV.RDB$USER_TYPE = userType AND
PRIV.RDB$GRANTOR NOT MISSING
{
@@ -12224,11 +12679,11 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
MetaName owner;
if ((grantorRevoker == PRIV.RDB$GRANTOR) ||
((objType == obj_sql_role) && (PRIV.RDB$PRIVILEGE[0] == 'M') && // This is ROLE to USER grant
- (currentUser != user) && // And current user does not revoke his own grant
- ((isItSqlRole(tdbb, transaction, objName, owner) && // Pick up role owner name
+ (currentUser != user.object) && // And current user does not revoke his own grant
+ ((isItSqlRole(tdbb, transaction, objName.object, owner) && // Pick up role owner name
(attachment->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT) || // God-like check
(owner == currentUser))) || // Current user is role owner
- (getGrantorOption(tdbb, transaction, currentUser, obj_user, objName) == 2)))) // or has ADMIN option
+ (getGrantorOption(tdbb, transaction, currentUser, obj_user, objName.object) == 2)))) // or has ADMIN option
{
MetaName newField = NULL;
int newOptions = 0;
@@ -12258,14 +12713,16 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
{
// msg 246: @1 is not grantor of @2 on @3 to @4.
status_exception::raise(Arg::PrivateDyn(246) <<
- grantorRevoker.c_str() << privilegeName(priv[0]) << objName.c_str() <<
- user.c_str());
+ grantorRevoker.c_str() << privilegeName(priv[0]) << objName.toQuotedString() <<
+ user.toQuotedString());
}
// msg 247: Warning: @1 on @2 is not granted to @3.
ERR_post_warning(
Arg::Warning(isc_dyn_miss_priv_warning) <<
- Arg::Str(privilegeName(priv[0])) << Arg::Str(objName) << Arg::Str(user));
+ Arg::Str(privilegeName(priv[0])) <<
+ objName.toQuotedString() <<
+ user.toQuotedString());
}
}
}
@@ -12273,7 +12730,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
// Check if the grantor has grant privilege on the relation/field.
void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* transaction,
- const char* grantor, const char* privilege, const MetaName& relationName,
+ const char* grantor, const char* privilege, const QualifiedName& relationName,
const MetaName& fieldName, bool topLevel)
{
const Attachment* attachment = tdbb->getAttachment();
@@ -12286,8 +12743,9 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
bool relationExists = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- REL IN RDB$RELATIONS WITH
- REL.RDB$RELATION_NAME = relationName.c_str()
+ REL IN RDB$RELATIONS
+ WITH REL.RDB$SCHEMA_NAME = relationName.schema.c_str() AND
+ REL.RDB$RELATION_NAME = relationName.object.c_str()
{
relationExists = true;
if (!REL.RDB$FLAGS.NULL && (REL.RDB$FLAGS & REL_sql))
@@ -12298,7 +12756,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
if (!relationExists)
{
// table/view .. does not exist
- status_exception::raise(Arg::PrivateDyn(175) << relationName.c_str());
+ status_exception::raise(Arg::PrivateDyn(175) << relationName.toQuotedString());
}
// Verify the the input field exists.
@@ -12310,9 +12768,10 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
request.reset(tdbb, drq_gcg5, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- G_FLD IN RDB$RELATION_FIELDS WITH
- G_FLD.RDB$RELATION_NAME = relationName.c_str() AND
- G_FLD.RDB$FIELD_NAME = fieldName.c_str()
+ G_FLD IN RDB$RELATION_FIELDS
+ WITH G_FLD.RDB$SCHEMA_NAME = relationName.schema.c_str() AND
+ G_FLD.RDB$RELATION_NAME = relationName.object.c_str() AND
+ G_FLD.RDB$FIELD_NAME = fieldName.c_str()
{
fieldExists = true;
}
@@ -12322,7 +12781,8 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
{
// column .. does not exist in table/view ..
status_exception::raise(Arg::PrivateDyn(176) <<
- fieldName.c_str() << relationName.c_str());
+ fieldName <<
+ relationName.toQuotedString());
}
}
@@ -12339,9 +12799,10 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
request.reset(tdbb, drq_gcg2, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- REL IN RDB$RELATIONS WITH
- REL.RDB$RELATION_NAME = relationName.c_str() AND
- REL.RDB$OWNER_NAME = UPPERCASE(grantor)
+ REL IN RDB$RELATIONS
+ WITH REL.RDB$SCHEMA_NAME = relationName.schema.c_str() AND
+ REL.RDB$RELATION_NAME = relationName.object.c_str() AND
+ REL.RDB$OWNER_NAME = UPPERCASE(grantor)
{
grantorIsOwner = true;
}
@@ -12367,7 +12828,8 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
PRV IN RDB$USER_PRIVILEGES WITH
((PRV.RDB$USER = UPPERCASE(grantor) AND
PRV.RDB$USER_TYPE = obj_user) OR (PRV.RDB$USER_TYPE = obj_sql_role)) AND
- PRV.RDB$RELATION_NAME = relationName.c_str() AND
+ PRV.RDB$RELATION_SCHEMA_NAME EQ relationName.schema.c_str() AND
+ PRV.RDB$RELATION_NAME = relationName.object.c_str() AND
PRV.RDB$OBJECT_TYPE = obj_relation AND
PRV.RDB$PRIVILEGE = privilege
{
@@ -12403,7 +12865,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
{
// no grant option for privilege .. on column .. of [base] table/view ..
status_exception::raise(Arg::PrivateDyn(topLevel ? 167 : 168) <<
- privilegeName(*privilege) << fieldName.c_str() << relationName.c_str());
+ privilegeName(*privilege) << fieldName.c_str() << relationName.toQuotedString());
}
if (goFld == -1)
@@ -12412,14 +12874,14 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
{
// no grant option for privilege .. on [base] table/view .. (for column ..)
status_exception::raise(Arg::PrivateDyn(topLevel ? 169 : 170) <<
- privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
+ privilegeName(*privilege) << relationName.toQuotedString() << fieldName.c_str());
}
if (goRel == -1)
{
// no .. privilege with grant option on [base] table/view .. (for column ..)
status_exception::raise(Arg::PrivateDyn(topLevel ? 171 : 172) <<
- privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
+ privilegeName(*privilege) << relationName.toQuotedString() << fieldName.c_str());
}
}
}
@@ -12428,13 +12890,13 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
if (goRel == 0)
{
// no grant option for privilege .. on table/view ..
- status_exception::raise(Arg::PrivateDyn(173) << privilegeName(*privilege) << relationName.c_str());
+ status_exception::raise(Arg::PrivateDyn(173) << privilegeName(*privilege) << relationName.toQuotedString());
}
if (goRel == -1)
{
// no .. privilege with grant option on table/view ..
- status_exception::raise(Arg::PrivateDyn(174) << privilegeName(*privilege) << relationName.c_str());
+ status_exception::raise(Arg::PrivateDyn(174) << privilegeName(*privilege) << relationName.toQuotedString());
}
}
@@ -12450,25 +12912,29 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
request.reset(tdbb, drq_gcg3, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
- G_FLD IN RDB$RELATION_FIELDS CROSS
- G_VIEW IN RDB$VIEW_RELATIONS WITH
- G_FLD.RDB$RELATION_NAME = relationName.c_str() AND
- G_FLD.RDB$BASE_FIELD NOT MISSING AND
- G_VIEW.RDB$VIEW_NAME EQ G_FLD.RDB$RELATION_NAME AND
- G_VIEW.RDB$VIEW_CONTEXT EQ G_FLD.RDB$VIEW_CONTEXT
+ G_FLD IN RDB$RELATION_FIELDS
+ CROSS G_VIEW IN RDB$VIEW_RELATIONS
+ WITH G_FLD.RDB$SCHEMA_NAME = relationName.schema.c_str() AND
+ G_FLD.RDB$RELATION_NAME = relationName.object.c_str() AND
+ G_FLD.RDB$BASE_FIELD NOT MISSING AND
+ G_VIEW.RDB$SCHEMA_NAME EQ G_FLD.RDB$SCHEMA_NAME AND
+ G_VIEW.RDB$VIEW_NAME EQ G_FLD.RDB$RELATION_NAME AND
+ G_VIEW.RDB$VIEW_CONTEXT EQ G_FLD.RDB$VIEW_CONTEXT
{
if (fieldName.hasData())
{
if (fieldName == G_FLD.RDB$FIELD_NAME)
{
checkGrantorCanGrantRelation(tdbb, transaction, grantor, privilege,
- G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false);
+ QualifiedName(G_VIEW.RDB$RELATION_NAME, G_VIEW.RDB$RELATION_SCHEMA_NAME),
+ G_FLD.RDB$BASE_FIELD, false);
}
}
else
{
checkGrantorCanGrantRelation(tdbb, transaction, grantor, privilege,
- G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false);
+ QualifiedName(G_VIEW.RDB$RELATION_NAME, G_VIEW.RDB$RELATION_SCHEMA_NAME),
+ G_FLD.RDB$BASE_FIELD, false);
}
}
END_FOR
@@ -12553,7 +13019,7 @@ void GrantRevokeNode::checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transac
// Check if the grantor has grant option on DDL privilege
void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& grantor, const char* privilege, const MetaName& objName)
+ const MetaName& grantor, const char* privilege, const QualifiedName& objName)
{
const Attachment* attachment = tdbb->getAttachment();
@@ -12567,7 +13033,8 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
PRV IN RDB$USER_PRIVILEGES
WITH ((PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND
PRV.RDB$USER_TYPE = obj_user) OR (PRV.RDB$USER_TYPE = obj_sql_role)) AND
- PRV.RDB$RELATION_NAME EQ objName.c_str() AND
+ PRV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(objName.schema.c_str(), '') AND
+ PRV.RDB$RELATION_NAME EQ objName.object.c_str() AND
PRV.RDB$OBJECT_TYPE >= obj_database AND // it might be deleted but I believe it's more efficient
PRV.RDB$PRIVILEGE EQ privilege
{
@@ -12589,14 +13056,14 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
if (!grantable)
{
// no @1 privilege with grant option on DDL @2
- status_exception::raise(Arg::PrivateDyn(299) << privilegeName(*privilege) << objName.c_str());
+ status_exception::raise(Arg::PrivateDyn(299) << privilegeName(*privilege) << objName.toQuotedString());
}
}
// Check if the grantor has grant option on generator privilege
void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
- const char* privilege, const MetaName& objName, SSHORT objType)
+ const char* privilege, const QualifiedName& objName, SSHORT objType)
{
const Attachment* attachment = tdbb->getAttachment();
@@ -12610,7 +13077,8 @@ void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* trans
PRV IN RDB$USER_PRIVILEGES
WITH ((PRV.RDB$USER = UPPERCASE(grantor) AND
PRV.RDB$USER_TYPE = obj_user) OR (PRV.RDB$USER_TYPE = obj_sql_role)) AND
- PRV.RDB$RELATION_NAME EQ objName.c_str() AND
+ PRV.RDB$RELATION_SCHEMA_NAME EQUIV NULLIF(objName.schema.c_str(), '') AND
+ PRV.RDB$RELATION_NAME EQ objName.object.c_str() AND
PRV.RDB$OBJECT_TYPE = objType AND
PRV.RDB$PRIVILEGE EQ privilege
{
@@ -12628,32 +13096,59 @@ void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* trans
if (!grantable)
{
// no @1 privilege with grant option on object @2
- status_exception::raise(Arg::PrivateDyn(300) << privilegeName(*privilege) << objName.c_str());
+ status_exception::raise(Arg::PrivateDyn(300) << privilegeName(*privilege) << objName.toQuotedString());
}
}
-void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, const MetaName& object,
- const MetaName& user, const MetaName& field, const TEXT* privilege, SSHORT userType,
+void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& object,
+ const QualifiedName& user, const MetaName& field, const TEXT* privilege, SSHORT userType,
SSHORT objType, int option, const MetaName& grantor)
{
AutoCacheRequest request(tdbb, drq_s_grant, DYN_REQUESTS);
STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
+ {
+ if (object.schema.hasData())
+ {
+ strcpy(PRIV.RDB$RELATION_SCHEMA_NAME, object.schema.c_str());
+ PRIV.RDB$RELATION_SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ PRIV.RDB$RELATION_SCHEMA_NAME.NULL = TRUE;
+
PRIV.RDB$FIELD_NAME.NULL = TRUE;
- strcpy(PRIV.RDB$RELATION_NAME, object.c_str());
- strcpy(PRIV.RDB$USER, user.c_str());
+
+ if (object.object.hasData())
+ {
+ strcpy(PRIV.RDB$RELATION_NAME, object.object.c_str());
+ PRIV.RDB$RELATION_NAME.NULL = FALSE;
+ }
+ else
+ PRIV.RDB$RELATION_NAME.NULL = TRUE;
+
+ if (user.schema.hasData())
+ {
+ strcpy(PRIV.RDB$USER_SCHEMA_NAME, user.schema.c_str());
+ PRIV.RDB$USER_SCHEMA_NAME.NULL = FALSE;
+ }
+ else
+ PRIV.RDB$USER_SCHEMA_NAME.NULL = TRUE;
+
+ strcpy(PRIV.RDB$USER, user.object.c_str());
+
strcpy(PRIV.RDB$GRANTOR, grantor.c_str());
PRIV.RDB$USER_TYPE = userType;
PRIV.RDB$OBJECT_TYPE = objType;
- {
+
if (field.hasData())
{
strcpy(PRIV.RDB$FIELD_NAME, field.c_str());
PRIV.RDB$FIELD_NAME.NULL = FALSE;
setFieldClassName(tdbb, transaction, object, field);
}
+
PRIV.RDB$PRIVILEGE[0] = privilege[0];
PRIV.RDB$PRIVILEGE[1] = 0;
PRIV.RDB$GRANT_OPTION = option;
@@ -12663,7 +13158,7 @@ void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, cons
// For field level grants, be sure the field has a unique class name.
void GrantRevokeNode::setFieldClassName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relation, const MetaName& field)
+ const QualifiedName& relation, const MetaName& field)
{
AutoCacheRequest request(tdbb, drq_s_f_class, DYN_REQUESTS);
@@ -12672,21 +13167,24 @@ void GrantRevokeNode::setFieldClassName(thread_db* tdbb, jrd_tra* transaction,
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
RFR IN RDB$RELATION_FIELDS
WITH RFR.RDB$FIELD_NAME = field.c_str() AND
- RFR.RDB$RELATION_NAME = relation.c_str() AND
+ RFR.RDB$SCHEMA_NAME = relation.schema.c_str() AND
+ RFR.RDB$RELATION_NAME = relation.object.c_str() AND
RFR.RDB$SECURITY_CLASS MISSING
{
MODIFY RFR
while (!unique)
{
sprintf(RFR.RDB$SECURITY_CLASS, "%s%" SQUADFORMAT, SQL_FLD_SECCLASS_PREFIX,
- DPM_gen_id(tdbb, MET_lookup_generator(tdbb, SQL_SECCLASS_GENERATOR), false, 1));
+ DPM_gen_id(tdbb,
+ MET_lookup_generator(tdbb, QualifiedName(SQL_SECCLASS_GENERATOR, SYSTEM_SCHEMA)), false, 1));
unique = true;
AutoCacheRequest request2(tdbb, drq_s_u_class, DYN_REQUESTS);
FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
RFR1 IN RDB$RELATION_FIELDS
- WITH RFR1.RDB$SECURITY_CLASS = RFR.RDB$SECURITY_CLASS
+ WITH RFR1.RDB$SCHEMA_NAME = RFR.RDB$SCHEMA_NAME AND
+ RFR1.RDB$SECURITY_CLASS = RFR.RDB$SECURITY_CLASS
{
unique = false;
}
@@ -12815,7 +13313,7 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
relationType(REL.RDB$RELATION_TYPE.NULL, REL.RDB$RELATION_TYPE);
if (relType == rel_persistent)
- pubTables.add(REL.RDB$RELATION_NAME);
+ pubTables.add(QualifiedName(REL.RDB$RELATION_NAME, REL.RDB$SCHEMA_NAME));
}
END_FOR
@@ -12836,16 +13334,16 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
{
AutoCacheRequest request(tdbb, drq_l_pub_rel_name, DYN_REQUESTS);
- for (const MetaName* iter = pubTables.begin(); iter != pubTables.end(); ++iter)
+ for (const auto& tableName : pubTables)
{
- const MetaName& tableName = *iter;
bool found = false;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
REL IN RDB$RELATIONS
- WITH REL.RDB$SYSTEM_FLAG EQ 0
- AND REL.RDB$VIEW_BLR MISSING
- AND REL.RDB$RELATION_NAME EQ tableName.c_str()
+ WITH REL.RDB$SYSTEM_FLAG EQ 0 AND
+ REL.RDB$VIEW_BLR MISSING AND
+ REL.RDB$SCHEMA_NAME EQ tableName.schema.c_str() AND
+ REL.RDB$RELATION_NAME EQ tableName.object.c_str()
{
const rel_t relType =
relationType(REL.RDB$RELATION_TYPE.NULL, REL.RDB$RELATION_TYPE);
@@ -12856,14 +13354,12 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
END_FOR
if (!found)
- status_exception::raise(Arg::Gds(isc_dyn_table_not_found) << tableName);
+ status_exception::raise(Arg::Gds(isc_dyn_table_not_found) << tableName.toQuotedString());
}
}
- for (const MetaName* iter = pubTables.begin(); iter != pubTables.end(); ++iter)
+ for (const auto& tableName : pubTables)
{
- const MetaName& tableName = *iter;
-
if (clauses & CLAUSE_PUB_INCL_TABLE)
{
try
@@ -12897,32 +13393,58 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
if (clauses & CLAUSE_END_BACKUP)
changeBackupMode(tdbb, transaction, CLAUSE_END_BACKUP);
- if (setDefaultCharSet.hasData() || setDefaultCollation.hasData() || linger >= 0 ||
+ if (setDefaultCharSet.object.hasData() || setDefaultCollation.object.hasData() || linger >= 0 ||
ssDefiner.isAssigned())
{
- AutoCacheRequest request(tdbb, drq_m_database, DYN_REQUESTS);
- FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ static const CachedRequestId databaseRequestHandleId;
+ AutoCacheRequest databaseRequestHandle(tdbb, databaseRequestHandleId);
+
+ FOR(REQUEST_HANDLE databaseRequestHandle TRANSACTION_HANDLE transaction)
DBB IN RDB$DATABASE
{
MODIFY DBB USING
- if (setDefaultCharSet.hasData())
+ if (setDefaultCharSet.object.hasData())
{
- if (!METD_get_charset(transaction, setDefaultCharSet.length(),
- setDefaultCharSet.c_str()))
+ if (!METD_get_charset(transaction, setDefaultCharSet))
{
// specified character set not found
- status_exception::raise(Arg::Gds(isc_charset_not_found) << setDefaultCharSet);
+ status_exception::raise(Arg::Gds(isc_charset_not_found) << setDefaultCharSet.toQuotedString());
}
+ DBB.RDB$CHARACTER_SET_SCHEMA_NAME.NULL = FALSE;
+ strcpy(DBB.RDB$CHARACTER_SET_SCHEMA_NAME, setDefaultCharSet.schema.c_str());
+
DBB.RDB$CHARACTER_SET_NAME.NULL = FALSE;
- strcpy(DBB.RDB$CHARACTER_SET_NAME, setDefaultCharSet.c_str());
+ strcpy(DBB.RDB$CHARACTER_SET_NAME, setDefaultCharSet.object.c_str());
+
+ if (create)
+ {
+ static const CachedRequestId schemaRequestHandleId;
+ AutoCacheRequest schemaRequestHandle(tdbb, schemaRequestHandleId);
+
+ FOR (REQUEST_HANDLE schemaRequestHandle TRANSACTION_HANDLE transaction)
+ SCH IN RDB$SCHEMAS
+ WITH SCH.RDB$SCHEMA_NAME EQ PUBLIC_SCHEMA
+ {
+ MODIFY SCH USING
+ {
+ SCH.RDB$CHARACTER_SET_SCHEMA_NAME.NULL = FALSE;
+ strcpy(SCH.RDB$CHARACTER_SET_SCHEMA_NAME, setDefaultCharSet.schema.c_str());
+
+ SCH.RDB$CHARACTER_SET_NAME.NULL = FALSE;
+ strcpy(SCH.RDB$CHARACTER_SET_NAME, setDefaultCharSet.object.c_str());
+ }
+ END_MODIFY
+ }
+ END_FOR
+ }
dsql_dbb* dbb = transaction->getDsqlAttachment();
- dbb->dbb_dfl_charset = ""; // reset in the cache
+ dbb->dbb_dfl_charset.clear(); // reset in the cache
}
- if (!DBB.RDB$CHARACTER_SET_NAME.NULL && setDefaultCollation.hasData())
+ if (!DBB.RDB$CHARACTER_SET_NAME.NULL && setDefaultCollation.object.hasData())
{
AlterCharSetNode alterCharSetNode(dsqlScratch->getPool(), setDefaultCharSet, setDefaultCollation);
alterCharSetNode.execute(tdbb, dsqlScratch, transaction);
@@ -12951,7 +13473,7 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
Database* const db = tdbb->getDatabase();
db->dbb_crypto_manager->prepareChangeCryptState(tdbb, cryptPlugin, keyName);
- DFW_post_work(transaction, dfw_db_crypt, cryptPlugin.c_str(), 0);
+ DFW_post_work(transaction, dfw_db_crypt, cryptPlugin.c_str(), {}, 0);
}
savePoint.release(); // everything is ok
@@ -13072,4 +13594,472 @@ void AlterDatabaseNode::defineDifference(thread_db* tdbb, jrd_tra* transaction,
}
+//----------------------
+
+
+string CreateAlterSchemaNode::internalPrint(NodePrinter& printer) const
+{
+ DdlNode::internalPrint(printer);
+
+ NODE_PRINT(printer, name);
+ NODE_PRINT(printer, create);
+ NODE_PRINT(printer, alter);
+ NODE_PRINT(printer, createIfNotExistsOnly);
+ NODE_PRINT(printer, setDefaultCharSet);
+
+ return "CreateAlterSchemaNode";
+}
+
+DdlNode* CreateAlterSchemaNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
+{
+ if (create && (name == "INFORMATION_SCHEMA" || name == "DEFINITION_SCHEMA"))
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_create_reserved_schema) << name.toQuotedString());
+
+ dsqlScratch->ddlSchema = name;
+
+ if (setDefaultCharSet.object.hasData())
+ {
+ dsqlScratch->qualifyExistingName(setDefaultCharSet, obj_charset);
+
+ if (!METD_get_charset(dsqlScratch->getTransaction(), setDefaultCharSet))
+ status_exception::raise(Arg::Gds(isc_charset_not_found) << setDefaultCharSet.toQuotedString());
+ }
+
+ return DdlNode::dsqlPass(dsqlScratch);
+}
+
+void CreateAlterSchemaNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ if (alter)
+ {
+ if (SCL_check_schema(tdbb, name, SCL_alter) || !create)
+ return;
+ }
+
+ SCL_check_create_access(tdbb, obj_schemas, {});
+}
+
+void CreateAlterSchemaNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
+{
+ fb_assert(create || alter);
+
+ // run all statements under savepoint control
+ AutoSavePoint savePoint(tdbb, transaction);
+
+ if (alter)
+ {
+ if (!executeAlter(tdbb, dsqlScratch, transaction))
+ {
+ if (create) // create or alter
+ executeCreate(tdbb, dsqlScratch, transaction);
+ else
+ status_exception::raise(Arg::Gds(isc_dyn_schema_not_found) << name.toQuotedString());
+ }
+ }
+ else
+ executeCreate(tdbb, dsqlScratch, transaction);
+
+ savePoint.release(); // everything is ok
+}
+
+void CreateAlterSchemaNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
+{
+ const auto dbb = transaction->getDsqlAttachment();
+ const QualifiedName qualifiedName(name);
+ const auto attachment = transaction->getAttachment();
+ const auto& ownerName = attachment->getEffectiveUserName();
+
+ if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, qualifiedName, obj_schema))
+ return;
+
+ auto defaultCharSet = setDefaultCharSet;
+
+ if (defaultCharSet.object.isEmpty())
+ defaultCharSet = METD_get_database_charset(transaction);
+
+ fb_assert(defaultCharSet.object.hasData());
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_SCHEMA, qualifiedName, {});
+
+ DYN_UTIL_check_unique_name(tdbb, transaction, qualifiedName, obj_schema);
+
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ SCH IN RDB$SCHEMAS USING
+ {
+ strcpy(SCH.RDB$SCHEMA_NAME, name.c_str());
+ SCH.RDB$SYSTEM_FLAG = 0;
+ strcpy(SCH.RDB$OWNER_NAME, ownerName.c_str());
+ strcpy(SCH.RDB$CHARACTER_SET_NAME, defaultCharSet.object.c_str());
+ strcpy(SCH.RDB$CHARACTER_SET_SCHEMA_NAME, defaultCharSet.schema.c_str());
+ }
+ END_STORE
+
+ static const CachedRequestId userPrivRequestHandleId;
+ AutoCacheRequest userPrivRequestHandle(tdbb, userPrivRequestHandleId);
+
+ for (int obj = obj_database + 1; obj < obj_type_MAX; obj++)
+ {
+ if (bool useSchema; isDdlObject(obj, &useSchema) && useSchema)
+ {
+ for (const char* privilege = ALL_DDL_PRIVILEGES; *privilege; ++privilege)
+ {
+ STORE(REQUEST_HANDLE userPrivRequestHandle TRANSACTION_HANDLE transaction)
+ X IN RDB$USER_PRIVILEGES
+ {
+ strcpy(X.RDB$RELATION_SCHEMA_NAME, name.c_str());
+ strcpy(X.RDB$RELATION_NAME, getSecurityClassName(obj));
+
+ strcpy(X.RDB$USER, ownerName.c_str());
+ X.RDB$USER_TYPE = obj_user;
+ X.RDB$OBJECT_TYPE = obj;
+ X.RDB$PRIVILEGE[0] = *privilege;
+ X.RDB$PRIVILEGE[1] = 0;
+ X.RDB$GRANT_OPTION = WITH_GRANT_OPTION;
+ }
+ END_STORE
+ }
+ }
+ }
+
+ storePrivileges(tdbb, transaction, qualifiedName, obj_schema, USAGE_PRIVILEGES);
+
+ dbb->dbb_schemas_dfl_charset.put(name, defaultCharSet);
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_SCHEMA, qualifiedName, {});
+}
+
+bool CreateAlterSchemaNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
+{
+ const auto dbb = transaction->getDsqlAttachment();
+ const QualifiedName qualifiedName(name);
+
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+ bool modified = false;
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ SCH IN RDB$SCHEMAS
+ WITH SCH.RDB$SCHEMA_NAME = name.c_str()
+ {
+ if (SCH.RDB$SYSTEM_FLAG)
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_mod_system_schema));
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_SCHEMA, qualifiedName, {});
+
+ MODIFY SCH
+ {
+ if (setDefaultCharSet.object.hasData())
+ {
+ strcpy(SCH.RDB$CHARACTER_SET_NAME, setDefaultCharSet.object.c_str());
+ strcpy(SCH.RDB$CHARACTER_SET_SCHEMA_NAME, setDefaultCharSet.schema.c_str());
+ }
+
+ modified = true;
+ }
+ END_MODIFY
+ }
+ END_FOR
+
+ if (modified)
+ {
+ if (setDefaultCharSet.object.hasData())
+ dbb->dbb_schemas_dfl_charset.put(name, setDefaultCharSet);
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_SCHEMA, qualifiedName, {});
+ }
+
+ return modified;
+}
+
+
+//----------------------
+
+
+string DropSchemaNode::internalPrint(NodePrinter& printer) const
+{
+ DdlNode::internalPrint(printer);
+
+ NODE_PRINT(printer, name);
+ NODE_PRINT(printer, silent);
+
+ return "DropSchemaNode";
+}
+
+void DropSchemaNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
+{
+ SCL_check_schema(tdbb, name, SCL_drop);
+}
+
+void DropSchemaNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
+{
+ const auto dbb = transaction->getDsqlAttachment();
+ const QualifiedName qualifiedName(name);
+
+ // run all statements under savepoint control
+ AutoSavePoint savePoint(tdbb, transaction);
+
+ bool found = false;
+
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ SCH IN RDB$SCHEMAS
+ WITH SCH.RDB$SCHEMA_NAME = name.c_str()
+ {
+ if (SCH.RDB$SYSTEM_FLAG)
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_mod_system_schema));
+
+ found = true;
+
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_SCHEMA, qualifiedName, {});
+
+ if (collectObjects(tdbb, transaction))
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_drop_non_emptyschema) << name.toQuotedString());
+
+ ERASE SCH;
+
+ if (!SCH.RDB$SECURITY_CLASS.NULL)
+ deleteSecurityClass(tdbb, transaction, SCH.RDB$SECURITY_CLASS);
+
+ static const CachedRequestId privRequestHandleId;
+ AutoCacheRequest privRequestHandle(tdbb, privRequestHandleId);
+
+ FOR(REQUEST_HANDLE privRequestHandle TRANSACTION_HANDLE transaction)
+ PRIV IN RDB$USER_PRIVILEGES
+ WITH PRIV.RDB$RELATION_SCHEMA_NAME = name.c_str()
+ {
+ ERASE PRIV;
+ }
+ END_FOR
+
+ static const CachedRequestId secClsRequestHandleId;
+ AutoCacheRequest secClsRequestHandle(tdbb, secClsRequestHandleId);
+
+ for (int obj = obj_database + 1; obj < obj_type_MAX; obj++)
+ {
+ if (bool useSchema; isDdlObject(obj, &useSchema) && useSchema)
+ {
+ const auto secClassName = string(getSecurityClassName(obj)) + "$" + name.c_str();
+
+ FOR(REQUEST_HANDLE secClsRequestHandle TRANSACTION_HANDLE transaction)
+ SC IN RDB$SECURITY_CLASSES
+ WITH SC.RDB$SECURITY_CLASS = secClassName.c_str()
+ {
+ ERASE SC;
+ }
+ END_FOR
+ }
+ }
+
+ deletePrivilegesByRelName(tdbb, transaction, qualifiedName, obj_schema);
+
+ dbb->dbb_schemas_dfl_charset.remove(name);
+
+ /* FIXME:
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText(name.schema.length(), ttype_metadata, (UCHAR*) const_cast(name.schema.c_str()));
+ nameDesc.makeText(name.object.length(), ttype_metadata, (UCHAR*) const_cast(name.object.c_str()));
+ DFW_post_work(transaction, dfw_drop_package_header, &nameDesc, &schemaDesc, 0);
+ */
+ }
+ END_FOR
+
+ if (!found && !silent)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(isc_dyn_schema_not_found) << name.toQuotedString());
+ }
+
+ if (found)
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_SCHEMA, qualifiedName, {});
+
+ savePoint.release(); // everything is ok
+}
+
+bool DropSchemaNode::collectObjects(thread_db* tdbb, jrd_tra* transaction,
+ Array>* objects)
+{
+ if (objects)
+ objects->clear();
+
+ { // fields
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ FLD IN RDB$FIELDS
+ WITH FLD.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY FLD.RDB$FIELD_NAME
+ {
+ if (objects)
+ objects->add({obj_field, FLD.RDB$FIELD_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // relations
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ REL IN RDB$RELATIONS
+ WITH REL.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY REL.RDB$RELATION_NAME
+ {
+ if (objects)
+ objects->add({obj_relation, REL.RDB$RELATION_NAME});
+ }
+ END_FOR
+ }
+
+ { // triggers
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ TRG IN RDB$TRIGGERS
+ WITH TRG.RDB$SCHEMA_NAME EQ name.c_str() AND
+ TRG.RDB$RELATION_NAME MISSING
+ SORTED BY TRG.RDB$TRIGGER_NAME
+ {
+ if (objects)
+ objects->add({obj_trigger, TRG.RDB$TRIGGER_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // functions
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ FUN IN RDB$FUNCTIONS
+ WITH FUN.RDB$SCHEMA_NAME EQ name.c_str() AND
+ FUN.RDB$PACKAGE_NAME MISSING
+ SORTED BY FUN.RDB$FUNCTION_NAME
+ {
+ if (objects)
+ objects->add({obj_udf, FUN.RDB$FUNCTION_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // generators
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ GEN IN RDB$GENERATORS
+ WITH GEN.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY GEN.RDB$GENERATOR_NAME
+ {
+ if (objects)
+ objects->add({obj_generator, GEN.RDB$GENERATOR_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // procedures
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ PRC IN RDB$PROCEDURES
+ WITH PRC.RDB$SCHEMA_NAME EQ name.c_str() AND
+ PRC.RDB$PACKAGE_NAME MISSING
+ SORTED BY PRC.RDB$PROCEDURE_NAME
+ {
+ if (objects)
+ objects->add({obj_procedure, PRC.RDB$PROCEDURE_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // character sets
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ CSC IN RDB$CHARACTER_SETS
+ WITH CSC.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY CSC.RDB$CHARACTER_SET_NAME
+ {
+ if (objects)
+ objects->add({obj_charset, CSC.RDB$CHARACTER_SET_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // collations
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ COL IN RDB$COLLATIONS
+ WITH COL.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY COL.RDB$COLLATION_NAME
+ {
+ if (objects)
+ objects->add({obj_collation, COL.RDB$COLLATION_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // exceptions
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ XCP IN RDB$EXCEPTIONS
+ WITH XCP.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY XCP.RDB$EXCEPTION_NAME
+ {
+ if (objects)
+ objects->add({obj_exception, XCP.RDB$EXCEPTION_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ { // packages
+ static const CachedRequestId requestHandleId;
+ AutoCacheRequest requestHandle(tdbb, requestHandleId);
+
+ FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ PKG IN RDB$PACKAGES
+ WITH PKG.RDB$SCHEMA_NAME EQ name.c_str()
+ SORTED BY PKG.RDB$PACKAGE_NAME
+ {
+ if (objects)
+ objects->add({obj_package_header, PKG.RDB$PACKAGE_NAME});
+ else
+ return true;
+ }
+ END_FOR
+ }
+
+ return objects && objects->hasData();
+}
+
+
} // namespace Jrd
diff --git a/src/dsql/DdlNodes.h b/src/dsql/DdlNodes.h
index 7f3f1b15df..c78de0d648 100644
--- a/src/dsql/DdlNodes.h
+++ b/src/dsql/DdlNodes.h
@@ -167,9 +167,7 @@ struct CollectedParameter
bid defaultValue;
};
-typedef Firebird::GenericMap<
- Firebird::Pair > >
- CollectedParameterMap;
+typedef Firebird::LeftPooledMap CollectedParameterMap;
class ExecInSecurityDb
@@ -194,6 +192,7 @@ public:
dropNode(p, createNode->name)
{
dropNode.silent = true;
+ dropNode.recreate = true;
}
public:
@@ -234,7 +233,18 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(ERROR_CODE) << createNode->name;
+ statusVector << Firebird::Arg::Gds(ERROR_CODE) << nameToString(createNode->name);
+ }
+
+private:
+ Firebird::string nameToString(const QualifiedName& name)
+ {
+ return name.toQuotedString();
+ }
+
+ Firebird::string nameToString(const MetaName& name)
+ {
+ return name.toQuotedString();
}
protected:
@@ -246,8 +256,7 @@ protected:
class AlterCharSetNode : public DdlNode
{
public:
- AlterCharSetNode(MemoryPool& pool, const MetaName& aCharSet,
- const MetaName& aDefaultCollation)
+ AlterCharSetNode(MemoryPool& pool, const QualifiedName& aCharSet, const QualifiedName& aDefaultCollation)
: DdlNode(pool),
charSet(pool, aCharSet),
defaultCollation(pool, aDefaultCollation)
@@ -259,15 +268,26 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(charSet, obj_charset);
+ protectSystemSchema(charSet.schema, obj_charset);
+ dsqlScratch->ddlSchema = charSet.schema;
+
+ dsqlScratch->qualifyExistingName(defaultCollation, obj_collation);
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_charset_failed) << charSet;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_charset_failed) << charSet.toQuotedString();
}
private:
- MetaName charSet;
- MetaName defaultCollation;
+ QualifiedName charSet;
+ QualifiedName defaultCollation;
};
@@ -344,11 +364,11 @@ class CommentOnNode : public DdlNode
{
public:
CommentOnNode(MemoryPool& pool, int aObjType,
- const QualifiedName& aObjName, const MetaName& aSubName,
+ const QualifiedName& aName, const MetaName& aSubName,
const Firebird::string aText)
: DdlNode(pool),
objType(aObjType),
- objName(pool, aObjName),
+ name(pool, aName),
subName(pool, aSubName),
text(pool, aText),
str(pool)
@@ -357,13 +377,14 @@ public:
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- str = objName.toString();
+ str = name.toQuotedString();
if (subName.hasData())
str.append(".").append(subName.c_str());
@@ -373,7 +394,7 @@ protected:
private:
int objType;
- QualifiedName objName;
+ QualifiedName name;
MetaName subName;
Firebird::string text, str;
};
@@ -382,7 +403,7 @@ private:
class CreateAlterFunctionNode : public DdlNode
{
public:
- CreateAlterFunctionNode(MemoryPool& pool, const MetaName& aName)
+ CreateAlterFunctionNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
create(true),
@@ -395,7 +416,6 @@ public:
body(NULL),
compiled(false),
invalid(false),
- package(pool),
packageOwner(pool),
privateScope(false),
preserveDefaults(false),
@@ -416,7 +436,7 @@ protected:
Firebird::Arg::Gds(createAlterCode(create, alter,
isc_dsql_create_func_failed, isc_dsql_alter_func_failed,
isc_dsql_create_alter_func_failed)) <<
- name;
+ name.toQuotedString();
}
private:
@@ -438,20 +458,19 @@ private:
void collectParameters(thread_db* tdbb, jrd_tra* transaction, CollectedParameterMap& items);
public:
- MetaName name;
+ QualifiedName name;
bool create;
bool alter;
bool createIfNotExistsOnly = false;
NestConst external;
Firebird::TriState deterministic;
- Firebird::Array > parameters;
+ Firebird::Array> parameters;
NestConst returnType;
NestConst localDeclList;
Firebird::string source;
NestConst body;
bool compiled;
bool invalid;
- MetaName package;
MetaName packageOwner;
bool privateScope;
bool preserveDefaults;
@@ -463,7 +482,7 @@ public:
class AlterExternalFunctionNode : public DdlNode
{
public:
- AlterExternalFunctionNode(MemoryPool& p, const MetaName& aName)
+ AlterExternalFunctionNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName),
clauses(p)
@@ -475,14 +494,23 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_udf);
+ protectSystemSchema(name.schema, obj_udf);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_func_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_func_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
ExternalClause clauses;
};
@@ -490,17 +518,15 @@ public:
class DropFunctionNode : public DdlNode
{
public:
- DropFunctionNode(MemoryPool& pool, const MetaName& aName)
+ DropFunctionNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
- silent(false),
- package(pool)
+ silent(false)
{
}
public:
- static void dropArguments(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& functionName, const MetaName& packageName);
+ static void dropArguments(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& functionName);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
@@ -511,13 +537,13 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_func_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_func_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
- MetaName package;
+ bool recreate = false;
};
@@ -528,7 +554,7 @@ typedef RecreateNode body;
bool compiled;
bool invalid;
- MetaName package;
MetaName packageOwner;
bool privateScope;
bool preserveDefaults;
@@ -601,17 +625,15 @@ public:
class DropProcedureNode : public DdlNode
{
public:
- DropProcedureNode(MemoryPool& pool, const MetaName& aName)
+ DropProcedureNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
- silent(false),
- package(pool)
+ silent(false)
{
}
public:
- static void dropParameters(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& procedureName, const MetaName& packageName);
+ static void dropParameters(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& procedureName);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
@@ -622,13 +644,13 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_proc_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_proc_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
- MetaName package;
+ bool recreate = false;
};
@@ -669,8 +691,8 @@ protected:
}
public:
- MetaName name;
- MetaName relationName;
+ QualifiedName name;
+ QualifiedName relationName;
std::optional type;
Firebird::TriState active;
std::optional position;
@@ -687,7 +709,7 @@ public:
class CreateAlterTriggerNode : public DdlNode, public TriggerDefinition
{
public:
- CreateAlterTriggerNode(MemoryPool& p, const MetaName& aName)
+ CreateAlterTriggerNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
TriggerDefinition(p),
create(true),
@@ -713,7 +735,7 @@ protected:
Firebird::Arg::Gds(createAlterCode(create, alter,
isc_dsql_create_trigger_failed, isc_dsql_alter_trigger_failed,
isc_dsql_create_alter_trigger_failed)) <<
- name;
+ name.toQuotedString();
}
virtual void preModify(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
@@ -721,7 +743,7 @@ protected:
if (alter)
{
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_TRIGGER, name, NULL);
+ DDL_TRIGGER_ALTER_TRIGGER, name, {});
}
}
@@ -730,7 +752,7 @@ protected:
if (alter)
{
executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_ALTER_TRIGGER, name, NULL);
+ DDL_TRIGGER_ALTER_TRIGGER, name, {});
}
}
@@ -768,7 +790,7 @@ public:
class DropTriggerNode : public DdlNode
{
public:
- DropTriggerNode(MemoryPool& p, const MetaName& aName)
+ DropTriggerNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName),
silent(false)
@@ -784,24 +806,41 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_trigger_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_trigger_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
+ bool recreate = false;
};
-typedef RecreateNode
- RecreateTriggerNode;
+class RecreateTriggerNode :
+ public RecreateNode
+{
+public:
+ using RecreateNode::RecreateNode;
+
+public:
+ DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override
+ {
+ createNode->dsqlPass(dsqlScratch);
+
+ if (dropNode.name.schema.isEmpty())
+ dropNode.name.schema = createNode->name.schema;
+
+ dropNode.dsqlPass(dsqlScratch);
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+};
class CreateCollationNode : public DdlNode
{
public:
- CreateCollationNode(MemoryPool& p, const MetaName& aName,
- const MetaName& aForCharSet)
+ CreateCollationNode(MemoryPool& p, const QualifiedName& aName, const QualifiedName& aForCharSet)
: DdlNode(p),
name(p, aName),
forCharSet(p, aForCharSet),
@@ -848,13 +887,13 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_create_collation_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_create_collation_failed) << name.toQuotedString();
}
public:
- MetaName name;
- MetaName forCharSet;
- MetaName fromName;
+ QualifiedName name;
+ QualifiedName forCharSet;
+ QualifiedName fromName;
Firebird::string fromExternal;
Firebird::UCharBuffer specificAttributes;
bool createIfNotExistsOnly = false;
@@ -870,7 +909,7 @@ private:
class DropCollationNode : public DdlNode
{
public:
- DropCollationNode(MemoryPool& p, const MetaName& aName)
+ DropCollationNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName)
{
@@ -881,14 +920,23 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_collation);
+ protectSystemSchema(name.schema, obj_collation);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_collation_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_collation_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent = false;
};
@@ -896,11 +944,11 @@ public:
class CreateDomainNode : public DdlNode
{
public:
- CreateDomainNode(MemoryPool& p, ParameterClause* aNameType)
+ CreateDomainNode(MemoryPool& p, const QualifiedName& aName, dsql_fld* aType, ValueSourceClause* aDefaultClause)
: DdlNode(p),
- nameType(aNameType),
- notNull(false),
- check(NULL)
+ name(aName),
+ type(aType),
+ defaultClause(aDefaultClause)
{
}
@@ -909,16 +957,29 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyNewName(name);
+ protectSystemSchema(name.schema, obj_collation);
+ dsqlScratch->ddlSchema = name.schema;
+
+ type->resolve(dsqlScratch);
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_create_domain_failed) << nameType->name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_create_domain_failed) << name.toQuotedString();
}
public:
- NestConst nameType;
- bool notNull;
+ QualifiedName name;
+ NestConst type;
+ NestConst defaultClause;
NestConst check;
+ bool notNull = false;
bool createIfNotExistsOnly = false;
};
@@ -926,13 +987,9 @@ public:
class AlterDomainNode : public DdlNode
{
public:
- AlterDomainNode(MemoryPool& p, const MetaName& aName)
+ AlterDomainNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName),
- dropConstraint(false),
- dropDefault(false),
- setConstraint(NULL),
- setDefault(NULL),
renameTo(p)
{
}
@@ -942,62 +999,83 @@ public:
static ULONG checkUpdateNumericType(const dyn_fld& origFld, const dyn_fld& newFld);
static void getDomainType(thread_db* tdbb, jrd_tra* transaction, dyn_fld& dynFld);
static void modifyLocalFieldIndex(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName,
+ const QualifiedName& relationName, const MetaName& fieldName,
const MetaName& newFieldName);
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_field);
+ protectSystemSchema(name.schema, obj_field);
+ dsqlScratch->ddlSchema = name.schema;
+
+ if (type)
+ type->resolve(dsqlScratch);
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_domain_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_domain_failed) << name.toQuotedString();
}
private:
void rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimensions);
public:
- MetaName name;
- bool dropConstraint;
- bool dropDefault;
+ QualifiedName name;
NestConst setConstraint;
NestConst setDefault;
MetaName renameTo;
Firebird::AutoPtr type;
Firebird::TriState notNullFlag; // true = NOT NULL / false = NULL
+ bool dropConstraint = false;
+ bool dropDefault = false;
};
class DropDomainNode : public DdlNode
{
public:
- DropDomainNode(MemoryPool& p, const MetaName& aName)
+ DropDomainNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName)
{
}
static bool deleteDimensionRecords(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name);
+ const QualifiedName& name);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_field);
+ protectSystemSchema(name.schema, obj_field);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_domain_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_domain_failed) << name.toQuotedString();
}
private:
void check(thread_db* tdbb, jrd_tra* transaction);
public:
- MetaName name;
+ QualifiedName name;
bool silent = false;
};
@@ -1005,7 +1083,7 @@ public:
class CreateAlterExceptionNode : public DdlNode
{
public:
- CreateAlterExceptionNode(MemoryPool& p, const MetaName& aName,
+ CreateAlterExceptionNode(MemoryPool& p, const QualifiedName& aName,
const Firebird::string& aMessage)
: DdlNode(p),
name(p, aName),
@@ -1020,6 +1098,19 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_exception);
+
+ protectSystemSchema(name.schema, obj_exception);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
@@ -1027,7 +1118,7 @@ protected:
Firebird::Arg::Gds(createAlterCode(create, alter,
isc_dsql_create_except_failed, isc_dsql_alter_except_failed,
isc_dsql_create_alter_except_failed)) <<
- name;
+ name.toQuotedString();
}
private:
@@ -1035,7 +1126,7 @@ private:
bool executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
public:
- MetaName name;
+ QualifiedName name;
Firebird::string message;
bool create;
bool alter;
@@ -1046,7 +1137,7 @@ public:
class DropExceptionNode : public DdlNode
{
public:
- DropExceptionNode(MemoryPool& p, const MetaName& aName)
+ DropExceptionNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName),
silent(false)
@@ -1058,15 +1149,29 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_exception);
+
+ protectSystemSchema(name.schema, obj_exception);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_except_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_except_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
+ bool recreate = false;
};
@@ -1077,7 +1182,7 @@ typedef RecreateNodegetDsqlStatement()->setType(
- legacy ? DsqlStatement::TYPE_SET_GENERATOR : DsqlStatement::TYPE_DDL);
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_generator);
+
+ if (!restartSpecified)
+ protectSystemSchema(name.schema, obj_generator);
+
+ dsqlScratch->ddlSchema = name.schema;
+
+ dsqlScratch->getDsqlStatement()->setType(legacy ? DsqlStatement::TYPE_SET_GENERATOR : DsqlStatement::TYPE_DDL);
+
return this;
}
@@ -1127,7 +1242,7 @@ public:
bool createIfNotExistsOnly = false;
bool legacy;
bool restartSpecified;
- const MetaName name;
+ QualifiedName name;
std::optional value;
std::optional step;
};
@@ -1136,30 +1251,43 @@ public:
class DropSequenceNode : public DdlNode
{
public:
- DropSequenceNode(MemoryPool& pool, const MetaName& aName)
+ DropSequenceNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
silent(false)
{
}
- static void deleteIdentity(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name);
+ static void deleteIdentity(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_generator);
+
+ protectSystemSchema(name.schema, obj_generator);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_sequence_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_sequence_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
+ bool recreate = false;
};
@@ -1188,9 +1316,9 @@ public:
public:
MetaName name;
- MetaName relationName;
- MetaName fieldSource;
- MetaName identitySequence;
+ QualifiedName relationName;
+ QualifiedName fieldSource;
+ QualifiedName identitySequence;
std::optional identityType;
std::optional collationId;
Firebird::TriState notNullFlag; // true = NOT NULL / false = NULL
@@ -1260,7 +1388,7 @@ public:
Constraint::Type type;
Firebird::ObjectsArray columns;
NestConst index;
- MetaName refRelation;
+ QualifiedName refRelation;
Firebird::ObjectsArray refColumns;
const char* refUpdateAction;
const char* refDeleteAction;
@@ -1349,7 +1477,7 @@ public:
ConstraintType constraintType;
Firebird::ObjectsArray columns;
NestConst index;
- MetaName refRelation;
+ QualifiedName refRelation;
Firebird::ObjectsArray refColumns;
NestConst refAction;
NestConst check;
@@ -1392,7 +1520,7 @@ public:
dsql_fld* field;
NestConst defaultValue;
Firebird::ObjectsArray constraints;
- MetaName collate;
+ QualifiedName collate;
NestConst computed;
NestConst identityOptions;
bool notNullSpecified;
@@ -1487,13 +1615,16 @@ public:
RelationNode(MemoryPool& p, RelationSourceNode* aDsqlNode);
static bool deleteLocalField(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relationName, const MetaName& fieldName, bool silent,
+ const QualifiedName& relationName, const MetaName& fieldName, bool silent,
std::function preChangeHandler = {});
static void addToPublication(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& tableName, const MetaName& pubTame);
+ const QualifiedName& tableName, const MetaName& pubName);
static void dropFromPublication(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& tableName, const MetaName& pubTame);
+ const QualifiedName& tableName, const MetaName& pubName);
+
+public:
+ DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
protected:
virtual Firebird::string internalPrint(NodePrinter& printer) const
@@ -1535,7 +1666,7 @@ protected:
public:
NestConst dsqlNode;
- MetaName name;
+ QualifiedName name;
Firebird::Array > clauses;
Firebird::TriState ssDefiner;
Firebird::TriState replicationState;
@@ -1557,10 +1688,19 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyNewName(name);
+ protectSystemSchema(name.schema, obj_relation);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return RelationNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_create_table_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_create_table_failed) << name.toQuotedString();
}
private:
@@ -1583,6 +1723,15 @@ public:
{
}
+ DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_relation);
+ protectSystemSchema(name.schema, obj_relation);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return RelationNode::dsqlPass(dsqlScratch);
+ }
+
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
@@ -1591,7 +1740,7 @@ public:
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_table_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_table_failed) << name.toQuotedString();
}
private:
@@ -1603,7 +1752,7 @@ private:
class DropRelationNode : public DdlNode
{
public:
- DropRelationNode(MemoryPool& p, const MetaName& aName, bool aView = false)
+ DropRelationNode(MemoryPool& p, const QualifiedName& aName, bool aView = false)
: DdlNode(p),
name(p, aName),
view(aView),
@@ -1611,25 +1760,38 @@ public:
{
}
- static void deleteGlobalField(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& globalName);
+ static void deleteGlobalField(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& globalName);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, (view ? obj_view : obj_relation));
+
+ protectSystemSchema(name.schema, (view ? obj_view : obj_relation));
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(view ? isc_dsql_drop_view_failed :
- isc_dsql_drop_table_failed) << name;
+ statusVector << Firebird::Arg::Gds(view ? isc_dsql_drop_view_failed : isc_dsql_drop_table_failed) <<
+ name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool view;
bool silent;
+ bool recreate = false;
};
@@ -1665,7 +1827,7 @@ protected:
Firebird::Arg::Gds(createAlterCode(create, alter,
isc_dsql_create_view_failed, isc_dsql_alter_view_failed,
isc_dsql_create_alter_view_failed)) <<
- name;
+ name.toQuotedString();
}
private:
@@ -1710,7 +1872,7 @@ public:
conditionSource.clear();
}
- MetaName relation;
+ QualifiedName relation;
Firebird::ObjectsArray columns;
Firebird::TriState unique;
Firebird::TriState descending;
@@ -1720,34 +1882,35 @@ public:
bid expressionSource;
bid conditionBlr;
bid conditionSource;
- MetaName refRelation;
+ QualifiedName refRelation;
Firebird::ObjectsArray refColumns;
};
public:
- CreateIndexNode(MemoryPool& p, const MetaName& aName)
+ CreateIndexNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName)
{
}
public:
- static void store(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
- const Definition& definition, MetaName* referredIndexName = nullptr);
+ static void store(thread_db* tdbb, jrd_tra* transaction, QualifiedName& name,
+ const Definition& definition, QualifiedName* referredIndexName = nullptr);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_create_index_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_create_index_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool unique = false;
bool descending = false;
bool active = true;
@@ -1762,7 +1925,7 @@ public:
class AlterIndexNode : public DdlNode
{
public:
- AlterIndexNode(MemoryPool& p, const MetaName& aName, bool aActive)
+ AlterIndexNode(MemoryPool& p, const QualifiedName& aName, bool aActive)
: DdlNode(p),
name(p, aName),
active(aActive)
@@ -1774,14 +1937,22 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_index);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_index_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_index_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool active;
};
@@ -1789,7 +1960,7 @@ public:
class SetStatisticsNode : public DdlNode
{
public:
- SetStatisticsNode(MemoryPool& p, const MetaName& aName)
+ SetStatisticsNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName)
{
@@ -1800,43 +1971,58 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_index);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
// ASF: using ALTER INDEX's code.
- statusVector << Firebird::Arg::Gds(isc_dsql_alter_index_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_alter_index_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
};
class DropIndexNode : public DdlNode
{
public:
- DropIndexNode(MemoryPool& p, const MetaName& aName)
+ DropIndexNode(MemoryPool& p, const QualifiedName& aName)
: DdlNode(p),
name(p, aName)
{
}
- static bool deleteSegmentRecords(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name);
+ static bool deleteSegmentRecords(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& name);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const;
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_index);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_index_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_index_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent = false;
};
@@ -1877,8 +2063,6 @@ public:
CreateFilterNode(MemoryPool& p, const MetaName& aName)
: DdlNode(p),
name(p, aName),
- inputFilter(NULL),
- outputFilter(NULL),
entryPoint(p),
moduleName(p)
{
@@ -2253,6 +2437,7 @@ public:
const MetaName name;
MetaName plugin;
bool silent;
+ bool recreate = false;
};
@@ -2270,8 +2455,8 @@ typedef RecreateNode > PrivilegeClause;
-typedef Firebird::Pair > GranteeClause;
+typedef Firebird::NonPooledPair*> PrivilegeClause;
+typedef Firebird::NonPooledPair GranteeClause;
class GrantRevokeNode : public PrivilegesNode, private ExecInSecurityDb
{
@@ -2296,6 +2481,77 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ Firebird::Array grantees;
+
+ if (object)
+ grantees.add(object);
+
+ for (auto& user : users)
+ grantees.add(&user);
+
+ for (auto grantee : grantees)
+ {
+ switch (grantee->first)
+ {
+ case obj_charset:
+ case obj_collation:
+ case obj_exception:
+ case obj_field:
+ case obj_generator:
+ case obj_index:
+ case obj_package_header:
+ case obj_procedure:
+ case obj_relation:
+ case obj_view:
+ case obj_trigger:
+ case obj_udf:
+ dsqlScratch->qualifyExistingName(grantee->second, grantee->first);
+ break;
+
+ case obj_database:
+ case obj_schema:
+ case obj_user:
+ case obj_user_or_role:
+ case obj_sql_role:
+ case obj_privilege:
+ case obj_roles:
+ case obj_filters:
+ case obj_jobs:
+ case obj_tablespaces:
+ case obj_schemas:
+ break;
+
+ case obj_relations:
+ case obj_views:
+ case obj_procedures:
+ case obj_functions:
+ case obj_packages:
+ case obj_generators:
+ case obj_domains:
+ case obj_exceptions:
+ case obj_charsets:
+ case obj_collations:
+ fb_assert(grantee->second.object.hasData());
+
+ if (grantee->second.schema.isEmpty())
+ {
+ fb_assert(grantee->second.object.hasData());
+ dsqlScratch->qualifyNewName(grantee->second);
+ }
+
+ break;
+
+ default:
+ fb_assert(false);
+ break;
+ }
+ }
+
+ return PrivilegesNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
@@ -2309,20 +2565,20 @@ private:
void grantRevoke(thread_db* tdbb, jrd_tra* transaction, const GranteeClause* object,
const GranteeClause* userNod, const char* privs, MetaName field, int options);
static void checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
- const char* privilege, const MetaName& relationName,
+ const char* privilege, const QualifiedName& relationName,
const MetaName& fieldName, bool topLevel);
static void checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transaction,
const MetaName& grantor, const MetaName& roleName);
static void checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& grantor, const char* privilege, const MetaName& objName);
+ const MetaName& grantor, const char* privilege, const QualifiedName& objName);
static void checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
- const char* privilege, const MetaName& objName, SSHORT objType);
+ const char* privilege, const QualifiedName& objName, SSHORT objType);
static void storePrivilege(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& object, const MetaName& user,
+ const QualifiedName& object, const QualifiedName& user,
const MetaName& field, const TEXT* privilege, SSHORT userType,
SSHORT objType, int option, const MetaName& grantor);
static void setFieldClassName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& relation, const MetaName& field);
+ const QualifiedName& relation, const MetaName& field);
// Diagnostics print helper.
static const char* privilegeName(char symbol)
@@ -2404,6 +2660,12 @@ public:
public:
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ dsqlScratch->qualifyExistingName(setDefaultCharSet, obj_charset);
+ dsqlScratch->qualifyExistingName(setDefaultCollation, obj_collation);
+
+ for (auto& pubTable : pubTables)
+ dsqlScratch->qualifyExistingName(pubTable, obj_relation);
+
dsqlScratch->getDsqlStatement()->setType(
create ? DsqlStatement::TYPE_CREATE_DB : DsqlStatement::TYPE_DDL);
return this;
@@ -2434,15 +2696,92 @@ public:
SLONG linger = -1;
unsigned clauses = 0;
Firebird::string differenceFile;
- MetaName setDefaultCharSet;
- MetaName setDefaultCollation;
+ QualifiedName setDefaultCharSet;
+ QualifiedName setDefaultCollation;
MetaName cryptPlugin;
MetaName keyName;
Firebird::TriState ssDefiner;
- Firebird::Array pubTables;
+ Firebird::Array pubTables;
};
+class CreateAlterSchemaNode : public DdlNode
+{
+public:
+ CreateAlterSchemaNode(MemoryPool& pool, const MetaName& aName)
+ : DdlNode(pool),
+ name(pool, aName),
+ setDefaultCharSet(pool),
+ owner(pool)
+ {
+ }
+
+public:
+ DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override;
+ Firebird::string internalPrint(NodePrinter& printer) const override;
+ void checkPermission(thread_db* tdbb, jrd_tra* transaction) override;
+ void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) override;
+
+protected:
+ void putErrorPrefix(Firebird::Arg::StatusVector& statusVector) override
+ {
+ statusVector <<
+ Firebird::Arg::Gds(createAlterCode(create, alter,
+ isc_dsql_create_schema_failed, isc_dsql_alter_schema_failed,
+ isc_dsql_create_alter_schema_failed)) <<
+ name.toQuotedString();
+ }
+
+private:
+ void executeCreate(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ bool executeAlter(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+
+public:
+ MetaName name;
+ bool create = true;
+ bool alter = false;
+ bool createIfNotExistsOnly = false;
+ QualifiedName setDefaultCharSet;
+
+private:
+ MetaName owner;
+};
+
+
+class DropSchemaNode : public DdlNode
+{
+public:
+ DropSchemaNode(MemoryPool& pool, const MetaName& aName)
+ : DdlNode(pool),
+ name(pool, aName)
+ {
+ }
+
+public:
+ Firebird::string internalPrint(NodePrinter& printer) const override;
+ void checkPermission(thread_db* tdbb, jrd_tra* transaction) override;
+ void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction) override;
+
+protected:
+ void putErrorPrefix(Firebird::Arg::StatusVector& statusVector) override
+ {
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_schema_failed) << name.toQuotedString();
+ }
+
+private:
+ bool collectObjects(thread_db* tdbb, jrd_tra* transaction,
+ Firebird::Array>* objects = nullptr);
+
+public:
+ MetaName name;
+ bool silent = false;
+ bool recreate = false;
+};
+
+
+using RecreateSchemaNode = RecreateNode;
+
+
} // namespace
#endif // DSQL_DDL_NODES_H
diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp
index 586dfdb9ee..98242a8032 100644
--- a/src/dsql/DsqlCompilerScratch.cpp
+++ b/src/dsql/DsqlCompilerScratch.cpp
@@ -52,8 +52,8 @@ void DsqlCompilerScratch::dumpContextStack(const DsqlContextStack* stack)
context->ctx_context,
(context->ctx_flags & CTX_system) != 0,
(context->ctx_flags & CTX_returning) != 0,
- MAX_SQL_IDENTIFIER_SIZE, MAX_SQL_IDENTIFIER_SIZE, context->ctx_alias.c_str(),
- MAX_SQL_IDENTIFIER_SIZE, MAX_SQL_IDENTIFIER_SIZE, context->ctx_internal_alias.c_str());
+ MAX_SQL_IDENTIFIER_SIZE, MAX_SQL_IDENTIFIER_SIZE, context->ctx_alias[0].toQuotedString().c_str(),
+ MAX_SQL_IDENTIFIER_SIZE, MAX_SQL_IDENTIFIER_SIZE, context->ctx_internal_alias.toQuotedString().c_str());
}
}
#endif
@@ -99,40 +99,88 @@ void DsqlCompilerScratch::putDtype(const TypeClause* field, bool useSubType)
if (field->notNull)
appendUChar(blr_not_nullable);
- if (field->typeOfName.hasData())
+ if (field->typeOfName.object.hasData())
{
- if (field->typeOfTable.hasData())
+ if (field->typeOfTable.object.hasData())
{
if (field->explicitCollation)
{
- appendUChar(blr_column_name2);
- appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(field->typeOfTable.c_str());
- appendMetaString(field->typeOfName.c_str());
- appendUShort(field->textType);
+ if (field->typeOfTable.schema != ddlSchema)
+ {
+ appendUChar(blr_column_name3);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfTable.schema.c_str());
+ appendMetaString(field->typeOfTable.object.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUChar(1);
+ appendUShort(field->textType);
+ }
+ else
+ {
+ appendUChar(blr_column_name2);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfTable.object.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUShort(field->textType);
+ }
}
else
{
- appendUChar(blr_column_name);
- appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(field->typeOfTable.c_str());
- appendMetaString(field->typeOfName.c_str());
+ if (field->typeOfTable.schema != ddlSchema)
+ {
+ appendUChar(blr_column_name3);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfTable.schema.c_str());
+ appendMetaString(field->typeOfTable.object.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUChar(0);
+ }
+ else
+ {
+ appendUChar(blr_column_name);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfTable.object.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ }
}
}
else
{
if (field->explicitCollation)
{
- appendUChar(blr_domain_name2);
- appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(field->typeOfName.c_str());
- appendUShort(field->textType);
+ if (field->typeOfName.schema != ddlSchema)
+ {
+ appendUChar(blr_domain_name3);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfName.schema.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUChar(1);
+ appendUShort(field->textType);
+ }
+ else
+ {
+ appendUChar(blr_domain_name2);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUShort(field->textType);
+ }
}
else
{
- appendUChar(blr_domain_name);
- appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(field->typeOfName.c_str());
+ if (field->typeOfName.schema != ddlSchema)
+ {
+ appendUChar(blr_domain_name3);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfName.schema.c_str());
+ appendMetaString(field->typeOfName.object.c_str());
+ appendUChar(0);
+ }
+ else
+ {
+ appendUChar(blr_domain_name);
+ appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(field->typeOfName.object.c_str());
+ }
}
}
@@ -199,40 +247,88 @@ void DsqlCompilerScratch::putType(const TypeClause* type, bool useSubType)
if (type->notNull)
appendUChar(blr_not_nullable);
- if (type->typeOfName.hasData())
+ if (type->typeOfName.object.hasData())
{
- if (type->typeOfTable.hasData())
+ if (type->typeOfTable.object.hasData())
{
- if (type->collate.hasData())
+ if (type->collate.object.hasData())
{
- appendUChar(blr_column_name2);
- appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(type->typeOfTable.c_str());
- appendMetaString(type->typeOfName.c_str());
- appendUShort(type->textType);
+ if (type->typeOfTable.schema != ddlSchema)
+ {
+ appendUChar(blr_column_name3);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfTable.schema.c_str());
+ appendMetaString(type->typeOfTable.object.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUChar(1);
+ appendUShort(type->textType);
+ }
+ else
+ {
+ appendUChar(blr_column_name2);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfTable.object.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUShort(type->textType);
+ }
}
else
{
- appendUChar(blr_column_name);
- appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(type->typeOfTable.c_str());
- appendMetaString(type->typeOfName.c_str());
+ if (type->typeOfTable.schema != ddlSchema)
+ {
+ appendUChar(blr_column_name3);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfTable.schema.c_str());
+ appendMetaString(type->typeOfTable.object.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUChar(0);
+ }
+ else
+ {
+ appendUChar(blr_column_name);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfTable.object.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ }
}
}
else
{
- if (type->collate.hasData())
+ if (type->collate.object.hasData())
{
- appendUChar(blr_domain_name2);
- appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(type->typeOfName.c_str());
- appendUShort(type->textType);
+ if (type->typeOfName.schema != ddlSchema)
+ {
+ appendUChar(blr_domain_name3);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfName.schema.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUChar(1);
+ appendUShort(type->textType);
+ }
+ else
+ {
+ appendUChar(blr_domain_name2);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUShort(type->textType);
+ }
}
else
{
- appendUChar(blr_domain_name);
- appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
- appendMetaString(type->typeOfName.c_str());
+ if (type->typeOfName.schema != ddlSchema)
+ {
+ appendUChar(blr_domain_name3);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfName.schema.c_str());
+ appendMetaString(type->typeOfName.object.c_str());
+ appendUChar(0);
+ }
+ else
+ {
+ appendUChar(blr_domain_name);
+ appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of);
+ appendMetaString(type->typeOfName.object.c_str());
+ }
}
}
@@ -285,7 +381,7 @@ void DsqlCompilerScratch::putType(const TypeClause* type, bool useSubType)
// Write out local variable field data type.
void DsqlCompilerScratch::putLocalVariableDecl(dsql_var* variable, DeclareVariableNode* hostParam,
- const MetaName& collationName)
+ QualifiedName& collationName)
{
const auto field = variable->field;
@@ -476,14 +572,14 @@ void DsqlCompilerScratch::genParameters(Array >& para
for (FB_SIZE_T i = 0; i < parameters.getCount(); ++i)
{
ParameterClause* parameter = parameters[i];
- putDebugArgument(fb_dbg_arg_input, i, parameter->name.c_str());
+ putDebugArgument(fb_dbg_arg_input, i, parameter->name.c_str()); // TODO: ?
putType(parameter->type, true);
// Add slot for null flag (parameter2).
appendUChar(blr_short);
appendUChar(0);
- makeVariable(parameter->type, parameter->name.c_str(),
+ makeVariable(parameter->type, parameter->name.c_str(), // TODO: ?
dsql_var::TYPE_INPUT, 0, (USHORT) (2 * i), 0);
}
}
@@ -498,14 +594,14 @@ void DsqlCompilerScratch::genParameters(Array >& para
for (FB_SIZE_T i = 0; i < returns.getCount(); ++i)
{
ParameterClause* parameter = returns[i];
- putDebugArgument(fb_dbg_arg_output, i, parameter->name.c_str());
+ putDebugArgument(fb_dbg_arg_output, i, parameter->name.c_str()); // TODO: ?
putType(parameter->type, true);
// Add slot for null flag (parameter2).
appendUChar(blr_short);
appendUChar(0);
- makeVariable(parameter->type, parameter->name.c_str(),
+ makeVariable(parameter->type, parameter->name.c_str(), // TODO: ?
dsql_var::TYPE_OUTPUT, 1, (USHORT) (2 * i), i);
}
}
@@ -540,7 +636,7 @@ void DsqlCompilerScratch::addCTEs(WithClause* withClause)
// Add CTE name into CTE aliases stack. It allows later to search for
// aliases of given CTE.
- addCTEAlias((*cte)->alias);
+ addCTEAlias((*cte)->alias.c_str());
}
else
ctes.add(*cte);
@@ -932,12 +1028,12 @@ RseNode* DsqlCompilerScratch::pass1RseIsRecursive(RseNode* input)
// Check if table reference is recursive i.e. its name is equal to the name of current processing CTE.
bool DsqlCompilerScratch::pass1RelProcIsRecursive(RecordSourceNode* input)
{
- MetaName relName;
+ QualifiedName relName;
string relAlias;
if (auto procNode = nodeAs(input))
{
- relName = procNode->dsqlName.identifier;
+ relName = procNode->dsqlName;
relAlias = procNode->alias;
}
else if (auto relNode = nodeAs(input))
@@ -951,10 +1047,10 @@ bool DsqlCompilerScratch::pass1RelProcIsRecursive(RecordSourceNode* input)
fb_assert(currCtes.hasData());
const SelectExprNode* currCte = currCtes.object();
- const bool recursive = currCte->alias == relName.c_str();
+ const bool recursive = relName.schema.isEmpty() && currCte->alias == relName.object.c_str();
if (recursive)
- addCTEAlias(relAlias.hasData() ? relAlias.c_str() : relName.c_str());
+ addCTEAlias(relAlias.hasData() ? relAlias.c_str() : relName.object.c_str());
return recursive;
}
diff --git a/src/dsql/DsqlCompilerScratch.h b/src/dsql/DsqlCompilerScratch.h
index 8755b7cb2d..a7e8ad81fc 100644
--- a/src/dsql/DsqlCompilerScratch.h
+++ b/src/dsql/DsqlCompilerScratch.h
@@ -96,6 +96,7 @@ public:
mainScratch(aMainScratch),
outerMessagesMap(p),
outerVarsMap(p),
+ ddlSchema(p),
ctes(p),
cteAliases(p),
subFunctions(p),
@@ -151,16 +152,49 @@ public:
dsqlStatement = aDsqlStatement;
}
+ void qualifyNewName(QualifiedName& name) const
+ {
+ using namespace Firebird;
+
+ const auto tdbb = JRD_get_thread_data();
+
+ if (!dbb->dbb_attachment->qualifyNewName(tdbb, name))
+ {
+ if (name.schema.isEmpty())
+ status_exception::raise(Arg::Gds(isc_dyn_cannot_infer_schema));
+ else
+ status_exception::raise(Arg::Gds(isc_dyn_schema_not_found) << name.schema.toQuotedString());
+ }
+ }
+
+ void qualifyExistingName(QualifiedName& name, ObjectType objectType) const
+ {
+ if (!(name.schema.isEmpty() && name.object.hasData()))
+ return;
+
+ const auto tdbb = JRD_get_thread_data();
+ const auto attachment = tdbb->getAttachment();
+
+ if (ddlSchema.hasData())
+ {
+ Firebird::ObjectsArray schemaSearchPath({ddlSchema, SYSTEM_SCHEMA});
+ attachment->qualifyExistingName(tdbb, name, objectType, &schemaSearchPath);
+ }
+ else
+ attachment->qualifyExistingName(tdbb, name, objectType);
+ }
+
void putBlrMarkers(ULONG marks);
void putDtype(const TypeClause* field, bool useSubType);
void putType(const TypeClause* type, bool useSubType);
- void putLocalVariableDecl(dsql_var* variable, DeclareVariableNode* hostParam, const MetaName& collationName);
+ void putLocalVariableDecl(dsql_var* variable, DeclareVariableNode* hostParam, QualifiedName& collationName);
void putLocalVariableInit(dsql_var* variable, const DeclareVariableNode* hostParam);
- void putLocalVariable(dsql_var* variable, DeclareVariableNode* hostParam, const MetaName& collationName)
+ void putLocalVariable(dsql_var* variable)
{
- putLocalVariableDecl(variable, hostParam, collationName);
- putLocalVariableInit(variable, hostParam);
+ QualifiedName dummyCollationName;
+ putLocalVariableDecl(variable, nullptr, dummyCollationName);
+ putLocalVariableInit(variable, nullptr);
}
void putOuterMaps();
@@ -301,8 +335,8 @@ public:
USHORT errorHandlers = 0; // count of active error handlers
USHORT clientDialect = 0; // dialect passed into the API call
USHORT inOuterJoin = 0; // processing inside outer-join part
- Firebird::string aliasRelationPrefix; // prefix for every relation-alias.
- MetaName package; // package being defined
+ Firebird::ObjectsArray aliasRelationPrefix; // prefix for every relation-alias.
+ QualifiedName package; // package being defined
Firebird::Stack currCtes; // current processing CTE's
dsql_ctx* recursiveCtx = nullptr; // context of recursive CTE
USHORT recursiveCtxId = 0; // id of recursive union stream context
@@ -317,6 +351,7 @@ public:
DsqlCompilerScratch* mainScratch = nullptr;
Firebird::NonPooledMap outerMessagesMap; //
Firebird::NonPooledMap outerVarsMap; //
+ MetaName ddlSchema;
private:
Firebird::HalfStaticArray ctes; // common table expressions
diff --git a/src/dsql/DsqlRequests.cpp b/src/dsql/DsqlRequests.cpp
index cb68720f7e..9c95a2f241 100644
--- a/src/dsql/DsqlRequests.cpp
+++ b/src/dsql/DsqlRequests.cpp
@@ -1055,7 +1055,10 @@ void DsqlDdlRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
(internalScratch->flags & DsqlCompilerScratch::FLAG_INTERNAL_REQUEST);
if (!isInternalRequest && node->mustBeReplicated())
- REPL_exec_sql(tdbb, req_transaction, getDsqlStatement()->getOrgText());
+ {
+ REPL_exec_sql(tdbb, req_transaction, getDsqlStatement()->getOrgText(),
+ *getDsqlStatement()->getSchemaSearchPath());
+ }
}
catch (status_exception& ex)
{
diff --git a/src/dsql/DsqlStatementCache.cpp b/src/dsql/DsqlStatementCache.cpp
index 2ba98386a2..5d50e5cfab 100644
--- a/src/dsql/DsqlStatementCache.cpp
+++ b/src/dsql/DsqlStatementCache.cpp
@@ -259,16 +259,37 @@ void DsqlStatementCache::buildStatementKey(thread_db* tdbb, RefStrPtr& key, cons
{
const auto attachment = tdbb->getAttachment();
+ const auto searchPathLen = std::accumulate(
+ attachment->att_schema_search_path->begin(),
+ attachment->att_schema_search_path->end(),
+ 0u,
+ [](const auto& len, const auto& pathItem) {
+ return len + pathItem.length() + 1u;
+ }
+ );
+
const SSHORT charSetId = isInternalRequest ? CS_METADATA : attachment->att_charset;
const int debugOptions = (int) attachment->getDebugOptions().getDsqlKeepBlr();
key = FB_NEW_POOL(getPool()) RefString(getPool());
+ key->resize(1 + sizeof(charSetId) + text.length() + 1 + searchPathLen + 1);
- key->resize(1 + sizeof(charSetId) + text.length());
char* p = key->begin();
- *p = (clientDialect << 2) | (int(isInternalRequest) << 1) | debugOptions;
- memcpy(p + 1, &charSetId, sizeof(charSetId));
- memcpy(p + 1 + sizeof(charSetId), text.c_str(), text.length());
+ *p++ = (clientDialect << 2) | (int(isInternalRequest) << 1) | debugOptions;
+ memcpy(p, &charSetId, sizeof(charSetId));
+ p += sizeof(charSetId);
+ memcpy(p, text.c_str(), text.length() + 1);
+ p += text.length() + 1;
+
+ for (const auto& pathItem : *attachment->att_schema_search_path)
+ {
+ memcpy(p, pathItem.c_str(), pathItem.length() + 1);
+ p += pathItem.length() + 1;
+ }
+
+ *p = '\0';
+
+ fb_assert(p + 1 == key->end());
}
void DsqlStatementCache::buildVerifyKey(thread_db* tdbb, string& key, bool isInternalRequest)
diff --git a/src/dsql/DsqlStatements.cpp b/src/dsql/DsqlStatements.cpp
index 47117b26a6..8741004cf1 100644
--- a/src/dsql/DsqlStatements.cpp
+++ b/src/dsql/DsqlStatements.cpp
@@ -36,6 +36,16 @@ using namespace Jrd;
// Class DsqlStatement
+DsqlStatement::DsqlStatement(MemoryPool& pool, dsql_dbb* aDsqlAttachment)
+ : PermanentStorage(pool),
+ dsqlAttachment(aDsqlAttachment),
+ ports(pool)
+{
+ pool.setStatsGroup(memoryStats);
+
+ schemaSearchPath = dsqlAttachment->dbb_attachment->att_schema_search_path;
+}
+
// Rethrow an exception with isc_no_meta_update and prefix codes.
void DsqlStatement::rethrowDdlException(status_exception& ex, bool metadataUpdate, DdlNode* node)
{
@@ -80,6 +90,7 @@ int DsqlStatement::release()
void DsqlStatement::doRelease()
{
+ fb_assert(!cacheKey.hasData());
setSqlText(nullptr);
setOrgText(nullptr, 0);
diff --git a/src/dsql/DsqlStatements.h b/src/dsql/DsqlStatements.h
index 1ab48fc986..15ba7d0d91 100644
--- a/src/dsql/DsqlStatements.h
+++ b/src/dsql/DsqlStatements.h
@@ -68,16 +68,7 @@ public:
static void rethrowDdlException(Firebird::status_exception& ex, bool metadataUpdate, DdlNode* node);
public:
- DsqlStatement(MemoryPool& pool, dsql_dbb* aDsqlAttachment)
- : PermanentStorage(pool),
- dsqlAttachment(aDsqlAttachment),
- type(TYPE_SELECT),
- flags(0),
- blrVersion(5),
- ports(pool)
- {
- pool.setStatsGroup(memoryStats);
- }
+ DsqlStatement(MemoryPool& pool, dsql_dbb* aDsqlAttachment);
protected:
virtual ~DsqlStatement() = default;
@@ -139,6 +130,8 @@ public:
void setCacheKey(Firebird::RefStrPtr& value) { cacheKey = value; }
void resetCacheKey() { cacheKey = nullptr; }
+ const auto getSchemaSearchPath() const { return schemaSearchPath; }
+
public:
virtual bool isDml() const
{
@@ -174,9 +167,9 @@ protected:
protected:
dsql_dbb* dsqlAttachment;
Firebird::MemoryStats memoryStats;
- Type type; // Type of statement
- ULONG flags; // generic flag
- unsigned blrVersion;
+ Type type = TYPE_SELECT; // Type of statement
+ ULONG flags = 0; // generic flag
+ unsigned blrVersion = 5;
Firebird::RefStrPtr sqlText;
Firebird::RefStrPtr orgText;
Firebird::RefStrPtr cacheKey;
@@ -185,6 +178,7 @@ protected:
dsql_msg* receiveMsg = nullptr; // Per record message to be received
dsql_par* eof = nullptr; // End of file parameter
DsqlCompilerScratch* scratch = nullptr;
+ Firebird::RefPtr>> schemaSearchPath;
private:
Firebird::AtomicCounter refCounter;
diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp
index 8320ab355b..17fc95f6fe 100644
--- a/src/dsql/ExprNodes.cpp
+++ b/src/dsql/ExprNodes.cpp
@@ -4007,7 +4007,7 @@ dsc* CoalesceNode::execute(thread_db* tdbb, Request* request) const
//--------------------
-CollateNode::CollateNode(MemoryPool& pool, ValueExprNode* aArg, const MetaName& aCollation)
+CollateNode::CollateNode(MemoryPool& pool, ValueExprNode* aArg, const QualifiedName& aCollation)
: TypedNode(pool),
arg(aArg),
collation(pool, aCollation)
@@ -4033,7 +4033,7 @@ ValueExprNode* CollateNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
}
ValueExprNode* CollateNode::pass1Collate(DsqlCompilerScratch* dsqlScratch, ValueExprNode* input,
- const MetaName& collation)
+ QualifiedName& collation)
{
thread_db* tdbb = JRD_get_thread_data();
MemoryPool& pool = *tdbb->getDefaultPool();
@@ -4735,6 +4735,98 @@ ValueExprNode* CurrentRoleNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
//--------------------
+static RegisterNode regCurrentSchemaNode({blr_current_schema});
+
+DmlNode* CurrentSchemaNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScratch* /*csb*/,
+ const UCHAR /*blrOp*/)
+{
+ return FB_NEW_POOL(pool) CurrentSchemaNode(pool);
+}
+
+string CurrentSchemaNode::internalPrint(NodePrinter& printer) const
+{
+ ValueExprNode::internalPrint(printer);
+
+ return "CurrentSchemaNode";
+}
+
+void CurrentSchemaNode::setParameterName(dsql_par* parameter) const
+{
+ parameter->par_name = parameter->par_alias = "CURRENT_SCHEMA";
+}
+
+void CurrentSchemaNode::genBlr(DsqlCompilerScratch* dsqlScratch)
+{
+ dsqlScratch->appendUChar(blr_current_schema);
+}
+
+void CurrentSchemaNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
+{
+ desc->dsc_dtype = dtype_varying;
+ desc->dsc_scale = 0;
+ desc->dsc_flags = DSC_nullable;
+ desc->dsc_ttype() = ttype_metadata;
+ desc->dsc_length = MAX_SQL_IDENTIFIER_LEN + sizeof(USHORT);
+}
+
+void CurrentSchemaNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* desc)
+{
+ desc->dsc_dtype = dtype_text;
+ desc->dsc_ttype() = ttype_metadata;
+ desc->dsc_length = MAX_SQL_IDENTIFIER_LEN;
+ desc->dsc_scale = 0;
+ desc->dsc_flags = DSC_nullable;
+}
+
+ValueExprNode* CurrentSchemaNode::copy(thread_db* tdbb, NodeCopier& /*copier*/) const
+{
+ return FB_NEW_POOL(*tdbb->getDefaultPool()) CurrentSchemaNode(*tdbb->getDefaultPool());
+}
+
+ValueExprNode* CurrentSchemaNode::pass2(thread_db* tdbb, CompilerScratch* csb)
+{
+ ValueExprNode::pass2(tdbb, csb);
+
+ dsc desc;
+ getDesc(tdbb, csb, &desc);
+ impureOffset = csb->allocImpure();
+
+ return this;
+}
+
+dsc* CurrentSchemaNode::execute(thread_db* tdbb, Request* request) const
+{
+ const auto attachment = tdbb->getAttachment();
+
+ QualifiedName name;
+ attachment->qualifyNewName(tdbb, name);
+
+ if (name.schema.hasData())
+ {
+ const auto impure = request->getImpure(impureOffset);
+
+ impure->vlu_desc.dsc_dtype = dtype_text;
+ impure->vlu_desc.dsc_sub_type = 0;
+ impure->vlu_desc.dsc_scale = 0;
+ impure->vlu_desc.setTextType(ttype_metadata);
+
+ impure->vlu_desc.dsc_address = reinterpret_cast(const_cast(name.schema.c_str()));
+ impure->vlu_desc.dsc_length = static_cast(name.schema.length());
+ return &impure->vlu_desc;
+ }
+ else
+ return nullptr;
+}
+
+ValueExprNode* CurrentSchemaNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
+{
+ return FB_NEW_POOL(dsqlScratch->getPool()) CurrentSchemaNode(dsqlScratch->getPool());
+}
+
+
+//--------------------
+
+
static RegisterNode regCurrentUserNode({blr_user_name});
DmlNode* CurrentUserNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScratch* /*csb*/,
@@ -5072,9 +5164,9 @@ dsc* DecodeNode::execute(thread_db* tdbb, Request* request) const
//--------------------
-static RegisterNode regDefaultNode({blr_default});
+static RegisterNode regDefaultNode({blr_default, blr_default2});
-DefaultNode::DefaultNode(MemoryPool& pool, const MetaName& aRelationName,
+DefaultNode::DefaultNode(MemoryPool& pool, const QualifiedName& aRelationName,
const MetaName& aFieldName)
: DsqlNode(pool),
relationName(aRelationName),
@@ -5083,10 +5175,17 @@ DefaultNode::DefaultNode(MemoryPool& pool, const MetaName& aRelationName,
{
}
-DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/)
+DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp)
{
- MetaName relationName, fieldName;
- csb->csb_blr_reader.getMetaName(relationName);
+ QualifiedName relationName;
+
+ if (blrOp == blr_default2)
+ csb->csb_blr_reader.getMetaName(relationName.schema);
+
+ csb->csb_blr_reader.getMetaName(relationName.object);
+ csb->qualifyExistingName(tdbb, relationName, obj_relation);
+
+ MetaName fieldName;
csb->csb_blr_reader.getMetaName(fieldName);
if (csb->collectingDependencies())
@@ -5113,7 +5212,7 @@ DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
if (fld)
{
- if (fld->fld_source_rel_field.first.hasData())
+ if (fld->fld_source_rel_field.first.object.hasData())
{
relationName = fld->fld_source_rel_field.first;
fieldName = fld->fld_source_rel_field.second;
@@ -5136,7 +5235,7 @@ DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
ValueExprNode* DefaultNode::createFromField(thread_db* tdbb, CompilerScratch* csb,
StreamType* map, jrd_fld* fld)
{
- if (fld->fld_generator_name.hasData())
+ if (fld->fld_generator_name.object.hasData())
{
// Make a (next value for ) expression.
@@ -5145,10 +5244,15 @@ ValueExprNode* DefaultNode::createFromField(thread_db* tdbb, CompilerScratch* cs
bool sysGen = false;
if (!MET_load_generator(tdbb, genNode->generator, &sysGen, &genNode->step))
- status_exception::raise(Arg::Gds(isc_gennotdef) << Arg::Str(fld->fld_generator_name));
+ status_exception::raise(Arg::Gds(isc_gennotdef) << fld->fld_generator_name.toQuotedString());
if (sysGen)
- status_exception::raise(Arg::Gds(isc_cant_modify_sysobj) << "generator" << fld->fld_generator_name);
+ {
+ status_exception::raise(
+ Arg::Gds(isc_cant_modify_sysobj) <<
+ "generator" <<
+ fld->fld_generator_name.toQuotedString());
+ }
return genNode;
}
@@ -5194,8 +5298,15 @@ bool DefaultNode::setParameterType(DsqlCompilerScratch* /*dsqlScratch*/,
void DefaultNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
- dsqlScratch->appendUChar(blr_default);
- dsqlScratch->appendMetaString(relationName.c_str());
+ if (relationName.schema != dsqlScratch->ddlSchema)
+ {
+ dsqlScratch->appendUChar(blr_default2);
+ dsqlScratch->appendMetaString(relationName.schema.c_str());
+ }
+ else
+ dsqlScratch->appendUChar(blr_default);
+
+ dsqlScratch->appendMetaString(relationName.object.c_str());
dsqlScratch->appendMetaString(fieldName.c_str());
}
@@ -5947,7 +6058,7 @@ DmlNode* FieldNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
const USHORT context = csb->csb_blr_reader.getByte();
// check if this is a VALUE of domain's check constraint
- if (!csb->csb_domain_validation.isEmpty() && context == 0 &&
+ if (!csb->csb_domain_validation.object.isEmpty() && context == 0 &&
(blrOp == blr_fid || blrOp == blr_field))
{
if (blrOp == blr_fid)
@@ -6024,7 +6135,7 @@ DmlNode* FieldNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
if ((id = PAR_find_proc_field(procedure, name)) == -1)
{
PAR_error(csb, Arg::Gds(isc_fldnotdef2) <<
- Arg::Str(name) << Arg::Str(procedure->getName().toString()));
+ Arg::Str(name) << Arg::Str(procedure->getName().toQuotedString()));
}
}
else
@@ -6056,12 +6167,12 @@ DmlNode* FieldNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
if (tdbb->getAttachment()->isGbak())
{
PAR_warning(Arg::Warning(isc_fldnotdef) << Arg::Str(name) <<
- Arg::Str(relation->rel_name));
+ relation->rel_name.toQuotedString());
}
else if (!(relation->rel_flags & REL_deleted))
{
PAR_error(csb, Arg::Gds(isc_fldnotdef) << Arg::Str(name) <<
- Arg::Str(relation->rel_name));
+ relation->rel_name.toQuotedString());
}
else
PAR_error(csb, Arg::Gds(isc_ctxnotdef));
@@ -6129,7 +6240,7 @@ ValueExprNode* FieldNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
return this;
}
- if (dsqlScratch->isPsql() && !dsqlQualifier.hasData())
+ if (dsqlScratch->isPsql() && dsqlQualifier.object.isEmpty())
{
VariableNode* node = FB_NEW_POOL(dsqlScratch->getPool()) VariableNode(dsqlScratch->getPool());
node->line = line;
@@ -6153,7 +6264,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
thread_db* tdbb = JRD_get_thread_data();
if (list)
- *list = NULL;
+ *list = nullptr;
/* CVC: PLEASE READ THIS EXPLANATION IF YOU NEED TO CHANGE THIS CODE.
You should ensure that this function:
@@ -6213,7 +6324,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
dsql_ctx* context = stack.object();
if (context->ctx_scope_level != currentScopeLevel - 1 ||
- ((context->ctx_flags & CTX_cursor) && dsqlQualifier.isEmpty()) ||
+ ((context->ctx_flags & CTX_cursor) && dsqlQualifier.object.isEmpty()) ||
(!(context->ctx_flags & CTX_cursor) && dsqlCursorField))
{
continue;
@@ -6229,31 +6340,33 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
{
// If there's no name then we have most probable an asterisk that
// needs to be exploded. This should be handled by the caller and
- // when the caller can handle this, list is true.
+ // when the caller can handle this, list is not nullptr.
if (dsqlName.isEmpty())
{
if (list)
{
- dsql_ctx* stackContext = stack.object();
+ ambiguousCtxStack.push(context);
+ // FIXME: "Ambiguous field name between table @1 and table @2" is wrong here
+ PASS1_ambiguity_check(dsqlScratch, dsqlName, ambiguousCtxStack);
if (context->ctx_relation)
{
RelationSourceNode* relNode = FB_NEW_POOL(*tdbb->getDefaultPool())
RelationSourceNode(*tdbb->getDefaultPool());
- relNode->dsqlContext = stackContext;
+ relNode->dsqlContext = context;
*list = relNode;
}
else if (context->ctx_procedure)
{
ProcedureSourceNode* procNode = FB_NEW_POOL(*tdbb->getDefaultPool())
ProcedureSourceNode(*tdbb->getDefaultPool());
- procNode->dsqlContext = stackContext;
+ procNode->dsqlContext = context;
*list = procNode;
}
//// TODO: LocalTableSourceNode
fb_assert(*list);
- return NULL;
+ continue;
}
break;
@@ -6265,7 +6378,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
{
if (field->fld_name == dsqlName.c_str())
{
- if (dsqlQualifier.isEmpty())
+ if (dsqlQualifier.object.isEmpty())
{
if (!context->getImplicitJoinField(field->fld_name, usingField))
{
@@ -6290,7 +6403,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
node->column = column;
***/
}
- else if (dsqlQualifier.hasData() && !field)
+ else if (dsqlQualifier.object.hasData() && !field)
{
if (!(context->ctx_flags & CTX_view_with_check_modify))
{
@@ -6334,11 +6447,14 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
{
// if an qualifier is present check if we have the same derived
// table else continue;
- if (dsqlQualifier.hasData())
+ if (dsqlQualifier.object.hasData())
{
if (context->ctx_alias.hasData())
{
- if (dsqlQualifier != context->ctx_alias)
+ // FIXME:
+ fb_assert(context->ctx_alias.getCount() == 1);
+
+ if (dsqlQualifier != context->ctx_alias[0])
continue;
}
else
@@ -6373,7 +6489,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
{
NestConst usingField = NULL;
- if (dsqlQualifier.isEmpty())
+ if (dsqlQualifier.object.isEmpty())
{
if (!context->getImplicitJoinField(dsqlName, usingField))
break;
@@ -6401,7 +6517,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
}
}
- if (!node && dsqlQualifier.hasData())
+ if (!node && dsqlQualifier.object.hasData())
{
// If a qualifier was present and we didn't find
// a matching field then we should stop searching.
@@ -6424,14 +6540,14 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
// Clean up stack
ambiguousCtxStack.clear();
- if (!node)
- PASS1_field_unknown(dsqlQualifier.nullStr(), dsqlName.nullStr(), this);
+ if (!node && !(list && *list))
+ PASS1_field_unknown(dsqlQualifier.toQuotedString().nullStr(), dsqlName.toQuotedString().nullStr(), this);
return node;
}
// Attempt to resolve field against context. Return first field in context if successful, NULL if not.
-dsql_fld* FieldNode::resolveContext(DsqlCompilerScratch* dsqlScratch, const MetaName& qualifier, dsql_ctx* context)
+dsql_fld* FieldNode::resolveContext(DsqlCompilerScratch* dsqlScratch, const QualifiedName& qualifier, dsql_ctx* context)
{
// CVC: Warning: the second param, "name" is not used anymore and
// therefore it was removed. Thus, the local variable "table_name"
@@ -6451,37 +6567,29 @@ dsql_fld* FieldNode::resolveContext(DsqlCompilerScratch* dsqlScratch, const Meta
if (!relation && !procedure)
return nullptr;
- // if there is no qualifier, then we cannot match against
- // a context of a different scoping level
- // AB: Yes we can, but the scope level where the field is has priority.
- /***
- if (qualifier.isEmpty() && context->ctx_scope_level != dsqlScratch->scopeLevel)
- return nullptr;
- ***/
-
// AB: If this context is a system generated context as in NEW/OLD inside
// triggers, the qualifier by the field is mandatory. While we can't
// fall back from a higher scope-level to the NEW/OLD contexts without
// the qualifier present.
// An exception is a check-constraint that is allowed to reference fields
// without the qualifier.
- if (!dsqlScratch->checkConstraintTrigger && (context->ctx_flags & CTX_system) && qualifier.isEmpty())
+ if (!dsqlScratch->checkConstraintTrigger && (context->ctx_flags & CTX_system) && qualifier.object.isEmpty())
return nullptr;
- MetaString aliasName = context->ctx_internal_alias;
+ auto aliasName = context->ctx_internal_alias;
// AB: For a check constraint we should ignore the alias if the alias
// contains the "NEW" alias. This is because it is possible
// to reference a field by the complete table-name as alias
// (see EMPLOYEE table in examples for a example).
- if (dsqlScratch->checkConstraintTrigger && aliasName.hasData())
+ if (dsqlScratch->checkConstraintTrigger && aliasName.object.hasData())
{
// If a qualifier is present and it's equal to the alias then we've already the right table-name
- if (qualifier.isEmpty() || qualifier != aliasName)
+ if (qualifier.object.isEmpty() || qualifier != aliasName) // FIXME:
{
- if (aliasName == NEW_CONTEXT_NAME)
+ if (aliasName == QualifiedName(NEW_CONTEXT_NAME))
aliasName.clear();
- else if (aliasName == OLD_CONTEXT_NAME)
+ else if (aliasName == QualifiedName(OLD_CONTEXT_NAME))
{
// Only use the OLD context if it is explicit used. That means the
// qualifer should hold the "OLD" alias.
@@ -6490,13 +6598,13 @@ dsql_fld* FieldNode::resolveContext(DsqlCompilerScratch* dsqlScratch, const Meta
}
}
- if (aliasName.isEmpty())
- aliasName = relation ? relation->rel_name : procedure->prc_name.identifier;
+ if (aliasName.object.isEmpty())
+ aliasName = relation ? relation->rel_name : procedure->prc_name;
- fb_assert(aliasName.hasData());
+ fb_assert(aliasName.object.hasData());
// If a context qualifier is present, make sure this is the proper context
- if (qualifier.hasData() && qualifier != aliasName)
+ if (qualifier.object.hasData() && !PASS1_compare_alias(aliasName, qualifier))
return nullptr;
// Lookup field in relation or procedure
@@ -6811,7 +6919,10 @@ ValueExprNode* FieldNode::pass1(thread_db* tdbb, CompilerScratch* csb)
const SLONG ssRelationId = tail->csb_view ?
tail->csb_view->rel_id : (csb->csb_view ? csb->csb_view->rel_id : 0);
- CMP_post_access(tdbb, csb, relation->rel_security_name, ssRelationId,
+ CMP_post_access(tdbb, csb, relation->rel_security_name.schema, ssRelationId,
+ SCL_usage, obj_schemas, QualifiedName(relation->rel_name.schema));
+
+ CMP_post_access(tdbb, csb, relation->rel_security_name.object, ssRelationId,
privilege, obj_relations, relation->rel_name);
// Field-level privilege access is posted for every operation except DELETE
@@ -6819,7 +6930,7 @@ ValueExprNode* FieldNode::pass1(thread_db* tdbb, CompilerScratch* csb)
if (privilege != SCL_delete)
{
CMP_post_access(tdbb, csb, field->fld_security_name, ssRelationId,
- privilege, obj_column, field->fld_name, relation->rel_name);
+ privilege, obj_column, relation->rel_name, field->fld_name);
}
}
@@ -6835,7 +6946,7 @@ ValueExprNode* FieldNode::pass1(thread_db* tdbb, CompilerScratch* csb)
// Msg 364 "cannot access column %s in view %s"
ERR_post(Arg::Gds(isc_no_field_access) << Arg::Str(field->fld_name) <<
- Arg::Str(relation->rel_name));
+ relation->rel_name.toQuotedString());
}
// The previous test below is an apparent temporary fix
@@ -6886,7 +6997,7 @@ ValueExprNode* FieldNode::pass1(thread_db* tdbb, CompilerScratch* csb)
// This is an assignment to a computed column. Report the error here when we have the field name.
ERR_post(
Arg::Gds(isc_read_only_field) <<
- (string(relation->rel_name.c_str()) + "." + field->fld_name.c_str()));
+ (relation->rel_name.toQuotedString() + "." + field->fld_name.toQuotedString()));
}
FB_SIZE_T pos;
@@ -7058,10 +7169,10 @@ dsc* FieldNode::execute(thread_db* tdbb, Request* request) const
//--------------------
-static RegisterNode regGenIdNode({blr_gen_id, blr_gen_id2});
+static RegisterNode regGenIdNode({blr_gen_id, blr_gen_id2, blr_gen_id3});
GenIdNode::GenIdNode(MemoryPool& pool, bool aDialect1,
- const MetaName& name,
+ const QualifiedName& name,
ValueExprNode* aArg,
bool aImplicit, bool aIdentity)
: TypedNode(pool),
@@ -7077,25 +7188,34 @@ GenIdNode::GenIdNode(MemoryPool& pool, bool aDialect1,
DmlNode* GenIdNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp)
{
- MetaName name;
- csb->csb_blr_reader.getMetaName(name);
+ QualifiedName name;
- ValueExprNode* explicitStep = (blrOp == blr_gen_id2) ? NULL : PAR_parse_value(tdbb, csb);
- GenIdNode* const node =
- FB_NEW_POOL(pool) GenIdNode(pool, (csb->blrVersion == 4), name, explicitStep,
- (blrOp == blr_gen_id2), false);
+ if (blrOp == blr_gen_id3)
+ csb->csb_blr_reader.getMetaName(name.schema);
+
+ csb->csb_blr_reader.getMetaName(name.object);
+
+ if (name.object.isEmpty() && (name.schema == SYSTEM_SCHEMA || name.schema.isEmpty()))
+ name.schema = SYSTEM_SCHEMA;
+ else
+ csb->qualifyExistingName(tdbb, name, obj_generator);
+
+ const bool useExplicitStep = blrOp == blr_gen_id || (blrOp == blr_gen_id3 && csb->csb_blr_reader.getByte() != 0);
+ const auto explicitStep = useExplicitStep ? PAR_parse_value(tdbb, csb) : nullptr;
+ const auto node = FB_NEW_POOL(pool) GenIdNode(pool, (csb->blrVersion == 4), name, explicitStep,
+ !useExplicitStep, false);
// This check seems faster than ==, but assumes the special generator is named ""
- if (name.length() == 0) //(name == MASTER_GENERATOR)
+ if (name.schema == SYSTEM_SCHEMA && name.object.isEmpty()) //(name == MASTER_GENERATOR)
{
fb_assert(!MASTER_GENERATOR[0]);
if (!(csb->csb_g_flags & csb_internal))
- PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
+ PAR_error(csb, Arg::Gds(isc_gennotdef) << name.toQuotedString());
node->generator.id = 0;
}
else if (!MET_load_generator(tdbb, node->generator, &node->sysGen, &node->step))
- PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
+ PAR_error(csb, Arg::Gds(isc_gennotdef) << name.toQuotedString());
if (csb->collectingDependencies())
{
@@ -7124,6 +7244,8 @@ string GenIdNode::internalPrint(NodePrinter& printer) const
ValueExprNode* GenIdNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ dsqlScratch->qualifyExistingName(generator.name, obj_generator);
+
GenIdNode* const node = FB_NEW_POOL(dsqlScratch->getPool()) GenIdNode(dsqlScratch->getPool(),
dialect1, generator.name, doDsqlPass(dsqlScratch, arg), implicit, identity);
node->generator = generator;
@@ -7145,16 +7267,33 @@ bool GenIdNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
void GenIdNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
- if (implicit)
+ if (generator.name.schema != dsqlScratch->ddlSchema)
{
- dsqlScratch->appendUChar(blr_gen_id2);
- dsqlScratch->appendNullString(generator.name.c_str());
+ dsqlScratch->appendUChar(blr_gen_id3);
+ dsqlScratch->appendNullString(generator.name.schema.c_str());
+ dsqlScratch->appendNullString(generator.name.object.c_str());
+
+ if (implicit)
+ dsqlScratch->appendUChar(0);
+ else
+ {
+ dsqlScratch->appendUChar(1);
+ GEN_expr(dsqlScratch, arg);
+ }
}
else
{
- dsqlScratch->appendUChar(blr_gen_id);
- dsqlScratch->appendNullString(generator.name.c_str());
- GEN_expr(dsqlScratch, arg);
+ if (implicit)
+ {
+ dsqlScratch->appendUChar(blr_gen_id2);
+ dsqlScratch->appendNullString(generator.name.object.c_str());
+ }
+ else
+ {
+ dsqlScratch->appendUChar(blr_gen_id);
+ dsqlScratch->appendNullString(generator.name.object.c_str());
+ GEN_expr(dsqlScratch, arg);
+ }
}
}
@@ -7227,8 +7366,10 @@ ValueExprNode* GenIdNode::pass1(thread_db* tdbb, CompilerScratch* csb)
if (!identity)
{
- CMP_post_access(tdbb, csb, generator.secName, 0,
- SCL_usage, obj_generators, generator.name);
+ CMP_post_access(tdbb, csb, generator.secName.schema, 0, SCL_usage, obj_schemas,
+ QualifiedName(generator.name.schema));
+
+ CMP_post_access(tdbb, csb, generator.secName.object, 0, SCL_usage, obj_generators, generator.name);
}
return this;
@@ -7265,7 +7406,7 @@ dsc* GenIdNode::execute(thread_db* tdbb, Request* request) const
if (sysGen && change != 0)
{
if (!request->hasInternalStatement() && !tdbb->getAttachment()->isRWGbak())
- status_exception::raise(Arg::Gds(isc_cant_modify_sysobj) << "generator" << generator.name);
+ status_exception::raise(Arg::Gds(isc_cant_modify_sysobj) << "generator" << generator.name.toQuotedString());
}
const SINT64 new_val = DPM_gen_id(tdbb, generator.id, false, change);
@@ -7357,7 +7498,7 @@ void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
break;
case INFO_TYPE_EXCEPTION:
- desc->makeVarying(MAX_SQL_IDENTIFIER_LEN, ttype_metadata);
+ desc->makeVarying(MAX_QUALIFIED_NAME_TO_STRING_LEN, ttype_metadata);
break;
case INFO_TYPE_ERROR_MSG:
@@ -7399,7 +7540,7 @@ void InternalInfoNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
break;
case INFO_TYPE_EXCEPTION:
- desc->makeVarying(MAX_SQL_IDENTIFIER_LEN, ttype_metadata);
+ desc->makeVarying(MAX_QUALIFIED_NAME_TO_STRING_LEN, ttype_metadata);
break;
case INFO_TYPE_ERROR_MSG:
@@ -7476,14 +7617,16 @@ dsc* InternalInfoNode::execute(thread_db* tdbb, Request* request) const
if (!xcpCode)
return NULL;
- MetaName xcpName;
+ QualifiedName xcpName;
MET_lookup_exception(tdbb, xcpCode, xcpName, NULL);
- if (xcpName.isEmpty())
+ if (xcpName.object.isEmpty())
return NULL;
+ const auto xcpNameStr = xcpName.toQuotedString();
+
dsc desc;
- desc.makeText(xcpName.length(), ttype_metadata, (UCHAR*) xcpName.c_str());
+ desc.makeText(xcpNameStr.length(), ttype_metadata, (UCHAR*) xcpNameStr.c_str());
EVL_make_value(tdbb, &desc, impure);
return &impure->vlu_desc;
@@ -7920,27 +8063,27 @@ ValueExprNode* LiteralNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
constant->dsqlStr = dsqlStr;
constant->litDesc = litDesc;
- if (dsqlStr && dsqlStr->getCharSet().hasData())
+ if (dsqlStr && dsqlStr->getCharSet().object.hasData())
{
- const dsql_intlsym* resolved = METD_get_charset(dsqlScratch->getTransaction(),
- dsqlStr->getCharSet().length(), dsqlStr->getCharSet().c_str());
+ auto charSet = dsqlStr->getCharSet();
+ dsqlScratch->qualifyExistingName(charSet, obj_charset);
+ dsqlStr->setCharSet(charSet);
+
+ const dsql_intlsym* resolved = METD_get_charset(dsqlScratch->getTransaction(), charSet);
if (!resolved)
{
// character set name is not defined
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
- Arg::Gds(isc_charset_not_found) << dsqlStr->getCharSet());
+ Arg::Gds(isc_charset_not_found) << charSet.toQuotedString());
}
constant->litDesc.setTextType(resolved->intlsym_ttype);
}
else
{
- const MetaName charSetName = METD_get_charset_name(
- dsqlScratch->getTransaction(), constant->litDesc.getCharSet());
-
- const dsql_intlsym* sym = METD_get_charset(dsqlScratch->getTransaction(),
- charSetName.length(), charSetName.c_str());
+ const auto charSetName = METD_get_charset_name(dsqlScratch->getTransaction(), constant->litDesc.getCharSet());
+ const dsql_intlsym* sym = METD_get_charset(dsqlScratch->getTransaction(), charSetName);
fb_assert(sym);
if (sym)
@@ -7974,7 +8117,7 @@ ValueExprNode* LiteralNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
Arg::Gds(isc_dsql_string_char_length) <<
Arg::Num(charLength) <<
Arg::Num(MAX_STR_SIZE / charSet->maxBytesPerChar()) <<
- METD_get_charset_name(dsqlScratch->getTransaction(), constant->litDesc.getCharSet()));
+ METD_get_charset_name(dsqlScratch->getTransaction(), constant->litDesc.getCharSet()).toQuotedString());
}
else
constant->litDesc.dsc_length = charLength * charSet->maxBytesPerChar();
@@ -8125,7 +8268,7 @@ ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)
}
}
- delete dsqlStr; // Not needed anymore
+ delete dsqlStr.getObject(); // Not needed anymore
dsqlStr = nullptr;
ValueExprNode::pass2(tdbb, csb);
@@ -8767,7 +8910,7 @@ void DerivedFieldNode::setParameterName(dsql_par* parameter) const
value->setParameterName(parameter);
parameter->par_alias = name;
- parameter->par_rel_alias = context->ctx_alias;
+ parameter->par_rel_alias = context->getConcatenatedAlias();
}
void DerivedFieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
@@ -10007,7 +10150,7 @@ dsc* ParameterNode::execute(thread_db* tdbb, Request* request) const
static RegisterNode regRecordKeyNode({blr_dbkey, blr_record_version, blr_record_version2});
-RecordKeyNode::RecordKeyNode(MemoryPool& pool, UCHAR aBlrOp, const MetaName& aDsqlQualifier)
+RecordKeyNode::RecordKeyNode(MemoryPool& pool, UCHAR aBlrOp, const QualifiedName& aDsqlQualifier)
: TypedNode(pool),
dsqlQualifier(pool, aDsqlQualifier),
dsqlRelation(NULL),
@@ -10049,11 +10192,11 @@ string RecordKeyNode::internalPrint(NodePrinter& printer) const
ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
thread_db* tdbb = JRD_get_thread_data();
+ DsqlContextStack contexts;
+ ValueExprNode* node = nullptr;
- if (dsqlQualifier.isEmpty())
+ if (dsqlQualifier.object.isEmpty())
{
- DsqlContextStack contexts;
-
for (DsqlContextStack::iterator stack(*dsqlScratch->context); stack.hasData(); ++stack)
{
dsql_ctx* context = stack.object();
@@ -10075,19 +10218,19 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
raiseError(context);
if (context->ctx_flags & CTX_null)
- return NullNode::instance();
+ node = NullNode::instance();
+ else
+ {
+ //// TODO: LocalTableSourceNode
+ auto relNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(
+ dsqlScratch->getPool());
+ relNode->dsqlContext = context;
- PASS1_ambiguity_check(dsqlScratch, getAlias(true), contexts);
-
- //// TODO: LocalTableSourceNode
- auto relNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(
- dsqlScratch->getPool());
- relNode->dsqlContext = context;
-
- auto node = FB_NEW_POOL(dsqlScratch->getPool()) RecordKeyNode(dsqlScratch->getPool(), blrOp);
- node->dsqlRelation = relNode;
-
- return node;
+ const auto recordKeyNode = FB_NEW_POOL(dsqlScratch->getPool()) RecordKeyNode(
+ dsqlScratch->getPool(), blrOp);
+ recordKeyNode->dsqlRelation = relNode;
+ node = recordKeyNode;
+ }
}
}
else
@@ -10097,10 +10240,10 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
dsql_ctx* context = stack.object();
if ((!context->ctx_relation ||
- context->ctx_relation->rel_name != dsqlQualifier ||
- context->ctx_internal_alias.hasData()) &&
- (context->ctx_internal_alias.isEmpty() ||
- strcmp(dsqlQualifier.c_str(), context->ctx_internal_alias.c_str()) != 0))
+ !PASS1_compare_alias(context->ctx_relation->rel_name, dsqlQualifier) ||
+ context->ctx_internal_alias.object.hasData()) &&
+ (context->ctx_internal_alias.object.isEmpty() ||
+ !PASS1_compare_alias(context->ctx_internal_alias, dsqlQualifier)))
{
continue;
}
@@ -10109,24 +10252,30 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
raiseError(context);
if (context->ctx_flags & CTX_null)
- return NullNode::instance();
+ node = NullNode::instance();
+ else
+ {
+ //// TODO: LocalTableSourceNode
+ auto relNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(dsqlScratch->getPool());
+ relNode->dsqlContext = context;
- //// TODO: LocalTableSourceNode
- auto relNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(
- dsqlScratch->getPool());
- relNode->dsqlContext = context;
-
- auto node = FB_NEW_POOL(dsqlScratch->getPool()) RecordKeyNode(dsqlScratch->getPool(), blrOp);
- node->dsqlRelation = relNode;
-
- return node;
+ const auto recordKeyNode = FB_NEW_POOL(dsqlScratch->getPool()) RecordKeyNode(
+ dsqlScratch->getPool(), blrOp);
+ recordKeyNode->dsqlRelation = relNode;
+ node = recordKeyNode;
+ }
}
}
- // Field unresolved.
- PASS1_field_unknown(dsqlQualifier.nullStr(), getAlias(false), this);
+ PASS1_ambiguity_check(dsqlScratch, getAlias(true), contexts);
- return NULL;
+ if (!node)
+ {
+ // Field unresolved.
+ PASS1_field_unknown(dsqlQualifier.toQuotedString().nullStr(), getAlias(false), this);
+ }
+
+ return node;
}
bool RecordKeyNode::dsqlAggregate2Finder(Aggregate2Finder& /*visitor*/)
@@ -10555,14 +10704,14 @@ void RecordKeyNode::raiseError(dsql_ctx* context) const
}
string name = context->getObjectName();
- const string& alias = context->ctx_internal_alias;
+ const auto& alias = context->ctx_internal_alias;
- if (alias.hasData() && name != alias)
+ if (alias.object.hasData() && name != alias.toQuotedString())
{
if (name.hasData())
- name += " (alias " + alias + ")";
+ name += " (alias " + alias.toQuotedString() + ")";
else
- name = alias;
+ name = alias.toQuotedString();
}
status_exception::raise(
@@ -12344,12 +12493,16 @@ DmlNode* SysFuncCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScrat
if (literal && literal->litDesc.isText())
{
- MetaName relName;
- CVT2_make_metaname(&literal->litDesc, relName, tdbb->getAttachment()->att_dec_status);
+ MoveBuffer buff;
+ UCHAR* ptr = nullptr;
+ const auto len = CVT2_make_string2(&literal->litDesc, CS_METADATA, &ptr, buff,
+ tdbb->getAttachment()->att_dec_status);
+ name.assign(reinterpret_cast(ptr), len);
- const jrd_rel* const relation = MET_lookup_relation(tdbb, relName);
+ auto relName = QualifiedName::parseSchemaObject(string(reinterpret_cast(ptr), len));
+ csb->qualifyExistingName(tdbb, relName, obj_relation);
- if (relation)
+ if (const auto* const relation = MET_lookup_relation(tdbb, relName))
node->args->items[0] = MAKE_const_slong(relation->rel_id);
}
}
@@ -12484,15 +12637,7 @@ dsc* SysFuncCallNode::execute(thread_db* tdbb, Request* request) const
ValueExprNode* SysFuncCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
- QualifiedName qualifName(name);
-
- if (!dsqlSpecialSyntax && METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, qualifName))
- {
- UdfCallNode* node = FB_NEW_POOL(dsqlScratch->getPool()) UdfCallNode(dsqlScratch->getPool(), qualifName, args);
- return node->dsqlPass(dsqlScratch);
- }
-
- SysFuncCallNode* node = FB_NEW_POOL(dsqlScratch->getPool()) SysFuncCallNode(dsqlScratch->getPool(), name,
+ const auto node = FB_NEW_POOL(dsqlScratch->getPool()) SysFuncCallNode(dsqlScratch->getPool(), name,
doDsqlPass(dsqlScratch, args));
node->dsqlSpecialSyntax = dsqlSpecialSyntax;
@@ -12976,42 +13121,55 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
{
switch (subCode)
{
- case blr_invoke_function_type:
+ case blr_invoke_function_id:
{
- UCHAR functionType = blrReader.getByte();
+ bool isSub = false;
+ UCHAR functionIdCode;
- switch (functionType)
+ while ((functionIdCode = blrReader.getByte()) != blr_end)
{
- case blr_invoke_function_type_packaged:
- blrReader.getMetaName(name.package);
- break;
+ switch (functionIdCode)
+ {
+ case blr_invoke_function_id_schema:
+ blrReader.getMetaName(name.schema);
+ break;
- case blr_invoke_function_type_standalone:
- case blr_invoke_function_type_sub:
- break;
+ case blr_invoke_function_id_package:
+ blrReader.getMetaName(name.package);
+ break;
- default:
- PAR_error(csb, Arg::Gds(isc_random) << "Invalid blr_invoke_function_type");
- break;
+ case blr_invoke_function_id_name:
+ blrReader.getMetaName(name.object);
+ break;
+
+ case blr_invoke_function_id_sub:
+ isSub = true;
+ break;
+
+ default:
+ PAR_error(csb, Arg::Gds(isc_random) << "Invalid blr_invoke_function_id");
+ break;
+ }
}
- blrReader.getMetaName(name.identifier);
-
- if (functionType == blr_invoke_function_type_sub)
+ if (isSub)
{
for (auto curCsb = csb; curCsb && !node->function; curCsb = curCsb->mainCsb)
{
- if (DeclareSubFuncNode* declareNode; curCsb->subFunctions.get(name.identifier, declareNode))
+ if (DeclareSubFuncNode* declareNode; curCsb->subFunctions.get(name.object, declareNode))
node->function = declareNode->routine;
}
}
else if (!node->function)
+ {
+ csb->qualifyExistingName(tdbb, name, obj_udf);
node->function = Function::lookup(tdbb, name, false);
+ }
if (!node->function)
{
blrReader.setPos(startPos);
- PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toString());
+ PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toQuotedString());
}
break;
@@ -13019,7 +13177,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
case blr_invoke_function_arg_names:
{
- predateCheck(node->function, "blr_invoke_function_type", "blr_invoke_function_arg_names");
+ predateCheck(node->function, "blr_invoke_function_id", "blr_invoke_function_arg_names");
predateCheck(!node->args, "blr_invoke_function_arg_names", "blr_invoke_function_args");
argNamesPos = blrReader.getPos();
@@ -13038,7 +13196,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
}
case blr_invoke_function_args:
- predateCheck(node->function, "blr_invoke_function_type", "blr_invoke_function_args");
+ predateCheck(node->function, "blr_invoke_function_id", "blr_invoke_function_args");
argCount = blrReader.getWord();
node->args = PAR_args(tdbb, csb, argCount, MAX(argCount, node->function->fun_inputs));
@@ -13054,10 +13212,11 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
if (blrOp == blr_function2)
blrReader.getMetaName(name.package);
- blrReader.getMetaName(name.identifier);
+ blrReader.getMetaName(name.object);
if (blrOp == blr_function &&
- (name.identifier == "RDB$GET_CONTEXT" || name.identifier == "RDB$SET_CONTEXT"))
+ (name.schema.isEmpty() || name.schema == SYSTEM_SCHEMA) &&
+ (name.object == "RDB$GET_CONTEXT" || name.object == "RDB$SET_CONTEXT"))
{
blrReader.setPos(startPos);
return SysFuncCallNode::parse(tdbb, pool, csb, blr_sys_function);
@@ -13067,17 +13226,20 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
{
for (auto curCsb = csb; curCsb && !node->function; curCsb = curCsb->mainCsb)
{
- if (DeclareSubFuncNode* declareNode; curCsb->subFunctions.get(name.identifier, declareNode))
+ if (DeclareSubFuncNode* declareNode; curCsb->subFunctions.get(name.object, declareNode))
node->function = declareNode->routine;
}
}
else if (!node->function)
+ {
+ csb->qualifyExistingName(tdbb, name, obj_udf);
node->function = Function::lookup(tdbb, name, false);
+ }
if (!node->function)
{
blrReader.setPos(startPos);
- PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toString());
+ PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toQuotedString());
}
argCount = blrReader.getByte();
@@ -13098,13 +13260,13 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
{
if (tdbb->getAttachment()->isGbak() || (tdbb->tdbb_flags & TDBB_replicator))
{
- PAR_warning(Arg::Warning(isc_funnotdef) << name.toString() <<
+ PAR_warning(Arg::Warning(isc_funnotdef) << name.toQuotedString() <<
Arg::Warning(isc_modnotfound));
}
else
{
blrReader.setPos(startPos);
- PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toString() <<
+ PAR_error(csb, Arg::Gds(isc_funnotdef) << name.toQuotedString() <<
Arg::Gds(isc_modnotfound));
}
}
@@ -13180,15 +13342,15 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
FieldInfo fieldInfo;
if (parameter->prm_mechanism != prm_mech_type_of &&
- !fb_utils::implicit_domain(parameter->prm_field_source.c_str()))
+ !fb_utils::implicit_domain(parameter->prm_field_source.object.c_str()))
{
- const MetaNamePair namePair(parameter->prm_field_source, "");
+ const QualifiedNameMetaNamePair entry(parameter->prm_field_source, {});
- if (!csb->csb_map_field_info.get(namePair, fieldInfo))
+ if (!csb->csb_map_field_info.get(entry, fieldInfo))
{
dsc dummyDesc;
MET_get_domain(tdbb, csb->csb_pool, parameter->prm_field_source, &dummyDesc, &fieldInfo);
- csb->csb_map_field_info.put(namePair, fieldInfo);
+ csb->csb_map_field_info.put(entry, fieldInfo);
}
}
@@ -13211,7 +13373,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
}
if (mismatchStatus.hasData())
- status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toString() << mismatchStatus);
+ status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toQuotedString() << mismatchStatus);
// CVC: I will track ufds only if a function is not being dropped.
if (!node->function->isSubRoutine() && csb->collectingDependencies())
@@ -13249,29 +13411,37 @@ string UdfCallNode::internalPrint(NodePrinter& printer) const
void UdfCallNode::setParameterName(dsql_par* parameter) const
{
- parameter->par_name = parameter->par_alias = dsqlFunction->udf_name.identifier;
+ parameter->par_name = parameter->par_alias = dsqlFunction->udf_name.object;
}
void UdfCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
- if (dsqlArgNames || args->items.getCount() >= UCHAR_MAX)
+ if (dsqlArgNames || args->items.getCount() >= UCHAR_MAX || dsqlFunction->udf_name.schema != dsqlScratch->ddlSchema)
{
dsqlScratch->appendUChar(blr_invoke_function);
- dsqlScratch->appendUChar(blr_invoke_function_type);
+ dsqlScratch->appendUChar(blr_invoke_function_id);
- if (dsqlFunction->udf_name.package.hasData())
- {
- dsqlScratch->appendUChar(blr_invoke_function_type_packaged);
- dsqlScratch->appendMetaString(dsqlFunction->udf_name.package.c_str());
- }
+ if (dsqlFunction->udf_flags & UDF_subfunc)
+ dsqlScratch->appendUChar(blr_invoke_function_id_sub);
else
{
- dsqlScratch->appendUChar((dsqlFunction->udf_flags & UDF_subfunc) ?
- blr_invoke_function_type_sub : blr_invoke_function_type_standalone);
+ if (dsqlFunction->udf_name.schema != dsqlScratch->ddlSchema)
+ {
+ dsqlScratch->appendUChar(blr_invoke_function_id_schema);
+ dsqlScratch->appendMetaString(dsqlFunction->udf_name.schema.c_str());
+ }
+
+ if (dsqlFunction->udf_name.package.hasData())
+ {
+ dsqlScratch->appendUChar(blr_invoke_function_id_package);
+ dsqlScratch->appendMetaString(dsqlFunction->udf_name.package.c_str());
+ }
}
- dsqlScratch->appendMetaString(dsqlFunction->udf_name.identifier.c_str());
+ dsqlScratch->appendUChar(blr_invoke_function_id_name);
+ dsqlScratch->appendMetaString(dsqlFunction->udf_name.object.c_str());
+ dsqlScratch->appendUChar(blr_end);
if (dsqlArgNames && dsqlArgNames->hasData())
{
@@ -13301,7 +13471,7 @@ void UdfCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendMetaString(dsqlFunction->udf_name.package.c_str());
}
- dsqlScratch->appendMetaString(dsqlFunction->udf_name.identifier.c_str());
+ dsqlScratch->appendMetaString(dsqlFunction->udf_name.object.c_str());
dsqlScratch->appendUChar(args->items.getCount());
for (auto& arg : args->items)
@@ -13382,24 +13552,26 @@ ValueExprNode* UdfCallNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
if (!(csb->csb_g_flags & (csb_internal | csb_ignore_perm)))
{
+ SLONG ssRelationId = csb->csb_view ? csb->csb_view->rel_id : 0;
+
+ CMP_post_access(tdbb, csb, function->getSecurityName().schema, ssRelationId,
+ SCL_usage, obj_schemas, QualifiedName(function->getName().schema));
+
if (function->getName().package.isEmpty())
{
- SLONG ssRelationId = csb->csb_view ? csb->csb_view->rel_id : 0;
-
if (!ssRelationId && csb->csb_parent_relation)
{
fb_assert(csb->csb_parent_relation->rel_ss_definer.asBool());
ssRelationId = csb->csb_parent_relation->rel_id;
}
- CMP_post_access(tdbb, csb, function->getSecurityName(), ssRelationId,
- SCL_execute, obj_functions, function->getName().identifier);
+ CMP_post_access(tdbb, csb, function->getSecurityName().object, ssRelationId,
+ SCL_execute, obj_functions, function->getName());
}
else
{
- CMP_post_access(tdbb, csb, function->getSecurityName(),
- (csb->csb_view ? csb->csb_view->rel_id : 0),
- SCL_execute, obj_packages, function->getName().package);
+ CMP_post_access(tdbb, csb, function->getSecurityName().object, ssRelationId,
+ SCL_execute, obj_packages, function->getName().getSchemaAndPackage());
}
ExternalAccess temp(ExternalAccess::exa_function, function->getId());
@@ -13476,12 +13648,12 @@ dsc* UdfCallNode::execute(thread_db* tdbb, Request* request) const
{
status_exception::raise(
Arg::Gds(isc_func_pack_not_implemented) <<
- Arg::Str(function->getName().identifier) << Arg::Str(function->getName().package));
+ Arg::Str(function->getName().object) << function->getName().getSchemaAndPackage().toQuotedString());
}
else if (!function->isDefined())
{
status_exception::raise(
- Arg::Gds(isc_funnotdef) << Arg::Str(function->getName().toString()) <<
+ Arg::Gds(isc_funnotdef) << Arg::Str(function->getName().toQuotedString()) <<
Arg::Gds(isc_modnotfound));
}
@@ -13656,27 +13828,63 @@ dsc* UdfCallNode::execute(thread_db* tdbb, Request* request) const
ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ dsql_udf* function = nullptr;
+
+ if (name.package.isEmpty())
+ {
+ if (name.schema.isEmpty())
+ {
+ if (const auto subFunction = dsqlScratch->getSubFunction(name.object))
+ function = subFunction->dsqlFunction;
+ else if (dsqlScratch->package.object.hasData())
+ {
+ const QualifiedName packagedName(name.object, dsqlScratch->package.schema, dsqlScratch->package.object);
+ function = METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, packagedName);
+ }
+
+ if (!function)
+ dsqlScratch->qualifyExistingName(name, obj_udf);
+ }
+ else
+ {
+ QualifiedName packageName(name.schema);
+ dsqlScratch->qualifyExistingName(packageName, obj_package_header);
+
+ if (MET_check_package_exists(JRD_get_thread_data(), packageName))
+ {
+ name.schema = packageName.schema;
+ name.package = packageName.object;
+ }
+ }
+ }
+
+ if (!function)
+ function = METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, name);
+
+ if (!function)
+ {
+ ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
+ Arg::Gds(isc_dsql_function_err) <<
+ Arg::Gds(isc_random) << name.toQuotedString());
+ }
+
+ if (function->udf_private && function->udf_name.getSchemaAndPackage() != dsqlScratch->package)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_private_function) <<
+ function->udf_name.object <<
+ function->udf_name.getSchemaAndPackage().toQuotedString());
+ }
+
+ name = function->udf_name;
+
const auto node = FB_NEW_POOL(dsqlScratch->getPool()) UdfCallNode(dsqlScratch->getPool(), name,
doDsqlPass(dsqlScratch, args),
dsqlArgNames ?
FB_NEW_POOL(dsqlScratch->getPool()) ObjectsArray(dsqlScratch->getPool(), *dsqlArgNames) :
nullptr);
- if (name.package.isEmpty())
- {
- DeclareSubFuncNode* subFunction = dsqlScratch->getSubFunction(name.identifier);
- node->dsqlFunction = subFunction ? subFunction->dsqlFunction : NULL;
- }
-
- if (!node->dsqlFunction)
- node->dsqlFunction = METD_get_function(dsqlScratch->getTransaction(), dsqlScratch, name);
-
- if (!node->dsqlFunction)
- {
- ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
- Arg::Gds(isc_dsql_function_err) <<
- Arg::Gds(isc_random) << Arg::Str(name.toString()));
- }
+ node->dsqlFunction = function;
auto argIt = node->args->items.begin();
unsigned pos = 0;
@@ -13719,7 +13927,7 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
}
if (mismatchStatus.hasData())
- status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toString() << mismatchStatus);
+ status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toQuotedString() << mismatchStatus);
}
return node;
@@ -14063,7 +14271,7 @@ ValueExprNode* VariableNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if (!node->dsqlVar ||
(node->dsqlVar->type == dsql_var::TYPE_LOCAL && !node->dsqlVar->initialized && !dsqlScratch->mainScratch))
{
- PASS1_field_unknown(NULL, dsqlName.c_str(), this);
+ PASS1_field_unknown(NULL, dsqlName.toQuotedString().c_str(), this);
}
return node;
@@ -14394,16 +14602,16 @@ static void setParameterInfo(dsql_par* parameter, const dsql_ctx* context)
if (context->ctx_relation)
{
- parameter->par_rel_name = context->ctx_relation->rel_name.c_str();
- parameter->par_owner_name = context->ctx_relation->rel_owner.c_str();
+ parameter->par_rel_name = context->ctx_relation->rel_name;
+ parameter->par_owner_name = context->ctx_relation->rel_owner;
}
else if (context->ctx_procedure)
{
- parameter->par_rel_name = context->ctx_procedure->prc_name.identifier.c_str();
- parameter->par_owner_name = context->ctx_procedure->prc_owner.c_str();
+ parameter->par_rel_name = context->ctx_procedure->prc_name;
+ parameter->par_owner_name = context->ctx_procedure->prc_owner;
}
- parameter->par_rel_alias = context->ctx_alias.c_str();
+ parameter->par_rel_alias = context->getConcatenatedAlias();
}
diff --git a/src/dsql/ExprNodes.h b/src/dsql/ExprNodes.h
index fb79beccf5..50b74a9d37 100644
--- a/src/dsql/ExprNodes.h
+++ b/src/dsql/ExprNodes.h
@@ -339,7 +339,7 @@ public:
class CollateNode final : public TypedNode
{
public:
- CollateNode(MemoryPool& pool, ValueExprNode* aArg, const MetaName& aCollation);
+ CollateNode(MemoryPool& pool, ValueExprNode* aArg, const QualifiedName& aCollation);
virtual void getChildren(NodeRefsHolder& holder, bool dsql) const
{
@@ -353,7 +353,7 @@ public:
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
static ValueExprNode* pass1Collate(DsqlCompilerScratch* dsqlScratch, ValueExprNode* input,
- const MetaName& collation);
+ QualifiedName& collation);
// This class is used only in the parser. It turns in a CastNode in dsqlPass.
@@ -394,7 +394,7 @@ private:
public:
NestConst arg;
- MetaName collation;
+ QualifiedName collation;
};
@@ -530,6 +530,29 @@ public:
};
+class CurrentSchemaNode final : public TypedNode
+{
+public:
+ explicit CurrentSchemaNode(MemoryPool& pool)
+ : TypedNode(pool)
+ {
+ }
+
+ static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
+
+ Firebird::string internalPrint(NodePrinter& printer) const override;
+ ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch) override;
+ void setParameterName(dsql_par* parameter) const override;
+ void genBlr(DsqlCompilerScratch* dsqlScratch) override;
+ void make(DsqlCompilerScratch* dsqlScratch, dsc* desc) override;
+
+ void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) override;
+ ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const override;
+ ValueExprNode* pass2(thread_db* tdbb, CompilerScratch* csb) override;
+ dsc* execute(thread_db* tdbb, Request* request) const override;
+};
+
+
class CurrentUserNode final : public TypedNode
{
public:
@@ -612,7 +635,7 @@ public:
class DefaultNode : public DsqlNode
{
public:
- explicit DefaultNode(MemoryPool& pool, const MetaName& aRelationName,
+ explicit DefaultNode(MemoryPool& pool, const QualifiedName& aRelationName,
const MetaName& aFieldName);
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
@@ -631,7 +654,7 @@ public:
virtual ValueExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
public:
- const MetaName relationName;
+ const QualifiedName relationName;
const MetaName fieldName;
private:
@@ -839,10 +862,10 @@ public:
private:
static dsql_fld* resolveContext(DsqlCompilerScratch* dsqlScratch,
- const MetaName& qualifier, dsql_ctx* context);
+ const QualifiedName& qualifier, dsql_ctx* context);
public:
- MetaName dsqlQualifier;
+ QualifiedName dsqlQualifier;
MetaName dsqlName;
dsql_ctx* const dsqlContext;
dsql_fld* const dsqlField;
@@ -860,7 +883,7 @@ class GenIdNode final : public TypedNode
{
public:
GenIdNode(MemoryPool& pool, bool aDialect1,
- const MetaName& name,
+ const QualifiedName& name,
ValueExprNode* aArg,
bool aImplicit, bool aIdentity);
@@ -987,7 +1010,7 @@ public:
void fixMinSInt128(MemoryPool& pool);
public:
- const IntlString* dsqlStr = nullptr;
+ NestConst dsqlStr;
dsc litDesc;
USHORT litNumStringLength = 0;
};
@@ -1671,7 +1694,7 @@ public:
class RecordKeyNode final : public TypedNode
{
public:
- RecordKeyNode(MemoryPool& pool, UCHAR aBlrOp, const MetaName& aDsqlQualifier = NULL);
+ RecordKeyNode(MemoryPool& pool, UCHAR aBlrOp, const QualifiedName& aDsqlQualifier = {});
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
@@ -1748,7 +1771,7 @@ private:
void raiseError(dsql_ctx* context) const;
public:
- MetaName dsqlQualifier;
+ QualifiedName dsqlQualifier;
NestConst dsqlRelation;
StreamType recStream;
const UCHAR blrOp;
diff --git a/src/dsql/NodePrinter.h b/src/dsql/NodePrinter.h
index 4caa8fedc9..0f042b6b79 100644
--- a/src/dsql/NodePrinter.h
+++ b/src/dsql/NodePrinter.h
@@ -85,7 +85,7 @@ public:
text += "<";
text += s;
text += ">";
- text += value.toString();
+ text += value.toQuotedString();
text += "";
text += s;
text += ">\n";
diff --git a/src/dsql/Nodes.h b/src/dsql/Nodes.h
index 4df8900d54..d328c4445b 100644
--- a/src/dsql/Nodes.h
+++ b/src/dsql/Nodes.h
@@ -173,8 +173,6 @@ public:
};
-class DdlNode;
-
class DdlNode : public Node
{
public:
@@ -183,14 +181,24 @@ public:
{
}
+ static void protectSystemSchema(const MetaName& name, ObjectType objType)
+ {
+ if (name == SYSTEM_SCHEMA)
+ {
+ Firebird::status_exception::raise(
+ Firebird::Arg::Gds(isc_dyn_cannot_mod_obj_sys_schema) <<
+ getObjectName(objType));
+ }
+ }
+
static bool deleteSecurityClass(thread_db* tdbb, jrd_tra* transaction,
const MetaName& secClass);
static void storePrivileges(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name, int type, const char* privileges);
+ const QualifiedName& name, int type, const char* privileges);
static void deletePrivilegesByRelName(thread_db* tdbb, jrd_tra* transaction,
- const MetaName& name, int type);
+ const QualifiedName& name, int type);
public:
// Check permission on DDL operation. Return true if everything is OK.
@@ -221,8 +229,8 @@ public:
enum DdlTriggerWhen { DTW_BEFORE, DTW_AFTER };
static void executeDdlTrigger(thread_db* tdbb, jrd_tra* transaction,
- DdlTriggerWhen when, int action, const MetaName& objectName,
- const MetaName& oldNewObjectName, const Firebird::string& sqlText);
+ DdlTriggerWhen when, int action, const QualifiedName& objectName,
+ const QualifiedName& oldNewObjectName, const Firebird::string& sqlText);
protected:
typedef Firebird::Pair > MetaNameBidPair;
@@ -246,9 +254,9 @@ protected:
}
void executeDdlTrigger(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction,
- DdlTriggerWhen when, int action, const MetaName& objectName,
- const MetaName& oldNewObjectName);
- void storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
+ DdlTriggerWhen when, int action, const QualifiedName& objectName,
+ const QualifiedName& oldNewObjectName);
+ void storeGlobalField(thread_db* tdbb, jrd_tra* transaction, QualifiedName& name,
const TypeClause* field,
const Firebird::string& computedSource = "",
const BlrDebugWriter::BlrData& computedValue = BlrDebugWriter::BlrData());
@@ -468,6 +476,7 @@ public:
TYPE_CURRENT_TIME,
TYPE_CURRENT_TIMESTAMP,
TYPE_CURRENT_ROLE,
+ TYPE_CURRENT_SCHEMA,
TYPE_CURRENT_USER,
TYPE_DERIVED_EXPR,
TYPE_DECODE,
@@ -1655,7 +1664,7 @@ public:
class GeneratorItem : public Printable
{
public:
- GeneratorItem(Firebird::MemoryPool& pool, const MetaName& name)
+ GeneratorItem(Firebird::MemoryPool& pool, const QualifiedName& name)
: id(0), name(pool, name), secName(pool)
{}
@@ -1672,8 +1681,8 @@ public:
public:
SLONG id;
- MetaName name;
- MetaName secName;
+ QualifiedName name;
+ QualifiedName secName;
};
typedef Firebird::Array StreamMap;
diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp
index c13853ce09..4057fddf58 100644
--- a/src/dsql/PackageNodes.epp
+++ b/src/dsql/PackageNodes.epp
@@ -55,7 +55,7 @@ namespace
{
// Return function and procedure names (in the user charset) and optionally its details for a
// given package.
- void collectPackagedItems(thread_db* tdbb, jrd_tra* transaction, const MetaName& metaName,
+ void collectPackagedItems(thread_db* tdbb, jrd_tra* transaction, const QualifiedName& packageName,
SortedObjectsArray& functions,
SortedObjectsArray& procedures, bool details)
{
@@ -64,7 +64,8 @@ namespace
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$PACKAGE_NAME EQ metaName.c_str()
+ WITH FUN.RDB$SCHEMA_NAME EQ packageName.schema.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQ packageName.object.c_str()
{
Signature function(FUN.RDB$FUNCTION_NAME);
function.defined = !FUN.RDB$FUNCTION_BLR.NULL || !FUN.RDB$ENTRYPOINT.NULL;
@@ -77,21 +78,23 @@ namespace
FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction)
ARG IN RDB$FUNCTION_ARGUMENTS CROSS
FLD IN RDB$FIELDS
- WITH ARG.RDB$PACKAGE_NAME EQ metaName.c_str() AND
+ WITH ARG.RDB$SCHEMA_NAME EQ FUN.RDB$SCHEMA_NAME AND
+ ARG.RDB$PACKAGE_NAME EQ FUN.RDB$PACKAGE_NAME AND
ARG.RDB$FUNCTION_NAME EQ FUN.RDB$FUNCTION_NAME AND
+ FLD.RDB$SCHEMA_NAME EQUIV ARG.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ ARG.RDB$FIELD_SOURCE
{
SignatureParameter parameter(*getDefaultMemoryPool());
parameter.number = ARG.RDB$ARGUMENT_POSITION;
parameter.name = ARG.RDB$ARGUMENT_NAME;
- parameter.fieldSource = ARG.RDB$FIELD_SOURCE;
+ parameter.fieldSource = QualifiedName(ARG.RDB$FIELD_SOURCE, ARG.RDB$FIELD_SOURCE_SCHEMA_NAME);
parameter.mechanism = ARG.RDB$ARGUMENT_MECHANISM;
if (!ARG.RDB$FIELD_NAME.NULL)
- parameter.fieldName = ARG.RDB$FIELD_NAME;
+ parameter.fieldName = QualifiedName(ARG.RDB$FIELD_NAME);
if (!ARG.RDB$RELATION_NAME.NULL)
- parameter.relationName = ARG.RDB$RELATION_NAME;
+ parameter.relationName = QualifiedName(ARG.RDB$RELATION_NAME, ARG.RDB$RELATION_SCHEMA_NAME);
if (!ARG.RDB$COLLATION_ID.NULL)
parameter.collationId = ARG.RDB$COLLATION_ID;
if (!ARG.RDB$NULL_FLAG.NULL)
@@ -132,7 +135,8 @@ namespace
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRC IN RDB$PROCEDURES
- WITH PRC.RDB$PACKAGE_NAME EQ metaName.c_str()
+ WITH PRC.RDB$SCHEMA_NAME EQ packageName.schema.c_str() AND
+ PRC.RDB$PACKAGE_NAME EQ packageName.object.c_str()
{
Signature procedure(PRC.RDB$PROCEDURE_NAME);
procedure.defined = !PRC.RDB$PROCEDURE_BLR.NULL || !PRC.RDB$ENTRYPOINT.NULL;
@@ -142,21 +146,23 @@ namespace
FOR (REQUEST_HANDLE requestHandle2 TRANSACTION_HANDLE transaction)
PRM IN RDB$PROCEDURE_PARAMETERS CROSS
FLD IN RDB$FIELDS
- WITH PRM.RDB$PACKAGE_NAME EQ metaName.c_str() AND
+ WITH PRM.RDB$SCHEMA_NAME EQ PRC.RDB$SCHEMA_NAME AND
+ PRM.RDB$PACKAGE_NAME EQ PRC.RDB$PACKAGE_NAME AND
PRM.RDB$PROCEDURE_NAME EQ PRC.RDB$PROCEDURE_NAME AND
+ FLD.RDB$SCHEMA_NAME EQUIV PRM.RDB$FIELD_SOURCE_SCHEMA_NAME AND
FLD.RDB$FIELD_NAME EQ PRM.RDB$FIELD_SOURCE
{
SignatureParameter parameter(*getDefaultMemoryPool());
parameter.type = PRM.RDB$PARAMETER_TYPE;
parameter.number = PRM.RDB$PARAMETER_NUMBER;
parameter.name = PRM.RDB$PARAMETER_NAME;
- parameter.fieldSource = PRM.RDB$FIELD_SOURCE;
+ parameter.fieldSource = QualifiedName(PRM.RDB$FIELD_SOURCE, PRM.RDB$FIELD_SOURCE_SCHEMA_NAME);
parameter.mechanism = PRM.RDB$PARAMETER_MECHANISM;
if (!PRM.RDB$FIELD_NAME.NULL)
- parameter.fieldName = PRM.RDB$FIELD_NAME;
+ parameter.fieldName = QualifiedName(PRM.RDB$FIELD_NAME);
if (!PRM.RDB$RELATION_NAME.NULL)
- parameter.relationName = PRM.RDB$RELATION_NAME;
+ parameter.relationName = QualifiedName(PRM.RDB$RELATION_NAME, PRM.RDB$RELATION_SCHEMA_NAME);
if (!PRM.RDB$COLLATION_ID.NULL)
parameter.collationId = PRM.RDB$COLLATION_ID;
if (!PRM.RDB$NULL_FLAG.NULL)
@@ -216,6 +222,14 @@ string CreateAlterPackageNode::internalPrint(NodePrinter& printer) const
DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (create)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_package_header);
+
+ protectSystemSchema(name.schema, obj_package_header);
+ dsqlScratch->ddlSchema = name.schema;
+
if (alter && !items)
return DdlNode::dsqlPass(dsqlScratch);
@@ -235,18 +249,19 @@ DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
CreateAlterFunctionNode* const fun = (*items)[i].function;
ddlNode = fun;
- if (functionNames.exist(fun->name))
+ if (functionNames.exist(fun->name.object))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("FUNCTION") << Arg::Str(fun->name));
+ Arg::Str("FUNCTION") << fun->name.object);
}
- functionNames.add(fun->name);
+ functionNames.add(fun->name.object);
fun->alter = true;
- fun->package = name;
+ fun->name.schema = name.schema;
+ fun->name.package = name.object;
break;
}
@@ -255,18 +270,19 @@ DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
CreateAlterProcedureNode* const proc = (*items)[i].procedure;
ddlNode = proc;
- if (procedureNames.exist(proc->name))
+ if (procedureNames.exist(proc->name.object))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("PROCEDURE") << Arg::Str(proc->name));
+ Arg::Str("PROCEDURE") << proc->name.object);
}
- procedureNames.add(proc->name);
+ procedureNames.add(proc->name.object);
proc->alter = true;
- proc->package = name;
+ proc->name.schema = name.schema;
+ proc->name.package = name.object;
break;
}
@@ -280,6 +296,7 @@ DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
FB_NEW_POOL(pool) DsqlCompilerScratch(pool, dsqlScratch->getAttachment(),
dsqlScratch->getTransaction(), itemStatement);
+ itemScratch->ddlSchema = name.schema;
itemScratch->clientDialect = dsqlScratch->clientDialect;
itemScratch->flags |= DsqlCompilerScratch::FLAG_DDL;
itemScratch->package = name;
@@ -298,16 +315,13 @@ DdlNode* CreateAlterPackageNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void CreateAlterPackageNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
-
if (alter)
{
- if (SCL_check_package(tdbb, &dscName, SCL_alter) || !create)
+ if (SCL_check_package(tdbb, name, SCL_alter) || !create)
return;
}
- SCL_check_create_access(tdbb, obj_packages);
+ SCL_check_create_access(tdbb, obj_packages, name.schema);
}
@@ -332,7 +346,7 @@ void CreateAlterPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
if (!executeAlterIndividualParameters(tdbb, dsqlScratch, transaction))
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_not_found) << name.toQuotedString());
}
else if (!executeAlter(tdbb, dsqlScratch, transaction))
{
@@ -342,14 +356,14 @@ void CreateAlterPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_not_found) << name.toQuotedString());
}
}
- dsc desc;
- desc.makeText(name.length(), ttype_metadata,
- (UCHAR*) const_cast(name.c_str())); // safe const_cast
- DFW_post_work(transaction, dfw_modify_package_header, &desc, 0);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText(name.schema.length(), ttype_metadata, (UCHAR*) const_cast(name.schema.c_str()));
+ nameDesc.makeText(name.object.length(), ttype_metadata, (UCHAR*) const_cast(name.object.c_str()));
+ DFW_post_work(transaction, dfw_modify_package_header, &nameDesc, &schemaDesc, 0);
}
else
executeCreate(tdbb, dsqlScratch, transaction);
@@ -367,8 +381,7 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
if (createIfNotExistsOnly && !DYN_UTIL_check_unique_name_nothrow(tdbb, transaction, name, obj_package_header))
return;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_PACKAGE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_PACKAGE, name, {});
DYN_UTIL_check_unique_name(tdbb, transaction, name, obj_package_header);
@@ -377,8 +390,11 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES USING
{
+ PKG.RDB$SCHEMA_NAME.NULL = FALSE;
+ strcpy(PKG.RDB$SCHEMA_NAME, name.schema.c_str());
+
PKG.RDB$PACKAGE_NAME.NULL = FALSE;
- strcpy(PKG.RDB$PACKAGE_NAME, name.c_str());
+ strcpy(PKG.RDB$PACKAGE_NAME, name.object.c_str());
PKG.RDB$SYSTEM_FLAG.NULL = FALSE;
PKG.RDB$SYSTEM_FLAG = 0;
@@ -405,8 +421,7 @@ void CreateAlterPackageNode::executeCreate(thread_db* tdbb, DsqlCompilerScratch*
executeItems(tdbb, dsqlScratch, transaction);
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_PACKAGE,
- name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_PACKAGE, name, {});
}
@@ -420,12 +435,12 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
- WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PKG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PKG.RDB$PACKAGE_NAME EQ name.object.c_str()
{
modified = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_PACKAGE, name, {});
SortedObjectsArray existingFuncs(pool);
SortedObjectsArray existingProcs(pool);
@@ -436,8 +451,7 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
{
if (!functionNames.exist(i->name))
{
- DropFunctionNode dropNode(pool, i->name);
- dropNode.package = name;
+ DropFunctionNode dropNode(pool, QualifiedName(i->name, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -448,8 +462,7 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
{
if (!procedureNames.exist(i->name))
{
- DropProcedureNode dropNode(pool, i->name);
- dropNode.package = name;
+ DropProcedureNode dropNode(pool, QualifiedName(i->name, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -474,10 +487,10 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
owner = PKG.RDB$OWNER_NAME;
- dsc desc;
- desc.makeText(name.length(), ttype_metadata,
- (UCHAR*) const_cast(name.c_str())); // safe const_cast
- DFW_post_work(transaction, dfw_drop_package_body, &desc, 0);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText(name.schema.length(), ttype_metadata, (UCHAR*) const_cast(name.schema.c_str()));
+ nameDesc.makeText(name.object.length(), ttype_metadata, (UCHAR*) const_cast(name.object.c_str()));
+ DFW_post_work(transaction, dfw_drop_package_body, &nameDesc, &schemaDesc, 0);
}
END_FOR
@@ -485,8 +498,7 @@ bool CreateAlterPackageNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
{
executeItems(tdbb, dsqlScratch, transaction);
- executeDdlTrigger(tdbb, dsqlScratch, transaction,
- DTW_AFTER, DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_PACKAGE, name, {});
}
return modified;
@@ -500,12 +512,12 @@ bool CreateAlterPackageNode::executeAlterIndividualParameters(thread_db* tdbb, D
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
- WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PKG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PKG.RDB$PACKAGE_NAME EQ name.object.c_str()
{
modified = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_PACKAGE, name, {});
MODIFY PKG
if (ssDefiner.has_value())
@@ -523,10 +535,7 @@ bool CreateAlterPackageNode::executeAlterIndividualParameters(thread_db* tdbb, D
END_FOR
if (modified)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction,
- DTW_AFTER, DDL_TRIGGER_ALTER_PACKAGE, name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_PACKAGE, name, {});
return modified;
}
@@ -568,14 +577,11 @@ string DropPackageNode::internalPrint(NodePrinter& printer) const
void DropPackageNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_package(tdbb, &dscName, SCL_drop);
+ SCL_check_package(tdbb, name, SCL_drop);
}
-void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
MemoryPool& pool = dsqlScratch->getPool();
@@ -587,22 +593,22 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
- WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PKG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PKG.RDB$PACKAGE_NAME EQ name.object.c_str()
{
found = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_PACKAGE, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_PACKAGE, name, {});
ERASE PKG;
if (!PKG.RDB$SECURITY_CLASS.NULL)
deleteSecurityClass(tdbb, transaction, PKG.RDB$SECURITY_CLASS);
- dsc desc;
- desc.makeText(name.length(), ttype_metadata,
- (UCHAR*) const_cast(name.c_str())); // safe const_cast
- DFW_post_work(transaction, dfw_drop_package_header, &desc, 0);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText(name.schema.length(), ttype_metadata, (UCHAR*) const_cast(name.schema.c_str()));
+ nameDesc.makeText(name.object.length(), ttype_metadata, (UCHAR*) const_cast(name.object.c_str()));
+ DFW_post_work(transaction, dfw_drop_package_header, &nameDesc, &schemaDesc, 0);
}
END_FOR
@@ -610,7 +616,7 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_not_found) << name.toQuotedString());
}
SortedObjectsArray existingFuncs(pool);
@@ -620,8 +626,7 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
for (SortedObjectsArray::iterator i = existingFuncs.begin();
i != existingFuncs.end(); ++i)
{
- DropFunctionNode dropNode(pool, i->name);
- dropNode.package = name;
+ DropFunctionNode dropNode(pool, QualifiedName(i->name, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -629,8 +634,7 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
for (SortedObjectsArray::iterator i = existingProcs.begin();
i != existingProcs.end(); ++i)
{
- DropProcedureNode dropNode(pool, i->name);
- dropNode.package = name;
+ DropProcedureNode dropNode(pool, QualifiedName(i->name, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -639,9 +643,12 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES
- WITH ((PRIV.RDB$RELATION_NAME EQ name.c_str() AND
- PRIV.RDB$OBJECT_TYPE = obj_package_header) OR
- (PRIV.RDB$USER EQ name.c_str() AND PRIV.RDB$USER_TYPE = obj_package_header)) AND
+ WITH ((PRIV.RDB$RELATION_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$RELATION_NAME EQ name.object.c_str() AND
+ PRIV.RDB$OBJECT_TYPE = obj_package_header) OR
+ (PRIV.RDB$USER_SCHEMA_NAME EQ name.schema.c_str() AND
+ PRIV.RDB$USER EQ name.object.c_str() AND
+ PRIV.RDB$USER_TYPE = obj_package_header)) AND
PRIV.RDB$GRANTOR NOT MISSING
{
ERASE PRIV;
@@ -649,10 +656,7 @@ void DropPackageNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
END_FOR
if (found)
- {
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_PACKAGE,
- name, NULL);
- }
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_PACKAGE, name, {});
savePoint.release(); // everything is ok
}
@@ -676,6 +680,10 @@ string CreatePackageBodyNode::internalPrint(NodePrinter& printer) const
DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ dsqlScratch->qualifyExistingName(name, obj_package_header);
+ protectSystemSchema(name.schema, obj_package_header);
+ dsqlScratch->ddlSchema = name.schema;
+
MemoryPool& pool = dsqlScratch->getPool();
source.ltrim("\n\r\t ");
@@ -701,17 +709,18 @@ DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
CreateAlterFunctionNode* const fun = (*arrays[i])[j].function;
ddlNode = fun;
- if (functionNames[i].exist(fun->name))
+ if (functionNames[i].exist(fun->name.object))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("FUNCTION") << Arg::Str(fun->name));
+ Arg::Str("FUNCTION") << fun->name.object);
}
- functionNames[i].add(fun->name);
+ functionNames[i].add(fun->name.object);
- fun->package = name;
+ fun->name.schema = name.schema;
+ fun->name.package = name.object;
fun->create = true;
if (arrays[i] == items)
@@ -725,17 +734,18 @@ DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
CreateAlterProcedureNode* const proc = (*arrays[i])[j].procedure;
ddlNode = proc;
- if (procedureNames[i].exist(proc->name))
+ if (procedureNames[i].exist(proc->name.object))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("PROCEDURE") << Arg::Str(proc->name));
+ Arg::Str("PROCEDURE") << proc->name.object);
}
- procedureNames[i].add(proc->name);
+ procedureNames[i].add(proc->name.object);
- proc->package = name;
+ proc->name.schema = name.schema;
+ proc->name.package = name.object;
proc->create = true;
if (arrays[i] == items)
@@ -754,6 +764,7 @@ DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
FB_NEW_POOL(pool) DsqlCompilerScratch(pool, dsqlScratch->getAttachment(),
dsqlScratch->getTransaction(), itemStatement);
+ itemScratch->ddlSchema = name.schema;
itemScratch->clientDialect = dsqlScratch->clientDialect;
itemScratch->flags |= DsqlCompilerScratch::FLAG_DDL;
itemScratch->package = name;
@@ -773,12 +784,11 @@ DdlNode* CreatePackageBodyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
void CreatePackageBodyNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- SCL_check_create_access(tdbb, obj_packages);
+ SCL_check_create_access(tdbb, obj_packages, name.schema);
}
-void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
- jrd_tra* transaction)
+void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
MemoryPool& pool = dsqlScratch->getPool();
Attachment* attachment = transaction->getAttachment();
@@ -791,7 +801,8 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
- WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PKG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PKG.RDB$PACKAGE_NAME EQ name.object.c_str()
{
if (!PKG.RDB$VALID_BODY_FLAG.NULL && PKG.RDB$VALID_BODY_FLAG != 0)
{
@@ -800,11 +811,10 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_body_exists) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_body_exists) << name.toQuotedString());
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_CREATE_PACKAGE_BODY, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_PACKAGE_BODY, name, {});
MODIFY PKG
PKG.RDB$VALID_BODY_FLAG.NULL = FALSE;
@@ -824,7 +834,7 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_not_found) << name.toQuotedString());
}
SortedObjectsArray headerFuncs(pool);
@@ -861,18 +871,18 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
CreateAlterFunctionNode* func = elem.function;
if (arrays[i] == items)
- func->privateScope = !headerFuncs.exist(Signature(func->name));
- else if (existingFuncs.exist(Signature(func->name)))
+ func->privateScope = !headerFuncs.exist(Signature(func->name.object));
+ else if (existingFuncs.exist(Signature(func->name.object)))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("FUNCTION") << Arg::Str(func->name));
+ Arg::Str("FUNCTION") << func->name.toQuotedString());
}
func->packageOwner = owner;
func->preserveDefaults =
- existingFuncs.exist(Signature(func->name)) && arrays[i] == items;
+ existingFuncs.exist(Signature(func->name.object)) && arrays[i] == items;
func->executeDdl(tdbb, elem.dsqlScratch, transaction, true);
break;
}
@@ -882,18 +892,18 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
CreateAlterProcedureNode* proc = elem.procedure;
if (arrays[i] == items)
- proc->privateScope = !headerProcs.exist(Signature(proc->name));
- else if (existingProcs.exist(Signature(proc->name)))
+ proc->privateScope = !headerProcs.exist(Signature(proc->name.object));
+ else if (existingProcs.exist(Signature(proc->name.object)))
{
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_dyn_duplicate_package_item) <<
- Arg::Str("PROCEDURE") << Arg::Str(proc->name));
+ Arg::Str("PROCEDURE") << proc->name.toQuotedString());
}
proc->packageOwner = owner;
proc->preserveDefaults =
- existingProcs.exist(Signature(proc->name)) && arrays[i] == items;
+ existingProcs.exist(Signature(proc->name.object)) && arrays[i] == items;
proc->executeDdl(tdbb, elem.dsqlScratch, transaction, true);
break;
}
@@ -914,12 +924,12 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!found || !newFuncs[pos].defined)
{
status_exception::raise(
- Arg::Gds(isc_dyn_funcnotdef_package) << i->name.c_str() << name.c_str());
+ Arg::Gds(isc_dyn_funcnotdef_package) << i->name << name.toQuotedString());
}
else if (newFuncs[pos] != *i)
{
status_exception::raise(
- Arg::Gds(isc_dyn_funcsignat_package) << i->name.c_str() << name.c_str());
+ Arg::Gds(isc_dyn_funcsignat_package) << i->name << name.toQuotedString());
}
}
@@ -932,17 +942,16 @@ void CreatePackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
if (!found || !newProcs[pos].defined)
{
status_exception::raise(
- Arg::Gds(isc_dyn_procnotdef_package) << i->name.c_str() << name.c_str());
+ Arg::Gds(isc_dyn_procnotdef_package) << i->name << name.toQuotedString());
}
else if (newProcs[pos] != *i)
{
status_exception::raise(
- Arg::Gds(isc_dyn_procsignat_package) << i->name.c_str() << name.c_str());
+ Arg::Gds(isc_dyn_procsignat_package) << i->name << name.toQuotedString());
}
}
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_CREATE_PACKAGE_BODY, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_PACKAGE_BODY, name, {});
savePoint.release(); // everything is ok
}
@@ -964,9 +973,7 @@ string DropPackageBodyNode::internalPrint(NodePrinter& printer) const
void DropPackageBodyNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
- dsc dscName;
- dscName.makeText(name.length(), CS_METADATA, (UCHAR*) name.c_str());
- SCL_check_package(tdbb, &dscName, SCL_drop);
+ SCL_check_package(tdbb, name, SCL_drop);
}
@@ -983,21 +990,21 @@ void DropPackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PKG IN RDB$PACKAGES
- WITH PKG.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PKG.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PKG.RDB$PACKAGE_NAME EQ name.object.c_str()
{
found = true;
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE,
- DDL_TRIGGER_DROP_PACKAGE_BODY, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_PACKAGE_BODY, name, {});
MODIFY PKG
PKG.RDB$VALID_BODY_FLAG.NULL = TRUE;
PKG.RDB$PACKAGE_BODY_SOURCE.NULL = TRUE;
- dsc desc;
- desc.makeText(name.length(), ttype_metadata,
- (UCHAR*) const_cast(name.c_str())); // safe const_cast
- DFW_post_work(transaction, dfw_drop_package_body, &desc, 0);
+ dsc schemaDesc, nameDesc;
+ schemaDesc.makeText(name.schema.length(), ttype_metadata, (UCHAR*) const_cast(name.schema.c_str()));
+ nameDesc.makeText(name.object.length(), ttype_metadata, (UCHAR*) const_cast(name.object.c_str()));
+ DFW_post_work(transaction, dfw_drop_package_body, &nameDesc, &schemaDesc, 0);
END_MODIFY
}
END_FOR
@@ -1012,19 +1019,19 @@ void DropPackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
status_exception::raise(
Arg::Gds(isc_no_meta_update) <<
- Arg::Gds(isc_dyn_package_not_found) << Arg::Str(name));
+ Arg::Gds(isc_dyn_package_not_found) << name.toQuotedString());
}
requestHandle.reset(tdbb, drq_m_pkg_fun, DYN_REQUESTS);
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
FUN IN RDB$FUNCTIONS
- WITH FUN.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH FUN.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ FUN.RDB$PACKAGE_NAME EQ name.object.c_str()
{
if (!FUN.RDB$PRIVATE_FLAG.NULL && FUN.RDB$PRIVATE_FLAG != 0)
{
- DropFunctionNode dropNode(pool, FUN.RDB$FUNCTION_NAME);
- dropNode.package = name;
+ DropFunctionNode dropNode(pool, QualifiedName(FUN.RDB$FUNCTION_NAME, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -1046,12 +1053,12 @@ void DropPackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
PRC IN RDB$PROCEDURES
- WITH PRC.RDB$PACKAGE_NAME EQ name.c_str()
+ WITH PRC.RDB$SCHEMA_NAME EQ name.schema.c_str() AND
+ PRC.RDB$PACKAGE_NAME EQ name.object.c_str()
{
if (!PRC.RDB$PRIVATE_FLAG.NULL && PRC.RDB$PRIVATE_FLAG != 0)
{
- DropProcedureNode dropNode(pool, PRC.RDB$PROCEDURE_NAME);
- dropNode.package = name;
+ DropProcedureNode dropNode(pool, QualifiedName(PRC.RDB$PROCEDURE_NAME, name.schema, name.object));
dropNode.dsqlPass(dsqlScratch);
dropNode.executeDdl(tdbb, dsqlScratch, transaction, true);
}
@@ -1068,8 +1075,7 @@ void DropPackageBodyNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
}
END_FOR
- executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER,
- DDL_TRIGGER_DROP_PACKAGE_BODY, name, NULL);
+ executeDdlTrigger(tdbb, dsqlScratch, transaction, DTW_AFTER, DDL_TRIGGER_DROP_PACKAGE_BODY, name, {});
savePoint.release(); // everything is ok
}
diff --git a/src/dsql/PackageNodes.h b/src/dsql/PackageNodes.h
index 23868292dd..042f395562 100644
--- a/src/dsql/PackageNodes.h
+++ b/src/dsql/PackageNodes.h
@@ -68,7 +68,7 @@ public:
};
public:
- CreateAlterPackageNode(MemoryPool& pool, const MetaName& aName)
+ CreateAlterPackageNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
create(true),
@@ -94,7 +94,7 @@ protected:
Firebird::Arg::Gds(createAlterCode(create, alter,
isc_dsql_create_pack_failed, isc_dsql_alter_pack_failed,
isc_dsql_create_alter_pack_failed)) <<
- name;
+ name.toQuotedString();
}
private:
@@ -104,7 +104,7 @@ private:
void executeItems(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
public:
- MetaName name;
+ QualifiedName name;
bool create;
bool alter;
bool createIfNotExistsOnly = false;
@@ -122,7 +122,7 @@ private:
class DropPackageNode : public DdlNode
{
public:
- DropPackageNode(MemoryPool& pool, const MetaName& aName)
+ DropPackageNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
silent(false)
@@ -134,15 +134,29 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ if (recreate)
+ dsqlScratch->qualifyNewName(name);
+ else
+ dsqlScratch->qualifyExistingName(name, obj_package_header);
+
+ protectSystemSchema(name.schema, obj_package_header);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_pack_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_pack_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent;
+ bool recreate = false;
};
@@ -153,7 +167,7 @@ typedef RecreateNode* declaredItems;
Firebird::Array* items;
@@ -190,7 +204,7 @@ private:
class DropPackageBodyNode : public DdlNode
{
public:
- DropPackageBodyNode(MemoryPool& pool, const MetaName& aName)
+ DropPackageBodyNode(MemoryPool& pool, const QualifiedName& aName)
: DdlNode(pool),
name(pool, aName),
silent(false)
@@ -202,15 +216,25 @@ public:
virtual void checkPermission(thread_db* tdbb, jrd_tra* transaction);
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
+ virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
+ {
+ dsqlScratch->qualifyExistingName(name, obj_package_header);
+ protectSystemSchema(name.schema, obj_package_header);
+ dsqlScratch->ddlSchema = name.schema;
+
+ return DdlNode::dsqlPass(dsqlScratch);
+ }
+
protected:
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
{
- statusVector << Firebird::Arg::Gds(isc_dsql_drop_pack_body_failed) << name;
+ statusVector << Firebird::Arg::Gds(isc_dsql_drop_pack_body_failed) << name.toQuotedString();
}
public:
- MetaName name;
+ QualifiedName name;
bool silent; // Unused. Just to please RecreateNode template.
+ bool recreate = false;
};
diff --git a/src/dsql/Parser.cpp b/src/dsql/Parser.cpp
index c60bea0290..4b82e82659 100644
--- a/src/dsql/Parser.cpp
+++ b/src/dsql/Parser.cpp
@@ -408,28 +408,13 @@ int Parser::yylexAux()
if (tok_class & CHR_INTRODUCER)
{
- // The Introducer (_) is skipped, all other idents are copied
- // to become the name of the character set.
- char* p = string;
- for (; lex.ptr < lex.end && (classes(*lex.ptr) & CHR_IDENT); lex.ptr++)
- {
- if (lex.ptr >= lex.end)
- return -1;
+ if (lex.ptr >= lex.end)
+ return -1;
- check_copy_incr(p, UPPER7(*lex.ptr), string);
- }
+ if (classes(*lex.ptr) & (CHR_IDENT | CHR_QUOTE))
+ return TOK_INTRODUCER;
- check_bound(p, string);
-
- if (p > string + MAX_SQL_IDENTIFIER_LEN || p > string + METADATA_IDENTIFIER_CHAR_LEN)
- yyabandon(yyposn, -104, isc_dyn_name_longer);
-
- *p = 0;
-
- // make a string value to hold the name, the name is resolved in pass1_constant.
- yylval.metaNamePtr = FB_NEW_POOL(pool) MetaName(pool, string, p - string);
-
- return TOK_INTRODUCER;
+ return (UCHAR) c;
}
// parse a quoted string, being sure to look for double quotes
@@ -711,15 +696,14 @@ int Parser::yylexAux()
if (introducerCharSetName)
{
- const auto symbol = METD_get_charset(scratch->getTransaction(),
- introducerCharSetName->length(), introducerCharSetName->c_str());
+ const auto symbol = METD_get_charset(scratch->getTransaction(), *introducerCharSetName);
if (!symbol)
{
// character set name is not defined
ERRD_post(
Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
- Arg::Gds(isc_charset_not_found) << *introducerCharSetName);
+ Arg::Gds(isc_charset_not_found) << introducerCharSetName->toQuotedString());
}
currentCharSet = INTL_charset_lookup(tdbb, symbol->intlsym_ttype);
diff --git a/src/dsql/Parser.h b/src/dsql/Parser.h
index 51cb519562..d1a34f727b 100644
--- a/src/dsql/Parser.h
+++ b/src/dsql/Parser.h
@@ -225,6 +225,11 @@ private:
return (name ? *name : MetaName());
}
+ QualifiedName optName(QualifiedName* name)
+ {
+ return (name ? *name : QualifiedName());
+ }
+
void transformString(const char* start, unsigned length, Firebird::string& dest);
Firebird::string makeParseStr(const Position& p1, const Position& p2);
ParameterNode* make_parameter();
@@ -323,6 +328,11 @@ private:
return clause.hasData();
}
+ bool isDuplicateClause(const QualifiedName& clause)
+ {
+ return clause.object.hasData();
+ }
+
bool isDuplicateClause(const Firebird::TriState& clause)
{
return clause.isAssigned();
@@ -340,7 +350,7 @@ private:
return clause.hasData();
}
- void setCollate(TypeClause* fld, MetaName* name)
+ void setCollate(TypeClause* fld, QualifiedName* name)
{
if (name)
setClause(fld->collate, "COLLATE", *name);
@@ -380,7 +390,7 @@ private:
DsqlStatement* parsedStatement;
// Parser feedback for lexer
- MetaName* introducerCharSetName = nullptr;
+ QualifiedName* introducerCharSetName = nullptr;
// These value/posn are taken from the lexer
YYSTYPE yylval;
diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp
index 3252da179b..2bf62f1e6c 100644
--- a/src/dsql/StmtNodes.cpp
+++ b/src/dsql/StmtNodes.cpp
@@ -247,10 +247,10 @@ void AssignmentNode::validateTarget(CompilerScratch* csb, const ValueExprNode* t
if (error)
{
jrd_fld* field = MET_get_field(tail->csb_relation, fieldNode->fieldId);
- string fieldName(field ? field->fld_name.c_str() : "");
+ string fieldName(field ? field->fld_name.toQuotedString() : "");
if (field && tail->csb_relation)
- fieldName = string(tail->csb_relation->rel_name.c_str()) + "." + fieldName;
+ fieldName = tail->csb_relation->rel_name.toQuotedString() + "." + fieldName;
ERR_post(Arg::Gds(isc_read_only_field) << fieldName.c_str());
}
@@ -266,8 +266,10 @@ void AssignmentNode::dsqlValidateTarget(const ValueExprNode* target)
if (fieldNode && fieldNode->context &&
(fieldNode->context->ctx_flags & (CTX_system | CTX_cursor)) == CTX_cursor)
{
+ const auto contextAliases = fieldNode->context->getConcatenatedAlias();
+
ERR_post(Arg::Gds(isc_read_only_field) <<
- (fieldNode->context->ctx_alias + "." + fieldNode->name.c_str()));
+ (contextAliases + "." + fieldNode->name.toQuotedString()));
}
}
@@ -733,7 +735,7 @@ bool BlockNode::testAndFixupError(thread_db* tdbb, Request* request, const Excep
{
FB_SQLSTATE_STRING sqlstate;
fb_sqlstate(sqlstate, statusVector->getErrors());
- if (conditions[i].name == sqlstate)
+ if (conditions[i].name.object == sqlstate)
found = true;
}
break;
@@ -1662,7 +1664,7 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
dsqlFunction = implemetingForward ? prevDecl->dsqlFunction : FB_NEW_POOL(pool) dsql_udf(pool);
dsqlFunction->udf_flags = UDF_subfunc;
- dsqlFunction->udf_name.identifier = name;
+ dsqlFunction->udf_name.object = name;
fb_assert(dsqlBlock->returns.getCount() == 1);
const auto returnType = dsqlBlock->returns[0]->type;
@@ -1990,7 +1992,7 @@ DeclareSubProcNode* DeclareSubProcNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
dsqlProcedure = implemetingForward ? prevDecl->dsqlProcedure : FB_NEW_POOL(pool) dsql_prc(pool);
dsqlProcedure->prc_flags = PRC_subproc;
- dsqlProcedure->prc_name.identifier = name;
+ dsqlProcedure->prc_name.object = name;
dsqlProcedure->prc_in_count = USHORT(dsqlBlock->parameters.getCount());
dsqlProcedure->prc_out_count = USHORT(dsqlBlock->returns.getCount());
@@ -2298,6 +2300,8 @@ StmtNode* EraseNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
auto relation = dsqlRelation;
+ dsqlScratch->qualifyExistingName(relation->dsqlName, obj_relation);
+
const auto node = FB_NEW_POOL(dsqlScratch->getPool()) EraseNode(dsqlScratch->getPool());
node->dsqlCursorName = dsqlCursorName;
node->dsqlSkipLocked = dsqlSkipLocked;
@@ -2849,22 +2853,31 @@ DmlNode* ErrorHandlerNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScra
case blr_sql_state:
item.type = ExceptionItem::SQL_STATE;
- csb->csb_blr_reader.getString(item.name);
+ csb->csb_blr_reader.getMetaName(item.name.object);
break;
case blr_gds_code:
+ {
item.type = ExceptionItem::GDS_CODE;
- csb->csb_blr_reader.getString(item.name);
- item.name.lower();
- if (!(item.code = PAR_symbol_to_gdscode(item.name)))
- PAR_error(csb, Arg::Gds(isc_codnotdef) << item.name);
+ string str;
+ csb->csb_blr_reader.getString(str);
+ str.lower();
+ item.name.object = str;
+ if (!(item.code = PAR_symbol_to_gdscode(str)))
+ PAR_error(csb, Arg::Gds(isc_codnotdef) << item.name.object);
break;
+ }
case blr_exception:
- {
- csb->csb_blr_reader.getString(item.name);
+ case blr_exception2:
+ if (codeType == blr_exception2)
+ csb->csb_blr_reader.getMetaName(item.name.schema);
+
+ csb->csb_blr_reader.getMetaName(item.name.object);
+ csb->qualifyExistingName(tdbb, item.name, obj_exception);
+
if (!MET_load_exception(tdbb, item))
- PAR_error(csb, Arg::Gds(isc_xcpnotdef) << item.name);
+ PAR_error(csb, Arg::Gds(isc_xcpnotdef) << item.name.toQuotedString());
if (csb->collectingDependencies())
{
@@ -2874,7 +2887,6 @@ DmlNode* ErrorHandlerNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScra
}
break;
- }
case blr_default_code:
item.type = ExceptionItem::XCP_DEFAULT;
@@ -2927,17 +2939,26 @@ void ErrorHandlerNode::genBlr(DsqlCompilerScratch* dsqlScratch)
case ExceptionItem::SQL_STATE:
dsqlScratch->appendUChar(blr_sql_state);
- dsqlScratch->appendNullString(i->name.c_str());
+ dsqlScratch->appendNullString(i->name.object.c_str());
break;
case ExceptionItem::GDS_CODE:
dsqlScratch->appendUChar(blr_gds_code);
- dsqlScratch->appendNullString(i->name.c_str());
+ dsqlScratch->appendNullString(i->name.object.c_str());
break;
case ExceptionItem::XCP_CODE:
- dsqlScratch->appendUChar(blr_exception);
- dsqlScratch->appendNullString(i->name.c_str());
+ if (i->name.schema != dsqlScratch->ddlSchema)
+ {
+ dsqlScratch->appendUChar(blr_exception2);
+ dsqlScratch->appendNullString(i->name.schema.c_str());
+ dsqlScratch->appendNullString(i->name.object.c_str());
+ }
+ else
+ {
+ dsqlScratch->appendUChar(blr_exception);
+ dsqlScratch->appendNullString(i->name.object.c_str());
+ }
break;
case ExceptionItem::XCP_DEFAULT:
@@ -3033,44 +3054,57 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
{
switch (subCode)
{
- case blr_invsel_procedure_type:
+ case blr_invsel_procedure_id:
{
- UCHAR procedureType = blrReader.getByte();
+ bool isSub = false;
+ UCHAR procedureIdCode;
- switch (procedureType)
+ while ((procedureIdCode = blrReader.getByte()) != blr_end)
{
- case blr_invsel_procedure_type_packaged:
- blrReader.getMetaName(name.package);
- break;
+ switch (procedureIdCode)
+ {
+ case blr_invsel_procedure_id_schema:
+ blrReader.getMetaName(name.schema);
+ break;
- case blr_invsel_procedure_type_standalone:
- case blr_invsel_procedure_type_sub:
- break;
+ case blr_invsel_procedure_id_package:
+ blrReader.getMetaName(name.package);
+ break;
- default:
- PAR_error(csb, Arg::Gds(isc_random) << "Invalid blr_invsel_procedure_type");
- break;
+ case blr_invsel_procedure_id_name:
+ blrReader.getMetaName(name.object);
+ break;
+
+ case blr_invsel_procedure_id_sub:
+ isSub = true;
+ break;
+
+ default:
+ PAR_error(csb, Arg::Gds(isc_random) << "Invalid blr_invsel_procedure_id");
+ break;
+ }
}
- blrReader.getMetaName(name.identifier);
-
- if (procedureType == blr_invsel_procedure_type_sub)
+ if (isSub)
{
for (auto curCsb = csb; curCsb && !node->procedure; curCsb = curCsb->mainCsb)
{
- if (const auto declareNode = curCsb->subProcedures.get(name.identifier))
+ if (const auto declareNode = curCsb->subProcedures.get(name.object))
node->procedure = (*declareNode)->routine;
}
}
else if (!node->procedure)
+ {
+ csb->qualifyExistingName(tdbb, name, obj_procedure);
node->procedure = MET_lookup_procedure(tdbb, name, false);
+ }
break;
}
case blr_invsel_procedure_in_arg_names:
{
- predateCheck(node->procedure, "blr_invsel_procedure_type", "blr_invsel_procedure_in_arg_names");
+ predateCheck(node->procedure, "blr_invsel_procedure_id", "blr_invsel_procedure_in_arg_names");
predateCheck(!node->inputSources,
"blr_invsel_procedure_in_arg_names", "blr_invsel_procedure_in_args");
@@ -3090,7 +3124,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
}
case blr_invsel_procedure_in_args:
- predateCheck(node->procedure, "blr_invsel_procedure_type", "blr_invsel_procedure_in_args");
+ predateCheck(node->procedure, "blr_invsel_procedure_id", "blr_invsel_procedure_in_args");
inArgCount = blrReader.getWord();
node->inputSources = PAR_args(tdbb, csb, inArgCount,
MAX(inArgCount, node->procedure->getInputFields().getCount()));
@@ -3099,7 +3133,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
case blr_invsel_procedure_out_arg_names:
{
predateCheck(node->procedure,
- "blr_invsel_procedure_type", "blr_invsel_procedure_out_arg_names");
+ "blr_invsel_procedure_id", "blr_invsel_procedure_out_arg_names");
predateCheck(!node->outputTargets,
"blr_invsel_procedure_out_arg_names", "blr_invsel_procedure_out_args");
@@ -3120,7 +3154,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
}
case blr_invsel_procedure_out_args:
- predateCheck(node->procedure, "blr_invsel_procedure_type", "blr_invsel_procedure_out_args");
+ predateCheck(node->procedure, "blr_invsel_procedure_id", "blr_invsel_procedure_out_args");
outArgCount = blrReader.getWord();
node->outputTargets = PAR_args(tdbb, csb, outArgCount, outArgCount);
break;
@@ -3128,7 +3162,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
case blr_invsel_procedure_inout_arg_names:
{
predateCheck(node->procedure,
- "blr_invsel_procedure_type", "blr_invsel_procedure_inout_arg_names");
+ "blr_invsel_procedure_id", "blr_invsel_procedure_inout_arg_names");
predateCheck(!inOutArgs,
"blr_invsel_procedure_inout_arg_names", "blr_invsel_procedure_inout_args");
@@ -3148,7 +3182,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
}
case blr_invsel_procedure_inout_args:
- predateCheck(node->procedure, "blr_invsel_procedure_type", "blr_invsel_procedure_inout_args");
+ predateCheck(node->procedure, "blr_invsel_procedure_id", "blr_invsel_procedure_inout_args");
inOutArgCount = blrReader.getWord();
inOutArgs = PAR_args(tdbb, csb, inOutArgCount, inOutArgCount);
break;
@@ -3165,7 +3199,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
{
const USHORT pid = blrReader.getWord();
if (!(node->procedure = MET_lookup_procedure_id(tdbb, pid, false, false, 0)))
- name.identifier.printf("id %d", pid);
+ name.object.printf("id %d", pid);
break;
}
@@ -3173,18 +3207,21 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
if (blrOp == blr_exec_proc2)
blrReader.getMetaName(name.package);
- blrReader.getMetaName(name.identifier);
+ blrReader.getMetaName(name.object);
if (blrOp == blr_exec_subproc)
{
for (auto curCsb = csb; curCsb && !node->procedure; curCsb = curCsb->mainCsb)
{
- if (const auto declareNode = curCsb->subProcedures.get(name.identifier))
+ if (const auto declareNode = curCsb->subProcedures.get(name.object))
node->procedure = (*declareNode)->routine;
}
}
else
+ {
+ csb->qualifyExistingName(tdbb, name, obj_procedure);
node->procedure = MET_lookup_procedure(tdbb, name, false);
+ }
break;
}
@@ -3192,7 +3229,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
if (!node->procedure)
{
blrReader.setPos(blrStartPos);
- PAR_error(csb, Arg::Gds(isc_prcnotdef) << name.toString());
+ PAR_error(csb, Arg::Gds(isc_prcnotdef) << name.toQuotedString());
}
if ((inOutArgs || inOutArgNames) && (node->inputSources || inArgNames || node->outputTargets || outArgNames))
@@ -3300,14 +3337,14 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
if (tdbb->getAttachment()->isGbak() || (tdbb->tdbb_flags & TDBB_replicator))
{
PAR_warning(
- Arg::Warning(isc_prcnotdef) << name.toString() <<
+ Arg::Warning(isc_prcnotdef) << name.toQuotedString() <<
Arg::Warning(isc_modnotfound));
}
else
{
csb->csb_blr_reader.setPos(blrStartPos);
PAR_error(csb,
- Arg::Gds(isc_prcnotdef) << name.toString() <<
+ Arg::Gds(isc_prcnotdef) << name.toQuotedString() <<
Arg::Gds(isc_modnotfound));
}
}
@@ -3343,7 +3380,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
if (mismatchStatus.hasData())
{
status_exception::raise(Arg::Gds(isc_prcmismat) <<
- node->procedure->getName().toString() << mismatchStatus);
+ node->procedure->getName().toQuotedString() << mismatchStatus);
}
if (csb->collectingDependencies() && !node->procedure->isSubRoutine())
@@ -3400,13 +3437,37 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
- auto& pool = dsqlScratch->getPool();
dsql_prc* procedure = nullptr;
if (dsqlName.package.isEmpty())
{
- DeclareSubProcNode* subProcedure = dsqlScratch->getSubProcedure(dsqlName.identifier);
- procedure = subProcedure ? subProcedure->dsqlProcedure : NULL;
+ if (dsqlName.schema.isEmpty())
+ {
+ if (const auto subProcedure = dsqlScratch->getSubProcedure(dsqlName.object))
+ procedure = subProcedure->dsqlProcedure;
+ else if (dsqlScratch->package.object.hasData())
+ {
+ const QualifiedName packagedName(dsqlName.object,
+ dsqlScratch->package.schema, dsqlScratch->package.object);
+
+ if ((procedure = METD_get_procedure(dsqlScratch->getTransaction(), dsqlScratch, packagedName)))
+ dsqlName = packagedName;
+ }
+
+ if (!procedure)
+ dsqlScratch->qualifyExistingName(dsqlName, obj_procedure);
+ }
+ else
+ {
+ QualifiedName packageName(dsqlName.schema);
+ dsqlScratch->qualifyExistingName(packageName, obj_package_header);
+
+ if (MET_check_package_exists(JRD_get_thread_data(), packageName))
+ {
+ dsqlName.schema = packageName.schema;
+ dsqlName.package = packageName.object;
+ }
+ }
}
if (!procedure)
@@ -3416,13 +3477,24 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_procedure_err) <<
- Arg::Gds(isc_random) <<
- dsqlName.toString());
+ Arg::Gds(isc_random) << dsqlName.toQuotedString());
}
+ if (procedure->prc_private && procedure->prc_name.getSchemaAndPackage() != dsqlScratch->package)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_private_procedure) <<
+ procedure->prc_name.object <<
+ procedure->prc_name.getSchemaAndPackage().toQuotedString());
+ }
+
+ dsqlName = procedure->prc_name;
+
if (!dsqlScratch->isPsql())
dsqlScratch->getDsqlStatement()->setType(DsqlStatement::TYPE_EXEC_PROCEDURE);
+ auto& pool = dsqlScratch->getPool();
+
if (dsqlCallSyntax && !dsqlScratch->isPsql() && inputSources && inputSources->items.hasData())
{
const auto positionalArgCount = inputSources->items.getCount() -
@@ -3498,9 +3570,9 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
paramNode->dsqlParameterIndex = parameter->par_index;
DsqlDescMaker::fromField(¶meter->par_desc, field);
- parameter->par_name = parameter->par_alias = field->fld_name.c_str();
- parameter->par_rel_name = procedure->prc_name.identifier.c_str();
- parameter->par_owner_name = procedure->prc_owner.c_str();
+ parameter->par_name = parameter->par_alias = field->fld_name;
+ parameter->par_rel_name = procedure->prc_name;
+ parameter->par_owner_name = procedure->prc_owner;
}
field = field->fld_next;
@@ -3530,9 +3602,9 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
paramNode->dsqlParameterIndex = parameter->par_index;
DsqlDescMaker::fromField(¶meter->par_desc, *field);
- parameter->par_name = parameter->par_alias = (*field)->fld_name.c_str();
- parameter->par_rel_name = procedure->prc_name.identifier.c_str();
- parameter->par_owner_name = procedure->prc_owner.c_str();
+ parameter->par_name = parameter->par_alias = (*field)->fld_name;
+ parameter->par_rel_name = procedure->prc_name;
+ parameter->par_owner_name = procedure->prc_owner;
}
}
else
@@ -3542,7 +3614,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
}
if (mismatchStatus.hasData())
- status_exception::raise(Arg::Gds(isc_prcmismat) << dsqlName.toString() << mismatchStatus);
+ status_exception::raise(Arg::Gds(isc_prcmismat) << dsqlName.toQuotedString() << mismatchStatus);
}
}
}
@@ -3621,7 +3693,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
}
if (mismatchStatus.hasData())
- status_exception::raise(Arg::Gds(isc_prcmismat) << dsqlName.toString() << mismatchStatus);
+ status_exception::raise(Arg::Gds(isc_prcmismat) << dsqlName.toQuotedString() << mismatchStatus);
}
}
@@ -3634,7 +3706,7 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
const USHORT outCount = outputTargets ? outputTargets->items.getCount() : 0;
if (outCount != procedure->prc_out_count)
- ERRD_post(Arg::Gds(isc_prc_out_param_mismatch) << Arg::Str(dsqlName.toString()));
+ ERRD_post(Arg::Gds(isc_prc_out_param_mismatch) << Arg::Str(dsqlName.toQuotedString()));
}
node->outputTargets = dsqlPassArray(dsqlScratch, outputTargets);
@@ -3689,9 +3761,9 @@ ValueListNode* ExecProcedureNode::explodeOutputs(DsqlCompilerScratch* dsqlScratc
paramNode->dsqlParameterIndex = parameter->par_index;
DsqlDescMaker::fromField(¶meter->par_desc, field);
- parameter->par_name = parameter->par_alias = field->fld_name.c_str();
- parameter->par_rel_name = procedure->prc_name.identifier.c_str();
- parameter->par_owner_name = procedure->prc_owner.c_str();
+ parameter->par_name = parameter->par_alias = field->fld_name;
+ parameter->par_rel_name = procedure->prc_name;
+ parameter->par_owner_name = procedure->prc_owner;
}
return output;
@@ -3726,24 +3798,32 @@ void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
}
}
- if (dsqlInputArgNames || dsqlOutputArgNames || dsqlCallSyntax)
+ if (dsqlInputArgNames || dsqlOutputArgNames || dsqlCallSyntax || dsqlName.schema != dsqlScratch->ddlSchema)
{
dsqlScratch->appendUChar(blr_invoke_procedure);
- dsqlScratch->appendUChar(blr_invsel_procedure_type);
+ dsqlScratch->appendUChar(blr_invsel_procedure_id);
- if (dsqlName.package.hasData())
- {
- dsqlScratch->appendUChar(blr_invsel_procedure_type_packaged);
- dsqlScratch->appendMetaString(dsqlName.package.c_str());
- }
+ if (dsqlProcedure->prc_flags & PRC_subproc)
+ dsqlScratch->appendUChar(blr_invsel_procedure_id_sub);
else
{
- dsqlScratch->appendUChar((dsqlProcedure->prc_flags & PRC_subproc) ?
- blr_invsel_procedure_type_sub : blr_invsel_procedure_type_standalone);
+ if (dsqlName.schema != dsqlScratch->ddlSchema)
+ {
+ dsqlScratch->appendUChar(blr_invsel_procedure_id_schema);
+ dsqlScratch->appendMetaString(dsqlName.schema.c_str());
+ }
+
+ if (dsqlName.package.hasData())
+ {
+ dsqlScratch->appendUChar(blr_invsel_procedure_id_package);
+ dsqlScratch->appendMetaString(dsqlName.package.c_str());
+ }
}
- dsqlScratch->appendMetaString(dsqlName.identifier.c_str());
+ dsqlScratch->appendUChar(blr_invsel_procedure_id_name);
+ dsqlScratch->appendMetaString(dsqlName.object.c_str());
+ dsqlScratch->appendUChar(blr_end);
const bool useInOut = dsqlScratch->isPsql() && dsqlCallSyntax;
@@ -3799,7 +3879,7 @@ void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
else
dsqlScratch->appendUChar((dsqlProcedure->prc_flags & PRC_subproc) ? blr_exec_subproc : blr_exec_proc);
- dsqlScratch->appendMetaString(dsqlName.identifier.c_str());
+ dsqlScratch->appendMetaString(dsqlName.object.c_str());
// Input parameters.
if (inputSources)
@@ -3884,12 +3964,12 @@ void ExecProcedureNode::executeProcedure(thread_db* tdbb, Request* request) cons
{
status_exception::raise(
Arg::Gds(isc_proc_pack_not_implemented) <<
- Arg::Str(procedure->getName().identifier) << Arg::Str(procedure->getName().package));
+ Arg::Str(procedure->getName().object) << Arg::Str(procedure->getName().package));
}
else if (!procedure->isDefined())
{
status_exception::raise(
- Arg::Gds(isc_prcnotdef) << Arg::Str(procedure->getName().toString()) <<
+ Arg::Gds(isc_prcnotdef) << Arg::Str(procedure->getName().toQuotedString()) <<
Arg::Gds(isc_modnotfound));
}
@@ -5129,7 +5209,7 @@ void ExecBlockNode::genBlr(DsqlCompilerScratch* dsqlScratch)
const auto& variables = subRoutine ? dsqlScratch->outputVariables : dsqlScratch->variables;
for (const auto variable : variables)
- dsqlScratch->putLocalVariable(variable, nullptr, {});
+ dsqlScratch->putLocalVariable(variable);
dsqlScratch->setPsql(true);
@@ -5189,62 +5269,78 @@ DmlNode* ExceptionNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch
const UCHAR /*blrOp*/)
{
ExceptionNode* node = FB_NEW_POOL(pool) ExceptionNode(pool);
- const UCHAR type = csb->csb_blr_reader.peekByte();
const USHORT codeType = csb->csb_blr_reader.getByte();
// Don't create ExceptionItem if blr_raise is used.
- if (codeType != blr_raise)
+ if (codeType == blr_raise)
+ return node;
+
+ ExceptionItem* const item = FB_NEW_POOL(pool) ExceptionItem(pool);
+
+ switch (codeType)
{
- ExceptionItem* const item = FB_NEW_POOL(pool) ExceptionItem(pool);
-
- switch (codeType)
+ case blr_gds_code:
{
- case blr_gds_code:
- item->type = ExceptionItem::GDS_CODE;
- csb->csb_blr_reader.getString(item->name);
- item->name.lower();
- if (!(item->code = PAR_symbol_to_gdscode(item->name)))
- PAR_error(csb, Arg::Gds(isc_codnotdef) << item->name);
- break;
-
- case blr_exception:
- case blr_exception_msg:
- case blr_exception_params:
- {
- csb->csb_blr_reader.getString(item->name);
- if (!MET_load_exception(tdbb, *item))
- PAR_error(csb, Arg::Gds(isc_xcpnotdef) << item->name);
-
- if (csb->collectingDependencies())
- {
- CompilerScratch::Dependency dependency(obj_exception);
- dependency.number = item->code;
- csb->addDependency(dependency);
- }
- }
- break;
-
- default:
- fb_assert(false);
- break;
+ item->type = ExceptionItem::GDS_CODE;
+ string str;
+ csb->csb_blr_reader.getString(str);
+ str.lower();
+ item->name.object = str;
+ if (!(item->code = PAR_symbol_to_gdscode(str)))
+ PAR_error(csb, Arg::Gds(isc_codnotdef) << item->name.object);
+ break;
}
- node->exception = item;
+ case blr_exception:
+ case blr_exception2:
+ case blr_exception3:
+ case blr_exception_msg:
+ case blr_exception_params:
+ if (codeType == blr_exception2 || codeType == blr_exception3)
+ csb->csb_blr_reader.getMetaName(item->name.schema);
+
+ csb->csb_blr_reader.getMetaName(item->name.object);
+ csb->qualifyExistingName(tdbb, item->name, obj_exception);
+
+ if (!MET_load_exception(tdbb, *item))
+ PAR_error(csb, Arg::Gds(isc_xcpnotdef) << item->name.toQuotedString());
+
+ if (csb->collectingDependencies())
+ {
+ CompilerScratch::Dependency dependency(obj_exception);
+ dependency.number = item->code;
+ csb->addDependency(dependency);
+ }
+
+ if (codeType == blr_exception_msg ||
+ (codeType == blr_exception3 && csb->csb_blr_reader.getByte() != 0))
+ {
+ node->messageExpr = PAR_parse_value(tdbb, csb);
+ }
+
+ if (codeType == blr_exception_params || codeType == blr_exception3)
+ {
+ const USHORT count = csb->csb_blr_reader.getWord();
+ node->parameters = PAR_args(tdbb, csb, count, count);
+ }
+
+ break;
+
+ default:
+ fb_assert(false);
+ break;
}
- if (type == blr_exception_params)
- {
- const USHORT count = csb->csb_blr_reader.getWord();
- node->parameters = PAR_args(tdbb, csb, count, count);
- }
- else if (type == blr_exception_msg)
- node->messageExpr = PAR_parse_value(tdbb, csb);
+ node->exception = item;
return node;
}
StmtNode* ExceptionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
+ if (exception)
+ dsqlScratch->qualifyExistingName(exception->name, obj_exception);
+
if (parameters && parameters->items.getCount() > MsgFormat::SAFEARG_MAX_ARG)
{
status_exception::raise(
@@ -5287,29 +5383,69 @@ void ExceptionNode::genBlr(DsqlCompilerScratch* dsqlScratch)
// If exception value is defined, it means we have user-defined exception message
// here, so blr_exception_msg verb should be generated.
- if (parameters)
- dsqlScratch->appendUChar(blr_exception_params);
- else if (messageExpr)
- dsqlScratch->appendUChar(blr_exception_msg);
- else if (exception->type == ExceptionItem::GDS_CODE)
- dsqlScratch->appendUChar(blr_gds_code);
- else // Otherwise go usual way, i.e. generate blr_exception.
- dsqlScratch->appendUChar(blr_exception);
-
- dsqlScratch->appendNullString(exception->name.c_str());
-
- // If exception parameters or value is defined, generate appropriate BLR verbs.
- if (parameters)
+ if (exception->type == ExceptionItem::GDS_CODE)
{
- dsqlScratch->appendUShort(parameters->items.getCount());
-
- NestConst* ptr = parameters->items.begin();
- const NestConst* end = parameters->items.end();
- while (ptr < end)
- GEN_expr(dsqlScratch, *ptr++);
+ dsqlScratch->appendUChar(blr_gds_code);
+ dsqlScratch->appendNullString(exception->name.object.c_str());
+ }
+ else
+ {
+ if (exception->name.schema != dsqlScratch->ddlSchema)
+ {
+ if (!messageExpr && !parameters)
+ {
+ dsqlScratch->appendUChar(blr_exception2);
+ dsqlScratch->appendNullString(exception->name.schema.c_str());
+ dsqlScratch->appendNullString(exception->name.object.c_str());
+ }
+ else
+ {
+ dsqlScratch->appendUChar(blr_exception3);
+ dsqlScratch->appendNullString(exception->name.schema.c_str());
+ dsqlScratch->appendNullString(exception->name.object.c_str());
+
+ if (messageExpr)
+ {
+ dsqlScratch->appendUChar(1);
+ GEN_expr(dsqlScratch, messageExpr);
+ }
+ else
+ dsqlScratch->appendUChar(0);
+
+ if (parameters)
+ {
+ dsqlScratch->appendUShort(parameters->items.getCount());
+
+ for (auto parameter : parameters->items)
+ GEN_expr(dsqlScratch, parameter);
+ }
+ else
+ dsqlScratch->appendUShort(0);
+ }
+ }
+ else
+ {
+ if (parameters)
+ dsqlScratch->appendUChar(blr_exception_params);
+ else if (messageExpr)
+ dsqlScratch->appendUChar(blr_exception_msg);
+ else // Otherwise go usual way, i.e. generate blr_exception or blr_exception2.
+ dsqlScratch->appendUChar(blr_exception);
+
+ dsqlScratch->appendNullString(exception->name.object.c_str());
+
+ // If exception parameters or value is defined, generate appropriate BLR verbs.
+ if (parameters)
+ {
+ dsqlScratch->appendUShort(parameters->items.getCount());
+
+ for (auto parameter : parameters->items)
+ GEN_expr(dsqlScratch, parameter);
+ }
+ else if (messageExpr)
+ GEN_expr(dsqlScratch, messageExpr);
+ }
}
- else if (messageExpr)
- GEN_expr(dsqlScratch, messageExpr);
}
ExceptionNode* ExceptionNode::pass1(thread_db* tdbb, CompilerScratch* csb)
@@ -5319,8 +5455,10 @@ ExceptionNode* ExceptionNode::pass1(thread_db* tdbb, CompilerScratch* csb)
if (exception)
{
- CMP_post_access(tdbb, csb, exception->secName, 0,
- SCL_usage, obj_exceptions, exception->name);
+ CMP_post_access(tdbb, csb, exception->secName.schema, 0, SCL_usage, obj_schemas,
+ QualifiedName(exception->name.schema));
+
+ CMP_post_access(tdbb, csb, exception->secName.object, 0, SCL_usage, obj_exceptions, exception->name);
}
return this;
@@ -5374,8 +5512,8 @@ void ExceptionNode::setError(thread_db* tdbb) const
ERR_punt();
}
- MetaName exName;
- MetaName relationName;
+ QualifiedName exName;
+ QualifiedName relationName;
string message;
if (messageExpr)
@@ -5399,9 +5537,10 @@ void ExceptionNode::setError(thread_db* tdbb) const
case ExceptionItem::GDS_CODE:
if (xcpCode == isc_check_constraint)
{
- MET_lookup_cnstrt_for_trigger(tdbb, exName, relationName,
+ MetaName constraintName;
+ MET_lookup_cnstrt_for_trigger(tdbb, constraintName, relationName,
request->getStatement()->triggerName);
- ERR_post(Arg::Gds(xcpCode) << Arg::Str(exName) << Arg::Str(relationName));
+ ERR_post(Arg::Gds(xcpCode) << constraintName.toQuotedString() << relationName.toQuotedString());
}
else
ERR_post(Arg::Gds(xcpCode));
@@ -5425,19 +5564,19 @@ void ExceptionNode::setError(thread_db* tdbb) const
Arg::StatusVector status;
ISC_STATUS msgCode = parameters ? isc_formatted_exception : isc_random;
- if (s && exName.hasData())
+ if (s && exName.object.hasData())
{
status << Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
- Arg::Gds(isc_random) << Arg::Str(exName) <<
+ Arg::Gds(isc_random) << exName.toQuotedString() <<
Arg::Gds(msgCode);
}
else if (s)
status << Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
Arg::Gds(msgCode);
- else if (exName.hasData())
+ else if (exName.object.hasData())
{
ERR_post(Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
- Arg::Gds(isc_random) << Arg::Str(exName));
+ Arg::Gds(isc_random) << exName.toQuotedString());
}
else
ERR_post(Arg::Gds(isc_except) << Arg::Num(xcpCode));
@@ -6087,7 +6226,7 @@ void LocalDeclarationsNode::checkUniqueFieldsNames(const LocalDeclarationsNode*
{
ERRD_post(
Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str(parameter->name));
+ Arg::Gds(isc_dsql_duplicate_spec) << parameter->name);
}
}
}
@@ -6559,7 +6698,7 @@ StmtNode* MergeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
const auto badRel = tmpCtx->ctx_relation;
- PASS1_field_unknown((badRel ? badRel->rel_name.c_str() : NULL),
+ PASS1_field_unknown((badRel ? badRel->rel_name.toQuotedString().c_str() : NULL),
tmpName, notMatched.fields[&field - fields.begin()]);
}
}
@@ -7273,6 +7412,7 @@ StmtNode* ModifyNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, bool up
NestConst relation = nodeAs(dsqlRelation);
fb_assert(relation);
+ dsqlScratch->qualifyExistingName(relation->dsqlName, obj_relation);
NestConst* ptr;
@@ -8147,10 +8287,10 @@ const StmtNode* PostEventNode::execute(thread_db* tdbb, Request* request, ExeSta
jrd_tra* transaction = request->req_transaction;
DeferredWork* work = DFW_post_work(transaction, dfw_post_event,
- EVL_expr(tdbb, request, event), 0);
+ EVL_expr(tdbb, request, event), nullptr, 0);
if (argument)
- DFW_post_work_arg(transaction, work, EVL_expr(tdbb, request, argument), 0);
+ DFW_post_work_arg(transaction, work, EVL_expr(tdbb, request, argument), nullptr, 0);
// For an autocommit transaction, events can be posted without any updates.
@@ -8387,7 +8527,7 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
{
const auto badRel = tmpCtx->ctx_relation;
- PASS1_field_unknown((badRel ? badRel->rel_name.c_str() : NULL),
+ PASS1_field_unknown((badRel ? badRel->rel_name.toQuotedString().c_str() : NULL),
tmpName, dsqlFields[&field - fields.begin()]);
}
}
@@ -8452,7 +8592,8 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
// marks it with CTX_null so all fields be resolved to NULL constant.
dsql_ctx* old_context = FB_NEW_POOL(dsqlScratch->getPool()) dsql_ctx(dsqlScratch->getPool());
*old_context = *context;
- old_context->ctx_alias = old_context->ctx_internal_alias = OLD_CONTEXT_NAME;
+ old_context->ctx_alias.add(QualifiedName(OLD_CONTEXT_NAME));
+ old_context->ctx_internal_alias.object = OLD_CONTEXT_NAME;
old_context->ctx_flags |= CTX_system | CTX_null | CTX_returning;
dsqlScratch->context->push(old_context);
@@ -8460,7 +8601,8 @@ StmtNode* StoreNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch,
dsql_ctx* new_context = FB_NEW_POOL(dsqlScratch->getPool()) dsql_ctx(dsqlScratch->getPool());
*new_context = *context;
new_context->ctx_scope_level = ++dsqlScratch->scopeLevel;
- new_context->ctx_alias = new_context->ctx_internal_alias = NEW_CONTEXT_NAME;
+ new_context->ctx_alias.add(QualifiedName(NEW_CONTEXT_NAME));
+ new_context->ctx_internal_alias.object = NEW_CONTEXT_NAME;
new_context->ctx_flags |= CTX_system | CTX_returning;
dsqlScratch->context->push(new_context);
}
@@ -8716,7 +8858,7 @@ void StoreNode::makeDefaults(thread_db* tdbb, CompilerScratch* csb)
{
ValueExprNode* value;
- if (!*ptr1 || !((*ptr1)->fld_generator_name.hasData() || (value = (*ptr1)->fld_default_value)))
+ if (!*ptr1 || !((*ptr1)->fld_generator_name.object.hasData() || (value = (*ptr1)->fld_default_value)))
continue;
CompoundStmtNode* compoundNode = nodeAs(statement.getObject());
@@ -9153,7 +9295,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
GEN_parameter(dsqlScratch, parameter);
}
- if (parameter->par_dbkey_relname.hasData() && parameter->par_context)
+ if (parameter->par_dbkey_relname.object.hasData() && parameter->par_context)
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_dbkey);
@@ -9161,7 +9303,7 @@ void SelectNode::genBlr(DsqlCompilerScratch* dsqlScratch)
GEN_parameter(dsqlScratch, parameter);
}
- if (parameter->par_rec_version_relname.hasData() && parameter->par_context)
+ if (parameter->par_rec_version_relname.object.hasData() && parameter->par_context)
{
dsqlScratch->appendUChar(blr_assignment);
dsqlScratch->appendUChar(blr_record_version);
@@ -9255,17 +9397,18 @@ static RegisterNode regSetGeneratorNode({blr_set_generator});
DmlNode* SetGeneratorNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/)
{
- MetaName name;
- csb->csb_blr_reader.getMetaName(name);
+ QualifiedName name;
+ csb->csb_blr_reader.getMetaName(name.object);
+ csb->qualifyExistingName(tdbb, name, obj_generator);
SetGeneratorNode* const node = FB_NEW_POOL(pool) SetGeneratorNode(pool, name);
bool sysGen = false;
if (!MET_load_generator(tdbb, node->generator, &sysGen))
- PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
+ PAR_error(csb, Arg::Gds(isc_gennotdef) << name.toQuotedString());
if (sysGen)
- PAR_error(csb, Arg::Gds(isc_cant_modify_sysobj) << "generator" << name);
+ PAR_error(csb, Arg::Gds(isc_cant_modify_sysobj) << "generator" << name.toQuotedString());
node->value = PAR_parse_value(tdbb, csb);
@@ -9286,8 +9429,10 @@ SetGeneratorNode* SetGeneratorNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
doPass1(tdbb, csb, value.getAddress());
- CMP_post_access(tdbb, csb, generator.secName, 0,
- SCL_usage, obj_generators, generator.name);
+ CMP_post_access(tdbb, csb, generator.secName.schema, 0, SCL_usage, obj_schemas,
+ QualifiedName(generator.name.schema));
+
+ CMP_post_access(tdbb, csb, generator.secName.object, 0, SCL_usage, obj_generators, generator.name);
return this;
}
@@ -9305,13 +9450,13 @@ const StmtNode* SetGeneratorNode::execute(thread_db* tdbb, Request* request, Exe
jrd_tra* const transaction = request->req_transaction;
DdlNode::executeDdlTrigger(tdbb, transaction, DdlNode::DTW_BEFORE,
- DDL_TRIGGER_ALTER_SEQUENCE, generator.name, NULL, *request->getStatement()->sqlText);
+ DDL_TRIGGER_ALTER_SEQUENCE, generator.name, {}, *request->getStatement()->sqlText);
dsc* const desc = EVL_expr(tdbb, request, value);
DPM_gen_id(tdbb, generator.id, true, MOV_get_int64(tdbb, desc, 0));
DdlNode::executeDdlTrigger(tdbb, transaction, DdlNode::DTW_AFTER,
- DDL_TRIGGER_ALTER_SEQUENCE, generator.name, NULL, *request->getStatement()->sqlText);
+ DDL_TRIGGER_ALTER_SEQUENCE, generator.name, {}, *request->getStatement()->sqlText);
request->req_operation = Request::req_return;
}
@@ -9770,12 +9915,13 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
const USHORT lockMode = (tblLock.lockMode & LOCK_MODE_WRITE) ?
isc_tpb_lock_write : isc_tpb_lock_read;
- for (ObjectsArray::iterator i = tblLock.tables->begin();
+ for (ObjectsArray::iterator i = tblLock.tables->begin();
i != tblLock.tables->end();
++i)
{
dsqlScratch->appendUChar(lockMode);
- dsqlScratch->appendNullString(i->c_str()); // stuff table name
+ // FIXME: schema
+ dsqlScratch->appendNullString(i->object.c_str()); // stuff table name
dsqlScratch->appendUChar(lockLevel);
}
}
@@ -10008,6 +10154,23 @@ void SetOptimizeNode::execute(thread_db* tdbb, DsqlRequest* /*request*/, jrd_tra
//--------------------
+void SetSearchPathNode::execute(thread_db* tdbb, DsqlRequest* /*request*/, jrd_tra** /*traHandle*/) const
+{
+ const auto attachment = tdbb->getAttachment();
+
+ auto newSearchPath = makeRef(
+ FB_NEW_POOL(*attachment->att_pool) AnyRef>(*attachment->att_pool));
+
+ for (const auto& schema : *schemas)
+ newSearchPath->add(schema);
+
+ attachment->att_schema_search_path = std::move(newSearchPath);
+}
+
+
+//--------------------
+
+
void SetTimeZoneNode::execute(thread_db* tdbb, DsqlRequest* request, jrd_tra** /*traHandle*/) const
{
Attachment* const attachment = tdbb->getAttachment();
@@ -10080,22 +10243,23 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
auto& pool = dsqlScratch->getPool();
+ dsqlScratch->qualifyExistingName(relation->dsqlName, obj_relation);
+
if (!dsqlScratch->isPsql())
dsqlScratch->flags |= DsqlCompilerScratch::FLAG_UPDATE_OR_INSERT;
- RelationSourceNode* target = relation;
-
const auto querySpec = FB_NEW_POOL(pool) RseNode(pool);
querySpec->dsqlExplicitJoin = true;
querySpec->dsqlFrom = FB_NEW_POOL(pool) RecSourceListNode(pool, 1);
- querySpec->dsqlFrom->items[0] = target;
+ querySpec->dsqlFrom->items[0] = relation;
querySpec->rse_plan = plan;
const auto node = FB_NEW_POOL(pool) UpdateOrInsertNode(pool);
node->returning = returning;
- const auto& relationName = nodeAs(relation)->dsqlName;
- MetaName baseName = relationName;
+ const auto& relationName = relation->dsqlName;
+
+ auto baseName = relationName;
bool needSavePoint;
@@ -10123,8 +10287,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if ((ctxRelation->rel_flags & REL_view) && matching.isEmpty())
{
- auto baseRel = METD_get_view_base(dsqlScratch->getTransaction(), dsqlScratch,
- relationName.c_str(), viewFields);
+ auto baseRel = METD_get_view_base(dsqlScratch->getTransaction(), dsqlScratch, relationName, viewFields);
// Get the base table name if there is only one.
if (baseRel)
@@ -10160,10 +10323,10 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
equalityType = blr_eql;
- METD_get_primary_key(dsqlScratch->getTransaction(), baseName.c_str(), matchingCopy);
+ METD_get_primary_key(dsqlScratch->getTransaction(), baseName, matchingCopy);
if (matchingCopy.isEmpty())
- ERRD_post(Arg::Gds(isc_primary_key_required) << baseName);
+ ERRD_post(Arg::Gds(isc_primary_key_required) << baseName.toQuotedString());
}
// Build a boolean to use in the UPDATE dsqlScratch.
@@ -10240,7 +10403,7 @@ StmtNode* UpdateOrInsertNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
if (matching.hasData())
ERRD_post(Arg::Gds(isc_upd_ins_doesnt_match_matching));
else
- ERRD_post(Arg::Gds(isc_upd_ins_doesnt_match_pk) << baseName);
+ ERRD_post(Arg::Gds(isc_upd_ins_doesnt_match_pk) << baseName.toQuotedString());
}
// build the UPDATE node
@@ -10518,13 +10681,13 @@ static dsql_par* dsqlFindDbKey(const DsqlDmlStatement* statement, const Relation
const dsql_msg* message = statement->getReceiveMsg();
dsql_par* candidate = NULL;
- const MetaName& relName = relation_name->dsqlName;
+ const auto& relName = relation_name->dsqlName;
for (FB_SIZE_T i = 0; i < message->msg_parameters.getCount(); ++i)
{
dsql_par* parameter = message->msg_parameters[i];
- if (parameter->par_dbkey_relname.hasData() && parameter->par_dbkey_relname == relName)
+ if (parameter->par_dbkey_relname.object.hasData() && parameter->par_dbkey_relname == relName)
{
if (candidate)
return NULL;
@@ -10541,13 +10704,13 @@ static dsql_par* dsqlFindRecordVersion(const DsqlDmlStatement* statement, const
{
const dsql_msg* message = statement->getReceiveMsg();
dsql_par* candidate = NULL;
- const MetaName& relName = relation_name->dsqlName;
+ const auto& relName = relation_name->dsqlName;
for (FB_SIZE_T i = 0; i < message->msg_parameters.getCount(); ++i)
{
dsql_par* parameter = message->msg_parameters[i];
- if (parameter->par_rec_version_relname.hasData() &&
+ if (parameter->par_rec_version_relname.object.hasData() &&
parameter->par_rec_version_relname == relName)
{
if (candidate)
@@ -10782,7 +10945,7 @@ static void dsqlFieldAppearsOnce(const Array >& values,
if (name1 == name2)
{
- string str = field1->dsqlContext->ctx_relation->rel_name.c_str();
+ string str = field1->dsqlContext->ctx_relation->rel_name.toQuotedString();
str += ".";
str += name1.c_str();
@@ -10819,7 +10982,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
{
DEV_BLKCHK(dsqlScratch, dsql_type_req);
- const MetaName& relName = relation_name->dsqlName;
+ const auto& relName = relation_name->dsqlName;
// this function must throw an error if no cursor was found
const DeclareCursorNode* node = PASS1_cursor_name(dsqlScratch, cursor,
@@ -10853,8 +11016,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
Arg::Gds(isc_dsql_cursor_err) <<
- Arg::Gds(isc_dsql_cursor_rel_ambiguous) << Arg::Str(relName) <<
- cursor);
+ Arg::Gds(isc_dsql_cursor_rel_ambiguous) << relName.toQuotedString() << cursor);
}
else
context = candidate;
@@ -10875,7 +11037,7 @@ static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const M
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
Arg::Gds(isc_dsql_cursor_err) <<
- Arg::Gds(isc_dsql_cursor_rel_not_found) << Arg::Str(relName) << cursor);
+ Arg::Gds(isc_dsql_cursor_rel_not_found) << relName.toQuotedString() << cursor);
}
return context;
@@ -11206,8 +11368,8 @@ static ReturningClause* dsqlProcessReturning(DsqlCompilerScratch* dsqlScratch, d
if (!input)
return nullptr;
- AutoSaveRestore autoOldAlias(&oldContext->ctx_alias);
- AutoSaveRestore autoOldInternalAlias(&oldContext->ctx_internal_alias);
+ AutoSaveRestore> autoOldAlias(&oldContext->ctx_alias);
+ AutoSaveRestore autoOldInternalAlias(&oldContext->ctx_internal_alias);
AutoSetRestore autoFlags(&oldContext->ctx_flags, oldContext->ctx_flags | CTX_system | CTX_returning);
AutoSetRestore autoScopeLevel(&dsqlScratch->scopeLevel, dsqlScratch->scopeLevel + 1);
@@ -11242,9 +11404,13 @@ static ReturningClause* dsqlProcessReturning(DsqlCompilerScratch* dsqlScratch, d
newContext->ctx_flags |= CTX_null;
}
- oldContext->ctx_alias = oldContext->ctx_internal_alias = OLD_CONTEXT_NAME;
+ oldContext->ctx_alias.clear();
+ oldContext->ctx_alias.add().object = OLD_CONTEXT_NAME;
+ oldContext->ctx_internal_alias.object = OLD_CONTEXT_NAME;
- newContext->ctx_alias = newContext->ctx_internal_alias = NEW_CONTEXT_NAME;
+ newContext->ctx_alias.clear();
+ newContext->ctx_alias.add().object = NEW_CONTEXT_NAME;
+ newContext->ctx_internal_alias.object = NEW_CONTEXT_NAME;
newContext->ctx_flags |= CTX_returning;
newContext->ctx_scope_level = dsqlScratch->scopeLevel;
dsqlScratch->context->push(newContext);
@@ -11304,8 +11470,8 @@ static void dsqlSetParameterName(DsqlCompilerScratch* dsqlScratch, ExprNode* exp
{
ParameterNode* paramNode = nodeAs(exprNode);
dsql_par* parameter = paramNode->dsqlParameter;
- parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
- parameter->par_rel_name = relation->rel_name.c_str();
+ parameter->par_name = fieldNode->dsqlField->fld_name;
+ parameter->par_rel_name = relation->rel_name;
break;
}
}
@@ -11525,7 +11691,12 @@ static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jr
// unless this is an internal request, check access permission
- CMP_post_access(tdbb, csb, relation->rel_security_name, (view ? view->rel_id : 0),
+ const SLONG ssRelationId = view ? view->rel_id : 0;
+
+ CMP_post_access(tdbb, csb, relation->rel_security_name.schema, ssRelationId,
+ SCL_usage, obj_schemas, QualifiedName(relation->rel_name.schema));
+
+ CMP_post_access(tdbb, csb, relation->rel_security_name.object, ssRelationId,
priv, obj_relations, relation->rel_name);
// ensure that the view is set for the input streams,
@@ -11575,7 +11746,7 @@ static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jr
if (rse->rse_relations.getCount() != 1 || rse->rse_projection || rse->rse_sorted ||
rse->rse_relations[0]->getType() != RelationSourceNode::TYPE)
{
- ERR_post(Arg::Gds(isc_read_only_view) << Arg::Str(relation->rel_name));
+ ERR_post(Arg::Gds(isc_read_only_view) << relation->rel_name.toQuotedString());
}
// for an updateable view, return the view source
@@ -11739,7 +11910,7 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (nodeIs(assignFrom))
compoundNode->statements.remove(i);
}
- else if (relation->rel_view_rse && fld->fld_source_rel_field.first.hasData())
+ else if (relation->rel_view_rse && fld->fld_source_rel_field.first.object.hasData())
{
relation = MET_lookup_relation(tdbb, fld->fld_source_rel_field.first);
@@ -11763,15 +11934,15 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
if (insertOverride->has_value())
{
if (!identityType.has_value())
- ERR_post(Arg::Gds(isc_overriding_without_identity) << relation->rel_name);
+ ERR_post(Arg::Gds(isc_overriding_without_identity) << relation->rel_name.toQuotedString());
if (identityType == IDENT_TYPE_BY_DEFAULT && *insertOverride == OverrideClause::SYSTEM_VALUE)
- ERR_post(Arg::Gds(isc_overriding_system_invalid) << relation->rel_name);
+ ERR_post(Arg::Gds(isc_overriding_system_invalid) << relation->rel_name.toQuotedString());
}
else
{
if (identityType == IDENT_TYPE_ALWAYS)
- ERR_post(Arg::Gds(isc_overriding_missing) << relation->rel_name);
+ ERR_post(Arg::Gds(isc_overriding_missing) << relation->rel_name.toQuotedString());
}
}
@@ -11828,8 +11999,8 @@ static void validateExpressions(thread_db* tdbb, const Array& vali
if (vector && fieldNode->fieldId < vector->count() &&
(field = (*vector)[fieldNode->fieldId]))
{
- if (!relation->rel_name.isEmpty())
- name.printf("\"%s\".\"%s\"", relation->rel_name.c_str(), field->fld_name.c_str());
+ if (relation->rel_name.object.hasData())
+ name.printf("%s.\"%s\"", relation->rel_name.toQuotedString().c_str(), field->fld_name.c_str());
else
name.printf("\"%s\"", field->fld_name.c_str());
}
diff --git a/src/dsql/StmtNodes.h b/src/dsql/StmtNodes.h
index c6cede470d..a19bd464b1 100644
--- a/src/dsql/StmtNodes.h
+++ b/src/dsql/StmtNodes.h
@@ -97,11 +97,8 @@ public:
public:
Type type;
SLONG code;
- // ASF: There are some inconsistencies in the type of 'name'. Metanames have maximum of 31 chars,
- // while there are system exceptions with 32 chars. The parser always expects metanames, but
- // I'm following the legacy code and making this a string.
- Firebird::string name;
- MetaName secName;
+ QualifiedName name;
+ QualifiedName secName;
};
typedef Firebird::ObjectsArray ExceptionArray;
@@ -589,7 +586,7 @@ class ExecProcedureNode final : public TypedNode* aDsqlInputArgNames = nullptr)
: TypedNode(pool),
@@ -802,7 +799,7 @@ public:
class ExceptionNode final : public TypedNode
{
public:
- ExceptionNode(MemoryPool& pool, const MetaName& name,
+ ExceptionNode(MemoryPool& pool, const QualifiedName& name,
ValueExprNode* aMessageExpr = NULL, ValueListNode* aParameters = NULL)
: TypedNode(pool),
messageExpr(aMessageExpr),
@@ -810,7 +807,7 @@ public:
{
exception = FB_NEW_POOL(pool) ExceptionItem(pool);
exception->type = ExceptionItem::XCP_CODE;
- exception->name = name.c_str();
+ exception->name = name;
}
explicit ExceptionNode(MemoryPool& pool)
@@ -1386,7 +1383,7 @@ public:
class SetGeneratorNode final : public TypedNode
{
public:
- SetGeneratorNode(MemoryPool& pool, const MetaName& name, ValueExprNode* aValue = NULL)
+ SetGeneratorNode(MemoryPool& pool, const QualifiedName& name, ValueExprNode* aValue = NULL)
: TypedNode(pool),
generator(pool, name), value(aValue)
{
@@ -1561,7 +1558,7 @@ class SetTransactionNode : public TransactionNode
public:
struct RestrictionOption : Firebird::PermanentStorage
{
- RestrictionOption(MemoryPool& p, Firebird::ObjectsArray* aTables,
+ RestrictionOption(MemoryPool& p, Firebird::ObjectsArray* aTables,
unsigned aLockMode)
: PermanentStorage(p),
tables(aTables),
@@ -1569,7 +1566,7 @@ public:
{
}
- Firebird::ObjectsArray* tables;
+ Firebird::ObjectsArray* tables;
unsigned lockMode;
};
@@ -1908,6 +1905,32 @@ public:
};
+class SetSearchPathNode : public SessionManagementNode
+{
+public:
+ SetSearchPathNode(MemoryPool& pool, Firebird::ObjectsArray* aSchemas)
+ : SessionManagementNode(pool),
+ schemas(aSchemas)
+ {
+ }
+
+public:
+ virtual Firebird::string internalPrint(NodePrinter& printer) const
+ {
+ SessionManagementNode::internalPrint(printer);
+
+ NODE_PRINT(printer, schemas);
+
+ return "SetSearchPathNode";
+ }
+
+ virtual void execute(thread_db* tdbb, DsqlRequest* request, jrd_tra** traHandle) const;
+
+public:
+ NestConst> schemas;
+};
+
+
class SetTimeZoneNode : public SessionManagementNode
{
public:
diff --git a/src/dsql/ddl.cpp b/src/dsql/ddl.cpp
index 761a13913b..4c9487fe68 100644
--- a/src/dsql/ddl.cpp
+++ b/src/dsql/ddl.cpp
@@ -125,7 +125,7 @@ bool DDL_ids(const DsqlCompilerScratch* scratch)
void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
- const MetaName& collation_name, bool modifying)
+ QualifiedName& collation_name, bool modifying)
{
/**************************************
*
@@ -152,17 +152,18 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
*
**************************************/
- if (field->typeOfName.hasData())
+ if (field->typeOfName.object.hasData())
{
- if (field->typeOfTable.hasData())
+ if (field->typeOfTable.object.hasData())
{
- dsql_rel* relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch,
- field->typeOfTable.c_str());
+ dsqlScratch->qualifyExistingName(field->typeOfTable, obj_relation);
+
+ dsql_rel* relation = METD_get_relation(dsqlScratch->getTransaction(), dsqlScratch, field->typeOfTable);
const dsql_fld* fld = NULL;
if (relation)
{
- const MetaName fieldName(field->typeOfName);
+ const MetaName fieldName(field->typeOfName.object);
for (fld = relation->rel_fields; fld; fld = fld->fld_next)
{
@@ -188,16 +189,18 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
{
// column @1 does not exist in table/view @2
post_607(Arg::Gds(isc_dyn_column_does_not_exist) <<
- Arg::Str(field->typeOfName) <<
- field->typeOfTable);
+ field->typeOfName.toQuotedString() <<
+ field->typeOfTable.toQuotedString());
}
}
else
{
+ dsqlScratch->qualifyExistingName(field->typeOfName, obj_field);
+
if (!METD_get_domain(dsqlScratch->getTransaction(), field, field->typeOfName))
{
// Specified domain or source field does not exist
- post_607(Arg::Gds(isc_dsql_domain_not_found) << Arg::Str(field->typeOfName));
+ post_607(Arg::Gds(isc_dsql_domain_not_found) << field->typeOfName.toQuotedString());
}
}
@@ -217,7 +220,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
if ((field->dtype > dtype_any_text) && field->dtype != dtype_blob)
{
- if (field->charSet.hasData() || collation_name.hasData() || (field->flags & FLD_national))
+ if (field->charSet.object.hasData() || collation_name.object.hasData() || (field->flags & FLD_national))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) << Arg::Gds(isc_collation_requires_text));
@@ -236,7 +239,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) <<
Arg::Gds(isc_dsql_blob_type_unknown) <<
- Arg::Str(field->subTypeName));
+ field->subTypeName);
}
field->subType = blob_sub_type;
}
@@ -248,17 +251,17 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
Arg::Gds(isc_subtype_for_internal_use));
}
- if (field->charSet.hasData() && (field->subType == isc_blob_untyped))
+ if (field->charSet.object.hasData() && (field->subType == isc_blob_untyped))
field->subType = isc_blob_text;
- if (field->charSet.hasData() && (field->subType != isc_blob_text))
+ if (field->charSet.object.hasData() && (field->subType != isc_blob_text))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) <<
Arg::Gds(isc_collation_requires_text));
}
- if (collation_name.hasData() && (field->subType != isc_blob_text))
+ if (collation_name.object.hasData() && (field->subType != isc_blob_text))
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) <<
@@ -269,14 +272,14 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
return;
}
- if (field->charSetId.has_value() && collation_name.isEmpty())
+ if (field->charSetId.has_value() && collation_name.object.isEmpty())
{
// This field has already been resolved once, and the collation
// hasn't changed. Therefore, no need to do it again.
return;
}
- if (modifying && field->charSet.isEmpty() && field->collate.isEmpty())
+ if (modifying && field->charSet.object.isEmpty() && field->collate.object.isEmpty())
{
// Use charset and collation from already existing field if any
const dsql_fld* afield = field->fld_next;
@@ -311,15 +314,17 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
}
}
- if (!modifying && !(field->charSet.hasData() || field->charSetId.has_value() || // set if a domain
+ if (!modifying && !(field->charSet.object.hasData() || field->charSetId.has_value() || // set if a domain
(field->flags & FLD_national)))
{
// Attach the database default character set to the new field, if not otherwise specified
- MetaName defaultCharSet;
+ QualifiedName defaultCharSet;
- if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL)
- defaultCharSet = METD_get_default_charset(dsqlScratch->getTransaction());
+ if (dsqlScratch->ddlSchema.hasData())
+ defaultCharSet = METD_get_schema_charset(dsqlScratch->getTransaction(), dsqlScratch->ddlSchema);
+ else if (dsqlScratch->flags & DsqlCompilerScratch::FLAG_DDL)
+ defaultCharSet = METD_get_database_charset(dsqlScratch->getTransaction());
else
{
USHORT charSet = dsqlScratch->getAttachment()->dbb_attachment->att_charset;
@@ -327,7 +332,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
defaultCharSet = METD_get_charset_name(dsqlScratch->getTransaction(), charSet);
}
- if (defaultCharSet.hasData())
+ if (defaultCharSet.object.hasData())
field->charSet = defaultCharSet;
else
{
@@ -336,25 +341,27 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
assign_field_length(field, 1);
field->textType = 0;
- if (collation_name.isEmpty())
+ if (collation_name.object.isEmpty())
return;
}
}
- MetaName charset_name;
+ QualifiedName charset_name;
if (field->flags & FLD_national)
- charset_name = NATIONAL_CHARACTER_SET;
- else if (field->charSet.hasData())
+ charset_name = QualifiedName(NATIONAL_CHARACTER_SET, SYSTEM_SCHEMA);
+ else if (field->charSet.object.hasData())
+ {
+ dsqlScratch->qualifyExistingName(field->charSet, obj_charset);
charset_name = field->charSet;
+ }
// Find an intlsym for any specified character set name & collation name
const dsql_intlsym* resolved_type = NULL;
- if (charset_name.hasData())
+ if (charset_name.object.hasData())
{
- const dsql_intlsym* resolved_charset =
- METD_get_charset(dsqlScratch->getTransaction(), (USHORT) charset_name.length(), charset_name.c_str());
+ const dsql_intlsym* resolved_charset = METD_get_charset(dsqlScratch->getTransaction(), charset_name);
// Error code -204 (IBM's DB2 manual) is close enough
if (!resolved_charset)
@@ -362,23 +369,25 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
// specified character set not found
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) <<
- Arg::Gds(isc_charset_not_found) << Arg::Str(charset_name));
+ Arg::Gds(isc_charset_not_found) << charset_name.toQuotedString());
}
field->charSetId = resolved_charset->intlsym_charset_id;
resolved_type = resolved_charset;
}
- if (collation_name.hasData())
+ if (collation_name.object.hasData())
{
+ dsqlScratch->qualifyExistingName(collation_name, obj_collation);
+
const dsql_intlsym* resolved_collation = METD_get_collation(dsqlScratch->getTransaction(),
collation_name, field->charSetId.value_or(CS_NONE));
if (!resolved_collation)
{
- MetaName charSetName;
+ QualifiedName charSetName;
- if (charset_name.hasData())
+ if (charset_name.object.hasData())
charSetName = charset_name;
else
{
@@ -389,7 +398,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
// Specified collation not found
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
///Arg::Gds(isc_dsql_datatype_err) << // (too large status vector)
- Arg::Gds(isc_collation_not_found) << collation_name << charSetName);
+ Arg::Gds(isc_collation_not_found) << collation_name.toQuotedString() << charSetName.toQuotedString());
}
// If both specified, must be for same character set
@@ -402,7 +411,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
Arg::Gds(isc_dsql_datatype_err) <<
- Arg::Gds(isc_collation_not_for_charset) << collation_name);
+ Arg::Gds(isc_collation_not_for_charset) << collation_name.toQuotedString());
}
field->explicitCollation = true;
diff --git a/src/dsql/ddl_proto.h b/src/dsql/ddl_proto.h
index 8b1fae8c2d..f67187cdfa 100644
--- a/src/dsql/ddl_proto.h
+++ b/src/dsql/ddl_proto.h
@@ -68,7 +68,7 @@ const USHORT blr_dtypes[] = {
};
bool DDL_ids(const Jrd::DsqlCompilerScratch*);
-void DDL_resolve_intl_type(Jrd::DsqlCompilerScratch*, Jrd::dsql_fld*, const Jrd::MetaName&,
+void DDL_resolve_intl_type(Jrd::DsqlCompilerScratch*, Jrd::dsql_fld*, Jrd::QualifiedName&,
bool = false);
#endif // DSQL_DDL_PROTO_H
diff --git a/src/dsql/dsql.cpp b/src/dsql/dsql.cpp
index a6b9550662..c07bfd8ea5 100644
--- a/src/dsql/dsql.cpp
+++ b/src/dsql/dsql.cpp
@@ -121,6 +121,7 @@ dsql_dbb::dsql_dbb(MemoryPool& p, Attachment* attachment)
dbb_charsets_by_id(p),
dbb_cursors(p),
dbb_pool(p),
+ dbb_schemas_dfl_charset(p),
dbb_dfl_charset(p)
{
dbb_attachment = attachment;
@@ -132,6 +133,13 @@ dsql_dbb::~dsql_dbb()
}
+void dsql_fld::resolve(DsqlCompilerScratch* dsqlScratch, bool modifying)
+{
+ dsqlScratch->qualifyExistingName(collate, obj_collation);
+ DDL_resolve_intl_type(dsqlScratch, this, collate, modifying);
+}
+
+
// Execute a dynamic SQL statement.
void DSQL_execute(thread_db* tdbb,
jrd_tra** tra_handle,
@@ -711,15 +719,15 @@ string IntlString::toUtf8(jrd_tra* transaction) const
{
CHARSET_ID id = CS_dynamic;
- if (charset.hasData())
+ if (charset.object.hasData())
{
- const dsql_intlsym* resolved = METD_get_charset(transaction, charset.length(), charset.c_str());
+ const dsql_intlsym* resolved = METD_get_charset(transaction, charset);
if (!resolved)
{
// character set name is not defined
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
- Arg::Gds(isc_charset_not_found) << charset);
+ Arg::Gds(isc_charset_not_found) << charset.toQuotedString());
}
id = resolved->intlsym_charset_id;
@@ -1190,6 +1198,7 @@ static UCHAR* var_info(const dsql_msg* message,
for (const UCHAR* describe = items; describe < end_describe;)
{
USHORT length;
+ string str;
MetaName name;
const UCHAR* buffer = buf;
UCHAR item = *describe++;
@@ -1235,10 +1244,21 @@ static UCHAR* var_info(const dsql_msg* message,
length = 0;
break;
- case isc_info_sql_relation:
- if (param->par_rel_name.hasData())
+ case isc_info_sql_relation_schema:
+ if (param->par_rel_name.schema.hasData())
{
- name = attachment->nameToUserCharSet(tdbb, param->par_rel_name);
+ name = attachment->nameToUserCharSet(tdbb, param->par_rel_name.schema);
+ length = name.length();
+ buffer = reinterpret_cast(name.c_str());
+ }
+ else
+ length = 0;
+ break;
+
+ case isc_info_sql_relation:
+ if (param->par_rel_name.object.hasData())
+ {
+ name = attachment->nameToUserCharSet(tdbb, param->par_rel_name.object);
length = name.length();
buffer = reinterpret_cast(name.c_str());
}
@@ -1260,9 +1280,9 @@ static UCHAR* var_info(const dsql_msg* message,
case isc_info_sql_relation_alias:
if (param->par_rel_alias.hasData())
{
- name = attachment->nameToUserCharSet(tdbb, param->par_rel_alias);
- length = name.length();
- buffer = reinterpret_cast(name.c_str());
+ str = attachment->stringToUserCharSet(tdbb, param->par_rel_alias);
+ length = str.length();
+ buffer = reinterpret_cast(str.c_str());
}
else
length = 0;
diff --git a/src/dsql/dsql.h b/src/dsql/dsql.h
index 422e36c396..ecbeb74735 100644
--- a/src/dsql/dsql.h
+++ b/src/dsql/dsql.h
@@ -34,6 +34,7 @@
#ifndef DSQL_DSQL_H
#define DSQL_DSQL_H
+#include
#include "../common/classes/array.h"
#include "../common/classes/fb_atomic.h"
#include "../common/classes/GenericMap.h"
@@ -116,18 +117,19 @@ namespace Jrd {
class dsql_dbb : public pool_alloc
{
public:
- Firebird::LeftPooledMap dbb_relations; // known relations in database
+ Firebird::LeftPooledMap dbb_relations; // known relations in database
Firebird::LeftPooledMap