blob: 37145585fb8252d632e7c5b4c44cd88ee15fffdd [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 OPTTRIGGER_H
#define OPTTRIGGER_H
/* -*-C++-*-
**************************************************************************
*
* File: OptTrigger.h
* Description: After trigger backbone class for after trigger reorder & transformation
* Created: 6/24/98
* Language: C++
*
*
*
*
**************************************************************************
*/
#include "AllRelExpr.h"
#include "AccessSets.h"
#include "Triggers.h"
// -----------------------------------------------------------------------
// contents of this file
// -----------------------------------------------------------------------
class OptTriggersBackbone;
class OptTriggerGroupList;
class OptTriggerGroup;
class OptTriggerList;
class OptTrigger;
class OptColumnMapping;
// -----------------------------------------------------------------------
// forward references
// -----------------------------------------------------------------------
class BindWA;
class TriggerBindInfo;
//***************************************************************************
// OptTrigger
//
// Hold single trigger information, needed in optimizer pilot phase for reorder
//***************************************************************************
class OptTrigger : public NABasicObject
{
public:
// ---------------------------------------------------------------------
// Constructor functions
// ---------------------------------------------------------------------
OptTrigger(SubTreeAccessSet *treeAccessSet,
NABoolean isRowTrigger,
RelExpr *triggerSubTree,
RelExpr *parentSubTree);
// Dummy copy constructor - method body does not exist
OptTrigger(const OptTrigger &orig, NAMemory *h=0);
// ---------------------------------------------------------------------
// Accessor functions
// ---------------------------------------------------------------------
inline const SubTreeAccessSet *getAccessSet() const {return treeAccessSet_;}
inline NABoolean isRowTrigger() const {return isRowTrigger_;}
inline const RelExpr * getTriggerSubTree() const {return triggerSubtree_;}
inline const RelExpr * getTriggerParentSubTree() const {return triggerParentSubtree_;}
inline Int64 getTriggerTimeStamp() const
{return (triggerSubtree_->getInliningInfo().getTriggerObject()->getTimeStamp());}
private:
const SubTreeAccessSet *treeAccessSet_;
const NABoolean isRowTrigger_;
const RelExpr *triggerSubtree_; // from the Driving union down
const RelExpr *triggerParentSubtree_;// union or NULL (for reuse)
};// OptTrigger
typedef OptTrigger *OptTriggerPtr; // this typedef is used in OptTriggersBackbone::reorder
//***********************************************************************
// A list of OptTrigger
//***********************************************************************
class OptTriggerList : public LIST(OptTriggerPtr)
{
public:
OptTriggerList(): LIST(OptTriggerPtr)(CmpCommon::statementHeap()) { }
// Dummy copy constructor - method body does not exist
OptTriggerList(const OptTriggerList &orig, NAMemory *h=0);
RelExpr *createUnionSubTree() const;
};
//***********************************************************************
//
// OptTriggerGroup
//
// A group of trigger that has no conflict in their access sets
//
//***********************************************************************
class OptTriggerGroup : public NABasicObject
{
public:
enum TriggerGroupFlags {
// placed in piplined action
PIPELINED_ROW_TRIGGERS = 1,
// executed in paraller to IUD
IUD_PARALLEL_STATEMENT_TRIGGER,
// have conflict with previus group,
// can includes both row and statment triggers
BLOCKED_GROUP
};
// ---------------------------------------------------------------------
// Constructor functions
// ---------------------------------------------------------------------
OptTriggerGroup(TriggerGroupFlags flag, OptTriggersBackbone *backbone);
// Dummy copy constructor - method body does not exist
OptTriggerGroup(const OptTriggerGroup &orig);
virtual ~OptTriggerGroup() {}
inline CollIndex entries() const
{ return (rowTriggerGroup_.entries()+statmentTriggerGroup_.entries());}
//If the group is empty the answer is FALSE
NABoolean isConflicting(const SubTreeAccessSet *) const;
// add trigger to group
void addTrigger(const OptTriggerPtr trigger);
// get group tree representation
RelExpr *toTree();
// creates the sub-tree that handles the row triggers in the group
RelExpr *createRowTriggersSubTree();
// ---------------------------------------------------------------------
// Accessor functions
// ---------------------------------------------------------------------
inline NABoolean isPipeLinedRowTriggesGroup() const
{return ((Flags_ == PIPELINED_ROW_TRIGGERS) ? TRUE : FALSE);}
inline NABoolean isIudParallelStatmentGroup() const
{return ((Flags_ == IUD_PARALLEL_STATEMENT_TRIGGER) ? TRUE : FALSE);}
inline NABoolean isBlockedGroup() const
{return ((Flags_ == BLOCKED_GROUP) ? TRUE :FALSE);}
private:
//---------------------------------------------------------------------------
// methods for generating the temp-table scan for blocked triggers' groups
//---------------------------------------------------------------------------
RelExpr *buildTempScanTree();
RelExpr *buildTempTableScanNodes(OptColumnMapping& colMapping,
BindWA *bindWA);
//---------------------------------------------------------------------------
// data members
//---------------------------------------------------------------------------
OptTriggerList rowTriggerGroup_;// The triggers in the current group
OptTriggerList statmentTriggerGroup_;// The triggers in the current group
SubTreeAccessSet groupAccessSet_;
const TriggerGroupFlags Flags_; // see triggerGroupFlags
OptTriggersBackbone * backbone_;
ValueIdSet reqOutput_; // required output of the generated temp-table scan
};// OptTriggerGroup
// ***********************************************************************
// A list of OptTriggerGrp
// ***********************************************************************
//
class OptTriggerGroupList : public LIST(OptTriggerGroup *)
{
public:
OptTriggerGroupList(): LIST(OptTriggerGroup *)(CmpCommon::statementHeap()) { }
// Dummy copy constructor - method body does not exist
OptTriggerGroupList(const OptTriggerGroupList &orig, NAMemory *h=0);
};
//***********************************************************************
//
// OptTriggersBackbone
//
// The after trigger backbone of single IUD statement. This class contains
// the backbone elements, to enable reassemble of the backbone after the
// reorder and grouping of the triggers.
//
//***********************************************************************
class OptTriggersBackbone : public NABasicObject
{
public:
// ---------------------------------------------------------------------
// Constructor functions
// ---------------------------------------------------------------------
OptTriggersBackbone(RelExpr *drivingBackbone)
: beforeTriggerDrivingNode_(NULL),
tempDeleteDrivingNode_(NULL),
statmentTriggerDrivingNode_(NULL),
rowTriggerDrivingNode_(NULL),
riDrivingNode_(NULL),
pipeLineDrivingNode_(NULL),
pipeLineDrivingNodeParent_(NULL),
tempInsertDrivingNode_(NULL),
tempInsertDrivingNodeParent_(NULL),
iudDrivingNode_(NULL),
iudDrivingNodeParent_(NULL),
iudNode_(NULL),
beforeTriggersExist_(FALSE),
triggerList_(NULL),
triggerGroups_(NULL),
drivingBackbone_(drivingBackbone),
pParent_(NULL),
pNext_(NULL),
triggerBindInfo_(NULL),
tempTableUsage_(0L)
{}
~OptTriggersBackbone();
// initialize the object - set pointers to key nodes in the backbone
void init();
RelExpr *getTransformedTree();
// ---------------------------------------------------------------------
// Accessor functions
// ---------------------------------------------------------------------
inline NABoolean hasBeforeTriggers() const
{ return beforeTriggersExist_; }
inline GenericUpdate *getTriggeringNode() const
{ return iudNode_; }
inline RelExpr *getIudDrivingNode() const
{ return iudDrivingNode_; }
inline TriggerBindInfo *getTriggerBindInfo() const
{ return triggerBindInfo_; }
// force the cardinality of the given expression to be the same as the
// IUD node that started the whole backbone
void forceCardinalityAsIud(RelExpr *expr) const;
ColReference *createNewExecIdRef();
// ---------------------------------------------------------------------
// Static utility methods for general use
// ---------------------------------------------------------------------
static void SetUnionCharacteristicInputs(RelExpr *pUnion);
static void SetTsjCharacteristicInputs(RelExpr *pTsj);
static void PrepareNewBindWA(BindWA &bindWA, TriggerBindInfo *bindInfo);
static RelExpr * BindAndNormalizeNewlyConstructedTree(BindWA *bindWA, RelExpr *topNode);
private:
// dummy copy constructor - method body does not exist
OptTriggersBackbone(const OptTriggersBackbone &orig);
NABoolean hasConflicts() const;
NABoolean leftTreeHasConflicts(RelExpr *drivingNode) const;
void removeTempInsert();
RelExpr *removeTempDelete();
void createTriggerList();
void addToTriggerList(RelExpr *drivingNode, NABoolean isRowTrigger);
void reorder();
void group();
RelExpr *cleanDummies(RelExpr *);
void replacePipelinedRowTriggers(RelExpr *rowTriggerTree);
RelExpr *toTree();
void fixCardinalityAndCollectTempUsage(RelExpr *rootNode,
NABoolean enterInnerBackbone);
void collectTempTableUsage(RelExpr *node);
void setUsageAccordingToUniqueUidPredicate(const ValueIdSet &uniqueUidPred);
void fixTempInsertSubtree();
RelExpr *buildOptimizedTempInsert(BindWA *bindWA);
inline void addTempTableUsage(Lng32 usage) { tempTableUsage_ |= usage; }
// Tagging methods for the various key nodes in the backbone
void initBeforeTriggerDrivingNode();
void initTempDeleteDrivingNodeAndAdvance();
void initStatmentTriggerDrivingNodeAndAdvance();
void initPipeLineDrivingNode();
void initRowTriggerDrivingNode();
void initRiDrivingNode();
GenericUpdate *findLeftmostGU(ExprNode *expr);
void advanceInTree();
// The blocked union node separating the before triggers from the after trigger
RelExpr *beforeTriggerDrivingNode_;
// The blocked union node on top of the temp-delete node
RelExpr *tempDeleteDrivingNode_;
// The ordered union node on top of the statement triggers
RelExpr *statmentTriggerDrivingNode_;
// The union node on top of the row triggers if and only if row triggers exist
RelExpr *rowTriggerDrivingNode_;
// The TSJ node on top of row triggers and/or RI
RelExpr *pipeLineDrivingNode_;
RelExpr *pipeLineDrivingNodeParent_;
// The union node on top of the row RI, if and only if RI exists
RelExpr *riDrivingNode_;
// The TSJ on top of the temp-insert
RelExpr *tempInsertDrivingNode_;
RelExpr *tempInsertDrivingNodeParent_;
// iud sub tree, include im if exists
RelExpr *iudDrivingNode_;
RelExpr *iudDrivingNodeParent_;
// The triggering IUD node - the one that started it all
GenericUpdate *iudNode_;
NABoolean beforeTriggersExist_;
OptTriggerList *triggerList_;
OptTriggerGroupList *triggerGroups_;
// The following members are in use during the initalization of the object
// and through the tagging of the key nodes in the backbone.
RelExpr *drivingBackbone_; // the tree to transform
RelExpr *pNext_; // current node - the next to be evaluated
RelExpr *pParent_; // parent of current node
TriggerBindInfo *triggerBindInfo_; // information collected during binding
Lng32 tempTableUsage_; // specify which values are actually needed
};// class OptTriggersBackbone
//***********************************************************************
//
// OptColumnMapping
//
// A mapping between the old and new column names and their valueIds.
// This mapping holds only columns needed by a specific row trigger group.
//
//***********************************************************************
class OptColumnMapping : public NABasicObject
{
public:
struct ColumnMapping {
const ColRefName *colName_;
ValueId topValueId_;
ValueId topVeg_;
};
typedef LIST(ColumnMapping *) MappingList;
OptColumnMapping(TriggerBindInfo *bindInfo,
OperatorTypeEnum iudOpType,
CollHeap *heap);
void initializeMappings(ValueIdSet &reqOutput);
ItemExpr *buildSelectListFromNeededInputs();
RelExpr *buildMapValueIdNode(RelExpr *topNode);
inline NABoolean isOldNeeded() const { return oldNeeded_; }
inline NABoolean isNewNeeded() const { return newNeeded_; }
private:
void createInitialMappingLists(ValueIdSet &reqOutput);
void findCommonColumns();
void checkWhichTablesAreNeeded();
ColumnMapping *findEqualCols(MappingList &colsList,
ColumnMapping *colToFind,
CollIndex startAt);
private:
TriggerBindInfo *bindInfo_;
OperatorTypeEnum iudOpType_;
MappingList mappingArray_; // The final mapping list
MappingList newCols_; // temp list for NEW columns.
MappingList oldCols_; // temp list for OLD columns.
MappingList newCommonCols_; // temp list for NEW common columns.
MappingList oldCommonCols_; // temp list for OLD common columns.
NABoolean oldNeeded_;
NABoolean newNeeded_;
NAString atNew_; // "@NEW"
NAString atOld_; // "@OLD"
NABoolean dummyFeed_; // TRUE when the triggers are not using any of the OLD and NEW values.
CollHeap *heap_;
};
#endif /* OPTTRIGGER_H */