blob: a80bec3a88e5fe71c720edde4035ec7d59d5cb22 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#include "GroupAttr.h"
#include "AllRelExpr.h"
#include "RelSample.h"
#include "Generator.h"
#include "GenExpGenerator.h"
#include "ExpCriDesc.h"
#include "ComTdbSample.h"
#include "ExplainTupleMaster.h"
// PhysSample::preCodeGen() -------------------------------------------
// Perform local query rewrites such as for the creation and
// population of intermediate tables, for accessing partitioned
// data. Rewrite the value expressions after minimizing the dataflow
// using the transitive closure of equality predicates.
//
// PhysSample::preCodeGen() - is basically the same as the RelExpr::
// preCodeGen() except that here we replace the VEG references in the
// sortKey() list, as well as the selectionPred().
//
// Parameters:
//
// Generator *generator
// IN/OUT : A pointer to the generator object which contains the state,
// and tools (e.g. expression generator) to generate code for
// this node.
//
// ValueIdSet &externalInputs
// IN : The set of external Inputs available to this node.
//
//
RelExpr * PhysSample::preCodeGen(Generator * generator,
const ValueIdSet & externalInputs,
ValueIdSet &pulledNewInputs)
{
// Do nothing if this node has already been processed.
//
if (nodeIsPreCodeGenned())
return this;
// Resolve the VEGReferences and VEGPredicates, if any, that appear
// in the Characteristic Inputs, in terms of the externalInputs.
//
getGroupAttr()->resolveCharacteristicInputs(externalInputs);
// My Characteristics Inputs become the external inputs for my children.
// preCodeGen my only child.
//
ValueIdSet childPulledInputs;
child(0) = child(0)->preCodeGen(generator, externalInputs, pulledNewInputs);
if(!child(0).getPtr())
return NULL;
// Process additional any additional inputs the child wants.
//
getGroupAttr()->addCharacteristicInputs(childPulledInputs);
pulledNewInputs += childPulledInputs;
// The sampledCols() only have access to the Input Values.
// These can come from the parent or be the outputs of the child.
// Compute the set of available values for the sampledCols() and use
// these to resolve any VEG references that the sampledCols() may need.
//
ValueIdSet availableValues;
getInputValuesFromParentAndChildren(availableValues);
sampledColumns().replaceVEGExpressions
(availableValues,
getGroupAttr()->getCharacteristicInputs());
// Ditto, for the balance expression.
//
balanceExpr().replaceVEGExpressions
(availableValues,
getGroupAttr()->getCharacteristicInputs());
requiredOrder().
replaceVEGExpressions(availableValues,
getGroupAttr()->getCharacteristicInputs());
// The selectionPred has access to only the output values generated by
// Sequence and input values from the parent. Compute the set of available
// values for the selectionPred and resolve any VEG references
// that the selection predicates may need.
//
getInputAndPotentialOutputValues(availableValues);
NABoolean replicatePredicates = TRUE;
selectionPred().replaceVEGExpressions
(availableValues,
getGroupAttr()->getCharacteristicInputs(),
FALSE, // no key predicates here
0 /* no need for idempotence here */,
replicatePredicates
);
// Resolve VEG references in the outputs and remove redundant
// outputs.
//
getGroupAttr()->resolveCharacteristicOutputs
(availableValues,
getGroupAttr()->getCharacteristicInputs());
// Mark this node as done and return.
//
markAsPreCodeGenned();
return this;
} // PhysSample::preCodeGen
short
PhysSample::codeGen(Generator *generator)
{
// Get a local handle on some of the generator objects.
//
CollHeap *wHeap = generator->wHeap();
Space *space = generator->getSpace();
MapTable *mapTable = generator->getMapTable();
ExpGenerator *expGen = generator->getExpGenerator();
// Allocate a new map table for this node. This must be done
// before generating the code for my child so that this local
// map table will be sandwiched between the map tables already
// generated and the map tables generated by my offspring.
//
// Only the items available as output from this node will
// be put in the local map table. Before exiting this function, all of
// my offsprings map tables will be removed. Thus, none of the outputs
// from nodes below this node will be visible to nodes above it except
// those placed in the local map table and those that already exist in
// my ancestors map tables. This is the standard mechanism used in the
// generator for managing the access to item expressions.
//
MapTable *localMapTable = generator->appendAtEnd();
// Since this operation doesn't modify the row on the way down the tree,
// go ahead and generate the child subtree. Capture the given composite row
// descriptor and the child's returned TDB and composite row descriptor.
//
ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN);
child(0)->codeGen(generator);
ComTdb *childTdb = (ComTdb*)generator->getGenObj();
ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP);
ExplainTuple *childExplainTuple = generator->getExplainTuple();
// Geneate the sampling expression.
//
ex_expr *balExpr = NULL;
Int32 returnFactorOffset = 0;
ValueId val;
val = balanceExpr().init();
if(balanceExpr().next(val))
expGen->generateSamplingExpr(val, &balExpr, returnFactorOffset);
// Alias the sampleColumns() so that they reference the underlying
// expressions directly. This is done to avoid having to generate and
// execute a project expression that simply moves the columns from
// one tupp to another to reflect the application of the sampledCol
// function.
//
// ValueId valId;
// for(valId = sampledColumns().init();
// sampledColumns().next(valId);
// sampledColumns().advance(valId))
// {
// MapInfo *mapInfoChild = localMapTable->getMapInfoAsIs
// (valId.getItemExpr()->child(0)->castToItemExpr()->getValueId());
// GenAssert(mapInfoChild, "Sample::codeGen -- no child map info.");
// Attributes *attr = mapInfoChild->getAttr();
// MapInfo *mapInfo = localMapTable->addMapInfoToThis(valId, attr);
// mapInfo->codeGenerated();
// }
// check if any of the columns inthe sampled columns are lob columns. If so, return an error.
ValueId valId;
for(valId = sampledColumns().init();
sampledColumns().next(valId);
sampledColumns().advance(valId))
{
const NAType &colType = valId.getType();
if ((colType.getFSDatatype() == REC_BLOB) ||
(colType.getFSDatatype() == REC_CLOB))
{
*CmpCommon::diags() << DgSqlCode(-4322);
GenExit();
}
}
// Now, remove all attributes from the map table except the
// the stuff in the local map table -- the result of this node.
//
// localMapTable->removeAll();
// Generate the expression to evaluate predicate on the sampled row.
//
ex_expr *postPred = 0;
if (!selectionPred().isEmpty()) {
ItemExpr * newPredTree
= selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE);
expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED,
&postPred);
}
// Construct the Sample TDB.
//
ComTdbSample *sampleTdb
= new(space) ComTdbSample(NULL,
balExpr,
returnFactorOffset,
postPred,
childTdb,
givenCriDesc,
childCriDesc,
(queue_index)getDefault(GEN_SAMPLE_SIZE_DOWN),
(queue_index)getDefault(GEN_SAMPLE_SIZE_UP));
generator->initTdbFields(sampleTdb);
if(!generator->explainDisabled()) {
generator->
setExplainTuple(addExplainInfo(sampleTdb,
childExplainTuple,
0,
generator));
}
generator->setCriDesc(givenCriDesc, Generator::DOWN);
generator->setCriDesc(childCriDesc, Generator::UP);
generator->setGenObj(this, sampleTdb);
return 0;
}
ExplainTuple*
PhysSample::addSpecificExplainInfo(ExplainTupleMaster *explainTuple,
ComTdb * tdb,
Generator *generator)
{
NAString buffer = "sample_type: ";
switch(sampleType()) {
case RANDOM:
buffer += "RANDOM ";
break;
case PERIODIC:
buffer += "PERIODIC ";
break;
case FIRSTN:
buffer += "FIRST ";
break;
case CLUSTER:
buffer += "CLUSTER ";
break;
default:
buffer += "UNKNOWN ";
break;
}
explainTuple->setDescription(buffer);
return(explainTuple);
}