mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:40:38 +01:00
Improvement CORE-5704 : Avoid UPDATE of RDB$DATABASE by ALTER DATABASE statement when possible
This commit is contained in:
parent
dc2a7e5708
commit
62735f4cf8
@ -48,6 +48,7 @@
|
||||
#include "../jrd/exe_proto.h"
|
||||
#include "../jrd/intl_proto.h"
|
||||
#include "../common/isc_f_proto.h"
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/scl_proto.h"
|
||||
#include "../jrd/vio_proto.h"
|
||||
@ -11959,34 +11960,65 @@ bool AlterDatabaseNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||
jrd_tra* transaction)
|
||||
{
|
||||
// Take a LCK_alter_database lock to prevent altering of the database from
|
||||
// parallel transactions
|
||||
|
||||
if (!transaction->tra_alter_db_lock)
|
||||
{
|
||||
Lock* lock = FB_NEW_RPT(*transaction->tra_pool, 0) Lock(tdbb, 0, LCK_alter_database);
|
||||
lock->lck_data = transaction->tra_number;
|
||||
if (LCK_lock(tdbb, lock, LCK_write, transaction->getLockWait()))
|
||||
transaction->tra_alter_db_lock = lock;
|
||||
else
|
||||
{
|
||||
const TraNumber conflict_trans = LCK_read_data(tdbb, lock);
|
||||
delete lock;
|
||||
|
||||
// msg 297: Concurrent ALTER DATABASE is not supported
|
||||
Arg::PrivateDyn status(297);
|
||||
|
||||
if (conflict_trans)
|
||||
status << Arg::Gds(isc_concurrent_transaction) << Arg::Num(conflict_trans);
|
||||
|
||||
status_exception::raise(status);
|
||||
}
|
||||
}
|
||||
|
||||
// run all statements under savepoint control
|
||||
AutoSavePoint savePoint(tdbb, transaction);
|
||||
|
||||
Attachment* const attachment = transaction->tra_attachment;
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
if (clauses & CLAUSE_DROP_DIFFERENCE)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_DROP_DIFFERENCE);
|
||||
|
||||
SLONG dbAlloc = PageSpace::maxAlloc(tdbb->getDatabase());
|
||||
SLONG start = create ? createLength + 1 : 0;
|
||||
AutoCacheRequest request(tdbb, drq_m_database, DYN_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
DBB IN RDB$DATABASE
|
||||
for (NestConst<DbFileClause>* i = files.begin(); i != files.end(); ++i)
|
||||
{
|
||||
MODIFY DBB USING
|
||||
if (clauses & CLAUSE_DROP_DIFFERENCE)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_DROP_DIFFERENCE);
|
||||
DbFileClause* file = *i;
|
||||
|
||||
for (NestConst<DbFileClause>* i = files.begin(); i != files.end(); ++i)
|
||||
{
|
||||
DbFileClause* file = *i;
|
||||
start = MAX(start, file->start);
|
||||
defineFile(tdbb, transaction, 0, false, false, dbAlloc,
|
||||
file->name.c_str(), start, file->length);
|
||||
start += file->length;
|
||||
}
|
||||
|
||||
start = MAX(start, file->start);
|
||||
defineFile(tdbb, transaction, 0, false, false, dbAlloc,
|
||||
file->name.c_str(), start, file->length);
|
||||
start += file->length;
|
||||
}
|
||||
if (differenceFile.hasData())
|
||||
defineDifference(tdbb, transaction, differenceFile.c_str());
|
||||
|
||||
if (differenceFile.hasData())
|
||||
defineDifference(tdbb, transaction, differenceFile.c_str());
|
||||
if (clauses & CLAUSE_BEGIN_BACKUP)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_BEGIN_BACKUP);
|
||||
|
||||
if (clauses & CLAUSE_END_BACKUP)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_END_BACKUP);
|
||||
|
||||
if (setDefaultCharSet.hasData() || setDefaultCollation.hasData() || linger >= 0 ||
|
||||
ssDefiner.specified)
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_m_database, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
DBB IN RDB$DATABASE
|
||||
{
|
||||
MODIFY DBB USING
|
||||
|
||||
if (setDefaultCharSet.hasData())
|
||||
{
|
||||
@ -12000,6 +12032,7 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
|
||||
DBB.RDB$CHARACTER_SET_NAME.NULL = FALSE;
|
||||
strcpy(DBB.RDB$CHARACTER_SET_NAME, setDefaultCharSet.c_str());
|
||||
|
||||
dsql_dbb* dbb = transaction->getDsqlAttachment();
|
||||
dbb->dbb_dfl_charset = ""; // reset in the cache
|
||||
}
|
||||
|
||||
@ -12021,17 +12054,12 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
|
||||
DBB.RDB$SQL_SECURITY = ssDefiner.value ? FB_TRUE : FB_FALSE;
|
||||
}
|
||||
|
||||
if (clauses & CLAUSE_BEGIN_BACKUP)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_BEGIN_BACKUP);
|
||||
|
||||
if (clauses & CLAUSE_END_BACKUP)
|
||||
changeBackupMode(tdbb, transaction, CLAUSE_END_BACKUP);
|
||||
END_MODIFY
|
||||
END_MODIFY
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
END_FOR
|
||||
|
||||
// Allow update above to work as a lock, preventing altering of the database from parallel transactions
|
||||
// Moreover, it should load crypt plugin if it (by a miracle) wasn't already loaded yet
|
||||
// Load crypt plugin if it (by a miracle) wasn't already loaded yet
|
||||
if (clauses & CLAUSE_CRYPT)
|
||||
{
|
||||
Database* const db = tdbb->getDatabase();
|
||||
|
@ -573,6 +573,7 @@ static lck_owner_t get_owner_type(enum lck_t lock_type)
|
||||
case LCK_btr_dont_gc:
|
||||
case LCK_rel_gc:
|
||||
case LCK_record_gc:
|
||||
case LCK_alter_database:
|
||||
owner_type = LCK_OWNER_attachment;
|
||||
break;
|
||||
|
||||
|
@ -70,7 +70,8 @@ enum lck_t {
|
||||
LCK_rel_rescan, // Relation forced rescan lock
|
||||
LCK_crypt, // Crypt lock for single crypt thread
|
||||
LCK_crypt_status, // Notifies about changed database encryption status
|
||||
LCK_record_gc // Record-level GC lock
|
||||
LCK_record_gc, // Record-level GC lock
|
||||
LCK_alter_database // ALTER DATABASE lock
|
||||
};
|
||||
|
||||
// Lock owner types
|
||||
|
@ -1247,6 +1247,9 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
|
||||
|
||||
// Release the locks associated with the transaction
|
||||
|
||||
if (transaction->tra_alter_db_lock)
|
||||
LCK_release(tdbb, transaction->tra_alter_db_lock);
|
||||
|
||||
vec<Lock*>* vector = transaction->tra_relation_locks;
|
||||
if (vector)
|
||||
{
|
||||
|
@ -259,6 +259,7 @@ public:
|
||||
BlobIndexTree* tra_blobs; // pointer to actual list of active blobs
|
||||
ArrayField* tra_arrays; // Linked list of active arrays
|
||||
Lock* tra_lock; // lock for transaction
|
||||
Lock* tra_alter_db_lock; // lock for ALTER DATABASE statement(s)
|
||||
vec<Lock*>* tra_relation_locks; // locks for relations
|
||||
TransactionBitmap* tra_commit_sub_trans; // committed sub-transactions
|
||||
Savepoint* tra_save_point; // list of savepoints
|
||||
|
@ -6,7 +6,7 @@ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUM
|
||||
('2015-01-07 18:01:51', 'GFIX', 3, 134)
|
||||
('1996-11-07 13:39:40', 'GPRE', 4, 1)
|
||||
('2017-02-05 20:37:00', 'DSQL', 7, 41)
|
||||
('2016-12-27 12:30:00', 'DYN', 8, 297)
|
||||
('2018-01-08 20:22:00', 'DYN', 8, 298)
|
||||
('1996-11-07 13:39:40', 'INSTALL', 10, 1)
|
||||
('1996-11-07 13:38:41', 'TEST', 11, 4)
|
||||
('2015-07-23 14:20:00', 'GBAK', 12, 370)
|
||||
|
@ -2071,6 +2071,7 @@ COMMIT WORK;
|
||||
(NULL, 'CreateAlterRoleNode::execute', 'DdlNodes.epp', NULL, 8, 294, NULL, 'Access to SYSTEM PRIVILEGES in ROLES denied to @1', NULL, NULL);
|
||||
(NULL, 'grant/revoke', 'DdlNode.epp', NULL, 8, 295, NULL, 'Only @1, DB owner @2 or user with privilege USE_GRANTED_BY_CLAUSE can use GRANTED BY clause', NULL, NULL);
|
||||
('dyn_cant_use_zero_inc_ident', NULL, 'DdlNodes.epp', NULL, 8, 296, NULL, 'INCREMENT BY 0 is an illegal option for identity column @1 of table @2', NULL, NULL);
|
||||
('dyn_concur_alter_database', 'AlterDatabaseNode::execute', 'DdlNodes.epp', NULL, 8, 297, NULL, 'Concurrent ALTER DATABASE is not supported', NULL, NULL);
|
||||
COMMIT WORK;
|
||||
-- TEST
|
||||
(NULL, 'main', 'test.c', NULL, 11, 0, NULL, 'This is a modified text message', NULL, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user