Skip to content

Commit cc42422

Browse files
committed
Fix transaction table reservation.
1 parent 41fa3a5 commit cc42422

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
@@ -3163,6 +3163,11 @@ static void transaction_options(thread_db* tdbb,
31633163
transaction->tra_flags |= TRA_auto_release_temp_blobid;
31643164
break;
31653165

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

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

3187-
const USHORT len = *tpb++;
3193+
USHORT len = *tpb++;
31883194
if (len > MAX_SQL_IDENTIFIER_LEN)
31893195
{
31903196
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
@@ -3213,16 +3219,70 @@ static void transaction_options(thread_db* tdbb,
32133219
Arg::Str(option_name));
32143220
}
32153221

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

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

32283288
// force a scan to read view information

0 commit comments

Comments
 (0)