Esempio n. 1
0
TEST_F(DRBinaryLogTest, VerifyHiddenColumns) {
    ASSERT_FALSE(flush(98));

    // single row write transaction
    beginTxn(99, 99, 98, 70);
    TableTuple first_tuple = insertTuple(m_table, prepareTempTuple(m_table, 42, 55555, "349508345.34583", "a thing", "a totally different thing altogether", 5433));
    endTxn(true);

    flushAndApply(99);

    TableTuple tuple = m_tableReplica->lookupTupleByValues(first_tuple);
    NValue drTimestamp = tuple.getHiddenNValue(m_table->getDRTimestampColumnIndex());
    NValue drTimestampReplica = tuple.getHiddenNValue(m_tableReplica->getDRTimestampColumnIndex());
    EXPECT_EQ(ValuePeeker::peekAsBigInt(drTimestamp), 70);
    EXPECT_EQ(0, drTimestamp.compare(drTimestampReplica));
}
Esempio n. 2
0
NValue SubqueryExpression::eval(const TableTuple *tuple1, const TableTuple *tuple2) const
{
    // Get the subquery context with the last evaluation result and parameters used to obtain that result

    ExecutorContext* exeContext = ExecutorContext::getExecutorContext();

    SubqueryContext* context = exeContext->getSubqueryContext(m_subqueryId);

    bool hasPriorResult = (context != NULL) && context->hasValidResult();
    bool paramsChanged = false;
    NValueArray& parameterContainer = *(exeContext->getParameterContainer());
    VOLT_TRACE ("Running subquery: %d", m_subqueryId);

    // Substitute parameters.
    if (m_tveParams.get() != NULL) {
        size_t paramsCnt = m_tveParams->size();
        for (size_t i = 0; i < paramsCnt; ++i) {
            AbstractExpression* tveParam = (*m_tveParams)[i];
            NValue param = tveParam->eval(tuple1, tuple2);
            // compare the new param value with the previous one. Since this parameter is set
            // by this subquery, no other subquery can change its value. So, we don't need to
            // save its value on the side for future comparisons.
            NValue& prevParam = parameterContainer[m_paramIdxs[i]];
            if (hasPriorResult) {
                if (param.compare(prevParam) == VALUE_COMPARE_EQUAL) {
                    continue;
                }
                paramsChanged = true;
            }
            // Update the value stored in the executor context's parameter container:
            prevParam = param.copyNValue();
        }
    }

    // Note the other (non-tve) parameter values and check if they've changed since the last invocation.
    if (hasPriorResult) {
        std::vector<NValue>& lastParams = context->accessLastParams();
        assert(lastParams.size() == m_otherParamIdxs.size());
        for (size_t i = 0; i < lastParams.size(); ++i) {
            NValue& prevParam = parameterContainer[m_otherParamIdxs[i]];
            if (lastParams[i].compare(prevParam) != VALUE_COMPARE_EQUAL) {
                lastParams[i] = prevParam.copyNValue();
                paramsChanged = true;
            }
        }
        if (paramsChanged) {
            // If parameters have changed since the last execution,
            // the cached result of the prior execution is obsolete.
            // In particular, it should not be mistaken for the correct result for the current
            // parameters in the event that the current execution fails.
            // This subquery context will be restored to validity when its new result is set
            // after execution succeeds.
            context->invalidateResult();
        } else {
            // If the parameters haven't changed since the last execution, reuse the known result.
            return context->getResult();
        }
    }

    // Out of luck. Need to run the executors. Clean up the output tables with cached results
    exeContext->cleanupExecutorsForSubquery(m_subqueryId);
    exeContext->executeExecutors(m_subqueryId);

    if (context == NULL) {
        // Preserve the value for the next run. Only 'other' parameters need to be copied
        std::vector<NValue> lastParams;
        lastParams.reserve(m_otherParamIdxs.size());
        for (size_t i = 0; i < m_otherParamIdxs.size(); ++i) {
            NValue& prevParam = parameterContainer[m_otherParamIdxs[i]];
            lastParams.push_back(prevParam.copyNValue());
        }
        context = exeContext->setSubqueryContext(m_subqueryId, lastParams);
    }

    // Update the cached result for the current params. All params are already updated
    NValue retval = ValueFactory::getIntegerValue(m_subqueryId);
    context->setResult(retval);
    return retval;
}