Skip to content

Commit 46b6340

Browse files
committed
Fix transaction table reservation.
1 parent d68696a commit 46b6340

File tree

5 files changed

+86
-12
lines changed

5 files changed

+86
-12
lines changed

src/common/classes/ClumpletReader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,11 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
292292
case Tpb:
293293
switch (tag)
294294
{
295-
case isc_tpb_lock_write:
296-
case isc_tpb_lock_read:
295+
case isc_tpb_lock_write:
296+
case isc_tpb_lock_read:
297297
case isc_tpb_lock_timeout:
298298
case isc_tpb_at_snapshot_number:
299+
case isc_tpb_lock_table_schema:
299300
return TraditionalDpb;
300301
}
301302
return SingleTpb;

src/dsql/StmtNodes.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9873,6 +9873,9 @@ void SetTransactionNode::execute(thread_db* tdbb, DsqlRequest* request, jrd_tra*
98739873
void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
98749874
const RestrictionOption& tblLock, USHORT lockLevel)
98759875
{
9876+
const auto tdbb = JRD_get_thread_data();
9877+
const auto attachment = dsqlScratch->getAttachment()->dbb_attachment;
9878+
98769879
if (tblLock.tables->isEmpty())
98779880
return;
98789881

@@ -9884,11 +9887,19 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
98849887
const USHORT lockMode = (tblLock.lockMode & LOCK_MODE_WRITE) ?
98859888
isc_tpb_lock_write : isc_tpb_lock_read;
98869889

9887-
for (const auto& tableName : *tblLock.tables)
9890+
for (auto& tableName : *tblLock.tables)
98889891
{
98899892
dsqlScratch->appendUChar(lockMode);
9890-
// FIXME: schema
9891-
dsqlScratch->appendNullString(tableName.object.c_str()); // stuff table name
9893+
dsqlScratch->appendNullString(attachment->nameToUserCharSet(tdbb, tableName.object).c_str());
9894+
9895+
dsqlScratch->qualifyExistingName(tableName, obj_relation);
9896+
9897+
if (tableName.schema.hasData())
9898+
{
9899+
dsqlScratch->appendUChar(isc_tpb_lock_table_schema);
9900+
dsqlScratch->appendNullString(attachment->nameToUserCharSet(tdbb, tableName.schema).c_str());
9901+
}
9902+
98929903
dsqlScratch->appendUChar(lockLevel);
98939904
}
98949905
}

src/include/firebird/impl/consts_pub.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@
274274
#define isc_tpb_read_consistency 22
275275
#define isc_tpb_at_snapshot_number 23
276276
#define isc_tpb_auto_release_temp_blobid 24
277+
#define isc_tpb_lock_table_schema 25
277278

278279

279280
/************************/

src/include/gen/Firebird.pas

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4189,6 +4189,7 @@ IProfilerStatsImpl = class(IProfilerStats)
41894189
isc_tpb_read_consistency = byte(22);
41904190
isc_tpb_at_snapshot_number = byte(23);
41914191
isc_tpb_auto_release_temp_blobid = byte(24);
4192+
isc_tpb_lock_table_schema = byte(25);
41924193
isc_bpb_version1 = byte(1);
41934194
isc_bpb_source_type = byte(1);
41944195
isc_bpb_target_type = byte(2);

src/jrd/tra.cpp

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3162,6 +3162,11 @@ static void transaction_options(thread_db* tdbb,
31623162
transaction->tra_flags |= TRA_auto_release_temp_blobid;
31633163
break;
31643164

3165+
case isc_tpb_lock_table_schema:
3166+
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
3167+
Arg::Gds(isc_tpb_reserv_before_table) << Arg::Str("isc_tpb_lock_table_schema"));
3168+
break;
3169+
31653170
case isc_tpb_lock_write:
31663171
// Cannot set a R/W table reservation if the whole txn is R/O.
31673172
if (read_only.asBool())
@@ -3170,9 +3175,10 @@ static void transaction_options(thread_db* tdbb,
31703175
Arg::Gds(isc_tpb_writelock_after_readtxn));
31713176
}
31723177
anylock_write = true;
3173-
// fall into
3178+
[[fallthrough]];
31743179
case isc_tpb_lock_read:
31753180
{
3181+
QualifiedName relationName;
31763182
const char* option_name = (op == isc_tpb_lock_read) ?
31773183
"isc_tpb_lock_read" : "isc_tpb_lock_write";
31783184

@@ -3183,7 +3189,7 @@ static void transaction_options(thread_db* tdbb,
31833189
Arg::Gds(isc_tpb_reserv_missing_tlen) << Arg::Str(option_name));
31843190
}
31853191

3186-
const USHORT len = *tpb++;
3192+
USHORT len = *tpb++;
31873193
if (len > MAX_SQL_IDENTIFIER_LEN)
31883194
{
31893195
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
@@ -3212,16 +3218,70 @@ static void transaction_options(thread_db* tdbb,
32123218
Arg::Str(option_name));
32133219
}
32143220

3215-
const MetaName orgName(reinterpret_cast<const char*>(tpb), len);
3216-
const QualifiedName relationName(attachment->nameToMetaCharSet(tdbb, orgName));
3221+
relationName.object = attachment->nameToMetaCharSet(tdbb,
3222+
string(reinterpret_cast<const char*>(tpb), len));
32173223

32183224
tpb += len;
3225+
3226+
if (tpb < end && *tpb == isc_tpb_lock_table_schema)
3227+
{
3228+
// Do we have space for the identifier length?
3229+
if (++tpb >= end)
3230+
{
3231+
ERR_post(
3232+
Arg::Gds(isc_bad_tpb_content) <<
3233+
Arg::Gds(isc_tpb_reserv_missing_tlen) << Arg::Str("isc_tpb_lock_table_schema"));
3234+
}
3235+
3236+
len = *tpb++;
3237+
if (len > MAX_SQL_IDENTIFIER_LEN)
3238+
{
3239+
ERR_post(
3240+
Arg::Gds(isc_bad_tpb_content) <<
3241+
Arg::Gds(isc_tpb_reserv_long_tlen) <<
3242+
Arg::Num(len) << Arg::Str("isc_tpb_lock_table_schema"));
3243+
}
3244+
3245+
if (!len)
3246+
{
3247+
ERR_post(
3248+
Arg::Gds(isc_bad_tpb_content) <<
3249+
Arg::Gds(isc_tpb_reserv_null_tlen) <<
3250+
Arg::Str("isc_tpb_lock_table_schema"));
3251+
}
3252+
3253+
// Does the identifier length surpasses the remaining of the TPB?
3254+
if (tpb >= end)
3255+
{
3256+
ERR_post(
3257+
Arg::Gds(isc_bad_tpb_content) <<
3258+
Arg::Gds(isc_tpb_reserv_missing_tname) <<
3259+
Arg::Num(len) << Arg::Str("isc_tpb_lock_table_schema"));
3260+
}
3261+
3262+
if (end - tpb < len)
3263+
{
3264+
ERR_post(
3265+
Arg::Gds(isc_bad_tpb_content) <<
3266+
Arg::Gds(isc_tpb_reserv_corrup_tlen) <<
3267+
Arg::Num(len) << Arg::Str("isc_tpb_lock_table_schema"));
3268+
}
3269+
3270+
relationName.schema = attachment->nameToMetaCharSet(tdbb,
3271+
string(reinterpret_cast<const char*>(tpb), len));
3272+
3273+
tpb += len;
3274+
}
3275+
3276+
attachment->qualifyExistingName(tdbb, relationName, {obj_relation});
3277+
32193278
jrd_rel* relation = MET_lookup_relation(tdbb, relationName);
32203279
if (!relation)
32213280
{
3222-
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
3223-
Arg::Gds(isc_tpb_reserv_relnotfound) << relationName.toQuotedString() <<
3224-
Arg::Str(option_name));
3281+
ERR_post(
3282+
Arg::Gds(isc_bad_tpb_content) <<
3283+
Arg::Gds(isc_tpb_reserv_relnotfound) <<
3284+
relationName.toQuotedString() << Arg::Str(option_name));
32253285
}
32263286

32273287
// force a scan to read view information

0 commit comments

Comments
 (0)