void Chunk::merge(ConstChunk const& with, boost::shared_ptr<Query>& query) { if (getDiskChunk() != NULL) throw USER_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_CHUNK_ALREADY_EXISTS); setCount(0); // unknown AttributeDesc const& attr = getAttributeDesc(); char* dst = (char*)getData(); Value const& defaultValue = attr.getDefaultValue(); if (dst != NULL && (isSparse() || isRLE() || with.isSparse() || with.isRLE() || attr.isNullable() || TypeLibrary::getType(attr.getType()).variableSize() || !defaultValue.isZero())) { int sparseMode = isSparse() ? ChunkIterator::SPARSE_CHUNK : 0; boost::shared_ptr<ChunkIterator> dstIterator = getIterator(query, sparseMode|ChunkIterator::APPEND_CHUNK|ChunkIterator::NO_EMPTY_CHECK); boost::shared_ptr<ConstChunkIterator> srcIterator = with.getConstIterator(ChunkIterator::IGNORE_EMPTY_CELLS|ChunkIterator::IGNORE_DEFAULT_VALUES); if (getArrayDesc().getEmptyBitmapAttribute() != NULL) { while (!srcIterator->end()) { if (!dstIterator->setPosition(srcIterator->getPosition())) throw SYSTEM_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_OPERATION_FAILED) << "setPosition"; Value const& value = srcIterator->getItem(); dstIterator->writeItem(value); ++(*srcIterator); } } else { // ignore default values while (!srcIterator->end()) { Value const& value = srcIterator->getItem(); if (value != defaultValue) { if (!dstIterator->setPosition(srcIterator->getPosition())) throw SYSTEM_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_OPERATION_FAILED) << "setPosition"; dstIterator->writeItem(value); } ++(*srcIterator); } } dstIterator->flush(); } else { PinBuffer scope(with); char* src = (char*)with.getData(); if (dst == NULL) { allocate(with.getSize()); setSparse(with.isSparse()); setRLE(with.isRLE()); memcpy(getData(), src, getSize()); } else { if (getSize() != with.getSize()) throw USER_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_CANT_MERGE_CHUNKS_WITH_VARYING_SIZE); for (size_t j = 0, n = getSize(); j < n; j++) { dst[j] |= src[j]; } } write(query); } }
void Chunk::aggregateMerge(ConstChunk const& with, AggregatePtr const& aggregate, boost::shared_ptr<Query>& query) { if (getDiskChunk() != NULL) throw USER_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_CHUNK_ALREADY_EXISTS); if (isReadOnly()) throw USER_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_CANT_UPDATE_READ_ONLY_CHUNK); AttributeDesc const& attr = getAttributeDesc(); if (aggregate->getStateType().typeId() != attr.getType()) throw SYSTEM_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_TYPE_MISMATCH_BETWEEN_AGGREGATE_AND_CHUNK); if (!attr.isNullable()) throw SYSTEM_EXCEPTION(SCIDB_SE_INTERNAL, SCIDB_LE_AGGREGATE_STATE_MUST_BE_NULLABLE);//enforce equivalency w above merge() setCount(0); char* dst = (char*)getData(); if (dst != NULL) { int sparseMode = isSparse() ? ChunkIterator::SPARSE_CHUNK : 0; boost::shared_ptr<ChunkIterator>dstIterator = getIterator(query, sparseMode|ChunkIterator::APPEND_CHUNK|ChunkIterator::NO_EMPTY_CHECK); boost::shared_ptr<ConstChunkIterator> srcIterator = with.getConstIterator(ChunkIterator::IGNORE_NULL_VALUES); while (!srcIterator->end()) { Value& val = srcIterator->getItem(); if (!val.isNull()) { if (!dstIterator->setPosition(srcIterator->getPosition())) throw SYSTEM_EXCEPTION(SCIDB_SE_MERGE, SCIDB_LE_OPERATION_FAILED) << "setPosition"; Value& val2 = dstIterator->getItem(); if (!val2.isNull()) { aggregate->merge(val, val2); } dstIterator->writeItem(val); } ++(*srcIterator); } dstIterator->flush(); } else { PinBuffer scope(with); char* src = (char*)with.getData(); allocate(with.getSize()); setSparse(with.isSparse()); setRLE(with.isRLE()); memcpy(getData(), src, getSize()); write(query); } }