本文整理汇总了C++中AbstractExpression::debug方法的典型用法代码示例。如果您正苦于以下问题:C++ AbstractExpression::debug方法的具体用法?C++ AbstractExpression::debug怎么用?C++ AbstractExpression::debug使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类AbstractExpression
的用法示例。
在下文中一共展示了AbstractExpression::debug方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: p_execute
bool IndexScanExecutor::p_execute(const NValueArray ¶ms)
{
assert(m_node);
assert(m_node == dynamic_cast<IndexScanPlanNode*>(m_abstractNode));
// update local target table with its most recent reference
Table* targetTable = m_node->getTargetTable();
TableIndex *tableIndex = targetTable->index(m_node->getTargetIndexName());
IndexCursor indexCursor(tableIndex->getTupleSchema());
TableTuple searchKey(tableIndex->getKeySchema());
searchKey.moveNoHeader(m_searchKeyBackingStore);
assert(m_lookupType != INDEX_LOOKUP_TYPE_EQ ||
searchKey.getSchema()->columnCount() == m_numOfSearchkeys);
int activeNumOfSearchKeys = m_numOfSearchkeys;
IndexLookupType localLookupType = m_lookupType;
SortDirectionType localSortDirection = m_sortDirection;
//
// INLINE LIMIT
//
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(m_abstractNode->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
TableTuple temp_tuple;
ProgressMonitorProxy pmp(m_engine, this);
if (m_aggExec != NULL) {
const TupleSchema * inputSchema = tableIndex->getTupleSchema();
if (m_projectionNode != NULL) {
inputSchema = m_projectionNode->getOutputTable()->schema();
}
temp_tuple = m_aggExec->p_execute_init(params, &pmp, inputSchema, m_outputTable);
} else {
temp_tuple = m_outputTable->tempTuple();
}
// Short-circuit an empty scan
if (m_node->isEmptyScan()) {
VOLT_DEBUG ("Empty Index Scan :\n %s", m_outputTable->debug().c_str());
if (m_aggExec != NULL) {
m_aggExec->p_execute_finish();
}
return true;
}
//
// SEARCH KEY
//
bool earlyReturnForSearchKeyOutOfRange = false;
searchKey.setAllNulls();
VOLT_TRACE("Initial (all null) search key: '%s'", searchKey.debugNoHeader().c_str());
for (int ctr = 0; ctr < activeNumOfSearchKeys; ctr++) {
NValue candidateValue = m_searchKeyArray[ctr]->eval(NULL, NULL);
if (candidateValue.isNull()) {
// when any part of the search key is NULL, the result is false when it compares to anything.
// do early return optimization, our index comparator may not handle null comparison correctly.
earlyReturnForSearchKeyOutOfRange = true;
break;
}
try {
searchKey.setNValue(ctr, candidateValue);
}
catch (const SQLException &e) {
// This next bit of logic handles underflow, overflow and search key length
// exceeding variable length column size (variable lenght mismatch) when
// setting up the search keys.
// e.g. TINYINT > 200 or INT <= 6000000000
// VarChar(3 bytes) < "abcd" or VarChar(3) > "abbd"
// re-throw if not an overflow, underflow or variable length mismatch
// currently, it's expected to always be an overflow or underflow
if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW | SQLException::TYPE_VAR_LENGTH_MISMATCH)) == 0) {
throw e;
}
// handle the case where this is a comparison, rather than equality match
// comparison is the only place where the executor might return matching tuples
// e.g. TINYINT < 1000 should return all values
if ((localLookupType != INDEX_LOOKUP_TYPE_EQ) &&
(ctr == (activeNumOfSearchKeys - 1))) {
if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
if ((localLookupType == INDEX_LOOKUP_TYPE_GT) ||
(localLookupType == INDEX_LOOKUP_TYPE_GTE)) {
// gt or gte when key overflows returns nothing except inline agg
earlyReturnForSearchKeyOutOfRange = true;
break;
}
else {
// for overflow on reverse scan, we need to
// do a forward scan to find the correct start
// point, which is exactly what LTE would do.
// so, set the lookupType to LTE and the missing
// searchkey will be handled by extra post filters
localLookupType = INDEX_LOOKUP_TYPE_LTE;
//.........这里部分代码省略.........
示例2: p_execute
bool SeqScanExecutor::p_execute(const NValueArray ¶ms) {
SeqScanPlanNode* node = dynamic_cast<SeqScanPlanNode*>(m_abstractNode);
assert(node);
Table* output_table = node->getOutputTable();
assert(output_table);
Table* input_table = (node->isSubQuery()) ?
node->getChildren()[0]->getOutputTable():
node->getTargetTable();
assert(input_table);
//* for debug */std::cout << "SeqScanExecutor: node id " << node->getPlanNodeId() <<
//* for debug */ " input table " << (void*)input_table <<
//* for debug */ " has " << input_table->activeTupleCount() << " tuples " << std::endl;
VOLT_TRACE("Sequential Scanning table :\n %s",
input_table->debug().c_str());
VOLT_DEBUG("Sequential Scanning table : %s which has %d active, %d"
" allocated",
input_table->name().c_str(),
(int)input_table->activeTupleCount(),
(int)input_table->allocatedTupleCount());
//
// OPTIMIZATION: NESTED PROJECTION
//
// Since we have the input params, we need to call substitute to
// change any nodes in our expression tree to be ready for the
// projection operations in execute
//
int num_of_columns = -1;
ProjectionPlanNode* projection_node = dynamic_cast<ProjectionPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_PROJECTION));
if (projection_node != NULL) {
num_of_columns = static_cast<int> (projection_node->getOutputColumnExpressions().size());
}
//
// OPTIMIZATION: NESTED LIMIT
// How nice! We can also cut off our scanning with a nested limit!
//
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
//
// OPTIMIZATION:
//
// If there is no predicate and no Projection for this SeqScan,
// then we have already set the node's OutputTable to just point
// at the TargetTable. Therefore, there is nothing we more we need
// to do here
//
if (node->getPredicate() != NULL || projection_node != NULL ||
limit_node != NULL || m_aggExec != NULL)
{
//
// Just walk through the table using our iterator and apply
// the predicate to each tuple. For each tuple that satisfies
// our expression, we'll insert them into the output table.
//
TableTuple tuple(input_table->schema());
TableIterator iterator = input_table->iteratorDeletingAsWeGo();
AbstractExpression *predicate = node->getPredicate();
if (predicate)
{
VOLT_TRACE("SCAN PREDICATE A:\n%s\n", predicate->debug(true).c_str());
}
int limit = -1;
int offset = -1;
if (limit_node) {
limit_node->getLimitAndOffsetByReference(params, limit, offset);
}
int tuple_ctr = 0;
int tuple_skipped = 0;
TempTable* output_temp_table = dynamic_cast<TempTable*>(output_table);
ProgressMonitorProxy pmp(m_engine, this, node->isSubQuery() ? NULL : input_table);
TableTuple temp_tuple;
if (m_aggExec != NULL) {
const TupleSchema * inputSchema = input_table->schema();
if (projection_node != NULL) {
inputSchema = projection_node->getOutputTable()->schema();
}
temp_tuple = m_aggExec->p_execute_init(params, &pmp,
inputSchema, output_temp_table);
} else {
temp_tuple = output_temp_table->tempTuple();
}
while ((limit == -1 || tuple_ctr < limit) && iterator.next(tuple))
{
VOLT_TRACE("INPUT TUPLE: %s, %d/%d\n",
tuple.debug(input_table->name()).c_str(), tuple_ctr,
(int)input_table->activeTupleCount());
pmp.countdownProgress();
//
// For each tuple we need to evaluate it against our predicate
//
if (predicate == NULL || predicate->eval(&tuple, NULL).isTrue())
{
//.........这里部分代码省略.........
示例3: p_execute
bool IndexScanExecutor::p_execute(const NValueArray ¶ms)
{
assert(m_node);
assert(m_node == dynamic_cast<IndexScanPlanNode*>(m_abstractNode));
assert(m_outputTable);
assert(m_outputTable == static_cast<TempTable*>(m_node->getOutputTable()));
// update local target table with its most recent reference
Table* targetTable = m_node->getTargetTable();
TableIndex *tableIndex = targetTable->index(m_node->getTargetIndexName());
TableTuple searchKey(tableIndex->getKeySchema());
searchKey.moveNoHeader(m_searchKeyBackingStore);
assert(m_lookupType != INDEX_LOOKUP_TYPE_EQ ||
searchKey.getSchema()->columnCount() == m_numOfSearchkeys);
int activeNumOfSearchKeys = m_numOfSearchkeys;
IndexLookupType localLookupType = m_lookupType;
SortDirectionType localSortDirection = m_sortDirection;
// INLINE PROJECTION
// Set params to expression tree via substitute()
assert(m_numOfColumns == m_outputTable->columnCount());
if (m_projectionNode != NULL && m_projectionAllTupleArray == NULL)
{
for (int ctr = 0; ctr < m_numOfColumns; ctr++)
{
assert(m_projectionNode->getOutputColumnExpressions()[ctr]);
m_projectionExpressions[ctr]->substitute(params);
assert(m_projectionExpressions[ctr]);
}
}
//
// INLINE LIMIT
//
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(m_abstractNode->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
//
// SEARCH KEY
//
searchKey.setAllNulls();
VOLT_TRACE("Initial (all null) search key: '%s'", searchKey.debugNoHeader().c_str());
for (int ctr = 0; ctr < activeNumOfSearchKeys; ctr++) {
m_searchKeyArray[ctr]->substitute(params);
NValue candidateValue = m_searchKeyArray[ctr]->eval(NULL, NULL);
try {
searchKey.setNValue(ctr, candidateValue);
}
catch (const SQLException &e) {
// This next bit of logic handles underflow and overflow while
// setting up the search keys.
// e.g. TINYINT > 200 or INT <= 6000000000
// re-throw if not an overflow or underflow
// currently, it's expected to always be an overflow or underflow
if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
throw e;
}
// handle the case where this is a comparison, rather than equality match
// comparison is the only place where the executor might return matching tuples
// e.g. TINYINT < 1000 should return all values
if ((localLookupType != INDEX_LOOKUP_TYPE_EQ) &&
(ctr == (activeNumOfSearchKeys - 1))) {
if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
if ((localLookupType == INDEX_LOOKUP_TYPE_GT) ||
(localLookupType == INDEX_LOOKUP_TYPE_GTE)) {
// gt or gte when key overflows returns nothing
return true;
}
else {
// for overflow on reverse scan, we need to
// do a forward scan to find the correct start
// point, which is exactly what LTE would do.
// so, set the lookupType to LTE and the missing
// searchkey will be handled by extra post filters
localLookupType = INDEX_LOOKUP_TYPE_LTE;
}
}
if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
if ((localLookupType == INDEX_LOOKUP_TYPE_LT) ||
(localLookupType == INDEX_LOOKUP_TYPE_LTE)) {
// lt or lte when key underflows returns nothing
return true;
}
else {
// don't allow GTE because it breaks null handling
localLookupType = INDEX_LOOKUP_TYPE_GT;
}
}
// if here, means all tuples with the previous searchkey
// columns need to be scaned. Note, if only one column,
// then all tuples will be scanned
activeNumOfSearchKeys--;
if (localSortDirection == SORT_DIRECTION_TYPE_INVALID) {
//.........这里部分代码省略.........
示例4: p_execute
bool SeqScanExecutor::p_execute(const NValueArray ¶ms) {
SeqScanPlanNode* node = dynamic_cast<SeqScanPlanNode*>(m_abstractNode);
assert(node);
Table* output_table = node->getOutputTable();
assert(output_table);
Table* target_table = dynamic_cast<Table*>(node->getTargetTable());
assert(target_table);
//cout << "SeqScanExecutor: node id" << node->getPlanNodeId() << endl;
VOLT_TRACE("Sequential Scanning table :\n %s",
target_table->debug().c_str());
VOLT_DEBUG("Sequential Scanning table : %s which has %d active, %d"
" allocated, %d used tuples",
target_table->name().c_str(),
(int)target_table->activeTupleCount(),
(int)target_table->allocatedTupleCount(),
(int)target_table->usedTupleCount());
//
// OPTIMIZATION: NESTED PROJECTION
//
// Since we have the input params, we need to call substitute to
// change any nodes in our expression tree to be ready for the
// projection operations in execute
//
int num_of_columns = (int)output_table->columnCount();
ProjectionPlanNode* projection_node = dynamic_cast<ProjectionPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_PROJECTION));
if (projection_node != NULL) {
for (int ctr = 0; ctr < num_of_columns; ctr++) {
assert(projection_node->getOutputColumnExpressions()[ctr]);
projection_node->getOutputColumnExpressions()[ctr]->substitute(params);
}
}
//
// OPTIMIZATION: NESTED LIMIT
// How nice! We can also cut off our scanning with a nested limit!
//
int limit = -1;
int offset = -1;
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
if (limit_node != NULL) {
limit_node->getLimitAndOffsetByReference(params, limit, offset);
}
//
// OPTIMIZATION:
//
// If there is no predicate and no Projection for this SeqScan,
// then we have already set the node's OutputTable to just point
// at the TargetTable. Therefore, there is nothing we more we need
// to do here
//
if (node->getPredicate() != NULL || projection_node != NULL ||
limit_node != NULL)
{
//
// Just walk through the table using our iterator and apply
// the predicate to each tuple. For each tuple that satisfies
// our expression, we'll insert them into the output table.
//
TableTuple tuple(target_table->schema());
TableIterator iterator = target_table->iterator();
AbstractExpression *predicate = node->getPredicate();
VOLT_TRACE("SCAN PREDICATE A:\n%s\n", predicate->debug(true).c_str());
if (predicate)
{
predicate->substitute(params);
assert(predicate != NULL);
VOLT_DEBUG("SCAN PREDICATE B:\n%s\n",
predicate->debug(true).c_str());
}
int tuple_ctr = 0;
int tuple_skipped = 0;
while (iterator.next(tuple))
{
VOLT_TRACE("INPUT TUPLE: %s, %d/%d\n",
tuple.debug(target_table->name()).c_str(), tuple_ctr,
(int)target_table->activeTupleCount());
//
// For each tuple we need to evaluate it against our predicate
//
if (predicate == NULL || predicate->eval(&tuple, NULL).isTrue())
{
// Check if we have to skip this tuple because of offset
if (tuple_skipped < offset) {
tuple_skipped++;
continue;
}
//
// Nested Projection
// Project (or replace) values from input tuple
//
if (projection_node != NULL)
{
TableTuple &temp_tuple = output_table->tempTuple();
for (int ctr = 0; ctr < num_of_columns; ctr++)
{
//.........这里部分代码省略.........
示例5: p_execute
bool NestLoopExecutor::p_execute(const NValueArray ¶ms) {
VOLT_DEBUG("executing NestLoop...");
NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(m_abstractNode);
assert(node);
assert(node->getInputTables().size() == 2);
Table* output_table_ptr = node->getOutputTable();
assert(output_table_ptr);
// output table must be a temp table
TempTable* output_table = dynamic_cast<TempTable*>(output_table_ptr);
assert(output_table);
Table* outer_table = node->getInputTables()[0];
assert(outer_table);
Table* inner_table = node->getInputTables()[1];
assert(inner_table);
VOLT_TRACE ("input table left:\n %s", outer_table->debug().c_str());
VOLT_TRACE ("input table right:\n %s", inner_table->debug().c_str());
//
// Pre Join Expression
//
AbstractExpression *preJoinPredicate = node->getPreJoinPredicate();
if (preJoinPredicate) {
preJoinPredicate->substitute(params);
VOLT_TRACE ("Pre Join predicate: %s", preJoinPredicate == NULL ?
"NULL" : preJoinPredicate->debug(true).c_str());
}
//
// Join Expression
//
AbstractExpression *joinPredicate = node->getJoinPredicate();
if (joinPredicate) {
joinPredicate->substitute(params);
VOLT_TRACE ("Join predicate: %s", joinPredicate == NULL ?
"NULL" : joinPredicate->debug(true).c_str());
}
//
// Where Expression
//
AbstractExpression *wherePredicate = node->getWherePredicate();
if (wherePredicate) {
wherePredicate->substitute(params);
VOLT_TRACE ("Where predicate: %s", wherePredicate == NULL ?
"NULL" : wherePredicate->debug(true).c_str());
}
// Join type
JoinType join_type = node->getJoinType();
assert(join_type == JOIN_TYPE_INNER || join_type == JOIN_TYPE_LEFT);
int outer_cols = outer_table->columnCount();
int inner_cols = inner_table->columnCount();
TableTuple outer_tuple(node->getInputTables()[0]->schema());
TableTuple inner_tuple(node->getInputTables()[1]->schema());
TableTuple &joined = output_table->tempTuple();
TableTuple null_tuple = m_null_tuple;
TableIterator iterator0 = outer_table->iterator();
while (iterator0.next(outer_tuple)) {
// did this loop body find at least one match for this tuple?
bool match = false;
// For outer joins if outer tuple fails pre-join predicate
// (join expression based on the outer table only)
// it can't match any of inner tuples
if (preJoinPredicate == NULL || preJoinPredicate->eval(&outer_tuple, NULL).isTrue()) {
// populate output table's temp tuple with outer table's values
// probably have to do this at least once - avoid doing it many
// times per outer tuple
joined.setNValues(0, outer_tuple, 0, outer_cols);
TableIterator iterator1 = inner_table->iterator();
while (iterator1.next(inner_tuple)) {
// Apply join filter to produce matches for each outer that has them,
// then pad unmatched outers, then filter them all
if (joinPredicate == NULL || joinPredicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
match = true;
// Filter the joined tuple
if (wherePredicate == NULL || wherePredicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
// Matched! Complete the joined tuple with the inner column values.
joined.setNValues(outer_cols, inner_tuple, 0, inner_cols);
output_table->insertTupleNonVirtual(joined);
}
}
}
}
//
// Left Outer Join
//
if (join_type == JOIN_TYPE_LEFT && !match) {
// Still needs to pass the filter
if (wherePredicate == NULL || wherePredicate->eval(&outer_tuple, &null_tuple).isTrue()) {
joined.setNValues(outer_cols, null_tuple, 0, inner_cols);
output_table->insertTupleNonVirtual(joined);
//.........这里部分代码省略.........
示例6: p_execute
bool IndexCountExecutor::p_execute(const NValueArray ¶ms)
{
assert(m_node);
assert(m_node == dynamic_cast<IndexCountPlanNode*>(m_abstractNode));
assert(m_outputTable);
assert(m_outputTable == static_cast<TempTable*>(m_node->getOutputTable()));
assert(m_targetTable);
assert(m_targetTable == m_node->getTargetTable());
VOLT_DEBUG("IndexCount: %s.%s\n", m_targetTable->name().c_str(),
m_index->getName().c_str());
int activeNumOfSearchKeys = m_numOfSearchkeys;
IndexLookupType localLookupType = m_lookupType;
bool searchKeyUnderflow = false, endKeyOverflow = false;
// Overflow cases that can return early without accessing the index need this
// default 0 count as their result.
TableTuple& tmptup = m_outputTable->tempTuple();
tmptup.setNValue(0, ValueFactory::getBigIntValue( 0 ));
//
// SEARCH KEY
//
if (m_numOfSearchkeys != 0) {
m_searchKey.setAllNulls();
VOLT_DEBUG("<Index Count>Initial (all null) search key: '%s'", m_searchKey.debugNoHeader().c_str());
for (int ctr = 0; ctr < activeNumOfSearchKeys; ctr++) {
m_searchKeyArray[ctr]->substitute(params);
NValue candidateValue = m_searchKeyArray[ctr]->eval(NULL, NULL);
try {
m_searchKey.setNValue(ctr, candidateValue);
}
catch (const SQLException &e) {
// This next bit of logic handles underflow and overflow while
// setting up the search keys.
// e.g. TINYINT > 200 or INT <= 6000000000
// re-throw if not an overflow or underflow
// currently, it's expected to always be an overflow or underflow
if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
throw e;
}
// handle the case where this is a comparison, rather than equality match
// comparison is the only place where the executor might return matching tuples
// e.g. TINYINT < 1000 should return all values
if ((localLookupType != INDEX_LOOKUP_TYPE_EQ) &&
(ctr == (activeNumOfSearchKeys - 1))) {
assert (localLookupType == INDEX_LOOKUP_TYPE_GT || localLookupType == INDEX_LOOKUP_TYPE_GTE);
if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
m_outputTable->insertTuple(tmptup);
return true;
} else if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
searchKeyUnderflow = true;
break;
} else {
throw e;
}
}
// if a EQ comparision is out of range, then return no tuples
else {
m_outputTable->insertTuple(tmptup);
return true;
}
break;
}
}
VOLT_TRACE("Search key after substitutions: '%s'", m_searchKey.debugNoHeader().c_str());
}
if (m_numOfEndkeys != 0) {
//
// END KEY
//
m_endKey.setAllNulls();
VOLT_DEBUG("Initial (all null) end key: '%s'", m_endKey.debugNoHeader().c_str());
for (int ctr = 0; ctr < m_numOfEndkeys; ctr++) {
m_endKeyArray[ctr]->substitute(params);
NValue endKeyValue = m_endKeyArray[ctr]->eval(NULL, NULL);
try {
m_endKey.setNValue(ctr, endKeyValue);
}
catch (const SQLException &e) {
// This next bit of logic handles underflow and overflow while
// setting up the search keys.
// e.g. TINYINT > 200 or INT <= 6000000000
// re-throw if not an overflow or underflow
// currently, it's expected to always be an overflow or underflow
if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
throw e;
}
if (ctr == (m_numOfEndkeys - 1)) {
assert (m_endType == INDEX_LOOKUP_TYPE_LT || m_endType == INDEX_LOOKUP_TYPE_LTE);
if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
m_outputTable->insertTuple(tmptup);
return true;
} else if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
//.........这里部分代码省略.........
示例7: p_execute
bool NestLoopExecutor::p_execute(const NValueArray ¶ms, ReadWriteTracker *tracker) {
VOLT_DEBUG("executing NestLoop...");
NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(abstract_node);
assert(node);
assert(node->getInputTables().size() == 2);
Table* output_table_ptr = node->getOutputTable();
assert(output_table_ptr);
// output table must be a temp table
TempTable* output_table = dynamic_cast<TempTable*>(output_table_ptr);
assert(output_table);
Table* outer_table = node->getInputTables()[0];
assert(outer_table);
Table* inner_table = node->getInputTables()[1];
assert(inner_table);
VOLT_TRACE ("input table left:\n %s", outer_table->debug().c_str());
VOLT_TRACE ("input table right:\n %s", inner_table->debug().c_str());
//
// Join Expression
//
AbstractExpression *predicate = node->getPredicate();
if (predicate) {
predicate->substitute(params);
VOLT_TRACE ("predicate: %s", predicate == NULL ?
"NULL" : predicate->debug(true).c_str());
}
int outer_cols = outer_table->columnCount();
int inner_cols = inner_table->columnCount();
TableTuple outer_tuple(node->getInputTables()[0]->schema());
TableTuple inner_tuple(node->getInputTables()[1]->schema());
TableTuple &joined = output_table->tempTuple();
TableIterator iterator0(outer_table);
while (iterator0.next(outer_tuple)) {
// populate output table's temp tuple with outer table's values
// probably have to do this at least once - avoid doing it many
// times per outer tuple
for (int col_ctr = 0; col_ctr < outer_cols; col_ctr++) {
joined.setNValue(col_ctr, outer_tuple.getNValue(col_ctr));
}
TableIterator iterator1(inner_table);
while (iterator1.next(inner_tuple)) {
if (predicate == NULL || predicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
// Matched! Complete the joined tuple with the inner column values.
for (int col_ctr = 0; col_ctr < inner_cols; col_ctr++) {
joined.setNValue(col_ctr + outer_cols, inner_tuple.getNValue(col_ctr));
}
output_table->insertTupleNonVirtual(joined);
}
}
}
return (true);
}
示例8: p_execute
bool NestLoopExecutor::p_execute(const NValueArray ¶ms) {
VOLT_DEBUG("executing NestLoop...");
NestLoopPlanNode* node = dynamic_cast<NestLoopPlanNode*>(m_abstractNode);
assert(node);
assert(node->getInputTableCount() == 2);
// output table must be a temp table
assert(m_tmpOutputTable);
Table* outer_table = node->getInputTable();
assert(outer_table);
Table* inner_table = node->getInputTable(1);
assert(inner_table);
VOLT_TRACE ("input table left:\n %s", outer_table->debug().c_str());
VOLT_TRACE ("input table right:\n %s", inner_table->debug().c_str());
//
// Pre Join Expression
//
AbstractExpression *preJoinPredicate = node->getPreJoinPredicate();
if (preJoinPredicate) {
VOLT_TRACE ("Pre Join predicate: %s", preJoinPredicate == NULL ?
"NULL" : preJoinPredicate->debug(true).c_str());
}
//
// Join Expression
//
AbstractExpression *joinPredicate = node->getJoinPredicate();
if (joinPredicate) {
VOLT_TRACE ("Join predicate: %s", joinPredicate == NULL ?
"NULL" : joinPredicate->debug(true).c_str());
}
//
// Where Expression
//
AbstractExpression *wherePredicate = node->getWherePredicate();
if (wherePredicate) {
VOLT_TRACE ("Where predicate: %s", wherePredicate == NULL ?
"NULL" : wherePredicate->debug(true).c_str());
}
// Join type
JoinType join_type = node->getJoinType();
assert(join_type == JOIN_TYPE_INNER || join_type == JOIN_TYPE_LEFT);
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
int limit = -1;
int offset = -1;
if (limit_node) {
limit_node->getLimitAndOffsetByReference(params, limit, offset);
}
int outer_cols = outer_table->columnCount();
int inner_cols = inner_table->columnCount();
TableTuple outer_tuple(node->getInputTable(0)->schema());
TableTuple inner_tuple(node->getInputTable(1)->schema());
const TableTuple& null_tuple = m_null_tuple.tuple();
TableIterator iterator0 = outer_table->iteratorDeletingAsWeGo();
int tuple_ctr = 0;
int tuple_skipped = 0;
ProgressMonitorProxy pmp(m_engine, this, inner_table);
TableTuple join_tuple;
if (m_aggExec != NULL) {
VOLT_TRACE("Init inline aggregate...");
const TupleSchema * aggInputSchema = node->getTupleSchemaPreAgg();
join_tuple = m_aggExec->p_execute_init(params, &pmp, aggInputSchema, m_tmpOutputTable);
} else {
join_tuple = m_tmpOutputTable->tempTuple();
}
bool earlyReturned = false;
while ((limit == -1 || tuple_ctr < limit) && iterator0.next(outer_tuple)) {
pmp.countdownProgress();
// populate output table's temp tuple with outer table's values
// probably have to do this at least once - avoid doing it many
// times per outer tuple
join_tuple.setNValues(0, outer_tuple, 0, outer_cols);
// did this loop body find at least one match for this tuple?
bool match = false;
// For outer joins if outer tuple fails pre-join predicate
// (join expression based on the outer table only)
// it can't match any of inner tuples
if (preJoinPredicate == NULL || preJoinPredicate->eval(&outer_tuple, NULL).isTrue()) {
// By default, the delete as we go flag is false.
TableIterator iterator1 = inner_table->iterator();
while ((limit == -1 || tuple_ctr < limit) && iterator1.next(inner_tuple)) {
pmp.countdownProgress();
// Apply join filter to produce matches for each outer that has them,
// then pad unmatched outers, then filter them all
if (joinPredicate == NULL || joinPredicate->eval(&outer_tuple, &inner_tuple).isTrue()) {
match = true;
// Filter the joined tuple
//.........这里部分代码省略.........
示例9: p_execute
bool NestLoopIndexExecutor::p_execute(const NValueArray ¶ms)
{
assert(dynamic_cast<NestLoopIndexPlanNode*>(m_abstractNode));
NestLoopIndexPlanNode* node = static_cast<NestLoopIndexPlanNode*>(m_abstractNode);
// output table must be a temp table
assert(m_tmpOutputTable);
// target table is a persistent table
assert(dynamic_cast<PersistentTable*>(m_indexNode->getTargetTable()));
PersistentTable* inner_table = static_cast<PersistentTable*>(m_indexNode->getTargetTable());
TableIndex* index = inner_table->index(m_indexNode->getTargetIndexName());
assert(index);
IndexCursor indexCursor(index->getTupleSchema());
//outer_table is the input table that have tuples to be iterated
assert(node->getInputTableCount() == 1);
Table* outer_table = node->getInputTable();
assert(outer_table);
VOLT_TRACE("executing NestLoopIndex with outer table: %s, inner table: %s",
outer_table->debug().c_str(), inner_table->debug().c_str());
//
// Substitute parameter to SEARCH KEY Note that the expressions
// will include TupleValueExpression even after this substitution
//
int num_of_searchkeys = static_cast <int> (m_indexNode->getSearchKeyExpressions().size());
for (int ctr = 0; ctr < num_of_searchkeys; ctr++) {
VOLT_TRACE("Search Key[%d]:\n%s",
ctr, m_indexNode->getSearchKeyExpressions()[ctr]->debug(true).c_str());
}
// end expression
AbstractExpression* end_expression = m_indexNode->getEndExpression();
if (end_expression) {
VOLT_TRACE("End Expression:\n%s", end_expression->debug(true).c_str());
}
// post expression
AbstractExpression* post_expression = m_indexNode->getPredicate();
if (post_expression != NULL) {
VOLT_TRACE("Post Expression:\n%s", post_expression->debug(true).c_str());
}
// initial expression
AbstractExpression* initial_expression = m_indexNode->getInitialExpression();
if (initial_expression != NULL) {
VOLT_TRACE("Initial Expression:\n%s", initial_expression->debug(true).c_str());
}
// SKIP NULL EXPRESSION
AbstractExpression* skipNullExpr = m_indexNode->getSkipNullPredicate();
// For reverse scan edge case NULL values and forward scan underflow case.
if (skipNullExpr != NULL) {
VOLT_DEBUG("Skip NULL Expression:\n%s", skipNullExpr->debug(true).c_str());
}
// pre join expression
AbstractExpression* prejoin_expression = node->getPreJoinPredicate();
if (prejoin_expression != NULL) {
VOLT_TRACE("Prejoin Expression:\n%s", prejoin_expression->debug(true).c_str());
}
// where expression
AbstractExpression* where_expression = node->getWherePredicate();
if (where_expression != NULL) {
VOLT_TRACE("Where Expression:\n%s", where_expression->debug(true).c_str());
}
LimitPlanNode* limit_node = dynamic_cast<LimitPlanNode*>(node->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT));
int limit = CountingPostfilter::NO_LIMIT;
int offset = CountingPostfilter::NO_OFFSET;
if (limit_node) {
limit_node->getLimitAndOffsetByReference(params, limit, offset);
}
// Init the postfilter
CountingPostfilter postfilter(m_tmpOutputTable, where_expression, limit, offset);
//
// OUTER TABLE ITERATION
//
TableTuple outer_tuple(outer_table->schema());
TableTuple inner_tuple(inner_table->schema());
TableIterator outer_iterator = outer_table->iteratorDeletingAsWeGo();
int num_of_outer_cols = outer_table->columnCount();
assert (outer_tuple.sizeInValues() == outer_table->columnCount());
assert (inner_tuple.sizeInValues() == inner_table->columnCount());
const TableTuple &null_inner_tuple = m_null_inner_tuple.tuple();
ProgressMonitorProxy pmp(m_engine->getExecutorContext(), this);
// The table filter to keep track of inner tuples that don't match any of outer tuples for FULL joins
TableTupleFilter innerTableFilter;
if (m_joinType == JOIN_TYPE_FULL) {
// Prepopulate the set with all inner tuples
innerTableFilter.init(inner_table);
}
TableTuple join_tuple;
// It's not immediately obvious here, so there's some subtlety to
// note with respect to the schema of the join_tuple.
//.........这里部分代码省略.........