blob: c4f258a9a327c9b0e16c51dd0670fc44a3abadbd [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 @@@
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File: StmtNode.h
* Description: Stmt nodes implementation
* Created: 3/6/95
* Language: C++
*
*
*
*
******************************************************************************
*/
#ifndef STMTNODE_H
#define STMTNODE_H
#include "ItemColRef.h"
#include "RelControl.h"
#include "SQLCLIdev.h"
#include "TableDesc.h"
#include "ValueDesc.h"
#include "mbdact.h"
// -----------------------------------------------------------------------
// contents of this file
// -----------------------------------------------------------------------
class StmtNode;
// -----------------------------------------------------------------------
// forward references
//
// - ShortStringSequence is defined in SqlParser.y, and not in this file.
// However, by placing a forward reference here, then in other files,
// such as sqlcomp's parser.C file, where they include Y.tab.h,
// "ShortStringSequence" won't cause a problem for its being undefined.
// -----------------------------------------------------------------------
class ShortStringSequence;
// -----------------------------------------------------------------------
// Helpful Definitions
// -----------------------------------------------------------------------
typedef NASimpleArray<NAString*> NAStringList;
// -----------------------------------------------------------------------
// A generic statement node.
// -----------------------------------------------------------------------
class StmtNode : public ExprNode
{
public:
// default constructor
StmtNode(OperatorTypeEnum otype
// QSTUFF
, NABoolean holdable = FALSE
// QSTUFF
) : ExprNode(otype)
// QSTUFF
, holdable_(holdable)
// QSTUFF
{ setNonCacheable(); };
// virtual destructor
virtual ~StmtNode() {};
virtual StmtNode *castToStatementExpr();
virtual const StmtNode *castToStatementExpr() const;
// method required for traversing an ExprNode tree
// access a child of an ExprNode
virtual ExprNode * getChild(Lng32 index);
// Method for replacing a particular child
virtual void setChild(Lng32 index, ExprNode *);
NABoolean isAQueryStatement() const { return getOperatorType() == STM_QUERY; }
virtual RelExpr * getQueryExpression() const;
StaticOnly isAStaticOnlyStatement() const
{
OperatorTypeEnum op = getOperatorType();
if (op == STM_MODULE || op == STM_TIMESTAMP)
return STATIC_ONLY_WITH_WORK_FOR_PREPROCESSOR;
RelExpr *re = getQueryExpression();
while (re && re->getOperatorType() == REL_ROOT)
re = re->child(0);
if (!re) return NOT_STATIC_ONLY;
return re->isAStaticOnlyStatement();
}
ExprNode *getStaticOnlyStatement()
{
OperatorTypeEnum op = getOperatorType();
if (op == STM_MODULE || op == STM_TIMESTAMP)
return this;
RelExpr *re = getQueryExpression();
while (re && re->getOperatorType() == REL_ROOT)
re = re->child(0);
if (!re) return NULL;
return re->isAStaticOnlyStatement() ? re : NULL;
}
virtual Int32 getArity() const;
// QSTUFF
// is used to indicate whether a cursor is holdable or not. This is put
// into the statement node to account for all three different types of
// cursors which are all derived from StmtNode
NABoolean isHoldable() const { return holdable_; };
// QSTUFF
private:
// QSTUFF
NABoolean holdable_;
// QSTUFF
};
class StmtQuery : public StmtNode
{
public:
StmtQuery( RelExpr * aQueryTree ) : StmtNode(STM_QUERY),
queryExpr_(aQueryTree)
{
}
virtual RelExpr * getQueryExpression() const;
// method required for traversing an ExprNode tree
// access a child of an ExprNode
virtual ExprNode * getChild(Lng32 index);
// Method for replacing a particular child
virtual void setChild(Lng32 index, ExprNode *);
virtual const NAString getText() const;
virtual Int32 getArity() const;
virtual void print(FILE * f,const char * prefix,const char *) const;
private:
RelExpr * queryExpr_;
};
enum { INPUT_DIRECTION, OUTPUT_DIRECTION };
/* Host Variable Expression Type Structure. */
/* */
struct HostVarExprType {
NAType *the_type;
NABoolean isNullable;
};
/* class StaticDescItem
* --------------------
* Purpose: This class represents a variant record. From the outside
* it can contain either a pointer to a HostVarExprType, or a
* ConstValue (but not both). The client code can check which case
* this variant record is. If the client code "gets" a pointer then
* the referenced data belongs to the client code. This class's
* destructor will delete allocated data if no "get" is ever performed.
*/
class StaticDescItem : public NABasicObject
{
public:
StaticDescItem (ConstValue*);
StaticDescItem (HostVarExprType*);
~StaticDescItem ();
NABoolean isDataTypePointer () const;
NABoolean isLiteralPointer () const;
ConstValue *getConstValuePtr ();
HostVarExprType *getDataTypePtr ();
private:
ConstValue *literalPointer;
HostVarExprType *dataTypePointer;
};
// three values, from an enumeration telling status of
// structure: no name, cursor name, or statement
// name.
enum StmtOrCursEnum { NAME_ABSENT, NAME_CURSOR, NAME_STATEMENT };
struct StmtOrCursTag {
NAString *theName;
StmtOrCursEnum tag;
};
/* We need a vector type in order to supply a data structure for */
/* host_var_type_list. We use the Collections.h ARRAY type to do this. */
/* Note that we use pointers to everything here. This will mean */
/* that we might want some clever way to delete everything without */
/* leaking all over the place. */
// Note that we have several instantiations of NASimpleArray where the
// actual implementation code should be identical, since we want
// the enums to be treated funamentally as long values.
typedef NASimpleArray<StaticDescItem*> DescTypeList;
// The following is provided as a derived class rather than
// as a typedef. This is so that we may write a forward reference:
//
// class SequenceOfLong;
//
// You can't do that with a typedef.
class SequenceOfLong : public NASimpleArray<Long*>
{
public:
SequenceOfLong (CollHeap * h=0) : NASimpleArray<Long*>(h) {}
// copy ctor
SequenceOfLong (const SequenceOfLong & orig, CollHeap * h=0) :
NASimpleArray<Long*>(orig,h) {}
};
//
// More Statement Nodes follow....
//
class StmtTimeStamp : public StmtNode
{
public:
Int64 timeStampValue;
StmtTimeStamp(Int64 new_value) : timeStampValue(new_value),
StmtNode(STM_TIMESTAMP)
{};
};
class StmtModule : public StmtNode
{
public:
StmtModule(CollHeap *h=0) :
StmtNode(STM_MODULE), name_(h), charSet_(h)
{}
StmtModule(const QualifiedName &mn, const NAString &cs, CollHeap *h) :
StmtNode(STM_MODULE), name_(mn,h), charSet_(cs,h)
{ assert(!cs.isNull()); }
StmtModule & operator=(const StmtModule &sm)
{
if (this != &sm) {
name_ = sm.name_;
charSet_ = sm.charSet_;
}
return *this;
}
QualifiedName &name() { return name_; }
NAString &charSet() { return charSet_; }
NABoolean isEmpty() const { return name_.getObjectName().isNull(); }
NABoolean isFull() const { return !name_.getCatalogName().isNull(); }
NABoolean applyDefaults(NABoolean wantR18behavior);
NABoolean unparse(NAString &result, NABoolean wantR18behavior);
NABoolean unparseSimple(NAString &result, NABoolean wantR18behavior);
void applyModuleCatalogSchema(const NAString& cat, const NAString& sch);
private:
StmtModule(const StmtModule &sm, CollHeap *h); // not written
QualifiedName name_;
NAString charSet_;
};
class StmtSourceFile : public StmtNode
{
public:
StmtSourceFile(NAString *src) : StmtNode(STM_SOURCE_FILE), pathname(src) {}
NAString *pathname;
};
class StmtProcedure : public StmtNode
{
public:
StmtProcedure(NAString *newName,
StmtNode *newBody) : StmtNode(STM_PROCEDURE),
name(newName), bodyStatement(newBody)
{ };
NAString *name;
StmtNode *bodyStatement;
};
/* This is the thing with the DescTypeList bound to a string thus representing */
/* a descriptor, whether it is input_or_output, and its name. */
/* */
/* This file declares a million of these structures that are */
/* aggregates: some data bound together along with a constructor for getting */
/* at it, and the client code gets to manage the dynamically allocated */
/* data. */
/* */
struct NamePlusDesc {
NamePlusDesc(NAString*, NABoolean, DescTypeList*);
NAString *descriptorName;
NABoolean isInput;
DescTypeList *descriptorArray;
};
/* The AllocStaticDesc statement node must hold members for the following */
/* items: the NamePlusDescriptor, the entity_tag, and the entity_name. */
/* */
/* Note that if entityTag == NAME_ABSENT then entityName is NULL. */
/* */
/* Also note that the client is responsible for managing the storage */
/* of the member data. */
/* */
class StmtAllocStaticDesc : public StmtNode
{
public:
NamePlusDesc *mainDescriptor;
StmtOrCursEnum entityTag;
NAString *entityName;
StmtAllocStaticDesc( NamePlusDesc*, StmtOrCursEnum, NAString*);
~StmtAllocStaticDesc() {};
/* we'll probably want the get() methods as well in here */
};
/* Now for the declaration of some statment classes to represent */
/* cursor declarations. */
/* */
class StmtDeclStatCurs : public StmtNode
{
public:
StmtDeclStatCurs(NAString*,RelExpr*
// QSTUFF
,NABoolean holdable = FALSE
// QSTUFF
);
NAString *cursorName;
RelExpr *cursorSpec;
};
class StmtDeclDynCurs : public StmtNode
{
public:
StmtDeclDynCurs(NAString*, NAString*
// QSTUFF
, NABoolean holdable = FALSE
// QSTUFF
);
NAString *cursorName;
NAString *stmtName;
};
/* This one is easy, rather like BEGIN/END DECLARE SECTION: just put */
/* an enumeration into a Statement Node in order to identify what */
/* kind of statement it is. */
/* */
class StmtXdynCurs : public StmtNode
{
public:
StmtXdynCurs(
// QSTUFF
NABoolean holdable = FALSE
// QSTUFF
) : StmtNode(STM_DECL_XDYNCURS
// QSTUFF
, holdable
// QSTUFF
) { };
};
/* Here's what we do then for entity_name, extended_input_designation, */
/* and open_cursor as well. For entity_name, the data is simply a pointer */
/* to a string (NAString, I DO NOT mean char*!). If the pointer is NULL, */
/* that means there is no string and that a host variable gives the name. */
/* If the pointer is NOT NULL then the string it points to is the literal */
/* name of the entity. */
/*
* DT_NULL -- no input designation specified at all
* DT_DESC_VIA_HV -- a host variable names a descriptor, so descName is NULL.
* DT_HVLIST -- there is a host variable list, so descName is NULL.
* DT_DESCRIPTOR -- the literal name of the descriptor is held by an NAString
* pointed to by descName.
*/
enum designator_tag { DT_NULL, DT_DESC_VIA_HV, DT_HVLIST, DT_DESCRIPTOR};
class designation : public NABasicObject
{
public:
designation(designator_tag); // where the new tag != DT_DESCRIPTOR
designation(NAString*); // for setting theTag to DT_DESCRIPTOR
designation();
NAString *descName;
designator_tag theTag;
};
/* The data structure associated with the open_cursor non-terminal */
/* is a structure with two members: 1) the cursor name, 2) the input */
/* designation. The cursor name is a pointer to a NAString. If the */
/* pointer is null, then a host variable names the cursor. Else, the */
/* pointer points to an NAString whose value is the cursor name. */
/* The input designation is a flag and a similar pointer. The flag */
/* tells if any using clause was present. If not, the pointer tells */
/* if/how a descriptor is named (literally, or via a host variable). */
/* */
class StmtOpen : public StmtNode
{
public:
StmtOpen(NAString* cn, designation* d=NULL) : StmtNode(STM_OPEN),
theCursorName(cn), inputDesignation(d)
{ };
NAString *theCursorName;
designation *inputDesignation;
};
/* For StmtFetch, again, we copy/paste/fix-up based on StmtOpen. */
/* */
class StmtFetch : public StmtNode
{
public:
StmtFetch(NAString* cn, designation* d) : StmtNode(STM_FETCH),
theCursorName(cn), outputDesignation(d)
{ };
NAString *theCursorName;
designation *outputDesignation;
};
/* The StmtNode for StmtPrepare is pretty simple. It merely needs */
/* to record the statement name, as entity (either literal, or */
/* via descriptor, meaning that a string host variable names it). */
/* */
class StmtPrepare : public StmtNode
{
public:
StmtPrepare(NAString *stmt_name) : StmtNode(STM_PREPARE),
theStatementName(stmt_name)
{ };
NAString *theStatementName;
};
/* For StmtExecute, again, we copy/paste/fix-up based on StmtOpen. */
/* */
class StmtExecute : public StmtNode
{
public:
StmtExecute(NAString* sn, designation* d=NULL, designation* d2=NULL)
: StmtNode(STM_EXECUTE), theStatementName(sn), inputDesignation(d),
outputDesignation(d2)
{ };
NAString *theStatementName;
designation *inputDesignation;
designation *outputDesignation;
};
/* We need a definition for StmtWhenever. */
/* */
class StmtWhenever : public StmtNode
{
public:
StmtWhenever(MBD_CONDITION con, action* ap) : StmtNode(STM_WHENEVER),
theCondition(con), theAction(ap)
{ };
MBD_CONDITION theCondition;
action *theAction;
};
class StmtXactCtl : public StmtNode
{
public:
StmtXactCtl(SQLTRANS_COMMAND nc) :
StmtNode(STM_XACT_CTL),theCommand(nc)
{ };
SQLTRANS_COMMAND theCommand;
};
class StmtDescribe : public StmtNode
{
public:
StmtDescribe(UInt32 dir, NAString *snp, NAString *dnp) :
StmtNode(STM_DESCRIBE),
direction(dir), statementName(snp), descriptorName(dnp)
{ };
NAString *statementName;
NAString *descriptorName;
UInt32 direction;
};
class StmtDeallocStm : public StmtNode
{
public:
StmtDeallocStm(NAString* theStatementName) :
StmtNode(STM_DEALLOC_STM), statementName(theStatementName) { };
NAString *statementName;
};
class StmtDeallocDesc : public StmtNode
{
public:
StmtDeallocDesc(NAString* theDescriptorName) :
StmtNode(STM_DEALLOC_DESC), descriptorName(theDescriptorName) { };
NAString *descriptorName;
};
class StmtClose : public StmtNode {
public:
StmtClose(NAString *theCursorName) :
StmtNode(STM_CLOSE), cursorName(theCursorName) { };
NAString* cursorName;
};
class StmtStmtDiag : public StmtNode {
public:
StmtStmtDiag(SequenceOfLong *inputList) :
StmtNode(STM_STMT_DIAGS), theList(inputList)
{assert(inputList !=NULL);}
~StmtStmtDiag()
{ delete theList; }
SequenceOfLong* getListPointer()
{
SequenceOfLong *result = theList;
assert(result!=NULL);
theList = NULL;
return result;
}
private:
SequenceOfLong *theList;
};
class StmtCondDiag : public StmtNode {
public:
StmtCondDiag(SequenceOfLong *inputList) :
StmtNode(STM_COND_DIAGS), theList(inputList)
{assert(inputList !=NULL);}
~StmtCondDiag()
{ delete theList; }
SequenceOfLong* getListPointer()
{
SequenceOfLong *result = theList;
assert(result!=NULL);
theList = NULL;
return result;
}
private:
SequenceOfLong *theList;
};
class StmtDescBase : public StmtNode {
public:
StmtDescBase(NAString* theDescriptorName,OperatorTypeEnum otype) :
StmtNode(otype), descriptorName(theDescriptorName) { }
~StmtDescBase();
NAString *theDescriptorLiteral() const;
protected:
NAString *descriptorName;
};
inline NAString *StmtDescBase::theDescriptorLiteral() const
{
return descriptorName;
}
// we need:
// get descriptor count -- the descriptor just needs to be specified
// in the StmtNode. This is just like for ALLOC and DEALLOC.
// I don't know how much sense it would make, but, you could
// have a template for these things, which takes a parameter of
// the oper-type-enum involved.
class StmtGetDescCount : public StmtDescBase {
public:
StmtGetDescCount(NAString* theDescriptorName) :
StmtDescBase(theDescriptorName,STM_GET_DESCCOUNT) { }
private:
};
class StmtGetRowsetSize : public StmtDescBase {
public:
StmtGetRowsetSize(NAString* theDescriptorName) :
StmtDescBase(theDescriptorName,STM_GET_ROWSETSIZE) { }
private:
};
// get descriptor item -- all we need is the list of the enum stuff, and
// we need the name of the descriptor. All the literal and
// hostvar stuff gets taken care of by other means.
class StmtGetDescItem : public StmtDescBase {
public:
StmtGetDescItem(NAString* theDescriptorName, SequenceOfLong* theItemList) :
theItems(theItemList),
StmtDescBase(theDescriptorName,STM_GET_DESCITEM) { }
SequenceOfLong *getItemsPtr() const
{
return theItems;
}
private:
SequenceOfLong *theItems;
};
// set descriptor item -- only need the descriptor name, and the list
// of items, much like for "get descriptor." The interesting
// thing here is: don't check for host var types until AFTER
// we know what statement it is (change in the preprocessor),
// since ANY type is allowed for the DATA item and only the
// runtime can type check that one; second thing is that
// there needs to be some clever way of routing so that
// the condition number gets routed separately from the
// other simple value specs.
// This class is virtually identical to the one for "get desc items."
// This similarity might be used to factor the code somehow.
class StmtSetDescItem : public StmtDescBase {
public:
StmtSetDescItem(NAString* theDescriptorName, SequenceOfLong*theItemList) :
theItems(theItemList),
StmtDescBase(theDescriptorName,STM_SET_DESCITEM) { }
SequenceOfLong *getItemsPtr() const
{
return theItems;
}
private:
SequenceOfLong *theItems;
};
// set descriptor count -- like many other statements, merely needs the
// name of the descriptor.
class StmtSetDescCount : public StmtDescBase {
public:
StmtSetDescCount(NAString* theDescriptorName) :
StmtDescBase(theDescriptorName,STM_SET_DESCCOUNT) { }
private:
};
class StmtSetRowsetSize : public StmtDescBase {
public:
StmtSetRowsetSize(NAString* theDescriptorName) :
StmtDescBase(theDescriptorName,STM_SET_ROWSETSIZE) { }
private:
};
// alloc descriptor -- all the parser has to do is to route the literal,
// if there is one, to the StmtNode::NAStringList, and do the
// host var role for the literal or the actual host var. This is
// for the simple value spec.
// And for the descriptor (which is either a literal or given by
// a simple host var) just the usual string for the designation,
// and possible routing that is needed in case of host variable.
class StmtAllocDesc : public StmtDescBase {
public:
StmtAllocDesc(NAString* theDescriptorName) :
StmtDescBase(theDescriptorName,STM_ALLOC_DESC) { }
private:
};
class StmtTransaction : public StmtNode {
public:
StmtTransaction( SequenceOfLong *theCmd ) :
StmtNode( STM_TRANSACTION ), theCommand_( theCmd )
{ assert( theCmd != NULL ); }
~StmtTransaction()
{ delete theCommand_; }
SequenceOfLong* getXactCommand()
{
SequenceOfLong *result = theCommand_;
assert( result != NULL );
theCommand_ = NULL;
return result;
}
private:
SequenceOfLong *theCommand_;
};
#endif /* STMTNODE_H */