| 11832 | } |
| 11833 | |
| 11834 | dsc* SubstringNode::perform(thread_db* tdbb, impure_value* impure, const dsc* valueDsc, |
| 11835 | const dsc* startDsc, const dsc* lengthDsc) |
| 11836 | { |
| 11837 | SINT64 sStart = MOV_get_long(tdbb, startDsc, 0); |
| 11838 | SINT64 sLength = MOV_get_long(tdbb, lengthDsc, 0); |
| 11839 | |
| 11840 | if (sLength < 0) |
| 11841 | status_exception::raise(Arg::Gds(isc_bad_substring_length) << Arg::Num(sLength)); |
| 11842 | |
| 11843 | if (sStart < 0) |
| 11844 | { |
| 11845 | sLength = MAX(sLength + sStart, 0); |
| 11846 | sStart = 0; |
| 11847 | } |
| 11848 | |
| 11849 | FB_UINT64 start = FB_UINT64(sStart); |
| 11850 | FB_UINT64 length = FB_UINT64(sLength); |
| 11851 | |
| 11852 | dsc desc; |
| 11853 | DataTypeUtil(tdbb).makeSubstr(&desc, valueDsc, startDsc, lengthDsc); |
| 11854 | |
| 11855 | if (desc.isText() && length > MAX_STR_SIZE) |
| 11856 | length = MAX_STR_SIZE; |
| 11857 | |
| 11858 | ULONG dataLen; |
| 11859 | |
| 11860 | if (valueDsc->isBlob()) |
| 11861 | { |
| 11862 | // Source string is a blob, things get interesting. |
| 11863 | |
| 11864 | fb_assert(desc.dsc_dtype == dtype_blob); |
| 11865 | |
| 11866 | desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_bid; |
| 11867 | |
| 11868 | blb* newBlob = blb::create(tdbb, tdbb->getRequest()->req_transaction, &impure->vlu_misc.vlu_bid); |
| 11869 | |
| 11870 | blb* blob = blb::open(tdbb, tdbb->getRequest()->req_transaction, |
| 11871 | reinterpret_cast<bid*>(valueDsc->dsc_address)); |
| 11872 | |
| 11873 | HalfStaticArray<UCHAR, BUFFER_LARGE> buffer; |
| 11874 | CharSet* charSet = INTL_charset_lookup(tdbb, valueDsc->getCharSet()); |
| 11875 | |
| 11876 | const FB_UINT64 byte_offset = start * charSet->maxBytesPerChar(); |
| 11877 | const FB_UINT64 byte_length = length * charSet->maxBytesPerChar(); |
| 11878 | |
| 11879 | if (charSet->isMultiByte()) |
| 11880 | { |
| 11881 | buffer.getBuffer(MIN(blob->blb_length, byte_offset + byte_length)); |
| 11882 | dataLen = blob->BLB_get_data(tdbb, buffer.begin(), buffer.getCount(), false); |
| 11883 | |
| 11884 | HalfStaticArray<UCHAR, BUFFER_LARGE> buffer2; |
| 11885 | buffer2.getBuffer(dataLen); |
| 11886 | |
| 11887 | dataLen = charSet->substring(dataLen, buffer.begin(), |
| 11888 | buffer2.getCapacity(), buffer2.begin(), start, length); |
| 11889 | newBlob->BLB_put_data(tdbb, buffer2.begin(), dataLen); |
| 11890 | } |
| 11891 | else if (byte_offset < blob->blb_length) |
nothing calls this directly
no test coverage detected