blob: 8d946b478810d2239c4e419f62bbd264839ac06a [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 CacheWA__H
#define CacheWA__H
/* -*-C++-*-
*************************************************************************
*
* File: CacheWA.h
* Description: The workarea used by {Rel|Item}Expr::normalizeForCache.
* It holds contextual information needed and generated by
* isCacheableExpr and normalizeForCache as the compiler
* decides whether a query is cacheable. For a cacheable
* query, normalizeForCache replaces query constants into
* ConstantParameters. ConstantParameters act like wildcards
* matching all constants that can be safely coerced into
* that constant's formal type. We cache only queries that
* have been normalizedForCache. The goal is to maximize the
* cache hit rate of every cached query plan.
*
* A query is cacheable after parse iff it is a tuple or
* tuplelist insert whose tuple values' types are known at
* parse-time. Thus, tuple inserts that have hostvars, dynamic
* parameters, subqueries, nulls are not cacheable after parse.
* "insert into t values(1),(2),(3)" is cacheable after parse.
* "insert into t values(?p1),(:hv2),(select a from s)" is not.
* A query is cacheable after bind iff it is an insert, delete,
* update, select whose compiled plan is insensitive to actual
* values of literals in that query. Thus, "delete from t where
* pk = 1" is cacheable after bind iff pk is a primary key or a
* column with a unique constraint because its compiled plan does
* not depend on the value "1". "delete from t where pk > 1"
* is not cacheable because its compiled plan may depend on the
* value "1".
* Determining query cacheability is implemented by {Rel|Item}
* Expr::isCacheableExpr(). Every ExprNode (the base class of
* RelExpr and ItemExpr) has a protected cacheable_ attribute
* that specifies that node's cacheability (returned by the
* isCacheableNode() method).
* Most ExprNodes start in the MAYBECAHEABLE state.
* Certain ExprNodes (such as ControlAbstractClass, Describe,
* StmtNode, ElemDDLNode, RelLock, RelTransaction) that
* represent non-DML queries are always NONCACHEABLE.
* (Tuple and tuplelist) Insert nodes (a class derived from
* RelExpr) become CACHEABLE_PARSE (ie, cacheable after parse)
* during their isCacheableExpr (top-down) query tree traversal.
* Some Insert, Delete, Update, Scan nodes (classes derived from
* RelExpr) become CACHEABLE_BIND (cacheable after bind) during
* their isCacheableExpr traversal.
* A query tree that has only MAYBECACHEABLE ExprNodes is not
* cacheable (ie, its isCacheableExpr() traversal returns FALSE).
* For a query tree to be cacheable after parse, its
* isCacheableExpr traversal must encounter a CACHEABLE_PARSE
* node which causes that query to be marked as
* cachewa.conditionallyCacheable_ and its descendant nodes are
* MAYBECACHEABLE or conditionallyCacheable_. No descendant's
* isCacheableExpr() call must return FALSE. Note that hostvars'
* and dynamic parameters' isCacheableExpr() return FALSE after
* parse but return TRUE after bind.
* For a query tree to be cacheable after bind, its
* isCacheableExpr traversal must encounter a CACHEABLE_BIND node
* (an insert, delete, update, scan) and its selection predicate,
* if present, must have at least one conjunctive equality of a
* literal against a primary key or a column with a unique
* constraint.
* To avoid an unnecessary isCacheableExpr traversal, say, after
* parse and then after bind, we set a node's cacheable_
* attribute to become NONCACHEABLE if that query has been
* determined not to be cacheable after any phase. For example,
* "select a from t intersect select b from s where c >= 1"
* is not cacheable after any phase.
* Created: August 3, 2000
* Language: C++
*
*
*
*
*************************************************************************
*/
#include "ItemColRef.h"
#include "exp_attrs.h"
#include "NAString.h"
#include "RelMisc.h"
#include "QCache.h"
// contents of this file
class CacheWA;
class ConstantParameters;
class SelParameters;
// Forward declarations
// ConstantParameters is used to represent a query's list of actual
// constant parameters after query has undergone normalizeForCache.
class ConstantParameters : public LIST(ConstantParameter*)
{
public:
// create an empty list
ConstantParameters(NAHeap *h);
// copy constructor
ConstantParameters(const ConstantParameters &s, NAHeap* h)
: NAList<ConstantParameter*>(s, h) {}
// free our allocated memory
virtual ~ConstantParameters();
// return our elements' total size in bytes
Lng32 getSize() const;
// return true & matching element if val is in this list
NABoolean find(ConstValue *val, ConstantParameter **match);
};
// SelParameters is used to represent a query's list of actual SelParameters
// after query has undergone normalizeForCache.
class SelParameters : public LIST(SelParameter*)
{
public:
// create an empty list
SelParameters(NAHeap *h);
// copy constructor
SelParameters(const SelParameters &s, NAHeap* h)
: NAList<SelParameter*>(s, h) {}
// free our allocated memory
virtual ~SelParameters();
// return our elements' total size in bytes
Lng32 getSize() const;
// return true & matching element if val is in this list
NABoolean find(ConstValue *val, SelParameter **match);
};
// CacheWA is the contextual work area for {Rel|Item}Expr::isCacheableExpr
// and {Rel|Item}Expr::normalizeForCache query tree traversals. It holds
// contextual information (such as the current phase of compilation,
// the cacheability of the current query, the
// parameterized query text, the query's cache key, the query root, etc)
// which is needed and generated by {Rel|Item}Expr::isCacheableExpr and
// {Rel|Item}Expr::normalizeForCache traversals of the query tree.
class CacheWA : public NABasicObject
{
public:
// Constructor
CacheWA(NAHeap *h);
private:
// copy constructor
CacheWA(const CacheWA &s); // not written and not used but is here
// nevertheless because code inspectors say it should.
// This will cause a link error if it's ever called.
public:
// Destructor function
virtual ~CacheWA();
// Dear code reader/inspector: Please do not (nit)pick on the following
// accessors as violations of coding guideline 7.3 (a function must never
// return a pointer to local data). The only purpose in life of cachewa
// is to hold "global" state for {Rel|Item}Expr::isCacheableExpr and
// {Rel|Item}Expr::normalizeForCache. Without these accessors, cachewa
// is useless.
// replace constant with new or existing ConstantParameter
void replaceWithNewOrOldConstParam(ConstValue *val, const NAType *typ,
ExprValueId& tgt, BindWA &bindWA);
// replace constant with new or existing SelParameter
void replaceWithNewOrOldSelParam(ConstValue *val, const NAType *typ,
const Selectivity sel, ExprValueId& tgt,
BindWA &bindWA);
// add ConstantParameter to current query's actual parameters
void addConstParam(ConstantParameter* p, BindWA& bindwa);
// add SelParameter to current query's selection parameters
void addSelParam(SelParameter* p, BindWA& bindwa);
// add referenced table
void addTable( NATable *t ) { tables_.insert(t); }
// get referenced tables
LIST(NATable*) &getTables() { return tables_; }
// return current query's actual parameters for backpatching cached plan
ConstantParameters &getConstParams() { return actuals_; }
// return current query's selection parameters for backpatching cached plan
SelParameters &getSelParams() { return sels_; }
LIST(Int32) &getConstParamPositionsInSql() { return sqlStmtConstParamPos_; }
LIST(Int32) &getSelParamPositionsInSql() { return sqlStmtSelParamPos_; }
LIST(Int32) &getHQCConstPositionsInSql() { return hqcSqlConstPos_; }
void bindConstant2SQC(BaseColumn* base, ConstantParameter* cParameter)
{
if (HQCKey_&& HQCKey_->isCacheable())
HQCKey_->bindConstant2SQC(base, cParameter, hqcSqlConstPos_);
}
void setHQCKey(HQCParseKey * key) { HQCKey_ = key;}
// return current query's formal parameter types
const ParameterTypeList* getFormalParamTypes();
// return current query's formal SelParamTypes
const SelParamTypeList* getFormalSelParamTypes();
// compose and return TextKey of current query
TextKey *getTextKey(const char *sText, Lng32 charset,
const QryStmtAttributeSet& attrs);
// traverse queryExpr and put together its cacheKey
void generateCacheKey(RelExpr *queryExpr, const char *sText, Lng32 charset,
const NAString& viewsUsed);
// caller wants us to remember an occurrence of a view join
void foundViewJoin();
// compose and return CacheKey of current query
CacheKey *getCacheKey(const QryStmtAttributeSet& attrs);
// return current phase of compilation
CmpPhase getPhase() const { return phase_; }
// used by subsequent phases to check if query is definitely cacheable
NABoolean isCacheable() const { return cacheable_; }
// is current query conditionally cacheable?
NABoolean isConditionallyCacheable() const
{ return conditionallyCacheable_; }
// mark current query as definitely cacheable
void setCacheable() { cacheable_ = TRUE; }
// mark current query as definitely not cacheable
void resetCacheable() { cacheable_ = FALSE; }
// tilt current query towards cacheability
void setConditionallyCacheable() { conditionallyCacheable_ = TRUE; }
// record current phase of compilation
void setPhase(CmpPhase p) { phase_ = p; }
// remember current query's true root
void setTopRoot(RelRoot* root) { topRoot_ = root; }
// return compiler's statementHeap
NAHeap *wHeap() const { return heap_; }
// append string s to current query's parameterized sql text
void operator+=(const char* s);
// add referenced column's valueid to usedKeys
void addToUsedKeys(BaseColumn *base);
// is this column parameterizable?
NABoolean isParameterizable(BaseColumn *base);
void setHasPredicate() { hasPredicate_ = TRUE; }
void setPredHasNoLit(NABoolean v) { predHasNoLit_ = v; }
NABoolean inc_N_check_still_cacheable();
void resetNofExprs() { numberOfExprs_ = 0; }
void incNofScans(TableDesc* td);
TransMode::IsolationLevel getIsoLvl() { return isoLvl_; }
TransMode::AccessMode getAccessMode() { return accMode_; }
TransMode::IsolationLevel getIsoLvlForUpdates() { return isoLvlIDU_; }
void setIsoLvl(TransMode::IsolationLevel l) { isoLvl_ = l; }
void setAccessMode(TransMode::AccessMode m) { accMode_ = m; }
void setIsoLvlForUpdates(TransMode::IsolationLevel l) { isoLvlIDU_ = l; }
Int16 getFlags() { return flags_ ; }
void setFlags(Int16 f) { flags_ = f; }
void setAutoCommit(TransMode::AutoCommit a) { autoCmt_ = a; }
void setRollbackMode(TransMode::RollbackMode r) { rbackMode_ = r; }
void setAutoabortInterval(Lng32 val) {autoabortInterval_ = val ; }
void setMultiCommit(TransMode::MultiCommit a) { multiCmt_ = a; }
NABoolean hasRewriteEnabledMV() { return hasRewriteEnabledMV_; }
void setRewriteEnabledMV(NABoolean x = TRUE) { hasRewriteEnabledMV_ = x; }
NABoolean hasParameterizedPred() { return hasParameterizedPred_; }
void setParameterizedPred(NABoolean x = TRUE) { hasParameterizedPred_ = x; }
NABoolean isUpdate() { return isUpdate_; } ;
void setIsUpdate(NABoolean x = TRUE) { isUpdate_ = x; } ;
NAString reqdShape_; // control query shape or empty string
private:
typedef TableDesc* TableDescPtr;
HQCParseKey* HQCKey_; //collect histogram info for a Hybrid Cache Key during NormalizeForCache.
Int32 numberOfExprs_; // number of ExprNodes in current query
// a query with more than N ExprNodes is not cacheable
Int32 numberOfScans_; // number of Scan nodes in current query
TableDescPtr *tabDescPtr_; // array of TableDesc pointers
ValueIdSet **usedKyPtr_; // array of ValueIdSet pointers
Int32 tabArraySize_; // size of the tabDescPtr_ and usedKyPtr_ arrays
Int32 requiredPrefixKeys_;
NABoolean hasPredicate_; // TRUE if query has a WHERE clause
NABoolean predHasNoLit_; // TRUE if predicate has no constants
NAHeap *heap_; // compiler's statementHeap
NAString qryText_; // parameterized sql statement text
TextKey *tkey_; // text key of current query
CacheKey *ckey_; // cache key of current query
TransMode::IsolationLevel isoLvl_; // tx isolation level
TransMode::AccessMode accMode_; // tx access mode
TransMode::IsolationLevel isoLvlIDU_; // tx isolation level for updates
TransMode::AutoCommit autoCmt_; // tx auto-commit
TransMode::MultiCommit multiCmt_; // tx multi-commit
Int16 flags_; // tx flags
TransMode::RollbackMode rbackMode_; // tx rollback mode
Lng32 autoabortInterval_ ; //tx autoabortInterval
SelParameters sels_; // list of actual selection parameters
LIST(Int32) sqlStmtConstParamPos_;
// list of positions in sql stmt
// that each constant occurs. Each is replaced
// by a const parameter
LIST(Int32) sqlStmtSelParamPos_;
// list of positions in sql stmt
// that each constant occurs. Each is replaced
// by a selParameter
LIST(Int32) hqcSqlConstPos_;
// used by the HQC logic to keep track of the correct
// order of the query constants
UInt32 posCounter_;
// used for keeping track of positions of aliased SelParams & ParamTypes
// valid positions are 1 up to count of SelParams & ConstantParameters
SelParamTypeList *selTypes_; // types & selectivities of sel parameters
// selTypes_ is always derived from sels_; it's only purpose in life
// is to allow ~CacheWA() to deallocate selTypes_.
ConstantParameters actuals_; // list of actual constant parameters
ParameterTypeList *parmTypes_; // types of actual constant parameters
// parmTypes_ is always derived from actuals_; it's only purpose in life
// is to allow ~CacheWA() to deallocate parmTypes_.
CmpPhase phase_; // compiler cache phase (PARSE or BIND)
RelRoot *topRoot_; // has inputVarTree
NABoolean cacheable_; // true iff current query is cacheable
// conditionallyCacheable_ is used by RelExpr::isCacheableExpr & its cohorts.
// It is set to true iff a RelExpr::isCacheableExpr() traversal has found
// a query node, such as a tuple insert that we definitely want to be
// cacheable at this phase subject only to the condition that it does
// not have any non-cacheable components. For example, we want all
// tuple inserts whose constants' types are reasonably-defined such as
// insert into t values(1, 3.14);
// to be cacheable after parse. However, dynamic-parameter-bearing
// tuple inserts such as
// insert into t values(?p1, ?p2);
// should be cacheable only after bind.
NABoolean conditionallyCacheable_;
NABoolean useView_;
// must be set to true for cacheable query that references a view.
// used to suppress text caching of such a query to avoid subverting
// revocation of privilege on referenced view(s).
NABoolean isViewJoin_; // true iff current query is a view join
// we want to safely cache view joins. But, there are view joins such as
// these two joins from regress/qatdml07
// select avg(firstt.large_int) from pvsel01 firstt, pvsel01 secondd
// group by firstt.medium_int;
// select avg(secondd.large_int) from pvsel01 firstt, pvsel01 secondd
// group by firstt.medium_int;
// whose only difference is in their "avg(<basecolref>)". Unfortunately,
// after view expansion, both "firstt.large_int" and "secondd.large_int"
// resolve to the same fully qualified <basecolref> name
// "cat.sch.btsel01.large_int". The end result can be a false cache hit.
// To avoid this problem, isViewJoin_ is set true when such a view join
// is detected by RelCache.cpp's Join::isCacheableExpr() and later used
// to prepend the query's original text into its cachekey.
NABoolean isUpdate_; // true iff the current query contains an update
// list of referenced tables for getting to their histograms' timestamps.
// used for "passive invalidation" of oached plans.
LIST(NATable*) tables_;
NABoolean hasRewriteEnabledMV_;
// true iff query references table that has rewrite enabled MV
NABoolean hasParameterizedPred_;
// true iff query has a parameterized equality predicate
}; // class CacheWA
#endif /* CacheWA__H */