bool OrderByExecutor::p_init(AbstractPlanNode* abstract_node, TempTableLimits* limits) { VOLT_TRACE("init OrderBy Executor"); OrderByPlanNode* node = dynamic_cast<OrderByPlanNode*>(abstract_node); assert(node); if (!node->isInline()) { assert(node->getInputTableCount() == 1); assert(node->getChildren()[0] != NULL); // // Our output table should look exactly like our input table // node-> setOutputTable(TableFactory:: getCopiedTempTable(node->databaseId(), node->getInputTable()->name(), node->getInputTable(), limits)); // pickup an inlined limit, if one exists limit_node = dynamic_cast<LimitPlanNode*>(node-> getInlinePlanNode(PLAN_NODE_TYPE_LIMIT)); } else { assert(node->getChildren().empty()); assert(node->getInlinePlanNode(PLAN_NODE_TYPE_LIMIT) == NULL); } #if defined(VOLT_LOG_LEVEL) #if VOLT_LOG_LEVEL<=VOLT_LEVEL_TRACE const std::vector<AbstractExpression*>& sortExprs = node->getSortExpressions(); for (int i = 0; i < sortExprs.size(); ++i) { VOLT_TRACE("Sort key[%d]:\n%s", i, sortExprs[i]->debug(true).c_str()); } #endif #endif return true; }
bool OrderByExecutor::p_execute(const NValueArray ¶ms) { OrderByPlanNode* node = dynamic_cast<OrderByPlanNode*>(m_abstractNode); assert(node); TempTable* output_table = dynamic_cast<TempTable*>(node->getOutputTable()); assert(output_table); Table* input_table = node->getInputTable(); assert(input_table); // // OPTIMIZATION: NESTED LIMIT // How nice! We can also cut off our scanning with a nested limit! // int limit = -1; int offset = -1; if (limit_node != NULL) { limit_node->getLimitAndOffsetByReference(params, limit, offset); } VOLT_TRACE("Running OrderBy '%s'", m_abstractNode->debug().c_str()); VOLT_TRACE("Input Table:\n '%s'", input_table->debug().c_str()); TableIterator iterator = input_table->iterator(); TableTuple tuple(input_table->schema()); vector<TableTuple> xs; ProgressMonitorProxy pmp(m_engine, this); while (iterator.next(tuple)) { pmp.countdownProgress(); assert(tuple.isActive()); xs.push_back(tuple); } VOLT_TRACE("\n***** Input Table PreSort:\n '%s'", input_table->debug().c_str()); if (limit >= 0 && xs.begin() + limit + offset < xs.end()) { // partial sort partial_sort(xs.begin(), xs.begin() + limit + offset, xs.end(), AbstractExecutor::TupleComparer(node->getSortExpressions(), node->getSortDirections())); } else { // full sort sort(xs.begin(), xs.end(), AbstractExecutor::TupleComparer(node->getSortExpressions(), node->getSortDirections())); } int tuple_ctr = 0; int tuple_skipped = 0; for (vector<TableTuple>::iterator it = xs.begin(); it != xs.end(); it++) { // // Check if has gone past the offset // if (tuple_skipped < offset) { tuple_skipped++; continue; } VOLT_TRACE("\n***** Input Table PostSort:\n '%s'", input_table->debug().c_str()); output_table->insertTupleNonVirtual(*it); pmp.countdownProgress(); // // Check whether we have gone past our limit // if (limit >= 0 && ++tuple_ctr >= limit) { break; } } VOLT_TRACE("Result of OrderBy:\n '%s'", output_table->debug().c_str()); cleanupInputTempTable(input_table); return true; }