8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 15:23:03 +01:00

Fixed bug #7256 : Inconsistent conversion of non-TEXT blobs in BLOB_APPEND

This commit is contained in:
Vlad Khorsun 2022-08-22 01:02:38 +03:00
parent 22aebe8c15
commit 58bc4dcc3d

View File

@ -1234,15 +1234,54 @@ void makeBinShift(DataTypeUtilBase*, const SysFunction* function, dsc* result,
} }
bool makeBlobAppendBlob(dsc* result, const dsc* arg, bid* blob_id = nullptr)
{
if (!arg)
return false;
ISC_QUAD* ptr = reinterpret_cast<ISC_QUAD*>(blob_id);
if (arg->isBlob())
{
result->makeBlob(arg->getBlobSubType(), arg->getTextType(), ptr);
return true;
}
if (arg->isNull())
return false;
if (arg->isText())
{
USHORT ttype = arg->getTextType();
if (ttype == ttype_binary)
result->makeBlob(isc_blob_untyped, ttype_binary, ptr);
else
result->makeBlob(isc_blob_text, ttype, ptr);
}
else
{
result->makeBlob(isc_blob_text, ttype_ascii, ptr);
}
return true;
}
void makeBlobAppend(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result, void makeBlobAppend(DataTypeUtilBase* dataTypeUtil, const SysFunction* function, dsc* result,
int argsCount, const dsc** args) int argsCount, const dsc** args)
{ {
USHORT ttype = CS_dynamic; if (argsCount > 0)
{
const dsc** ppArg = args;
const dsc** const end = args + argsCount;
if (argsCount > 0 && args[0]) for (; ppArg < end; ppArg++)
ttype = args[0]->getTextType(); if (makeBlobAppendBlob(result, *ppArg))
return;
}
result->makeBlob(isc_blob_text, ttype); fb_assert(false);
result->makeBlob(isc_blob_untyped, ttype_binary);
} }
@ -2297,8 +2336,6 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue
jrd_tra* transaction = request ? request->req_transaction : tdbb->getTransaction(); jrd_tra* transaction = request ? request->req_transaction : tdbb->getTransaction();
transaction = transaction->getOuter(); transaction = transaction->getOuter();
USHORT ttype = tdbb->getCharSet();
blb* blob = NULL; blb* blob = NULL;
bid blob_id; bid blob_id;
dsc blobDsc; dsc blobDsc;
@ -2312,21 +2349,13 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue
if (!arg0_null && argDsc->isBlob()) if (!arg0_null && argDsc->isBlob())
blob_id = *reinterpret_cast<bid*>(argDsc->dsc_address); blob_id = *reinterpret_cast<bid*>(argDsc->dsc_address);
const dsc* declDsc = argDsc; // Try to get blob type from declared var\param
if (!declDsc) if (!argDsc && (nodeIs<VariableNode>(args[0]) ||
declDsc = EVL_assign_to(tdbb, args[0]); nodeIs<ParameterNode>(args[0]) ))
if (declDsc && declDsc->isBlob())
{ {
ttype = declDsc->getTextType(); argDsc = EVL_assign_to(tdbb, args[0]);
blobDsc.makeBlob(declDsc->getBlobSubType(), ttype, (ISC_QUAD*)&blob_id); if (argDsc && argDsc->isBlob())
} makeBlobAppendBlob(&blobDsc, argDsc, &blob_id);
else
{
if (declDsc && declDsc->isText())
ttype = declDsc->getTextType();
blobDsc.makeBlob(isc_blob_text, ttype, (ISC_QUAD*) &blob_id);
} }
bool copyBlob = !blob_id.isEmpty(); bool copyBlob = !blob_id.isEmpty();
@ -2346,23 +2375,6 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue
} }
} }
if (!blob)
{
UCharBuffer bpb;
BLB_gen_bpb_from_descs(&blobDsc, &blobDsc, bpb);
bpb.push(isc_bpb_storage);
bpb.push(1);
bpb.push(isc_bpb_storage_temp);
blob = blb::create2(tdbb, transaction, &blob_id, bpb.getCount(), bpb.begin());
blob->blb_flags |= BLB_stream | BLB_close_on_read;
}
// if (copyBlob && argDsc && argDsc->isBlob())
// appendFromBlob(tdbb, transaction, blob, &blobDsc, argDsc);
EVL_make_value(tdbb, &blobDsc, impure);
for (FB_SIZE_T i = 0; i < args.getCount(); i++) for (FB_SIZE_T i = 0; i < args.getCount(); i++)
{ {
if (i == 0) if (i == 0)
@ -2377,11 +2389,33 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue
continue; continue;
} }
fb_assert(argDsc != nullptr);
if (!blobDsc.isBlob())
{
if (!makeBlobAppendBlob(&blobDsc, argDsc, &blob_id))
continue;
}
fb_assert(blobDsc.isBlob());
if (!blob)
{
UCharBuffer bpb;
BLB_gen_bpb_from_descs(&blobDsc, &blobDsc, bpb);
bpb.push(isc_bpb_storage);
bpb.push(1);
bpb.push(isc_bpb_storage_temp);
blob = blb::create2(tdbb, transaction, &blob_id, bpb.getCount(), bpb.begin());
blob->blb_flags |= BLB_stream | BLB_close_on_read;
}
if (!argDsc->isBlob()) if (!argDsc->isBlob())
{ {
MoveBuffer temp; MoveBuffer temp;
UCHAR* addr = NULL; UCHAR* addr = NULL;
SLONG len = MOV_make_string2(tdbb, argDsc, ttype, &addr, temp); SLONG len = MOV_make_string2(tdbb, argDsc, blobDsc.getTextType(), &addr, temp);
if (addr) if (addr)
blob->BLB_put_data(tdbb, addr, len); blob->BLB_put_data(tdbb, addr, len);
@ -2392,6 +2426,10 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue
} }
} }
if (!blob)
return nullptr;
EVL_make_value(tdbb, &blobDsc, impure);
return &impure->vlu_desc; return &impure->vlu_desc;
} }