blob: 5b5a4544787c2f32bb543c764678ad17437380a8 [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 HSCLI_H
#define HSCLI_H
/* -*-C++-*-
*****************************************************************************
*
* File: hs_cli.h
* Description: Classes for accessing tables using CLI calls.
* Created: 03/25/96
* Language: C++
*
*
*
*
*****************************************************************************
*/
// -----------------------------------------------------------------------
#include "Platform.h"
#include <stdarg.h>
#include "NAType.h"
#include "Int64.h"
#include "SQLCLIdev.h"
#include "hs_cont.h"
#include "hs_const.h"
#include "hs_log.h"
// -----------------------------------------------------------------------
// Externals.
// -----------------------------------------------------------------------
class HSGlobalsClass;
class HSDataBuffer;
class HSTableDef;
struct HSColDesc;
struct HSColGroupStruct;
struct HSColumnStruct;
class ISFixedChar;
class ISVarChar;
class MCWrapper;
template <class T> class HSPtrObj;
template <class T> class HSPtrArray;
// -----------------------------------------------------------------------
// Functions.
// -----------------------------------------------------------------------
// Execute a standalone dml/ddl operation, without retry.
Lng32 HSFuncExecQuery( const char *dml
, short sqlcode = - UERR_INTERNAL_ERROR
, Int64 *rowsAffected = NULL
, const char *errorToken = HS_QUERY_ERROR
, Int64 *srcTabRowCount = NULL
, const HSTableDef *tabDef = NULL
, short errorToIgnore = 0
, NABoolean checkMdam = FALSE
, NABoolean inactivateErrorCatcher = FALSE
);
// Body shared between HSFuncExecQuery and
// HSFuncExecTransactionalQueryWithRetry
Lng32 HSFuncExecQueryBody( const char *dml
, short sqlcode
, Int64 *rowsAffected
, const char *errorToken
, Int64 *srcTabRowCount
, const HSTableDef *tabDef
, short errorToIgnore
, NABoolean checkMdam
);
// Execute a standalone dml/ddl operation, with retry. Note
// that this method handles starting and committing or rolling
// back the transaction (as that needs to be part of the retry
// loop since Trafodion often aborts transactions when
// statements fail). Therefore, this function cannot be called
// within a transaction. In fact it guards against this and will
// return an error if it is called within a transaction. One
// consequence is that calls to this function cannot be
// done within the scope of an HSTranController object.
//
// Some thought should go into the choice of whether to use
// this function vs. HSFuncExecQuery. It is appropriate to use
// this function if the effect on the database is idempotent.
// Examples of this are most DDL operations, DELETE, UPDATE
// and INSERT statements that don't depend on prior state and
// don't include non-deterministic semantics such as SAMPLE.
// Operations that have non-transactional effects and non-
// deterministic semantics (such as UPSERT USING LOAD with a
// SAMPLE clause) should not be retried at this level.
//
Lng32 HSFuncExecTransactionalQueryWithRetry( const char *dml
, short sqlcode = - UERR_INTERNAL_ERROR
, Int64 *rowsAffected = NULL
, const char *errorToken = HS_QUERY_ERROR
, Int64 *srcTabRowCount = NULL
, const HSTableDef *tabDef = NULL
, short errorToIgnore = 0
, NABoolean checkMdam = FALSE
);
Lng32 HSFuncExecDDL( const char *dml
, short sqlcode = -UERR_INTERNAL_ERROR
, Int64 *rowsAffected = NULL
, const char *errorToken = HS_DDL_ERROR
, const HSTableDef *tabDef = NULL
);
Lng32 HSClearCLIDiagnostics();
// Obtain any JNI diagnostic text stored in the CLI
const char * HSFuncGetJniErrorStr();
// Create histogram tables if they don't exist.
Lng32 CreateHistTables (const HSGlobalsClass* hsGlobal);
Lng32 CreateHistView (const HSGlobalsClass* hsGlobal);
// Drop the sample table.
Lng32 DropSampleTable();
Lng32 checkMdam(SQLSTMT_ID *stmt);
Lng32 printPlan(SQLSTMT_ID *stmt);
void getRowCountFromStats(Int64 * rowsAffected , const HSTableDef *tabDef = NULL);
struct myVarChar
{
short len;
char val[HS_MAX_BOUNDARY_LEN];
myVarChar() : len(0) {}
myVarChar& operator=(const struct myVarChar &other)
{
len = other.len;
memmove(val, other.val, len);
return *this;
}
};
template <class T>
struct boundarySet
{
Lng32 size;
short nullInd[MAX_ROWSET];
short avgVarCharNullInd[MAX_ROWSET];
T data[MAX_ROWSET];
Int64 dataSum[MAX_ROWSET];
Int64 avgVarCharSize[MAX_ROWSET];
// This is used in gap processing.
double gapMagnitude[MAX_ROWSET];
boundarySet() : size(0) {}
};
void mergeAverage(NABoolean firstRowset,
double rowsetGapAvg, Int64 rowsetGapCount,
double &overallGapAvg_, Int64 &overallGapCount_);
// Convert UCS2 string represented by len (# bytes, not chars) and
// val (ptr to first byte of UCS2 string) to double.
double ucsToDouble(Int16 len, const char* val);
double ucsToDouble(myVarChar* ucs);
double ucsToDouble(const HSDataBuffer& hsDataBuff);
/*****************************************************************************/
/* CLASS: HSSample */
/* FUNCTION: Used for creating a single sample table, possibly persistent. */
/*****************************************************************************/
class HSSample
{
public:
HSSample(HSTableDef *tableDef, // input
Lng32 type, // input - sample type used for table creation
double sampleTblPercent, // input
NABoolean persistent = FALSE, // input - used to determine whether to drop
NABoolean isIUS = FALSE // input - whether the sample table
// is created for IUS
) : objDef(tableDef), sampleType(type),
samplePercent(sampleTblPercent), isPersistent(persistent),
isIUS_(isIUS),
makeAccessible_(FALSE)
{};
~HSSample() { if (!isPersistent) drop(); }
// Drop a sample table. Used internally by member function drop(), and from
// outside the class to drop an IUS persistent sample table that is replaced
// by a new one. This function only drops the table, it does not remove the
// row for it in the PERSISTENT_SAMPLES metadata table.
static Lng32 dropSample(NAString& sampTblName, HSTableDef *sourceTblDef);
// Set up vars for creating sample table, create table (by calling create), then
// insert appropriately from source table.
Lng32 make(NABoolean rowCountIsEstimate, // input - used for assigning tableRowCount
NAString &sampleTable, // output
Int64 &tableRowCnt, // output - rowcount of original table
Int64 &sampleRowCnt, // output
NABoolean isPersSample=FALSE, //input - used to specify if the
// method is being called to create
// persistent sample table for fetch
// count or not
NABoolean unpartitioned=FALSE, //input - used to specify if the
// method is being called to create
// unpartitioned persistent sample
Int64 minRowCtPerPartition = -1 // minimal row RC per partition
);
// Create sample table (called by make).
Lng32 create(NABoolean unpartitioned = FALSE,
NABoolean isPersSample = FALSE
);
Lng32 create(NAString& tblName,
NABoolean unpartitioned = FALSE,
NABoolean isPersSample = FALSE);
// Drop the sample table associated with this object if one exists. The member
// variable 'sampleTable' will contain the name of the sample table if so.
Lng32 drop() { return dropSample(sampleTable, objDef); }
NABoolean isIUS() { return isIUS_; }
private:
// Member function
void makeTableName(NABoolean isPersSample = FALSE);
NAString getTempTablePartitionInfo(NABoolean unpartitionedSample = FALSE,
NABoolean isPersSample=FALSE);
// Member variables
HSTableDef *objDef;
NAString sampleTable;
Lng32 sampleType;
NABoolean isPersistent;
double samplePercent;
Int64 TableRowCount;
Int64 sampleRowCount;
NABoolean unpartitionedSample;
NABoolean isIUS_;
NABoolean makeAccessible_;
};
/*****************************************************************************/
/* CLASS: HSDataBuffer */
/* FUNCTION: Maintains the interval VARACHR attributes of data. */
/* |------------------ */
/* | LEN | DATA | */
/* |------------------ */
/*****************************************************************************/
class HSDataBuffer
{
public:
HSDataBuffer() :
len(0), val(NULL)
{}
~HSDataBuffer()
{
NADELETEBASIC (val, STMTHEAP);
}
HSDataBuffer(const NAWchar *initVal)
{
len = NAWstrlen(initVal) * sizeof(NAWchar);
val = new (STMTHEAP) char[len];
memmove(val, initVal, len);
}
HSDataBuffer& operator=(const HSDataBuffer &other)
{
if (other.len > len)
{
NADELETEBASIC (val, STMTHEAP);
val = new (STMTHEAP) char[other.len];
}
len = other.len;
memmove(val, other.val, other.len);
return *this;
}
HSDataBuffer& operator=(const NAWchar *dataVal) // replace buffer contents
{
short newlen = NAWstrlen(dataVal) * sizeof(NAWchar);
if (newlen > len)
{
NADELETEBASIC (val, STMTHEAP);
val = new (STMTHEAP) char[newlen];
}
len = newlen;
memmove(val, dataVal, len);
return *this;
}
// Fill the buffer from newVal for newLen bytes. If nullTerm is true,
// terminate the string with a wide null character that is not included
// in the stored length. The null terminator is needed for certain
// operations performed by IUS for intervals read in from the metadata.
HSDataBuffer& copyFrom(const char *newVal, short newLen, NABoolean nullTerm = FALSE)
{
short extra = nullTerm ? 2 : 0;
if (newLen + extra > len)
{
NADELETEBASIC (val, STMTHEAP);
val = new (STMTHEAP) char[newLen+extra];
}
len = newLen;
memmove(val, newVal, len);
if (nullTerm)
*(((NAWchar*)val) + (len/sizeof(NAWchar))) = L'\0';
return *this;
}
inline short length() const {return len;}
inline short numChars() const {return len / sizeof(NAWchar);}
inline const char* data() const {return val;}
Lng32 addParenthesis();
Lng32 append(HSDataBuffer &dataBuffer);
private:
short len;
char *val;
};
/*****************************************************************************/
/* CLASS: HSTranMan */
/* FUNCTION: Transaction manager for all of Update Statistics needs. */
/* NOTES: This is a singleton class, which means that there could only be */
/* one instance of this class. */
/*****************************************************************************/
class HSTranMan
{
public:
static HSTranMan* Instance();
/* Begin Transaction */
Lng32 Begin(const char *title = "",
NABoolean inactivateErrorCatcher=FALSE);
/* Commit Transaction */
Lng32 Commit(NABoolean inactivateErrorCatcher=FALSE);
/* Rollback Transaction */
Lng32 Rollback(NABoolean inactivateErrorCatcher=FALSE);
// This method will tell you if there is currently a transaction
// running. The transaction could have been started by USER or this
// instance.
// T: transaction is running
// F: no transaction running
NABoolean InTransaction();
// This method tells you if the transaction was started by this
// instance.
// T: transaction was started by this instance.
// F: 1) no transaction running or 2) transaction was started by USER.
inline NABoolean StartedTransaction() const {return transStarted_;}
void logXactCode(const char* title);
protected:
HSTranMan(); /* ensure only 1 instance of class */
private:
NABoolean transStarted_; /* T: instance started transaction */
NABoolean extTrans_; /* T: external transaction running */
Lng32 retcode_;
static THREAD_P HSTranMan* instance_; /* 1 and only 1 instance */
};
/********************************************************************************/
/* CLASS: HSPrologEpilog */
/* FUNCTION: An instance of this class with automatic storage class should be */
/* used at the beginning of each function that is an entry point to */
/* ustat processing (UpdateStats, FetchHistograms). The ctor/dtor */
/* work in tandem to do any work or satisfy any invariants required */
/* at the beginning/end of processing. Currently, the only necessity */
/* is to ensure that any transaction initiated by ustat is terminated */
/* before returning from the ustat code. This is to catch any case */
/* where an exception disrupts the normal control flow such that the */
/* commit or rollback of a transaction is bypassed. Normally, this is */
/* precluded by use of an HSTranController object, but there are still*/
/* a few places where this is not used (some of which are not amenable*/
/* to its use). */
/********************************************************************************/
class HSPrologEpilog
{
public:
HSPrologEpilog(NAString scopeName);
virtual ~HSPrologEpilog();
private:
NAString scopeName_; // Used in log messages to identify function
HSTranMan* tranMan_;
HSLogMan* logMan_;
NABoolean enteredWithTranInProgress_;
};
/*****************************************************************************/
/* CLASS: HSTranController */
/* FUNCTION: */
/* Resource management class used to define a transaction's boundaries and */
/* ensure that the transaction is terminated. The class uses the RAII */
/* (Resource Acquisition Is Initialization) design pattern, using the ctor */
/* to begin a transaction and the dtor to end it. An instance of this class */
/* should be created on the stack in a function or block, to ensure that the */
/* transaction it starts will be terminated when the function or block exits,*/
/* even if there is an early return, as is the case when the HSHandleError */
/* define is invoked. */
/* */
/* The decision as to whether the transaction should be committed or rolled */
/* back in the dtor is determined by the value of a return code, the address */
/* of which is passed to HSTranController's ctor. */
/* */
/* Limitations: Unfortunately, Trafodion often aborts transactions when DDL */
/* or DML statements fail. This precludes using HSTranController in retry */
/* scenarios as the retry would either fail due to lack of a transaction or */
/* (worse) succeed in a separate transaction. The latter is worse because */
/* any other work done in the original transaction would silently be undone. */
/* To guard against this, HSFuncExecTransactionalQueryWithRetry raises an */
/* error if done within the scope of an HSTranController object. */
/*****************************************************************************/
class HSTranController
{
public:
HSTranController(const char* title = "", Lng32* returnCode = NULL);
~HSTranController();
// Function to stop current transaction and start a new one.
void stopStart(const char* title);
private:
HSTranMan* tranMan_;
HSLogMan* logMan_;
NAString title_;
Lng32* returnCodePtr_;
NABoolean startedTrans_;
// Function to end transaction.
void endTrans();
};
/*****************************************************************************/
/* CLASS: HSPersSamples */
/* FUNCTION: Handles persistent samples created for statistics needs. */
/* NOTES: This is a singleton class, which means that there could only be */
/* one instance of this class. */
/*****************************************************************************/
class HSPersSamples
{
public:
// Creates or returns instance.
static HSPersSamples* Instance(const NAString &catalog,
const NAString &schema);
Lng32 updIUSUpdateInfo(HSTableDef* tblDef,
const char* updHistory,
const char* updTimestampStr,
const char* updWhereCondition,
const Int64* requestedSampleRows = NULL,
const Int64* actualSampleRows = NULL);
Lng32 readIUSUpdateInfo(HSTableDef* tblDef,
char* updHistory,
Int64* updTimestamp);
// finds a persistent sample table for UID and reason code and returns it in 'table'.
// (returns ' ' in table if none is found).
Lng32 find(HSTableDef *tabDef, char reason, NAString &table,
Int64 &requestedRows, Int64 &sampleRows, double &sampleRate);
// finds a persistent sample table for UID and sample size and returns in 'table'.
// Will remove any 'obsolete' samples found.
Lng32 find(HSTableDef *tabDef, Int64 &actualRows, NABoolean isEstimate,
Int64 &sampleRows, double allowedDiff, NAString &table);
// create a persistent sample table and insert an entry for it into list.
Lng32 createAndInsert(HSTableDef *tabDef, NAString &sampleName,
Int64 &sampleRows, Int64 &actualRows,
NABoolean isEstimate, char reason,
NABoolean createDandI=FALSE,
Int64 minRowsCtPerPartition = -1);
// remove persistent sample table(s) based on uid, sampleRows, and the
// allowed difference between the number of rows and sampleRows.
Lng32 removeMatchingSamples(HSTableDef *tabDef, Int64 sampleRows, double allowedDiff);
// drop the named sample table and remove its entry from the
// PERSISTENT_SAMPLES table.
Lng32 removeSample(HSTableDef* tabDef, NAString& sampTblName,
char reason, const char* txnLabel);
~HSPersSamples();
protected: /* ensure only 1 instance of class */
HSPersSamples(const NAString &catalog,
const NAString &schema);
void setCatalogSchema(const NAString &catalog,
const NAString &schema);
private:
static THREAD_P HSPersSamples* instance_; /* 1 and only 1 instance */
NAString* catalog_;
NAString* schema_;
NABoolean triedCreatingSBPersistentSamples_;
};
/*****************************************************************************/
/* CLASS: HSPersData */
/* FUNCTION: Handles persistent data tables created for statistics needs. */
/* NOTES: This is a singleton class, which means that there could only be */
/* one instance of this class. */
/*****************************************************************************/
class HSPersData
{
public:
static HSPersData* Instance(const NAString &catalog); // creates or returns instance.
Lng32 insert(NAString &tableName, ULng32 objectSubId, ULng32 seqNum, NAString &data);
Lng32 remove(NAString &tableName, ULng32 objectSubId, ULng32 seqNum);
Lng32 fetch(NAString &tableName, ULng32 objectSubId, ULng32 seqNum, NAString &data);
protected:
HSPersData(); /* ensure only 1 instance of class */
private:
static THREAD_P HSPersData* instance_; /* 1 and only 1 instance */
static THREAD_P NAList<NAString>* persDataList_;
static THREAD_P NAString* catalog_;
static THREAD_P NAString* schema_;
};
// -----------------------------------------------------------------------
// Class to run a static cli statement without output host variables.
// -----------------------------------------------------------------------
#define HS_MODULE "HP_SYSTEM_CATALOG.SYSTEM_SCHEMA.SQLHIST_N29_000"
#define HS_MODULE_LENGTH 50 // more than needed
#define HS_STMTID "HS_CLI_DYNSTMT"
#define HS_INTERVAL_STMT_ID "HS_INTERVAL_STMT_ID"
#define HS_STMTID_LENGTH 50
#define HS_FUNC_EXEC_QUERY_STMTID "HS_FUNC_EXEC_QUERY_DYNSTMT"
class HSCliStatement {
public:
// Encoding indexes for static SQL statements.
// This index is a 32-bit number
// First 16 bits stores the number of host variables for that statement.
// Last 16 bits stores the statement index in the statementNames array.
//
// Literal ...1?? stands for operations on HISTOGRAMS table, while
// ...2?? for operations on HISTOGRAM_INTERVALS table.
//
// Statement names and number of host variables must match those in
// sqlhist.mdf file.
enum statementIndex {
BEGINWORK = 0x00000000,
COMMITWORK = 0x00000001,
ROBACKWORK = 0x00000002,
PRINTPLAN = 0x00010003,
INSERT101_MP = 0x000C0004, INSERT101_MX = 0x000C0005, INSERT101_MX_2300 = 0x00190006,
INSERT201_MP = 0x00070007, INSERT201_MX = 0x00070008, INSERT201_MX_2300 = 0x000E0009,
DELETE101_MP = 0x0002000A, DELETE101_MX = 0x0002000B, DELETE101_MX_2300 = 0x0002000C,
DELETE201_MP = 0x0002000D, DELETE201_MX = 0x0002000E, DELETE201_MX_2300 = 0x0002000F,
DELETE102_MP = 0x00040010, DELETE102_MX = 0x00040011, DELETE102_MX_2300 = 0x00040012,
DELETE202_MP = 0x00040013, DELETE202_MX = 0x00040014, DELETE202_MX_2300 = 0x00040015,
SECURITY101_MP = 0x00010016, SECURITY101_MX = 0x00010017, SECURITY101_MX_2300 = 0x00010018,
SECURITY201_MP = 0x00010019, SECURITY201_MX = 0x0001001A, SECURITY201_MX_2300 = 0x0001001B,
CURSOR101_MP = 0x0002001C, CURSOR101_MX = 0x0002001D, CURSOR101_MX_2300 = 0x0002001E,
CURSOR101_NOMC_MP = 0x0002001F, CURSOR101_NOMC_MX = 0x00020020, CURSOR101_NOMC_MX_2300 = 0x00020021,
CURSOR102_MP = 0x00020022, CURSOR102_MX = 0x00020023, CURSOR102_MX_2300 = 0x00020024,
CURSOR103_MP = 0x00020025, CURSOR103_MX = 0x00020026, CURSOR103_MX_2300 = 0x00020027,
CURSOR201_MP = 0x00020028, CURSOR201_MX = 0x00020029, CURSOR201_MX_2300 = 0x0002002A,
SHOWHIST_MP = 0x0003002B, SHOWHIST_MX = 0x0003002C, SHOWHIST_MX_2300 = 0x0003002D,
SHOWINT_MP = 0x0003002E, SHOWINT_MX = 0x0003002F, SHOWINT_MX_2300 = 0x00030030,
ROWCOUNT_FROM_STATS = 0x00010031, CURSOR104_MX_2300 = 0x00020032, INSERT104_MX_2300 = 0x00190033,
CURSOR105_MX_2300 = 0X00030034,
DELETE_PST = 0X00020035, INSERT_PST = 0X000D0036, CURSOR_PST = 0X00040037,
CURSOR_PST_REASON_CODE = 0x00030038,
CURSOR107_MX_2300 = 0x00030039,
DELETE_PDT = 0X0004003A, INSERT_PDT = 0X0005003B, CURSOR_PDT = 0X0004003C,
CURSOR_PST_UPDATE_INFO = 0x0002003D, UPDATE_PST_UPDATE_INFO = 0x0004003E,
CURSOR103_MX_2300_X = 0x0002003F
};
enum { MAX_NUM_HOST_VARIABLES = 0x19 };
HSCliStatement( statementIndex ix,
char * in01 = NULL, char * in02 = NULL, char * in03 = NULL,
char * in04 = NULL, char * in05 = NULL, char * in06 = NULL,
char * in07 = NULL, char * in08 = NULL, char * in09 = NULL,
char * in10 = NULL, char * in11 = NULL, char * in12 = NULL,
char * in13 = NULL, char * in14 = NULL, char * in15 = NULL,
char * in16 = NULL, char * in17 = NULL, char * in18 = NULL,
char * in19 = NULL, char * in20 = NULL, char * in21 = NULL,
char * in22 = NULL, char * in23 = NULL, char * in24 = NULL,
char * in25 = NULL
);
~HSCliStatement();
Lng32 open();
Lng32 fetch(Lng32 numParam,
void * out01, void * out02 = NULL, void * out03 = NULL,
void * out04 = NULL, void * out05 = NULL, void * out06 = NULL,
void * out07 = NULL, void * out08 = NULL, void * out09 = NULL,
void * out10 = NULL, void * out11 = NULL, void * out12 = NULL,
void * out13 = NULL, void * out14 = NULL, void * out15 = NULL,
void * out16 = NULL, void * out17 = NULL, void * out18 = NULL,
void * out19 = NULL, void * out20 = NULL, void * out21 = NULL,
void * out22 = NULL, void * out23 = NULL, void * out24 = NULL,
void * out25 = NULL
);
Lng32 close();
Lng32 execFetch(const char *dml, NABoolean hideError = FALSE);
static const Int64 largeZero = 0; // const Int64(0)
static const Int64 largeMinusOne = -1; // const Int64(-1)
static const short minusOne = -1; // const -1;
static THREAD_P Lng32 statementNum; // statement number
private:
SQLSTMT_ID stmt_;
SQLDESC_ID desc_;
SQLDESC_ID *pInputDesc_;
char stmtID_[HS_STMTID_LENGTH]; // statement name.
char descID_[HS_STMTID_LENGTH]; // input descriptor name.
// number of input host variables.
Lng32 numVars_;
// Addresses of input host variables.
char * in01_, * in02_, * in03_, * in04_,
* in05_, * in06_, * in07_, * in08_,
* in09_, * in10_, * in11_, * in12_,
* in13_, * in14_, * in15_, * in16_,
* in17_, * in18_, * in19_, * in20_,
* in21_, * in22_, * in23_, * in24_,
* in25_;
NABoolean validStmt_;
Lng32 retcode_;
};
/*****************************************************************************/
/* CLASS: HSinsertHist */
/* FUNCTION: Inserts data into the HISTOGRAM table using ROWSETS. */
/* NOTES: File SQLHIST.MDF and this class have dependencies. Make sure if */
/* any changes are made to either file, the other is maintained */
/*****************************************************************************/
class HSinsertHist
{
public:
HSinsertHist(const char *stmtID,
const char *histTable);
HSinsertHist(const char *histTable);
~HSinsertHist();
Lng32 initialize(); //initialize the ROWSET pointers
Lng32 prepareDynamic(); //after initialize, if using dynamic query
Lng32 addRow(const Int64 table_uid, //Add single data row into ROWSET
const ULng32 histogram_id,
const Lng32 col_position,
const Lng32 column_number,
const Lng32 colcount,
const Int16 interval_count,
const Int64 rowcount,
const Int64 total_uec,
const char *stats_time,
const HSDataBuffer &low_value,
const HSDataBuffer &high_value,
const char *read_time,
const short read_count,
const Int64 sample_secs,
const Int64 col_secs,
const short sample_percent,
const double cv,
const char reason,
const Int64 v1 = 0,
const Int64 v2 = 0,
const Int64 v3 = 0,
const Int64 v4 = 0,
const HSDataBuffer &v5 = HSDataBuffer(L"empty"),
const HSDataBuffer &v6 = HSDataBuffer(L"empty")
);
Lng32 flush(); //writes all data rows into table
void print();
private:
SQLSTMT_ID stmt_;
SQLDESC_ID desc_;
//==========================
// Used only for dynamic query version.
SQLDESC_ID srcDesc_;
NABoolean stmtAllocated_;
NABoolean srcDescAllocated_;
NABoolean inputDescAllocated_;
NAString stmtText_;
void setText();
//==========================
char stmtID_[HS_STMTID_LENGTH]; // statement name.
char descID_[HS_STMTID_LENGTH]; // input descriptor name.
Int64 tableUid_[MAX_ROWSET];
ULng32 histID_[MAX_ROWSET];
Lng32 colPosition_[MAX_ROWSET];
Lng32 colNumber_[MAX_ROWSET];
Lng32 colcount_[MAX_ROWSET];
Int16 intCount_[MAX_ROWSET];
Int64 rowCount_[MAX_ROWSET];
Int64 totalUEC_[MAX_ROWSET];
char statsTime_[MAX_ROWSET][TIMESTAMP_CHAR_LEN+1];
NAWchar lowValue_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
NAWchar hiValue_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
// automation histogram columns
char readTime_[MAX_ROWSET][TIMESTAMP_CHAR_LEN+1];
short readCount_[MAX_ROWSET];
Int64 sampleSecs_[MAX_ROWSET];
Int64 colSecs_[MAX_ROWSET];
short samplePercent_[MAX_ROWSET];
double cv_[MAX_ROWSET];
char reason_[MAX_ROWSET];
Int64 v1_[MAX_ROWSET];
Int64 v2_[MAX_ROWSET];
Int64 v3_[MAX_ROWSET];
Int64 v4_[MAX_ROWSET];
wchar_t v5_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
wchar_t v6_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
const char *tableName_;
// number of rows in ROWSET
Lng32 numRows_;
Lng32 retcode_;
};
/*****************************************************************************/
/* CLASS: HSinsertHistint */
/* FUNCTION: Inserts data into the HISTOGRAM_INTERVALS table using ROWSETS. */
/* NOTES: File SQLHIST.MDF and this class have dependencies. Make sure if */
/* any changes are made to either file, the other is maintained */
/*****************************************************************************/
class HSinsertHistint
{
public:
HSinsertHistint(const char *stmtID,
const char *histIntTable);
HSinsertHistint(const char *histIntTable);
~HSinsertHistint();
Lng32 initialize(); //initialize the ROWSET pointers
Lng32 prepareDynamic(); //after initialize, if using dynamic query
Lng32 addRow(const Int64 table_uid, //Add single data row into ROWSET
const ULng32 histogram_id,
const Int16 interval_number,
const Int64 interval_rowcount,
const Int64 interval_uec,
const HSDataBuffer &interval_boundary,
// the following are added in R2.3
const double std_dev_of_freq,
const Int64 interval_MFV_rowcount = 0,
const Int64 interval_MFV2_rowcount = 0,
const Int64 v3 = 0,
const Int64 v4 = 0,
const HSDataBuffer &mostFreqVal = HSDataBuffer(L"empty"),
const HSDataBuffer &v6 = HSDataBuffer(L"empty")
);
Lng32 flush(); //writes all data rows into table
void print();
//==========================
// Used only for dynamic query version.
SQLDESC_ID srcDesc_;
NABoolean stmtAllocated_;
NABoolean srcDescAllocated_;
NABoolean inputDescAllocated_;
NAString stmtText_;
void setText();
//==========================
private:
SQLSTMT_ID stmt_;
SQLDESC_ID desc_;
char stmtID_[HS_STMTID_LENGTH]; // statement name.
char descID_[HS_STMTID_LENGTH]; // input descriptor name.
Int64 tableUid_[MAX_ROWSET];
ULng32 histID_[MAX_ROWSET];
Int16 intNumber_[MAX_ROWSET];
Int64 intRowcount_[MAX_ROWSET];
Int64 intUec_[MAX_ROWSET];
NAWchar intBoundary_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
//the following columns are added in R2.3
double stdDevOfFreq_[MAX_ROWSET];
Int64 intMFVrowcount_[MAX_ROWSET];
Int64 intMFV2rowcount_[MAX_ROWSET];
Int64 v3_[MAX_ROWSET];
Int64 v4_[MAX_ROWSET];
wchar_t mostFreqVal_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
wchar_t v6_[MAX_ROWSET][HS_MAX_UCS_BOUNDARY_CHAR+1];
const char *tableName_;
// number of rows in ROWSET
Lng32 numRows_;
Lng32 retcode_;
};
/*****************************************************************************/
/* CLASS: HSinsertEmptyHist */
/* FUNCTION: Inserts empty entries into the HISTOGRAM table */
/* NOTES: use HSCliStatement to check existing empty histograms */
/* use HSinsertHist to insert new ones */
/* currently only used for multi-column histograms */
/*****************************************************************************/
class HSinsertEmptyHist
{
public:
HSinsertEmptyHist(const Int64 tableUID,
const char *tableName,
const char *histTable)
: tableUID_(tableUID),
tableName_(tableName),
histTable_(histTable),
colCount_(0)
{};
virtual ~HSinsertEmptyHist() {};
Lng32 addColumn(const Lng32 columnNumber);
Lng32 insert();
private:
HSinsertEmptyHist(const HSinsertEmptyHist&); // add to prevent the default one to be used
HSinsertEmptyHist& operator=(const HSinsertEmptyHist&); // add to prevent the default one to be used
const Int64 tableUID_;
const char *tableName_;
const char *histTable_;
Lng32 colNumber_[MAX_MC_COLUMNS];
Lng32 colCount_;
};
// -----------------------------------------------------------------------
// Cursor class to fetch boundaries, histid, rowcount, and update
// bitmaps, row counters.
// -----------------------------------------------------------------------
class HSCursor :public NABasicObject
{
public:
HSCursor(NAHeap *h=STMTHEAP, const char* stmtName = HS_STMTID);
~HSCursor();
// open the cursor.
inline Lng32 open( const char *clistr
, char *&dataBuf
, HSColDesc *&colDesc
)
{
retcode_ = prepare(clistr);
HSFilterWarning(retcode_);
if (retcode_)
{
dataBuf = NULL;
colDesc = NULL;
return retcode_;
}
dataBuf = dataBuf_;
colDesc = colDesc_;
return 0;
}
// get one row.
inline Lng32 getRow()
{
HSLogMan *LM = HSLogMan::Instance();
LM->StartTimer("SQL_EXEC_Fetch() called from HSinsertEmptyHist::getRow()");
retcode_ = SQL_EXEC_Fetch(stmt_,outputDesc_, 0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
LM->StopTimer();
if (retcode_ < 0)
{
HSFuncMergeDiags(-UERR_INTERNAL_ERROR, "getRow()", NULL, TRUE);
return -1;
}
else
return retcode_;
}
Lng32 fetchRowset();
inline Lng32 rowsetSize() {return rowsetSize_;}
// Determine boundaries of histograms.
Lng32 fetchBoundaries(HSColGroupStruct *group, Int64 &rowCount, Lng32 intCount,
NABoolean sampleUsed);
Lng32 prepareRowset(const char *cliStr, NABoolean orderAndGroup,
HSColGroupStruct *group, Lng32 maxRows);
Lng32 setRowsetPointers(HSColGroupStruct *group, Lng32 maxRows);
// Fetch a numerical type column from a table.
Lng32 fetchNumColumn( const char *clistr
, Lng32 *pSmallValue
, Int64 *pLargeValue = NULL
);
// Fetch a char type column from a table.
Lng32 fetchCharNumColumn( const char *clistr
, NAString &value1
, Int64 &value2
, double &value3
);
// Functions below used when the HSCursor is instantiated for a dynamic query.
Lng32 prepareQuery(const char *cliStr, Lng32 numParams, Lng32 numResults);
Lng32 open(Lng32 numParams = 0, void *in01 = NULL);
Lng32 fetch(Lng32 numResults,
void* out01, void* out02 = NULL, void* out03 = NULL,
void* out04 = NULL, void* out05 = NULL, void* out06 = NULL,
void* out07 = NULL, void* out08 = NULL, void* out09 = NULL,
void* out10 = NULL, void* out11 = NULL, void* out12 = NULL,
void* out13 = NULL, void* out14 = NULL, void* out15 = NULL,
void* out16 = NULL, void* out17 = NULL, void* out18 = NULL,
void* out19 = NULL, void* out20 = NULL, void* out21 = NULL,
void* out22 = NULL, void* out23 = NULL, void* out24 = NULL,
void* out25 = NULL);
Lng32 close();
SQLSTMT_ID* getStmt() {return stmt_;}
SQLDESC_ID* getOutDesc() {return outputDesc_;}
SQLDESC_ID* getInDesc() {return inputDesc_;}
Lng32 setCursorName(const char* name);
boundarySet<myVarChar>* getBoundaryRowset() const
{
return boundaryRowSet_;
}
private:
Lng32 prepareRowsetInternal(const char *cliStr, NABoolean orderAndGroup,
HSColGroupStruct *group, Lng32 maxRows);
struct groupMap {
groupMap()
: datatype(-1), base(-1), len(-1), startCol(-1), filler(0) {}
Lng32 datatype;
Lng32 scale;
Lng32 base;
Lng32 len;
Lng32 startCol;
Lng32 filler;
};
SQLSTMT_ID *stmt_;
SQLDESC_ID *srcDesc_;
SQLDESC_ID *outputDesc_;
SQLDESC_ID *inputDesc_;
Int32 stmtAllocated_;
Int32 srcDescAllocated_;
Int32 outputDescAllocated_;
Int32 inputDescAllocated_;
SQLCLI_OBJ_ID *cursorName_;
// Number of rows in last rowset read by fetchRowset().
Lng32 rowsetSize_;
// Column descriptor for output rows.
HSColDesc *colDesc_;
Lng32 numEntries_;
HSPtrObj<NAType> *ptrNAType_;
// output buffer to hold a row returned from CLI fetch.
char *dataBuf_;
Lng32 outputDataLen_;
// Each returned row may contain multiple column groups.
// groupMap describes base, len, startCol for each group in the
// output buffer.
groupMap *group_;
boundarySet<myVarChar> *boundaryRowSet_;
SQLCLI_QUAD_FIELDS *rowset_fields_;
Int32 closeStmtNeeded_;
Lng32 retcode_;
NAHeap *heap_;
NABoolean lastFetchReturned100_;
// prepare a dynamic sql statement.
Lng32 prepare(const char *cliStr, const Lng32 outDescEntries = 500);
// Construct a NAType for each column in the output row.
Lng32 buildNAType();
HSCursor(const HSCursor &other);
HSCursor& operator=(const HSCursor &other);
};
// Return the value as a double for computation of the magnitude
// of a gap. See also the template specializations that follow this.
//
template <class T>
static double getValueAsDouble(T* valPtr)
{
return (double)(*valPtr);
}
// This specialization of the foregoing template handles the
// myVarChar type, which is used for columns not processed by
// internal sort.
//
static double getValueAsDouble(myVarChar* valPtr)
{
return ucsToDouble(valPtr);
}
// This won't be called, just needs to exist to avoid compilation error for
// a template instantiation using ISFixedChar.
static double getValueAsDouble(ISFixedChar* valPtr)
{
assert(FALSE);
return 0;
}
// This won't be called, just needs to exist to avoid compilation error for
// a template instantiation using ISVarChar.
static double getValueAsDouble(ISVarChar* valPtr)
{
assert(FALSE);
return 0;
}
// This won't be called, just needs to exist to avoid compilation error for
// a template instantiation using ISVarChar.
static double getValueAsDouble(MCWrapper* valPtr)
{
assert(FALSE);
return 0;
}
// NOTE: The following function has to be defined in the header file so the
// compiler can see the definition to generate instantiations for
// the different types. Compilation fails if this is not placed here.
//
/****************************************************************************/
/* METHOD: profileGaps() */
/* PURPOSE: Go through the distinct values that make up a rowset, and set */
/* gap magnitude for each. The running overall gap magnitude */
/* average is updated with the information from this rowset. */
/* PARAMS: group(in) -- Group the rowset is for. */
/* boundaryRowSet(in) -- Contains the distinct values and */
/* their frequencies for this rowset. */
/* overallGapAvg(in/out) -- Average gap size for all values */
/* seen so far. Updated with */
/* information from this rowset. */
/* overallGapCount(in/out) -- Total number of gaps considered so */
/* far. Updated with the count from */
/* this rowset. */
/* firstRowset(in) -- TRUE if this is the first rowset for */
/* this group. If this is NOT the case, */
/* the static prevValue has the last */
/* value from the previous rowset. */
/****************************************************************************/
template <class T>
void profileGaps(HSColGroupStruct *group, boundarySet<T> *boundaryRowSet,
double &overallGapAvg, Int64 &overallGapCount,
NABoolean firstRowset);
#endif /* HSCLI_H */