blb.cpp (Firebird-3.0.2.32703-0.tar.bz2) | : | blb.cpp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 55 | skipping to change at line 55 | |||
#include "../jrd/exe.h" | #include "../jrd/exe.h" | |||
#include "../jrd/req.h" | #include "../jrd/req.h" | |||
#include "../jrd/blb.h" | #include "../jrd/blb.h" | |||
#include "../jrd/ods.h" | #include "../jrd/ods.h" | |||
#include "../jrd/lls.h" | #include "../jrd/lls.h" | |||
#include "gen/iberror.h" | #include "gen/iberror.h" | |||
#include "../jrd/blob_filter.h" | #include "../jrd/blob_filter.h" | |||
#include "../common/sdl.h" | #include "../common/sdl.h" | |||
#include "../jrd/intl.h" | #include "../jrd/intl.h" | |||
#include "../jrd/cch.h" | #include "../jrd/cch.h" | |||
#include "../dsql/ExprNodes.h" | ||||
#include "../common/gdsassert.h" | #include "../common/gdsassert.h" | |||
#include "../jrd/blb_proto.h" | #include "../jrd/blb_proto.h" | |||
#include "../jrd/blf_proto.h" | #include "../jrd/blf_proto.h" | |||
#include "../jrd/cch_proto.h" | #include "../jrd/cch_proto.h" | |||
#include "../jrd/dpm_proto.h" | #include "../jrd/dpm_proto.h" | |||
#include "../jrd/err_proto.h" | #include "../jrd/err_proto.h" | |||
#include "../jrd/evl_proto.h" | #include "../jrd/evl_proto.h" | |||
#include "../jrd/filte_proto.h" | #include "../jrd/filte_proto.h" | |||
#include "../yvalve/gds_proto.h" | #include "../yvalve/gds_proto.h" | |||
#include "../jrd/intl_proto.h" | #include "../jrd/intl_proto.h" | |||
skipping to change at line 90 | skipping to change at line 89 | |||
static ArrayField* alloc_array(jrd_tra*, Ods::InternalArrayDesc*); | static ArrayField* alloc_array(jrd_tra*, Ods::InternalArrayDesc*); | |||
//static blb* allocate_blob(thread_db*, jrd_tra*); | //static blb* allocate_blob(thread_db*, jrd_tra*); | |||
static ISC_STATUS blob_filter(USHORT, BlobControl*); | static ISC_STATUS blob_filter(USHORT, BlobControl*); | |||
//static blb* copy_blob(thread_db*, const bid*, bid*, USHORT, const UCHAR*, USHO RT); | //static blb* copy_blob(thread_db*, const bid*, bid*, USHORT, const UCHAR*, USHO RT); | |||
//static void delete_blob(thread_db*, blb*, ULONG); | //static void delete_blob(thread_db*, blb*, ULONG); | |||
//static void delete_blob_id(thread_db*, const bid*, ULONG, jrd_rel*); | //static void delete_blob_id(thread_db*, const bid*, ULONG, jrd_rel*); | |||
static ArrayField* find_array(jrd_tra*, const bid*); | static ArrayField* find_array(jrd_tra*, const bid*); | |||
static BlobFilter* find_filter(thread_db*, SSHORT, SSHORT); | static BlobFilter* find_filter(thread_db*, SSHORT, SSHORT); | |||
//static blob_page* get_next_page(thread_db*, blb*, WIN *); | //static blob_page* get_next_page(thread_db*, blb*, WIN *); | |||
//static void insert_page(thread_db*, blb*); | //static void insert_page(thread_db*, blb*); | |||
static void move_from_string(Jrd::thread_db*, const dsc*, dsc*, const ValueExprN ode*); | static void move_from_string(Jrd::thread_db*, const dsc*, dsc*, const record_par am* rpb, USHORT fieldId); | |||
static void move_to_string(Jrd::thread_db*, dsc*, dsc*); | static void move_to_string(Jrd::thread_db*, dsc*, dsc*); | |||
static void slice_callback(array_slice*, ULONG, dsc*); | static void slice_callback(array_slice*, ULONG, dsc*); | |||
static blb* store_array(thread_db*, jrd_tra*, bid*); | static blb* store_array(thread_db*, jrd_tra*, bid*); | |||
void blb::BLB_cancel(thread_db* tdbb) | void blb::BLB_cancel(thread_db* tdbb) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* b l b : : c a n c e l | * b l b : : c a n c e l | |||
* | * | |||
skipping to change at line 936 | skipping to change at line 935 | |||
blb_flags |= BLB_seek; | blb_flags |= BLB_seek; | |||
blb_flags &= ~BLB_eof; | blb_flags &= ~BLB_eof; | |||
return offset; | return offset; | |||
} | } | |||
// This function can't take from_desc as const because it may call store_array, | // This function can't take from_desc as const because it may call store_array, | |||
// which in turn calls blb::create2 that writes in the blob id. Although the | // which in turn calls blb::create2 that writes in the blob id. Although the | |||
// compiler allows to modify from_desc->dsc_address' contents when from_desc is | // compiler allows to modify from_desc->dsc_address' contents when from_desc is | |||
// constant, this is misleading so I didn't make the source descriptor constant. | // constant, this is misleading so I didn't make the source descriptor constant. | |||
void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const ValueExprNod e* field) | void blb::move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const record_param * rpb, USHORT fieldId) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* b l b : : m o v e | * b l b : : m o v e | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
* Functional description | * Functional description | |||
* Perform an assignment to a blob field or a blob descriptor. | * Perform an assignment to a blob field or a blob descriptor. | |||
* When assigning to a field, unless the blob is null, | * When assigning to a field, unless the blob is null, | |||
skipping to change at line 967 | skipping to change at line 966 | |||
if (from_desc->dsc_dtype != dtype_array && from_desc->dsc_dtype ! = dtype_quad) | if (from_desc->dsc_dtype != dtype_array && from_desc->dsc_dtype ! = dtype_quad) | |||
{ | { | |||
ERR_post(Arg::Gds(isc_array_convert_error)); | ERR_post(Arg::Gds(isc_array_convert_error)); | |||
} | } | |||
} | } | |||
else if (DTYPE_IS_BLOB_OR_QUAD(to_desc->dsc_dtype)) | else if (DTYPE_IS_BLOB_OR_QUAD(to_desc->dsc_dtype)) | |||
{ | { | |||
if (!DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype)) | if (!DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype)) | |||
{ | { | |||
// anything that can be copied into a string can be copie d into a blob | // anything that can be copied into a string can be copie d into a blob | |||
move_from_string(tdbb, from_desc, to_desc, field); | move_from_string(tdbb, from_desc, to_desc, rpb, fieldId); | |||
return; | return; | |||
} | } | |||
} | } | |||
else if (DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype)) | else if (DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype)) | |||
{ | { | |||
move_to_string(tdbb, from_desc, to_desc); | move_to_string(tdbb, from_desc, to_desc); | |||
return; | return; | |||
} | } | |||
else | else | |||
fb_assert(false); | fb_assert(false); | |||
bool simpleMove = true; | ||||
// If the target node is a field, we need more work to do. | // If the target node is a field, we need more work to do. | |||
const FieldNode* fieldNode = NULL; | // We should not materialize the blob if the destination field | |||
// stream (nod_union, for example) doesn't have a relation. | ||||
if (field) | const bool simpleMove = !rpb || (rpb->rpb_relation == NULL); | |||
{ | ||||
if ((fieldNode = ExprNode::as<FieldNode>(field))) | ||||
{ | ||||
// We should not materialize the blob if the destination | ||||
field | ||||
// stream (nod_union, for example) doesn't have a relatio | ||||
n. | ||||
simpleMove = tdbb->getRequest()->req_rpb[fieldNode->field | ||||
Stream].rpb_relation == NULL; | ||||
} | ||||
else if (!(ExprNode::is<ParameterNode>(field) || ExprNode::is<Var | ||||
iableNode>(field))) | ||||
BUGCHECK(199); // msg 199 expected field node | ||||
} | ||||
// Use local copy of source blob id to not change contents of from_desc i n | // Use local copy of source blob id to not change contents of from_desc i n | |||
// a case when it points to materialized temporary blob (see below for | // a case when it points to materialized temporary blob (see below for | |||
// assignment to *source). | // assignment to *source). | |||
bid srcBlobID = *(bid*)from_desc->dsc_address; | bid srcBlobID = *(bid*)from_desc->dsc_address; | |||
bid* source = &srcBlobID; | bid* source = &srcBlobID; | |||
bid* destination = (bid*) to_desc->dsc_address; | bid* destination = (bid*) to_desc->dsc_address; | |||
// If nothing changed, do nothing. If it isn't broken, don't fix it. | // If nothing changed, do nothing. If it isn't broken, don't fix it. | |||
if (*source == *destination) | if (*source == *destination) | |||
skipping to change at line 1051 | skipping to change at line 1038 | |||
copy_blob(tdbb, source, destination, bpb.getCount(), bpb. begin(), pageSpace); | copy_blob(tdbb, source, destination, bpb.getCount(), bpb. begin(), pageSpace); | |||
} | } | |||
else | else | |||
*destination = *source; | *destination = *source; | |||
return; | return; | |||
} | } | |||
jrd_req* request = tdbb->getRequest(); | jrd_req* request = tdbb->getRequest(); | |||
const USHORT id = fieldNode->fieldId; | ||||
record_param* rpb = &request->req_rpb[fieldNode->fieldStream]; | ||||
jrd_rel* relation = rpb->rpb_relation; | jrd_rel* relation = rpb->rpb_relation; | |||
if (relation->isVirtual()) { | if (relation->isVirtual()) { | |||
ERR_post(Arg::Gds(isc_read_only)); | ERR_post(Arg::Gds(isc_read_only)); | |||
} | } | |||
RelationPages* relPages = relation->getPages(tdbb); | RelationPages* relPages = relation->getPages(tdbb); | |||
Record* record = rpb->rpb_record; | Record* record = rpb->rpb_record; | |||
// If either the source value is null or the blob id itself is null | // If either the source value is null or the blob id itself is null | |||
// (all zeros), then the blob is null. | // (all zeros), then the blob is null. | |||
if ((request->req_flags & req_null) || source->isEmpty()) | if ((request->req_flags & req_null) || source->isEmpty()) | |||
{ | { | |||
record->setNull(id); | record->setNull(fieldId); | |||
destination->clear(); | destination->clear(); | |||
return; | return; | |||
} | } | |||
record->clearNull(id); | record->clearNull(fieldId); | |||
jrd_tra* transaction = request->req_transaction; | jrd_tra* transaction = request->req_transaction; | |||
transaction = transaction->getOuter(); | transaction = transaction->getOuter(); | |||
// If the target is a view, this must be from a view update trigger. | // If the target is a view, this must be from a view update trigger. | |||
// Just pass the blob id thru. | // Just pass the blob id thru. | |||
if (relation->rel_view_rse) | if (relation->rel_view_rse) | |||
{ | { | |||
// But if the sub_type or charset is different, create a new blob . | // But if the sub_type or charset is different, create a new blob . | |||
if (DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype) && | if (DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype) && | |||
skipping to change at line 2474 | skipping to change at line 2459 | |||
CCH_precedence(tdbb, &window, page_number); | CCH_precedence(tdbb, &window, page_number); | |||
CCH_MARK(tdbb, &window); | CCH_MARK(tdbb, &window); | |||
l = blb_sequence % blb_pointers; | l = blb_sequence % blb_pointers; | |||
page->blp_page[l] = page_number.getPageNum(); | page->blp_page[l] = page_number.getPageNum(); | |||
page->blp_length = (l + 1) << SHIFTLONG; | page->blp_length = (l + 1) << SHIFTLONG; | |||
CCH_RELEASE(tdbb, &window); | CCH_RELEASE(tdbb, &window); | |||
} | } | |||
static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc , | static void move_from_string(thread_db* tdbb, const dsc* from_desc, dsc* to_desc , | |||
const ValueExprNode* field) | const record_param* rpb, USHORT fieldId) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* m o v e _ f r o m _ s t r i n g | * m o v e _ f r o m _ s t r i n g | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
* Functional description | * Functional description | |||
* Perform an assignment to a blob field. It's capable of handling | * Perform an assignment to a blob field. It's capable of handling | |||
* strings (and anything that could be converted to strings) by | * strings (and anything that could be converted to strings) by | |||
skipping to change at line 2528 | skipping to change at line 2513 | |||
blob_desc.dsc_scale = to_desc->dsc_scale; // blob charset | blob_desc.dsc_scale = to_desc->dsc_scale; // blob charset | |||
blob_desc.dsc_flags = (blob_desc.dsc_flags & 0xFF) | (to_desc->dsc_flags & 0xFF00); // blob collation | blob_desc.dsc_flags = (blob_desc.dsc_flags & 0xFF) | (to_desc->dsc_flags & 0xFF00); // blob collation | |||
blob_desc.dsc_sub_type = to_desc->dsc_sub_type; | blob_desc.dsc_sub_type = to_desc->dsc_sub_type; | |||
blob_desc.dsc_dtype = dtype_blob; | blob_desc.dsc_dtype = dtype_blob; | |||
blob_desc.dsc_length = sizeof(ISC_QUAD); | blob_desc.dsc_length = sizeof(ISC_QUAD); | |||
blob_desc.dsc_address = reinterpret_cast<UCHAR*>(&temp_bid); | blob_desc.dsc_address = reinterpret_cast<UCHAR*>(&temp_bid); | |||
blob->BLB_put_segment(tdbb, fromstr, length); | blob->BLB_put_segment(tdbb, fromstr, length); | |||
blob->BLB_close(tdbb); | blob->BLB_close(tdbb); | |||
ULONG blob_temp_id = blob->getTempId(); | ULONG blob_temp_id = blob->getTempId(); | |||
blb::move(tdbb, &blob_desc, to_desc, field); | blb::move(tdbb, &blob_desc, to_desc, rpb, fieldId); | |||
// 14-June-2004. Nickolay Samofatov | // 14-June-2004. Nickolay Samofatov | |||
// The code below saves a lot of memory when bunches of records are | // The code below saves a lot of memory when bunches of records are | |||
// converted to blobs from strings. If blb::move is materialized blob we | // converted to blobs from strings. If blb::move is materialized blob we | |||
// can discard it without consequences since we know there are no other | // can discard it without consequences since we know there are no other | |||
// descriptors using temporary ID of blob we just created. If blob is | // descriptors using temporary ID of blob we just created. If blob is | |||
// still temporary we cannot free it as it may now be used inside | // still temporary we cannot free it as it may now be used inside | |||
// trigger for updatable view. In theory we could make this decision | // trigger for updatable view. In theory we could make this decision | |||
// solely via checking that destination field belongs to updatable | // solely via checking that destination field belongs to updatable | |||
// view, but direct check that blob is fully materialized should be | // view, but direct check that blob is fully materialized should be | |||
End of changes. 11 change blocks. | ||||
29 lines changed or deleted | 10 lines changed or added |