From 517fc10a4fd4941b2df70fd5a6742dc042a808a6 Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Wed, 17 Aug 2022 16:35:03 +0300 Subject: [PATCH] Fixed bug #7256 : Inconsistent conversion of non-TEXT blobs in BLOB_APPEND Changed according to discussion on GH. --- src/jrd/SysFunction.cpp | 115 +++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 42 deletions(-) diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index 59b5c5198e..a34d9f1090 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -1246,19 +1246,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(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, int argsCount, const dsc** args) { - if (argsCount > 0 && args[0]) + if (argsCount > 0) { - auto arg = args[0]; - if (arg->isBlob()) - result->makeBlob(arg->getBlobSubType(), arg->getTextType()); - else if (arg->isText()) - result->makeBlob(isc_blob_text, arg->getTextType()); + const dsc** ppArg = args; + const dsc** const end = args + argsCount; + + for (; ppArg < end; ppArg++) + if (makeBlobAppendBlob(result, *ppArg)) + return; } - else - result->makeBlob(isc_blob_text, CS_dynamic); + + fb_assert(false); + result->makeBlob(isc_blob_untyped, ttype_binary); } @@ -2331,8 +2366,6 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue jrd_tra* transaction = request ? request->req_transaction : tdbb->getTransaction(); transaction = transaction->getOuter(); - USHORT ttype = tdbb->getCharSet(); - blb* blob = NULL; bid blob_id; dsc blobDsc; @@ -2346,21 +2379,13 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue if (!arg0_null && argDsc->isBlob()) blob_id = *reinterpret_cast(argDsc->dsc_address); - const dsc* declDsc = argDsc; - if (!declDsc) - declDsc = EVL_assign_to(tdbb, args[0]); - - if (declDsc && declDsc->isBlob()) + // Try to get blob type from declared var\param + if (!argDsc && (nodeIs(args[0]) || + nodeIs(args[0]) )) { - ttype = declDsc->getTextType(); - blobDsc.makeBlob(declDsc->getBlobSubType(), ttype, (ISC_QUAD*)&blob_id); - } - else - { - if (declDsc && declDsc->isText()) - ttype = declDsc->getTextType(); - - blobDsc.makeBlob(isc_blob_text, ttype, (ISC_QUAD*) &blob_id); + argDsc = EVL_assign_to(tdbb, args[0]); + if (argDsc && argDsc->isBlob()) + makeBlobAppendBlob(&blobDsc, argDsc, &blob_id); } bool copyBlob = !blob_id.isEmpty(); @@ -2380,23 +2405,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++) { if (i == 0) @@ -2411,11 +2419,30 @@ dsc* evlBlobAppend(thread_db* tdbb, const SysFunction* function, const NestValue continue; } + if (!blobDsc.isBlob()) + if (!makeBlobAppendBlob(&blobDsc, argDsc, &blob_id)) + continue; + + fb_assert(blobDsc.isBlob()); + fb_assert(argDsc != nullptr); + + 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()) { MoveBuffer temp; 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) blob->BLB_put_data(tdbb, addr, len); @@ -2426,6 +2453,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; }