blob: 0614b9460d0c0185673b8bb2b3c3d8d2ed5de11d [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: CmpStoredProc.h
* Description: The definition of internal stored procedure related classes
* used in arkcmp.
*
*
* Created: 03/14/97
* Language: C++
*
*
*
*
*****************************************************************************
*/
#ifndef CMPSTOREDPROC__H
#define CMPSTOREDPROC__H
#include "NABasicObject.h"
#include "NAString.h"
#include "CmpISPStd.h"
// for the table descriptions
#include "CmpCommon.h"
#include "Collections.h" // for NAList
#include "Int64.h"
// execution of the ISP
#include "StoredProcInterface.h"
// contents of this file
class CmpSPInputFormat; // format description for stored procedure input parameters.
class CmpSPOutputFormat; // format description for stored procedure output table.
class CmpSPExecDataItem; // the data item(data/expr) passed from executor for execution of SP.
class CmpSPDataObject; // the data object (in/out/key) passed from executor for exection of SP.
class CmpStoredProc; // interface to stored procedure.
class CmpInternalSP; // interface to built-in stored procedure.
class CmpISPFuncs; // class to hold the built-in SP function pointers.
class CmpExecDataItem; // the basic data item sent from executor for ISP execution
class CmpExecDataItemInput; // the input data sent from executor
class CmpExecDataItemReply; // the reply sent back to executor for ISP execution result
class CmpSPDataObject; // the data object for stored procedure execution
class CmpISPDataObject; // the data object for internal stored procedure execution
// forward declaration
class ElemDDLColDef;
class ItemExpr;
class CmpMessageISPRequest;
class TrafDesc;
class TrafColumnsDesc;
// -----------------------------------------------------------------------
// CmpSPInputFormat class contains the definition of input data for the
// stored procedure.
// This class provides methods for arkcmp to retrieve the input data format,
// an ITEM_LIST of NATypeToItem at sql compile/bind time.
// It also provides methods ( currently 04/04/97 only one ) to
// convert the different type of description of input parameters into
// CmpSPInputFormat.
// -----------------------------------------------------------------------
class CmpSPInputFormat : public NABasicObject
{
public:
CmpSPInputFormat(CmpContext* context);
// Set the definition from SP_FIELDDESC_STRUCT[].
// return TRUE if success, FALSE if failed.
NABoolean SetFormat(Lng32 nCols, // number of columns
SP_FIELDDESC_STRUCT* fields);
ItemExpr* itemExpr() { return inputType_; }
virtual ~CmpSPInputFormat();
private:
// members
// input format is described as an ITEM_LIST of NATypeToItem ItemExprs.
ItemExpr* inputType_;
CmpContext* context_;
CmpSPInputFormat(const CmpSPInputFormat&);
const CmpSPInputFormat& operator=(const CmpSPInputFormat&);
}; // end of CmpSPInputFormat
// -----------------------------------------------------------------------
// CmpSPOutputFormat class describes the format of the stored procedure
// virtual tables. This class provides the interface routines to be used
// in binder. It also includes methods to convert description of output
// data format into CmpSPOutputFormat.
// -----------------------------------------------------------------------
class CmpSPOutputFormat : public NABasicObject
{
public:
CmpSPOutputFormat(CmpContext* context);
virtual ~CmpSPOutputFormat();
// Set the definition from SP_FIELDDESC_STRUCT[].
// return TRUE if success, FALSE if failed.
NABoolean SetFormat(Lng32 nCols, // number of columns
const char* tableName, // table name
SP_FIELDDESC_STRUCT* fields, // description
Lng32 nKeys, // number of keys
SP_KEYDESC_STRUCT *keys // index to the key columns
);
// generate the table_desc for binder, this method will create the
// TrafDesc for the virtual table. The memory is allocated from
// sqlcat/read.C allocate routine, i.e. HEAP defined in common/CmpCommon.h
// The memory allocated belongs to the caller,
// the caller should delete it accordingly.
TrafDesc* tableDesc() { return tableDesc_; }
NABoolean ValidTableFormat() { return !tableDesc_ ; }
// static function to convert an ElemDDLColDef into TrafColumnsDesc
// return TRUE if success, FALSE if not.
static NABoolean ElemDDLColDef2ColumnDescStruct(ElemDDLColDef* elemDDL,
const char* tableName,
TrafColumnsDesc* colDesc);
private:
// output format is described as TrafTableDesc
TrafDesc* tableDesc_;
Lng32 nCols_;
CmpContext* context_;
// methods to pupulate column_desc from SP_FIELDDESC_STRUCT
// return TRUE : success, FALSE : fail
NABoolean getColumnDesc(SP_FIELDDESC_STRUCT* fDesc,
TrafColumnsDesc* colsDesc);
NABoolean getKeysDesc(Lng32 nkeys, SP_KEYDESC_STRUCT* keys,
TrafDesc* &keysDesc);
CmpSPOutputFormat(const CmpSPOutputFormat&);
const CmpSPOutputFormat& operator=(const CmpSPOutputFormat&);
}; // CmpSPOutputFormat
// -----------------------------------------------------------------------
// CmpSPExecDataItem class contains the actual data/expression for execution
// of the stored procedure. The expression and actual data are prepared by
// executor and passed to arkcmp. This class also contains the methods to
// access/format the data from/to executor.
// -----------------------------------------------------------------------
class CmpSPExecDataItem : public NABasicObject
{
public:
// Construct the CmpSPExecDataItem from expr and data
CmpSPExecDataItem(ULng32 exprSize, void* expr,
ULng32 dataSize, void* data,
CmpContext* context);
virtual ~CmpSPExecDataItem();
friend ostream& operator<<(ostream&, const CmpSPExecDataItem&);
ULng32 exprSize() { return exprSize_; }
void* & expr() { return expr_; }
ULng32 dataSize() { return dataSize_; }
void* data() { return data_; }
ComDiagsArea* SPFuncsDiags() { return SPFuncsDiags_; }
CollHeap* wHeap();
protected:
ULng32 exprSize_;
void* expr_;
ULng32 dataSize_;
void* data_;
// The ComDiagsArea used in the expr->data conversion routines,
// It is used locally in CmpSPExtractFunc_ and CmpSPFormatFunc_.
// The reason to put it here is for performance reason. Since the
// CmpSPExtractFunc_ and CmpSPFormatFunc_ are called for each fields
// of each row, it is very time consuming to call the constructor/dtor
// of ComDiagsArea each time. So a copy of ComDiagsArea is kept here,
// initialized to 0 entries, cleanup only when error occurs, it will
// save some time to construct/destruct ComDiagsArea in most cases,
// i.e. no error, no cleanup needed at all.
ComDiagsArea* SPFuncsDiags_;
CmpContext* context_;
CmpSPExecDataItem(const CmpSPExecDataItem&);
const CmpSPExecDataItem& operator=(const CmpSPExecDataItem&);
}; // CmpSPExecDataItem
extern ostream& operator<<(ostream&, const CmpSPExecDataItem&);
// class that contains input expression/data sent from executor
class CmpSPExecDataItemInput : public CmpSPExecDataItem
{
public:
// In the constructor, the input data will be
// . prepared : i.e. unpacked, since it was packed by executor before sent.
// . positioned to the first row.
CmpSPExecDataItemInput(ULng32 exprSize,
void* expr,
ULng32 dataSize,
void* data,
CmpContext* context);
virtual ~CmpSPExecDataItemInput();
// advance the current buffer data() for one tuple,
// returns 0 if success,
// 1 if no more row ( the current pointer will not point to a valid row.
// -1 if fail.
short next();
// extract certain field of data from current row
// returns 0 if success, non 0 if failed.
short extract(ULng32 num, char* data, ULng32 datalen, NABoolean casting,
ComDiagsArea* diags)
{ return ExSPExtractInputValue(expr(), num, currentRow(), data, datalen, casting, diags); }
// methods to retrieve private members
void* control() { return control_; }
char* currentRow() { return currentRow_; }
ULng32 rowLength() { return rowLength_; }
private:
// private members
char* currentRow_;
ULng32 rowLength_;
void* control_;
CmpSPExecDataItemInput(const CmpSPExecDataItemInput&);
const CmpSPExecDataItemInput& operator=(const CmpSPExecDataItemInput&);
}; // CmpSPExecDataItemInput
// class that contains the reply tuples to be sent back to executor
class CmpSPExecDataItemReply : public CmpSPExecDataItem
{
public:
// In the constructor, the output data will be
// . allocated with size specified from outHeap. this data field will be taken
// away ( i.e. pointer owned by other routine ) to avoid copying. so it needs
// to come from the heap as specified.
// . initialized to the executor expected format
CmpSPExecDataItemReply(ULng32 exprSize,
void* expr,
ULng32 dataRowSize,
ULng32 dataTotalSize,
CmpSPExecDataItemInput* inputData,
CollHeap* outHeap,
CmpContext* context);
virtual ~CmpSPExecDataItemReply();
// prepare the reply buffer before sent back to executor.
// returns TRUE if success, FALSE otherwise.
NABoolean prepare();
// put certain field of data into output data row
// returns 0 if success, non 0 if failed.
short moveOutput(ULng32 num,char* data,ULng32 datalen, NABoolean casting,
ComDiagsArea* diags)
{ return ExSPMoveOutputValue(expr(),
num,
(char*)rowBuffer_,
data,
datalen,
casting,
diags,
wHeap());
}
// move the diags info from SP_ERROR_STRUCT into diags_
NABoolean MoveDiags(const SP_ERROR_STRUCT*, const SP_STATUS spStatus);
// merge the diags info from *pDiags into diags_
NABoolean MergeDiags(ComDiagsArea *pDiags);
ComDiagsArea& diags() { return diags_; }
// methods to get the private members
ULng32 rowLength() { return rowLength_; }
void* rowBuffer() { return rowBuffer_; }
// The following routines move the interter rowBuffer_ or diags_ into data_ buffer to be
// sent back to executor.
// Return 1 : if rowBuffer_ is full, the buffer is not moved in, need to ask executor for
// more space.
// 0 : if success, the buffer is moved in.
// -1 : fail with error.
// Add a row(rowBuffer_) into the data_ buffer
short AddARow();
// Add an EOR (End of Row) into the data_ buffer, this is required by executor.
short AddEOR();
NABoolean rowExist() const { return rowExist_; }
NABoolean EORExist() const { return EORExist_; }
NABoolean moreData() const { return rowExist_ || EORExist_; }
// This method takes the data_ out, it is the caller's responsibility to
// delete the memory allocated for data_ field. So data_ should be allocated
// from outHeap_ which is passed in from constructor.
void* takeData() { void* ret = data_; data_ = 0; return ret; }
void allocateData(ULng32 size);
private:
// private members
CollHeap* outHeap_; // the heap to allocate output data_ from, since this data_ pointer might
// be taken away for performance reason. The caller should pass in the
// CollHeap* to allocate data from.
CmpSPExecDataItemInput* inputData_; // pointer to the input data that passed in to generate
// this reply data.
ULng32 rowLength_; // the length of each row, either calculated from expression,
// or passed in from executor.
// in the processing routines, open(), fetch() and close() the following output buffer
// and diags_ are passed in to the built-in SP for output and being moved into the data_
// fields sent back to executor.
// In the future, for efficiency, we might want to use the pointer in data_ to directly
// move in data instead of move it into the data_ buffer.
void* rowBuffer_; // the temperary buffer for each row, allocated in the constructor, reused
// for each fetch.
ComDiagsArea diags_; // the buffer for ComDiagsArea for processing routines
// The following flags identify whethere this object contains data to be sent back to
// executor. They are
// . FALSE in the beginning
// . TRUE/FALSE accordingly after interface with SP execution implementation.
// . FALSE after packed into data_ buffer successfully.
NABoolean rowExist_; // flag to identify whether rowBuffer_ contains data to be sent
// back to executor.
NABoolean diagsExist_; // flag to identify whether diags_ contains info to be sent back
// to executor.
NABoolean EORExist_; // needs to send an EOR(End Of a Row) to the data_
CmpSPExecDataItemReply(const CmpSPExecDataItemReply&);
const CmpSPExecDataItemReply& operator=(const CmpSPExecDataItemReply&);
}; // CmpSPExecDataItemReply
// -----------------------------------------------------------------------
// CmpSPDataObject class contains the actual data(input/output/key) for
// execution of the stored procedure. It is to be passed into the
// processing routines, i.e. open(), fetch() and close() routines.
// -----------------------------------------------------------------------
class CmpSPDataObject : public NABasicObject
{
public:
CmpSPDataObject() {}
virtual ~CmpSPDataObject() {}
private:
CmpSPDataObject(const CmpSPDataObject&);
const CmpSPDataObject& operator=(const CmpSPDataObject&);
}; // CmpSPDataObject
// -----------------------------------------------------------------------
// CmpISPDataObject class contains the actual data/expression for execution of the
// stored procedure. It is to be passed into the processing routines, i.e.
// open(), fetch() and close() routines.
// -----------------------------------------------------------------------
class CmpISPDataObject : public CmpSPDataObject
{
public:
CmpISPDataObject(CmpMessageISPRequest* ,
CmpInternalSP* isp,
CollHeap* outHeap,
CmpContext* context);
virtual ~CmpISPDataObject();
CmpSPExecDataItemInput* input() { return &input_; }
CmpSPExecDataItem* key() { return &key_; }
CmpSPExecDataItemReply* output() { return &output_; }
// returns TRUE, if there is more data to be retrieved for output.
NABoolean moreData() const { return output_.moreData(); }
private:
// members
// ispRequest from executor is kept in this object, since it owns the data
// member inside this ispRequest for performance reason. It will be
// deleted when this object is out of scope.
CmpMessageISPRequest* ispRequest_;
CmpSPExecDataItemInput input_;
CmpSPExecDataItem key_; // ???? TODO
CmpSPExecDataItemReply output_;
CmpContext* context_;
// the CollHeap to allocate output data from
CollHeap* outHeap_;
CmpISPDataObject(const CmpISPDataObject&);
const CmpISPDataObject& operator=(const CmpISPDataObject&);
}; // CmpISPDataObject
// -----------------------------------------------------------------------
// CmpStoredProc class is used by arkcmp ( compiler main program ) to
// compile and execute stored procedure. ( currently only internal stored
// procedures )
// The input/output data of the stored procedures are treated as rows of data
// from virtual tables. The format of the data will be provided in the virtual
// functions. These functions are used in compilation of the SQL query of
// executing the stored procedure.
// To actually execute the stored procedure, executor calls arkcmp for
// execution. The execution mechanism is similiar to cursor, i.e.
// for each input data
// call open virtual method to start the process of input data.
// call fetch virtual method to fetch each row of data.
// call close virtual method when the there is no more output data.
//
// -----------------------------------------------------------------------
class CmpStoredProc : public NABasicObject
{
public:
CmpStoredProc(const NAString& procName, CmpContext* cmpContext);
virtual ~CmpStoredProc();
// virtual function to retrieve the input data format
// return TRUE if success, FALSE otherwise
// num is the number of input parameters expected, it is returned from
// parser.
virtual NABoolean InputFormat(Lng32 num, CmpSPInputFormat&);
// virtual function to retrieve the output data format
//return TRUE if success, FALSE otherwise
virtual NABoolean OutputFormat(CmpSPOutputFormat&);
// return status from open, fetch and close methods
enum ExecStatus { SUCCESS, MOREDATA, FAIL };
// virtual function to process input data
// return SUCESS if no error, return FAIL if there is error. The error information
// is put into the diags area in cmpContext_
virtual ExecStatus open(CmpSPDataObject&);
// virtual function to fetch output data
// return SUCESS if there is no more data, return MOREDATA if there are more data
// to be fetched, return FAIL if there is error. The error information is put
// into the diags area in CmpContext_
virtual ExecStatus fetch(CmpSPDataObject&);
// virtual function to end a process of one input data
// return SUCCESS if no error. return FAIL is there is error. The error information
// is put into the diags area in cmpContext_
virtual ExecStatus close(CmpSPDataObject&);
CmpContext* cmpContext() { return cmpContext_; }
const NAString& procName() const { return procName_; }
private:
NAString procName_;
CmpContext* cmpContext_;
CmpStoredProc(const CmpStoredProc&);
const CmpStoredProc& operator=(const CmpStoredProc&);
}; // CmpStoredProc
// -----------------------------------------------------------------------
// CmpInternalSP is the stored procedure class that runs in the mechanism
// as described in the 'Internal Stored Procedure ES'.
// These stored procedures are defined by the internal developer, the
// interfaces are
// from arkcmp : CmpISPStd.h
// from user defined internal SP : an xxxx.h file for declaration of
// interface routines. A DLL/LIB for the implementation.
// The user defined SP will be linked into arkcmp.
// The interface procedures are defined as C interface to accomidate C, C++
// routines. The basic routines are
// - routine to get the input data format.
// - routines to get the output data format, number of fields and format.
// The output data is treated as a virtual table.
// - routine to process the data, the processing is treated as in cursor,
// for each input row of data, OPEN, FETCH and CLOSE are called
// accordingly.
// -----------------------------------------------------------------------
//------------------------------------------------------------------------
// CmpISPFuncs is the class to maintain the index to built-in stored procedure
// implementation being linked in.
// Currently ( 05/20/97 ) a static array is maintained, being populated by
// in the constructor by calling some entry routines that built-in stored
// procedures provide.
//------------------------------------------------------------------------
class CmpISPFuncs
{
public:
// The structure to keep references to a built-in stored procedure,
// it is indexed by the procName_.
struct ProcFuncsStruct
{
char procName_[SP_STRING_MAX_LENGTH]; // null terminated
SP_COMPILE_FUNCPTR compileFunc_;
SP_INPUTFORMAT_FUNCPTR inFormatFunc_;
SP_PARSE_FUNCPTR parseFunc_;
SP_NUM_OUTPUTFIELDS_FUNCPTR outNumFormatFunc_;
SP_OUTPUTFORMAT_FUNCPTR outFormatFunc_;
SP_PROCESS_FUNCPTR procFunc_;
SP_HANDLE spHandle_;
ProcFuncsStruct(const char* procName=0,
SP_COMPILE_FUNCPTR compileFunc=0,
SP_INPUTFORMAT_FUNCPTR inFormatFunc=0,
SP_PARSE_FUNCPTR parseFunc=0,
SP_NUM_OUTPUTFIELDS_FUNCPTR outNumFormatFunc=0,
SP_OUTPUTFORMAT_FUNCPTR outFormatFunc=0,
SP_PROCESS_FUNCPTR procFunc=0,
SP_HANDLE spHandle=0)
{
if (procName)
strcpy(procName_, procName);
else
procName_[0] = 0;
compileFunc_ = compileFunc;
inFormatFunc_ = inFormatFunc;
parseFunc_ = parseFunc;
outNumFormatFunc_ = outNumFormatFunc;
outFormatFunc_ = outFormatFunc;
procFunc_ = procFunc;
spHandle_ = spHandle;
}
NABoolean operator == (const ProcFuncsStruct& other)
{
return(strcmp(procName_, other.procName_)== 0 );
}
};
// the static array for built-in stored procedure implementation
// reference. This should be a process wide information.
static NAList<ProcFuncsStruct> procFuncsArray_;
CmpISPFuncs();
virtual ~CmpISPFuncs();
// methods to access the interface function pointer
inline const ProcFuncsStruct& operator[](const NAString& name) const;
NABoolean ValidPFuncs(const ProcFuncsStruct& pFuncs) const;
// method to register function pointers for a built-in stored procedures,
// indexed by name. This will be the callback function for built-in
// stored procedures to register the function pointers.
static Int32 RegFuncs(const char* procName,
SP_COMPILE_FUNCPTR compileFunc,
SP_INPUTFORMAT_FUNCPTR inFormatFunc,
SP_PARSE_FUNCPTR parseFunc,
SP_NUM_OUTPUTFIELDS_FUNCPTR outNumFormatFunc,
SP_OUTPUTFORMAT_FUNCPTR outFormatFunc,
SP_PROCESS_FUNCPTR procFunc,
SP_HANDLE spHandle,
const char* version);
private:
CmpISPFuncs(const CmpISPFuncs&);
const CmpISPFuncs& operator = (const CmpISPFuncs&);
}; // end of CmpISPFuncs
class CmpInternalSP : public CmpStoredProc
{
public:
CmpInternalSP(const NAString& procName, CmpContext* cmpContext);
virtual ~CmpInternalSP();
// return the table name from procName
NAString OutTableName();
virtual NABoolean InputFormat(Lng32 num, CmpSPInputFormat&);
virtual NABoolean OutputFormat(CmpSPOutputFormat& );
// used only in ISP_UTIL command
// return TRUE if success, FALSE if fail.
NABoolean ParseInput(const NAString& param);
// virtual function to process input data
ExecStatus open(CmpISPDataObject&);
// virtual function to fetch output data
ExecStatus fetch(CmpISPDataObject&);
// virtual function to end a process of one input data
ExecStatus close(CmpISPDataObject&);
CmpISPDataObject* ispData() const { return ispData_; }
void SetCmpISPDataObject(CmpISPDataObject* ispData) { ispData_ = ispData; }
private:
// The Lookup Table for all the built-in stored procedured
CmpISPFuncs procFuncsLookupTable_;
// The entry of the built-in stored procedure interface
// routines for this instance of CmpInternalSP
CmpISPFuncs::ProcFuncsStruct procFuncs_;
// members for handles to interface routines
SP_COMPILE_HANDLE compHandle_;
SP_PROCESS_HANDLE procHandle_;
// SP_ERROR_STRUCT used for the interface routines to ISP
SP_ERROR_STRUCT spError_[SP_MAX_ERROR_STRUCTS];
// CmpISPDataObject contains data for execution of ISP
CmpISPDataObject* ispData_;
// state of the internalSP, the state of the CmpInternalSP could be
// NONE -> COMPILE -> NONE for compilation.
// NONE -> EXECUTE -> NONE for execution.
enum InterfaceState
{
COMPILE, // in compile of the SP query
PROCESS, // in execution of the SP query
NONE // none of the above
} state_;
// helper routines for compiler related tasks.
// method to start Compile cycle.
NABoolean startCompileCycle();
// methods for SP interface structure allocation
SP_FIELDDESC_STRUCT* allocSP_FIELDDESC_STRUCT(Lng32 num);
void deleteSP_FIELDDESC_STRUCT(SP_FIELDDESC_STRUCT*);
SP_KEYDESC_STRUCT* allocSP_KEYDESC_STRUCT(Lng32 num);
void deleteSP_KEYDESC_STRUCT(SP_KEYDESC_STRUCT*);
// private methods for error handling.
// initialize spError_ before each interface routine.
void initSP_ERROR_STRUCT();
// append the error info into cmpContext()->diags, sent back to arkcmp
void appendDiags();
CmpInternalSP(const CmpInternalSP&);
const CmpInternalSP& operator=(const CmpInternalSP&);
}; // CmpInternalSP
inline const CmpISPFuncs::ProcFuncsStruct&
CmpISPFuncs::operator[](const NAString& name) const
{
Int32 i;
for ( i=0; i < (Int32)(procFuncsArray_.entries()-1); i++)
if (name == procFuncsArray_[i].procName_)
return procFuncsArray_[i];
return procFuncsArray_[i];
}
// helper routines CmpInternalSP provides for the SP interface routines.
#ifndef CMPISPUTILS__C
extern "C"
{
extern SP_EXTRACT_FUNCPTR CmpSPExtractFunc;
extern SP_FORMAT_FUNCPTR CmpSPFormatFunc;
extern SP_KEYVALUE_FUNCPTR CmpSPKeyValueFunc;
}
#endif
#endif