blob: fcc8c303ea7747943270fb8a4e0bb09f3fffa7c7 [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 @@@
**********************************************************************/
#ifndef GEN_EXPGENERATOR_H
#define GEN_EXPGENERATOR_H
/* -*-C++-*-
*****************************************************************************
*
* File: GenExpGenerator.h
* Description: This class defines the expression generator.
*
*
* Created: 4/15/95
* Language: C++
*
*
*
*
*****************************************************************************
*/
#include "Generator.h"
#include "exp_expr.h"
#include "GenMapTable.h"
#include "ComSpace.h"
#include "exp_tuple_desc.h"
#include "parser.h"
#include "ComKeyRange.h"
#include "charinfo.h"
class RETDesc;
class IndexDesc;
class NAColumnArray;
class SearchKey;
class NAType;
class MdamKey;
class NAFileSet;
class Queue;
typedef const NAString *ConstNAStringPtr;
typedef const QualifiedName *ConstQualifiedNamePtr;
/////////////////////////////////////////////////////////////////////
// class AListNode.
// This is a simple implementation of a list. Only operations
// supported are appending to end of list and retrieving an
// element. Used to keep track of generated clauses (to back patch
// next clause address) and constants in the expression (to save
// constants at the end of expression generation). The last node
// of the list is the node whose element pointer is null.
/////////////////////////////////////////////////////////////////////
class AListNode0 : public NABasicObject
{
void * element;
AListNode0 *next;
CollHeap* wHeap_;
void addLast(void *element_)
{
if (!next) {
element = element_;
next = new(wHeap_) AListNode0(wHeap_);
}
}
public:
AListNode0(CollHeap* wHeap=CmpCommon::statementHeap())
{
element = 0;
next = 0;
wHeap_ = wHeap;
};
~AListNode0()
{
if (next)
{
delete next;
element = 0;
next = 0;
}
};
inline void * getElement(){return element;};
inline AListNode0 * getNext(){return next;};
void linkElement(void *element_)
{
// NB: prefer iteration over recursion because:
// 1) iteration is more efficient
// 2) recursion can overflow the stack
if (!next) {
addLast(element_);
}
else {
AListNode0 *predecessor = next;
AListNode0 *successor = next;
while (successor) {
predecessor = successor;
successor = successor->getNext();
}
predecessor->addLast(element_);
}
};
};
/////////////////////////////////////////////////////////////////////
// AListNode appends take O(1) instead of O(n) time
/////////////////////////////////////////////////////////////////////
class AListNode : public NABasicObject
{
AListNode0 *head_;
AListNode0 *tail_;
public:
AListNode(CollHeap* wHeap=CmpCommon::statementHeap()) : tail_(0) {
head_ = new (wHeap) AListNode0(wHeap);
};
~AListNode() {
if (head_) {
delete head_;
head_ = NULL;
}
tail_ = NULL;
};
void * getElement() { return head_->getElement(); };
AListNode0 * getNext() { return head_->getNext(); };
AListNode0 * getHead() { return head_; };
void linkElement(void *element_) {
if (!tail_) {
tail_ = head_;
}
tail_->linkElement(element_);
tail_ = tail_->getNext();
};
};
/////////////////////////////////////////////////////////////////
// class ExpGeneratorCacheSubstitution
//
// This class is used by ExpGeneratorCache to keep track of
// which expressions have been substituted for which in the
// course of common subexpression elimination. We need to keep
// track of this because we must undo it when we leave the
// context of an expression.
//
// For example, suppose that two equivalent ItemExprs are returned
// from DP2, and one of these is a characteristic output of the
// PartitionAccess node above the DP2 subtree. When PartitionAccess::codeGen
// generates the DP2 root move expression, it inserts Convert nodes
// on top of these ItemExprs so that the values can be moved into
// contiguous space. This has the effect of making these ItemExprs
// into temporary variables from the point of view of the move expression.
// and therefore we will do common subexpression elimination on them,
// setting the valueId in one to that of the other. Suppose by chance,
// the valueId that is in the characteristic output has been replaced.
//
// When the Generator pops back into Executor context (to generate
// the Executor side of the PartitionAccess), it wants to map the
// characteristic outputs and mark them as already generated. (We have
// to do this because the DP2 context is destroyed by the "pop", and
// we don't want to recompute what DP2 will already compute.) But,
// if we replaced the valueId with another which is not in the
// characteristic outputs, it won't be marked as already generated,
// and we may later attempt to generate it again. However, the values
// necessary to generate the value may not be mapped (having been left
// behind in the DP2 context), resulting in a Generator internal error.
//
// Thus, we must undo any valueId changes we make to ItemExpr nodes
// when we exit the context of generating a single expression.
/////////////////////////////////////////////////////////////////
class ExpGeneratorCacheSubstitution : public NABasicObject
{
private:
ItemExpr * ie_; // the ItemExpr that we changed
ValueId oldValueId_; // its valueId before common subexpression elimination
ValueId newValueId_; // its valueId after common subexpression elimination
public:
// the constructor performs valueId substitution on ie
ExpGeneratorCacheSubstitution(ItemExpr * ie,ValueId &newValueId);
~ExpGeneratorCacheSubstitution()
{ };
void undo(void); // undoes a valueId substitution (idempotently)
};
/////////////////////////////////////////////////////////////////
// class ExpGeneratorCache
//
// This class is a helper class used by the expression generator
// to do common subexpression elimination local to a given
// expression. Of course, in the long run, it would be better
// to push common subexpression elimination earlier in the compile
// (e.g. to Bind time), but that will have to wait for now.
// When such support is available, this class and its methods
// will become obsolete and can be deleted.
////////////////////////////////////////////////////////////////
class ExpGeneratorCache : public NABasicObject
{
private:
Generator * generator_; // so we can get access to heaps, etc.
// A note about storage policy: This class "owns" any objects
// referenced by the substitutions_ list, and therefore is
// responsible for deleting them. However, it does not "own"
// any objects referenced by the cachedCasts_ or cachedBiAriths_
// lists, and therefore must NOT delete them.
// for now, we'll cache only Cast and BiArith expressions
LIST(Cast *) cachedCasts_;
LIST(BiArith *) cachedBiAriths_;
// a list of any valueId substitutions made during the course
// of common subexpression elimination
LIST(ExpGeneratorCacheSubstitution *) substitutions_;
// Some kinds of expressions involve short-circuit evaluation;
// we have to be careful not to use a subexpression that may
// have not been evaluated. The variable below is incremented
// whenever we descend into a tree that is subject to short-
// circuit evaluation, and decremented whenever we rise out
// of that tree.
Lng32 level_;
// for testing purposes (so we can toggle old vs. new behavior)
NABoolean enableCommonSubexpressionElimination_;
public:
ExpGeneratorCache(Generator * generator);
~ExpGeneratorCache();
// add an expression (which has had code generated) to the cache
void add(ItemExpr * ie);
// attempts to eliminate the subexpression ie; returns TRUE if
// successful (in which case ie's ValueId is side-effected
// and the substitution is recorded in the substitutions_
// member of this class)
NABoolean expressionCanBeEliminated(ItemExpr * ie);
// for suppressing caching of conditionally evaluated expressions
// (could later generalize to a stack of ExpGeneratorCaches, so
// that expressions could be eliminated in local context)
void incrementLevel(void);
void decrementLevel(void);
// clear cache (which, as a side effect, undoes substitutions)
void clear(void);
void setEnableCommonSubexpressionElimination(NABoolean v)
{
enableCommonSubexpressionElimination_ = v;
}
NABoolean enableCommonSubexpressionElimination()
{
return enableCommonSubexpressionElimination_;
}
private:
// find an expression which has already been generated equivalent
// to the input parameter; if none exists, returns NULL
ItemExpr * findEquivalentGeneratedExpr(ItemExpr * ie);
}; // class ExpGeneratorCache
/////////////////////////////////////////////////////////////////
// class ExpGenerator
////////////////////////////////////////////////////////////////
class ExpGenerator : public NABasicObject
{
// points to the high level generator
Generator * generator;
// points to cache of generated expressions (for common subexpression
// elimination)
ExpGeneratorCache * cache_;
// set to true, if a new map table is allocated to generate
// this expression.
short mapTableAllocated;
// the map table which was allocated.
MapTable * mapTable_;
// anchor to the list of generated clauses.
AListNode * clause_list;
// anchor to the list of generated constants
AListNode * constant_list;
// anchor to the list of generated persistent intializers.
AListNode * persistentList_;
// length of constants area
ULng32 constants_length;
// length of temps area
ULng32 temps_length;
// length of persistent area
ULng32 persistentLength_;
enum Flags
{
// this flag, if set, indicates that the 'address' of
// constants and temps that are part of expression
// could be computed once at fixup
// time and assigned to the corresponding 'offset'
// fields in Attributes. To be set if we know for sure
// that the expression will not be shared among many
// TCB's at runtime. If this flag is set when the expression
// is being generated, then a similar flag is set in class
// ex_expr.
FIXUP_CONSTS_AND_TEMPS = 0x0001,
SHOWPLAN_ = 0x0002,
NOTRANSACTION_ = 0x0003,
// This flag is set whenever a new clause is generated and
// linked by calling ExpGenerator::linkClause method.
// The linkClause method attaches the generated clause to
// the ItemExpr node for which it was generated.
// This flag is reset before and after we generate code for any
// ItemExpr in ItemExpr::codegen_and_set_attrs.
// It is used by the parent to access Attributes of
// its children by looking at the appropriate operand of the
// generated clause instead of searching for it in the Map
// table. This is an optimization.
CLAUSE_LINKED_ = 0x0004,
// This flag is set for all inserts and simple non-optimized updates.
// It is set before generating any expressions, then cleared at the end.
FOR_INSERT_UPDATE_ = 0x0008,
// This flag is used to indicate to the expression generator
// that there is an expression (ex_expr) within an expression (ex_expr)
// and that both expressions must be generated in one space - tempSpace or
// fragment space.
IN_CONTAINER_EXPR_ = 0x0010,
// This flag is used to indicate that pcode can be generated for expressions
// involving varchars.
HANDLE_INDIRECT_VC_ = 0x0020,
// This flag is used to indicate if a case statement was generated.
// Predicate terms for case statements can't be reordered, and so PCODE
// opts must account for this.
CASE_STMT_GENERATED_ = 0x0040,
// In specific situations we don't generate a header clause when
// generating a contiguous move expression. An optimized update is one
// case - here the entire fetched row is copied to the update buffer, then
// specific fields are updated. The header clause is part of the entire
// fetched row thus does not need to be generated.
GEN_NO_HDR_ = 0x0080,
// if pcode has been generated, then expression generator removes the
// clauses (except for in case of showplan or clause_eval).
// If this flag is set, then clauses are not removed.
SAVE_CLAUSES_IN_EXPR = 0x0100,
IN_SEQUENCE_FUNC_EXPR = 0x0200
};
UInt16 pCodeMode_;
Int16 savedPCodeMode_;
ULng32 flags_;
// For processing ROWS SINCE operator.
ItemExpr *rowsSinceCounter_;
public:
ExpGenerator(Generator * generator_);
~ExpGenerator();
unsigned short getPCodeMode() { return pCodeMode_; }
void setPCodeMode(Int16 mode) { pCodeMode_ = mode; }
void addPCodeMode(Int16 mode) { pCodeMode_ |= mode; }
//
// Disable and save PCode generation in specific cases.
// Key encoding is the current scenario that does not work with pCode if
// data rows are being expanded.
void disablePCodeModeIfNeeded(Int16 genPCode,
NABoolean expandShortRows,
NABoolean addedFields)
{
if ( genPCode && expandShortRows && addedFields)
{
// PCode can not work on short rows since the key may have shifted
// due to:
// 1) adding a varchar field when a fixed field is the key
// 2) or adding a fixed field and a varchar is the key
// 3) or with Aligned format if a nullable field is added
// such that the null bitmap must expand past the current size
// or the null bitmap must be added when it wasn't present
savedPCodeMode_ = getPCodeMode();
setPCodeMode( ex_expr::PCODE_NONE );
}
}
void savePCodeMode()
{
savedPCodeMode_ = getPCodeMode();
}
//
// Restore any saved PCode mode ...
void restorePCodeMode()
{
if ( savedPCodeMode_ > 0 )
{
pCodeMode_ = savedPCodeMode_;
savedPCodeMode_ = -1;
}
}
// input is a ValueIdSet of aggregate nodes
short generateAggrExpr(const ValueIdSet &val_id_set,
ex_expr::exp_node_type node_type,
ex_expr ** expr,
short gen_last_clause,
NABoolean groupByOperation,
const ValueIdSet * vid = NULL);
// input is a ValueId which points to an arithmetic expression.
short generateArithExpr(const ValueId & val_id,
ex_expr::exp_node_type node_type,
ex_expr ** expr);
// Generate a bulk move for Aligned Format
short generateBulkMoveAligned(ValueIdList inValIdList,
ValueIdList &outValIdList,
UInt32 tupleLength,
Int32 *bulkMoveSrcStartOffset=NULL //IN(O)
);
// Generate a bulk move for Exploded Format
short generateBulkMove(ValueIdList inValIdList,
ValueIdList &outValIdList,
ULng32 tupleLength,
Lng32 *bulkMoveSrcStartOffset=NULL); //IN(O)
// See GenExpGenerator.C for details.
NABoolean processKeyEncodingOptimization(
const NAColumnArray &allColumns,
const NAColumnArray &indexKeyColumns,
const ValueIdList &indexKey,
const short keyTag,
ULng32 &keyLen,
ULng32 &firstKeyColumnOffset);
NABoolean isKeyEncodingNeeded(const IndexDesc * indexDesc,
ULng32 &keyLen,
ULng32 &firstKeyColumnOffset);
ItemExpr * generateKeyCast(const ValueId vid,
ItemExpr * dataConversionErrorFlag,
NABoolean desc_flag,
ExpTupleDesc::TupleDataFormat tf,
Lng32 &possibleErrorCount,
NABoolean allChosenPredsAreEqualPreds,
NABoolean castVarcharToAnsiChar);
// get the key value. Currently used during hbase checkAndDelete/Update
// calls. Used to validate that this value exists in the database.
short generateKeyColValueExpr(
const ValueId vid,
Int32 atp, Int32 atp_index,
ULng32 &len,
ex_expr ** colValExpr);
// input is the index descriptor. Generate an expression to
// extract and encode the key of the table and create a
// contiguous row of encoded keys.
// If optimizeKeyEncoding is TRUE, then check to see if encoding could
// be avoided. If so, return the offset to the first key column in
// the data row.
short generateKeyEncodeExpr(const IndexDesc * indexDesc,
Int32 atp, Int32 atp_index,
ExpTupleDesc::TupleDataFormat tf,
ULng32 &keyLen,
ex_expr ** key_expr,
NABoolean optimizeKeyEncoding,
ULng32 &firstKeyColumnOffset,
const ValueIdList * keyList = NULL,
NABoolean handleSerialization = FALSE);
short generateExtractKeyColsExpr(const ValueIdList &colVidList, //const IndexDesc * indexDesc,
Int32 atp, Int32 atp_index,
ULng32 &keyLen,
ex_expr ** key_expr);
// input is a value id list of key predicates
short generateKeyExpr(const NAColumnArray &indexKeyColumns,
const ValueIdList & val_id_list,
Int32 atp, Int32 atp_index,
ItemExpr * dataConversionErrorFlag,
ExpTupleDesc::TupleDataFormat tf,
ULng32 &keyLen,
ex_expr ** key_expr,
NABoolean allChosenPredsAreEqualPreds
);
short generateDeserializedMoveExpr(
const ValueIdList & valIdList,
Int32 atp,
Int32 atpIndex,
ExpTupleDesc::TupleDataFormat tdataF,
ULng32 &tupleLength,
ex_expr ** moveExpr,
ExpTupleDesc ** tupleDesc,
ExpTupleDesc::TupleDescFormat tdescF,
ValueIdList &deserColVIDlist,
ValueIdSet &alreadyDeserialized);
// generate expression for an exclude flag for a key value
short generateExclusionExpr(ItemExpr *expr,
Int32 atp,
Int32 atpindex,
ex_expr ** excl_expr);
// generate sampling expression
short generateSamplingExpr(const ValueId &valId,
ex_expr **balanceExpr,
Int32 &returnFactorOffset);
// input is a ValueIdSet
short generateSetExpr(const ValueIdSet &val_id_set,
ex_expr::exp_node_type node_type,
ex_expr ** expr,
Int16 gen_last_clause = -1,
ExpHdrInfo *hdrInfo = NULL);
short generateSequenceExpression(const ValueIdSet &sequenceItems,
ex_expr* &expr);
// input is a ValueIdList
short generateListExpr(const ValueIdList &val_id_list,
ex_expr::exp_node_type node_type,
ex_expr **expr,
Int32 atp = -1,
Int32 atpIndex = -1,
ExpHdrInfo * hdrInfo = NULL);
short genGuardedListExpr(const ValueIdSet guard,
const ValueIdList &val_id_list,
ex_expr::exp_node_type node_type,
ex_expr ** expr);
// input is a ValueId. Generate code for the ItemExprTree corresponding
// to this ValueId.
short generateExpr(const ValueId & val_id,
ex_expr::exp_node_type node_type,
ex_expr ** expr);
// input is a list of ValueIdUnion.
short generateUnionExpr(const ValueIdList &val_id_list,
ex_expr::exp_node_type node_type,
ex_expr ** left_expr,
ex_expr * * right_expr);
// generate code to do Describe Input and move input values
// from user area to executor area.
short generateInputExpr(const ValueIdList &val_id_list,
ex_expr::exp_node_type node_type,
ex_expr ** expr);
// generate code to do Describe Output and move output values
// from executor area to user area.
short generateOutputExpr(const ValueIdList &val_id_list,
ex_expr::exp_node_type node_type,
ex_expr ** expr,
RETDesc * ret_desc,
const ItemExprList *spOutParams,
ConstNAStringPtr *colNamesForExpr,
ConstQualifiedNamePtr *tblNamesForExpr);
//////////////////////////////////////////////////////////////////////
// Input is a ValueIdList to be copied into a contiguous buffer.
// Adds convert nodes before moving, if addConvNodes is true.
// Otherwise, assign contiguous offsets to the root item expr nodes
// for each value id in val_id_list.
// The result row has the specified tuple format tf.
// Generates and returns a new map table for the moved values.
// Also, optionally returns the description of the generated
// contiguous row in tupleDesc.
// Note: IN = input parameter. OUT = output required value.
// OUT(O) = output optional value.
///////////////////////////////////////////////////////////////////////
short generateContiguousMoveExpr(const ValueIdList & val_id_list, // IN
short addConvNodes, // IN
Int32 atp, // IN
Int32 atpIndex, // IN
ExpTupleDesc::TupleDataFormat tf, // IN
ULng32 &tupleLength, // OUT
ex_expr ** moveExpr, // OUT
ExpTupleDesc ** tupleDesc = NULL, // OUT(O)
ExpTupleDesc::TupleDescFormat tdescF
= ExpTupleDesc::SHORT_FORMAT , // IN(O)
MapTable ** newMapTable = NULL, // OUT(O)
ValueIdList *tgtValues = NULL, // OUT(O)
ULng32 start_offset = 0, // IN(O)
Lng32 *bulkMoveSrcStartOffset=NULL,//IN(O)
NABoolean disableConstFolding = FALSE, //IN
NAColumnArray * colArray = NULL, // IN
NABoolean doBulkMoves = TRUE); // IN
short genGuardedContigMoveExpr(const ValueIdSet guard,
const ValueIdList & val_id_list, // IN
short addConvNodes, // IN
Int32 atp, // IN
Int32 atpIndex, // IN
ExpTupleDesc::TupleDataFormat tf, // IN
ULng32 &tupleLength, // OUT
ex_expr ** moveExpr, // OUT
ExpTupleDesc ** tupleDesc = NULL, // OUT(O)
ExpTupleDesc::TupleDescFormat tdescF
= ExpTupleDesc::SHORT_FORMAT , // IN(O)
MapTable ** newMapTable = NULL, // OUT(O)
ValueIdList *tgtValues = NULL, // OUT(O)
ULng32 start_offset = 0); // IN(O)
///////////////////////////////////////////////////////////////////////
// Take an array of Attributes and assign offsets to them. Also make an
// (optional) tuple descriptor (either in long or in short format).
// Don't generate expression, don't update any map tables.
///////////////////////////////////////////////////////////////////////
short processAttributes(ULng32 numAttrs,
Attributes ** attrs,
ExpTupleDesc::TupleDataFormat tdataF,
ULng32 &tupleLength,
Int32 atp,
Int32 atpIndex,
ExpTupleDesc ** tupleDesc = NULL,
ExpTupleDesc::TupleDescFormat tdescF
= ExpTupleDesc::SHORT_FORMAT,
ULng32 startOffset = 0,
ExpHdrInfo * hdrInfo = NULL);
///////////////////////////////////////////////////////////////////////
// similar to processAttributes, but this time we create new Attributes
// and add them as a new map table to the current stack of map tables
///////////////////////////////////////////////////////////////////////
short processValIdList(
ValueIdList valIdList,
ExpTupleDesc::TupleDataFormat tdataF,
ULng32 &tupleLength,
Int32 atp,
Int32 atpIndex,
ExpTupleDesc ** tupleDesc = NULL,
ExpTupleDesc::TupleDescFormat tdescF = ExpTupleDesc::SHORT_FORMAT,
Lng32 startOffset = 0,
Attributes ***returnedAttrs = NULL, // sorry about the *** :-(
NAColumnArray * colArray = NULL,
NABoolean isIndex = FALSE,
NABoolean placeGuOutputFunctionsAtEnd = FALSE,
ExpHdrInfo * hdrInfo = NULL);
short computeTupleSize(const ValueIdList & valIdList,
ExpTupleDesc::TupleDataFormat tdataF,
ULng32 &tupleLength,
Lng32 startOffset = 0,
UInt32 * varCharSize = NULL,
UInt32 * headerSizePtr = NULL);
short assignAtpAndAtpIndex(
ValueIdList valIdList,
Int32 atp,
Int32 atpIndex);
// RETURN: -1, if an error. 0, if all ok.
Lng32 foldConstants(ItemExpr * inExpr, ItemExpr ** outExpr);
//////////////////////////////////////////////////////////////////////
// Input is a ValueIdList to be exploded into a contiguous buffer.
// Every other parameter is similar to generateContiguousMoveExpr.
///////////////////////////////////////////////////////////////////////
short generateExplodeExpr(const ValueIdList & val_id_list, // IN
Int32 atp, // IN
Int32 atpIndex, // IN
ExpTupleDesc::TupleDataFormat tf, // IN
ULng32 &tupleLength, // OUT
ex_expr ** moveExpr, // OUT
ExpTupleDesc ** tupleDesc = NULL, // OUT(O)
ExpTupleDesc::TupleDescFormat tdescF
= ExpTupleDesc::SHORT_FORMAT , // IN(O)
MapTable ** newMapTable = NULL, // OUT(O)
ValueIdList *tgtValues = NULL, // OUT(O)
ULng32 start_offset = 0); // IN(O)
short generateHeaderClause( Int32 atp,
Int32 atpIndex,
ExpHdrInfo *hdrInfo );
// init expr generation with space allocation
void initExprGen();
// called at the start of expr generation
short startExprGen(ex_expr ** expr,
ex_expr::exp_node_type node_type);
// short allocateMapTable = -1);
// called at the end of expr generation
short endExprGen(ex_expr ** expr,
short gen_last_clause = -1);
void incrementLevel(void) { cache_->incrementLevel(); };
void decrementLevel(void) { cache_->decrementLevel(); };
void setEnableCommonSubexpressionElimination(NABoolean v)
{
cache_->setEnableCommonSubexpressionElimination(v);
}
NABoolean enableCommonSubexpressionElimination()
{
return cache_->enableCommonSubexpressionElimination();
}
// proc defined in GenItemExpr.C
short genItemExpr(ItemExpr * item_expr, Attributes *** out_attr,
Lng32 num_attrs, short gen_child);
inline MapTable * getMapTable(){return generator->getMapTable();};
inline Space * getSpace(){return generator->getSpace();};
NABoolean genLeanExpr(){return generator->genLeanExpr();};
inline AListNode0 * getClauseList(){return clause_list->getHead();};
void initClauseList();
void linkClause(ItemExpr * node, ex_clause * clause);
void fixupNextClause();
void initConstantList();
AListNode * getConstantList();
void linkConstant(void * expr_tree);
char * placeConstants(AListNode *list, Int32 length);
// generate a null constant and type it to input type
ConstValue * generateNullConst(const NAType &type);
// Methods for persistent expression storage
//
void initPersistentList();
void linkPersistent(void *expTree);
AListNode *getPersistentList();
MapInfo *addPersistent(ValueId val, MapTable *mapTable);
inline ULng32 &persistentLength() { return persistentLength_; };
// static utility functions to create min/max constants and to convert
// an NAType to an Attributes object
static ItemExpr *getMinMaxValue(
const NAType &type,
short min_max /*0=min, -1=max, -2=max-without-null*/);
static Attributes *convertNATypeToAttributes(const NAType& t, CollHeap* h=0);
Attributes::DefaultClass getDefaultClass(const NAColumn * col);
short addDefaultValue(NAColumn * col, Attributes * attr,
ComDiagsArea * diagsArea = NULL,
COM_VERSION objectSchemaVersion = COM_VERS_UNKNOWN);
void addDefaultValues(const ValueIdList & val_id_list,
const NAColumnArray &naColArr,
ExpTupleDesc * tupleDesc,
NABoolean inputIsColumnList = FALSE);
void copyDefaultValues(
ExpTupleDesc * tgtTupleDesc,
ExpTupleDesc * srcTupleDesc);
short genColNameList(const NAColumnArray &naColArr,
Queue* &colNameList);
ItemExpr * createExprTree(const char * str,
UInt32 strlength = 0,
/* CharInfo::CharSet strCharSet = CharInfo::UnknownCharSet, */
Int32 num_params = 0,
ItemExpr * p1 = 0,
ItemExpr * p2 = 0,
ItemExpr * p3 = 0,
ItemExpr * p4 = 0,
ItemExpr * p5 = 0,
ItemExpr * p6 = 0)
{
Parser parser(generator->currentCmpContext());
return parser.getItemExprTree(str,strlength, /* for now */ CharInfo::ISO88591, num_params, p1,p2,p3,p4,p5,p6);
}
ItemExpr * createExprTree(const char * str,
CharInfo::CharSet charSet = CharInfo::ISO88591,
UInt32 strlength = 0,
Int32 num_params = 0,
ItemExpr * p1 = 0,
ItemExpr * p2 = 0,
ItemExpr * p3 = 0,
ItemExpr * p4 = 0,
ItemExpr * p5 = 0,
ItemExpr * p6 = 0)
{
Parser parser(generator->currentCmpContext());
if (! CharInfo::isSingleByteCharSet(charSet))
{
return parser.get_w_ItemExprTree((const NAWchar *)str,
strlength, num_params, p1,p2,p3,p4,p5,p6);
}
else
return parser.getItemExprTree(str,
strlength, charSet, num_params, p1,p2,p3,p4,p5,p6);
}
// this function returns an expr tree that multiplies the source
// by 10 ** exponent. If exponent is negative, the returned expr
// tree divides the source by 10 ** (- exponent).
ItemExpr * scaleBy10x(const ValueId & source, Lng32 exponent);
// if the scales of the source and target types are not
// the same, this function returns an expr tree to upscale
// or downscale the source to the target scale.
ItemExpr * matchScales(const ValueId & source,
const NAType & targetType);
// This is like matchScales(), except it does not add a Cast of the
// expr tree to the target datatype. Useful in key building, where
// we wish to handle truncation and overflow errors due to datatype
// conversion specially.
ItemExpr * matchScalesNoCast(const ValueId & source,
const NAType & targetType);
// if Cast from/to is not supported, convert to supported datatype.
short handleUnsupportedCast(Cast * castNode);
// if the source is an interval, this function returns an expr
// tree to convert the source type to numeric.
ItemExpr * convertIntervalToNumeric(const ValueId & source);
// if the source is a numeric, this function returns an expr
// tree to convert the source type to interval.
ItemExpr * convertNumericToInterval(const ValueId & source,
const NAType & targetType);
// if the source and target are intervals with different end fields,
// this function returns an expr tree to convert the source type to
// match the target's end field.
ItemExpr * matchIntervalEndFields(const ValueId & source,
const NAType & targetType);
// maptable allocated at the start of generating an expression.
inline MapTable * getExprMapTable(){return mapTable_;};
inline ULng32 getConstLength() {return constants_length;}
inline void addConstLength(ULng32 length)
{
constants_length += length;
}
MapInfo *addTemporary(ValueId val, MapTable *mapTable);
//
// Routines to get/set the current ROWS SINCE counter.
//
inline ItemExpr * getRowsSinceCounter(){return rowsSinceCounter_;}
inline void setRowsSinceCounter(ItemExpr *newCounter)
{ rowsSinceCounter_ = newCounter;}
inline ULng32 getTempsLength() {return temps_length;}
inline void addTempsLength(ULng32 length)
{
temps_length += length;
}
void setFixupConstsAndTemps(ULng32 v)
{
if (v != 0)
flags_ |= FIXUP_CONSTS_AND_TEMPS;
else
flags_ &= ~FIXUP_CONSTS_AND_TEMPS;
};
ULng32 getFixupConstsAndTemps()
{
return flags_ & FIXUP_CONSTS_AND_TEMPS;
}
void setShowplan(ULng32 v)
{
if (v != 0)
flags_ |= SHOWPLAN_;
else
flags_ &= ~SHOWPLAN_;
};
ULng32 getShowplan()
{
return flags_ & SHOWPLAN_;
}
void setNoTransaction(ULng32 v)
{
if (v != 0)
flags_ |= NOTRANSACTION_;
else
flags_ &= ~NOTRANSACTION_;
};
ULng32 getNoTransaction()
{
return flags_ & NOTRANSACTION_;
}
void setClauseLinked(NABoolean v)
{
if (v)
flags_ |= CLAUSE_LINKED_;
else
flags_ &= ~CLAUSE_LINKED_;
};
NABoolean clauseLinked()
{
return (flags_ & CLAUSE_LINKED_) != 0;
}
void setForInsertUpdate(NABoolean v)
{
if (v)
flags_ |= FOR_INSERT_UPDATE_;
else
flags_ &= ~FOR_INSERT_UPDATE_;
};
NABoolean forInsertUpdate()
{
return (flags_ & FOR_INSERT_UPDATE_) != 0;
}
// In specific situations no header clause is needed when writing (or updating)
// a disk format row - optimized updates.
void setNoHeaderNeeded(NABoolean v)
{
if (v)
flags_ |= GEN_NO_HDR_;
else
flags_ &= ~GEN_NO_HDR_;
};
// A header clause is only needed when writing one of the 2 SQL/MX disk
// formats & the flag is not set saying no header clause is needed.
NABoolean isHeaderNeeded(ExpTupleDesc::TupleDataFormat tdf)
{
return (ExpTupleDesc::isDiskFormat(tdf) && ((flags_ & GEN_NO_HDR_) == 0));
}
void setInContainerExpr(NABoolean v)
{
if (v)
flags_ |= IN_CONTAINER_EXPR_;
else
flags_ &= ~IN_CONTAINER_EXPR_;
};
NABoolean inContainerExpr()
{
return (flags_ & IN_CONTAINER_EXPR_) != 0;
}
void setHandleIndirectVC(NABoolean v)
{
if (v)
flags_ |= HANDLE_INDIRECT_VC_;
else
flags_ &= ~HANDLE_INDIRECT_VC_;
};
NABoolean handleIndirectVC()
{
return (flags_ & HANDLE_INDIRECT_VC_) != 0;
}
void setCaseStmtGenerated(NABoolean v)
{
if (v)
flags_ |= CASE_STMT_GENERATED_;
else
flags_ &= ~CASE_STMT_GENERATED_;
};
NABoolean caseStmtGenerated()
{
return (flags_ & CASE_STMT_GENERATED_) != 0;
}
void setSaveClausesInExpr(NABoolean value) {
if (value)
flags_ |= SAVE_CLAUSES_IN_EXPR;
else
flags_ &= ~SAVE_CLAUSES_IN_EXPR;
};
NABoolean saveClausesInExpr() {
return ((flags_ & SAVE_CLAUSES_IN_EXPR) != 0);
};
NABoolean inSequenceFuncExpr()
{ return (flags_ & IN_SEQUENCE_FUNC_EXPR) != 0; }
void setInSequenceFuncExpr(NABoolean v)
{ (v ? flags_ |= IN_SEQUENCE_FUNC_EXPR : flags_ &= ~IN_SEQUENCE_FUNC_EXPR); }
// The working heap for dynamic memory allocation, will be
// be destroyed at the end of each statement.
inline CollHeap* wHeap()
{ return ((generator) ? generator->wHeap() : 0);}
// for generating key information (e.g. single subset, Mdam)
short buildKeyInfo(keyRangeGen ** keyInfo, // out -- generated object
Generator * generator,
const NAColumnArray & keyColumns,
const ValueIdList & listOfKeyColumns,
const ValueIdList & beginKeyPred,
const ValueIdList & endKeyPred,
const SearchKey * searchKey,
const MdamKey * mdamKey,
const NABoolean reverseScan,
const ExpTupleDesc::TupleDataFormat tf);
};
// The next class is a helper used in the mdamCodeGen methods on
// ItemExprs. It helps to hide some classes from ItemExpr.h that
// we would rather not teach it about, but that the mdamCodeGen
// methods need to know about (hence the fact that all members have
// public accessors).
class MdamCodeGenHelper
{
private:
// the current disjunct number
CollIndex disjunctNumber_;
// the datatype of the key column in the key buffer
NAType *targetType_;
// TRUE if key is DESC, FALSE otherwise
NABoolean isDescending_;
// the atp number and index used for the result of the key expression
Int32 atp_;
Int32 atpIndex_;
// the format of the key buffer
ExpTupleDesc::TupleDataFormat tdataF_;
// the data conversion error flag, used for run-time modification
// of the Mdam predicate in the event of a data conversion error
ItemExpr * dataConversionErrorFlag_;
// the value ID of the key column that we are generating Mdam predicates
// for -- this helps us figure out which side of a comparison operator
// is the key column and which is the key value
ValueId keyColumn_;
public:
MdamCodeGenHelper(CollIndex disjunctNumber,
NAType *targetType,
NABoolean isDescending,
Int32 atp,
Int32 atpIndex,
ExpTupleDesc::TupleDataFormat tdataF,
ItemExpr * dataConversionErrorFlag,
ValueId keyColumn) :
disjunctNumber_(disjunctNumber),
targetType_(targetType),
isDescending_(isDescending),
atp_(atp),
atpIndex_(atpIndex),
tdataF_(tdataF),
dataConversionErrorFlag_(dataConversionErrorFlag),
keyColumn_(keyColumn)
{ };
~MdamCodeGenHelper() { };
// accessor methods
CollIndex getDisjunctNumber() { return disjunctNumber_; };
NAType *getTargetType() { return targetType_; };
NABoolean isDescending() { return isDescending_; };
Int32 getAtp() { return atp_; };
Int32 getAtpIndex() { return atpIndex_; };
ExpTupleDesc::TupleDataFormat getTupleDataFormat() { return tdataF_; };
ItemExpr * getDataConversionErrorFlag() { return dataConversionErrorFlag_; };
ValueId getKeyColumn() { return keyColumn_; };
// mutator method for atpIndex_, needed for processing 2ndary key value in
// case of MDAM_BETWEEN predtype.
void setAtpIndex(Int32 atpInx)
{
atpIndex_ = atpInx;
}
};
#endif