mirror of https://gitee.com/bigwinds/arangodb
add ability to 3.3 to read compressed AqlItemBlocks (#6517)
but not the ability to produce them. This way we can support running 3.3 as part of a mixed 3.3/3.4 cluster, and do not break any clusters that run mixed versions of 3.3 current and either 3.2 or 3.3 older versions
This commit is contained in:
parent
66ca6885e1
commit
f549dbe8cd
|
@ -100,77 +100,145 @@ AqlItemBlock::AqlItemBlock(ResourceMonitor* resourceMonitor, VPackSlice const sl
|
||||||
VPackArrayIterator dataIterator(data);
|
VPackArrayIterator dataIterator(data);
|
||||||
VPackArrayIterator rawIterator(raw);
|
VPackArrayIterator rawIterator(raw);
|
||||||
|
|
||||||
|
auto storeSingleValue = [this](size_t row, size_t column, VPackArrayIterator& it, std::vector<AqlValue>& madeHere) {
|
||||||
|
AqlValue a(it.value());
|
||||||
|
it.next();
|
||||||
|
try {
|
||||||
|
setValue(row, column, a); // if this throws, a is destroyed again
|
||||||
|
} catch (...) {
|
||||||
|
a.destroy();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
madeHere.emplace_back(a);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RunType {
|
||||||
|
NoRun = 0,
|
||||||
|
EmptyRun,
|
||||||
|
NextRun,
|
||||||
|
PositionalRun
|
||||||
|
};
|
||||||
|
|
||||||
|
int64_t runLength = 0;
|
||||||
|
size_t tablePos = 0;
|
||||||
|
RunType runType = NoRun;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// skip the first two records
|
// skip the first two records
|
||||||
rawIterator.next();
|
rawIterator.next();
|
||||||
rawIterator.next();
|
rawIterator.next();
|
||||||
int64_t emptyRun = 0;
|
|
||||||
|
|
||||||
for (RegisterId column = 0; column < _nrRegs; column++) {
|
for (RegisterId column = 0; column < _nrRegs; column++) {
|
||||||
for (size_t i = 0; i < _nrItems; i++) {
|
for (size_t i = 0; i < _nrItems; i++) {
|
||||||
if (emptyRun > 0) {
|
if (runLength > 0) {
|
||||||
emptyRun--;
|
switch (runType) {
|
||||||
} else {
|
case EmptyRun:
|
||||||
VPackSlice dataEntry = dataIterator.value();
|
// nothing to do
|
||||||
dataIterator.next();
|
break;
|
||||||
if (!dataEntry.isNumber()) {
|
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
case NextRun:
|
||||||
"data must contain only numbers");
|
storeSingleValue(i, column, rawIterator, madeHere);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PositionalRun:
|
||||||
|
TRI_ASSERT(tablePos < madeHere.size());
|
||||||
|
setValue(i, column, madeHere[tablePos]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NoRun: {
|
||||||
|
TRI_ASSERT(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int64_t n = dataEntry.getNumericValue<int64_t>();
|
|
||||||
if (n == 0) {
|
--runLength;
|
||||||
// empty, do nothing here
|
if (runLength == 0) {
|
||||||
} else if (n == -1) {
|
runType = NoRun;
|
||||||
// empty run:
|
tablePos = 0;
|
||||||
VPackSlice runLength = dataIterator.value();
|
}
|
||||||
dataIterator.next();
|
|
||||||
TRI_ASSERT(runLength.isNumber());
|
continue;
|
||||||
emptyRun = runLength.getNumericValue<int64_t>();
|
}
|
||||||
emptyRun--;
|
|
||||||
} else if (n == -2) {
|
VPackSlice dataEntry = dataIterator.value();
|
||||||
// a range
|
dataIterator.next();
|
||||||
VPackSlice lowBound = dataIterator.value();
|
if (!dataEntry.isNumber()) {
|
||||||
dataIterator.next();
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
VPackSlice highBound = dataIterator.value();
|
"data must contain only numbers");
|
||||||
dataIterator.next();
|
}
|
||||||
|
|
||||||
int64_t low =
|
int64_t n = dataEntry.getNumericValue<int64_t>();
|
||||||
VelocyPackHelper::getNumericValue<int64_t>(lowBound, 0);
|
if (n == 0) {
|
||||||
int64_t high =
|
// empty, do nothing here
|
||||||
VelocyPackHelper::getNumericValue<int64_t>(highBound, 0);
|
} else if (n == 1) {
|
||||||
AqlValue a(low, high);
|
// a VelocyPack value
|
||||||
try {
|
storeSingleValue(i, column, rawIterator, madeHere);
|
||||||
setValue(i, column, a);
|
} else if (n == -1 || n == -3 || n == -4) {
|
||||||
} catch (...) {
|
// -1: empty run, -3: run of "next" values, -4: run of positional values
|
||||||
a.destroy();
|
VPackSlice v = dataIterator.value();
|
||||||
throw;
|
dataIterator.next();
|
||||||
|
TRI_ASSERT(v.isNumber());
|
||||||
|
runLength = v.getNumericValue<int64_t>();
|
||||||
|
runLength--;
|
||||||
|
switch (n) {
|
||||||
|
case -1:
|
||||||
|
runType = EmptyRun;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -3:
|
||||||
|
runType = NextRun;
|
||||||
|
storeSingleValue(i, column, rawIterator, madeHere);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -4: {
|
||||||
|
runType = PositionalRun;
|
||||||
|
VPackSlice v = dataIterator.value();
|
||||||
|
dataIterator.next();
|
||||||
|
TRI_ASSERT(v.isNumber());
|
||||||
|
tablePos = v.getNumericValue<size_t>();
|
||||||
|
if (tablePos >= madeHere.size()) {
|
||||||
|
// safeguard against out-of-bounds accesses
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"found undefined data value");
|
||||||
|
}
|
||||||
|
|
||||||
|
setValue(i, column, madeHere[tablePos]);
|
||||||
}
|
}
|
||||||
} else if (n == 1) {
|
}
|
||||||
// a VelocyPack value
|
} else if (n == -2) {
|
||||||
AqlValue a(rawIterator.value());
|
// a range
|
||||||
rawIterator.next();
|
VPackSlice lowBound = dataIterator.value();
|
||||||
try {
|
dataIterator.next();
|
||||||
setValue(i, column, a); // if this throws, a is destroyed again
|
VPackSlice highBound = dataIterator.value();
|
||||||
} catch (...) {
|
dataIterator.next();
|
||||||
a.destroy();
|
|
||||||
throw;
|
int64_t low =
|
||||||
}
|
VelocyPackHelper::getNumericValue<int64_t>(lowBound, 0);
|
||||||
madeHere.emplace_back(a);
|
int64_t high =
|
||||||
} else if (n >= 2) {
|
VelocyPackHelper::getNumericValue<int64_t>(highBound, 0);
|
||||||
setValue(i, column, madeHere[static_cast<size_t>(n)]);
|
emplaceValue(i, column, low, high);
|
||||||
// If this throws, all is OK, because it was already put into
|
} else if (n >= 2) {
|
||||||
// the block elsewhere.
|
if (static_cast<size_t>(n) >= madeHere.size()) {
|
||||||
} else {
|
// safeguard against out-of-bounds accesses
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
"found undefined data value");
|
"found undefined data value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setValue(i, column, madeHere[static_cast<size_t>(n)]);
|
||||||
|
// If this throws, all is OK, because it was already put into
|
||||||
|
// the block elsewhere.
|
||||||
|
} else {
|
||||||
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||||
|
"found invalid data encoding value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
destroy();
|
destroy();
|
||||||
// TODO: rethrow?
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(runLength == 0);
|
||||||
|
TRI_ASSERT(runType == NoRun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief destroy the block, used in the destructor and elsewhere
|
/// @brief destroy the block, used in the destructor and elsewhere
|
||||||
|
|
Loading…
Reference in New Issue