Files
mars-flaim/sql/src/sqlquery.h
dsandersoremutah a7e6b942f8 Latest round of changes for SQL query optimization.
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@709 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-07-25 22:40:53 +00:00

571 lines
13 KiB
C++

//-------------------------------------------------------------------------
// Desc: Structures, classes, prototypes, and defines needed to support
// ODBC in FLAIM.
// Tabs: 3
//
// Copyright (c) 2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id$
//-------------------------------------------------------------------------
#ifndef FLAIMODBC_H
#define FLAIMODBC_H
// Forward declarations
struct SQL_NODE;
struct SQL_VALUE;
struct SQL_TABLE;
struct SQL_INDEX;
struct SQL_KEY;
struct SQL_COLUMN;
class FSTableCursor;
//-------------------------------------------------------------------------
// Desc: Types of nodes in SQL query.
//-------------------------------------------------------------------------
typedef enum
{
SQL_NO_NODE = 0,
SQL_OPERATOR_NODE,
SQL_VALUE_NODE,
SQL_COLUMN_NODE,
SQL_PRED_NODE
} eSQLNodeTypes;
#define SQL_FIRST_ARITH_OP SQL_BITAND_OP
#define SQL_LAST_ARITH_OP SQL_NEG_OP
FINLINE FLMBOOL isLegalSQLOperator(
eSQLQueryOperators eOperator)
{
return( (eOperator >= SQL_AND_OP && eOperator <= SQL_NEG_OP)
? TRUE
: FALSE);
}
FINLINE FLMBOOL isSQLLogicalOp(
eSQLQueryOperators eOperator)
{
return( (eOperator >= SQL_AND_OP && eOperator <= SQL_NOT_OP) ? TRUE : FALSE);
}
FINLINE FLMBOOL isSQLCompareOp(
eSQLQueryOperators eOperator)
{
return( (eOperator >= SQL_EQ_OP && eOperator <= SQL_GE_OP) ? TRUE : FALSE);
}
FINLINE FLMBOOL isSQLArithOp(
eSQLQueryOperators eOperator)
{
return( (eOperator >= SQL_FIRST_ARITH_OP &&
eOperator <= SQL_LAST_ARITH_OP) ? TRUE : FALSE);
}
FINLINE FLMBOOL isSQLValUnsigned(
eSQLValTypes eValType)
{
return( eValType == SQL_UINT_VAL || eValType == SQL_UINT64_VAL
? TRUE
: FALSE);
}
FINLINE FLMBOOL isSQLValSigned(
eSQLValTypes eValType)
{
return( eValType == SQL_INT_VAL || eValType == SQL_INT64_VAL
? TRUE
: FALSE);
}
FINLINE FLMBOOL isSQLVal64Bit(
eSQLValTypes eValType)
{
return( eValType == SQL_UINT64_VAL || eValType == SQL_INT64_VAL
? TRUE
: FALSE);
}
FINLINE FLMBOOL isSQLValNativeNum(
eSQLValTypes eValType)
{
return( eValType == SQL_UINT_VAL || eValType == SQL_INT_VAL
? TRUE
: FALSE);
}
typedef struct SQL_PRED
{
SQL_TABLE * pSQLTable;
FLMUINT uiColumnNum;
eSQLQueryOperators eOperator; // Operator of the predicate
FLMUINT uiCompareRules;// Comparison rules
FLMBOOL bNotted; // Has operator been notted?
SQL_VALUE * pFromValue; // Points to SQL_VALUE that has the FROM value for
// this predicate. Will be NULL for unary
// operators such as exists
FLMBOOL bInclFrom; // Flag indicating if the from value is
// inclusive.
SQL_VALUE * pUntilValue; // Points to SQL_VALUE that has the UNTIL value
// for this predicate.
FLMBOOL bInclUntil; // Flag indicating if until value is
// inclusive.
SQL_PRED * pNext;
} SQL_PRED;
typedef struct SQL_OP
{
eSQLQueryOperators eOperator;
FLMUINT uiCompareRules;
} SQL_OP;
typedef struct SQL_STRING_VALUE
{
FLMBYTE * pszStr; // Should always be null-terminated.
FLMUINT uiByteLen; // Includes null-terminating character.
FLMUINT uiNumChars; // Does not count null-terminating character.
} SQL_STRING_VALUE;
typedef struct SQL_BINARY_VALUE
{
FLMBYTE * pucValue;
FLMUINT uiByteLen;
} SQL_BINARY_VALUE;
typedef struct SQL_VALUE
{
eSQLValTypes eValType;
FLMUINT uiFlags;
#define SQL_VAL_IS_CONSTANT 0x0001 // During query evaluation, this indicates
// that this value is a constant. If it
// is a SQL_UTF8_VAL, then asterisks will
// be treated as a wildcard, unless
// escaped (\*). If the value is NOT
// a constant, the asterisk is NEVER
// treated as a wildcard, and the
// backslash is NEVER treated as an
// escape character.
#define SQL_VAL_HAS_WILDCARDS 0x0002 // This is only set if the value is a
// constant, SQL_UTF8_VAL, that has
// wildcards.
union
{
SQLBoolType eBool;
FLMUINT uiVal;
FLMUINT64 ui64Val;
FLMINT iVal;
FLMINT64 i64Val;
SQL_STRING_VALUE str;
SQL_BINARY_VALUE bin;
} val; // Holds or points to the atom value.
} SQL_VALUE;
/***************************************************************************
Desc: Can two values be compared?
***************************************************************************/
FINLINE FLMBOOL sqlCanCompare(
SQL_VALUE * pValue1,
SQL_VALUE * pValue2
)
{
if (!pValue1 || !pValue2 ||
pValue1->eValType == pValue2->eValType)
{
return( TRUE);
}
else
{
switch (pValue1->eValType)
{
case SQL_UINT_VAL:
case SQL_UINT64_VAL:
case SQL_INT_VAL:
case SQL_INT64_VAL:
return( (FLMBOOL)(pValue2->eValType == SQL_UINT_VAL ||
pValue2->eValType == SQL_UINT64_VAL ||
pValue2->eValType == SQL_INT_VAL ||
pValue2->eValType == SQL_INT64_VAL
? TRUE
: FALSE));
default:
return( FALSE);
}
}
}
typedef struct SQL_KEY
{
FSIndexCursor * pFSIndexCursor;
SQL_PRED ** ppPredicates; // Only used to set up pFSIndexCursor
FLMUINT uiComponentsUsed;
SQL_KEY * pNext; // Keys are kept in ascending order.
SQL_KEY * pPrev;
} SQL_KEY;
typedef struct SQL_INDEX
{
FLMUINT uiIndexNum;
SQL_KEY * pFirstSQLKey; // First key in list - keys are kept in ascending order.
SQL_KEY * pLastSQLKey; // Last key in list
SQL_INDEX * pNext;
SQL_INDEX * pPrev;
} SQL_INDEX;
typedef struct SQL_TABLE
{
FLMUINT uiTableNum;
FSTableCursor * pFSTableCursor;
FLMUINT64 ui64TotalCost;
FLMBOOL bScan;
FLMUINT uiIndexNum;
SQL_INDEX * pFirstSQLIndex;
SQL_INDEX * pLastSQLIndex;
SQL_TABLE * pNext;
SQL_TABLE * pPrev;
} SQL_TABLE;
typedef struct SQL_COLUMN
{
const char * pszTableAlias;
const char * pszColumnName;
SQL_TABLE * pSQLTable;
FLMUINT uiColumnNum;
} SQL_COLUMN;
typedef struct SQL_NODE
{
eSQLNodeTypes eNodeType; // Type of node this is
FLMUINT uiNestLevel; // Nesting level of node - only used when
// setting up the query
SQL_VALUE currVal; // Used only during evaluation to store
// temporary results thus far. This is
// also used for constant operands
// (eNodeType == SQL_VALUE_NODE)
FLMBOOL bNotted;
SQL_NODE * pParent; // Parent of this query node
SQL_NODE * pPrevSib; // Previous sibling of this query node
SQL_NODE * pNextSib; // Next sibling of this query node
SQL_NODE * pFirstChild; // First child of this query node
SQL_NODE * pLastChild; // Last child of this query node
union
{
SQL_OP op;
SQL_COLUMN column;
SQL_PRED pred;
} nd;
} SQL_NODE;
typedef struct SQL_ORDER_BY
{
SQL_TABLE * pSQLTable;
FLMUINT uiColumnNum;
FLMBOOL bDescending;
SQL_ORDER_BY * pNext;
} SQL_ORDER_BY;
FINLINE FLMBOOL isSQLNodeBool(
SQL_NODE * pNode)
{
return( (pNode->eNodeType == SQL_VALUE_NODE &&
pNode->currVal.eValType == SQL_BOOL_VAL) ? TRUE : FALSE);
}
typedef struct SQL_SUBQUERY
{
FLMUINT uiOperandCount;
SQL_NODE ** ppOperands;
SQL_SUBQUERY * pNext;
SQL_SUBQUERY * pPrev;
} SQL_SUBQUERY;
typedef struct SQL_DNF_NODE
{
SQL_DNF_NODE * pParent;
SQL_DNF_NODE * pFirstChild;
SQL_DNF_NODE * pLastChild;
SQL_DNF_NODE * pNextSib;
SQL_DNF_NODE * pPrevSib;
SQL_NODE * pNode; // If NULL, bAndOp is used to tell if it is an OR or AND operator
FLMBOOL bAndOp; // Only set if pNode is NULL.
} SQL_DNF_NODE;
//-------------------------------------------------------------------------
// Desc: SQLQuery class - for building up an SQL query.
//-------------------------------------------------------------------------
class SQLQuery : public F_Object
{
public:
SQLQuery();
~SQLQuery();
FINLINE FLMBOOL expectingOperand( void)
{
return( !m_bExpectingOperator);
}
FINLINE FLMBOOL expectingOperator( void)
{
return( m_bExpectingOperator);
}
RCODE addOperator(
eSQLQueryOperators eOperator,
FLMUINT uiCompareRules);
RCODE allocOperandNode(
eSQLNodeTypes eNodeType,
SQL_NODE ** ppSQLNode);
RCODE addTable(
FLMUINT uiTableNum,
SQL_TABLE ** ppSQLTable);
RCODE resolveColumnNames(
TABLE_ITEM * pTableList);
RCODE addColumn(
const char * pszTableAlias,
FLMUINT uiTableAliasLen,
const char * pszColumnName,
FLMUINT uiColumnNameLen);
RCODE addColumn(
FLMUINT uiTableNum,
FLMUINT uiColumnNum);
RCODE addUTF8String(
const FLMBYTE * pszUTF8Str,
FLMUINT uiStrLen,
FLMUINT uiNumChars);
RCODE addBinary(
const FLMBYTE * pucValue,
FLMUINT uiValueLen);
RCODE addUINT64(
FLMUINT64 ui64Num);
RCODE addINT64(
FLMINT64 i64Num);
RCODE addUINT(
FLMUINT uiNum);
RCODE addINT(
FLMINT iNum);
FINLINE RCODE addNumber(
FLMUINT64 ui64Num,
FLMBOOL bNeg)
{
if (!bNeg)
{
if (ui64Num <= (FLMUINT64)(FLM_MAX_UINT))
{
return( addUINT( (FLMUINT)ui64Num));
}
else
{
return( addUINT64( ui64Num));
}
}
else
{
if (ui64Num <= (FLMUINT64)(FLM_MAX_INT))
{
return( addINT( (FLMINT)(-((FLMINT64)ui64Num))));
}
else
{
return( addINT64( -((FLMINT64)ui64Num)));
}
}
}
RCODE addBoolean(
FLMBOOL bValue,
FLMBOOL bUnknown);
FINLINE FLMBOOL criteriaIsComplete( void)
{
// Make sure we have a completed expression
return( (m_uiNestLevel ||
(m_pLastNode && m_pLastNode->eNodeType == SQL_OPERATOR_NODE))
? FALSE
: TRUE);
}
RCODE orderBy(
FLMUINT uiTableNum,
FLMUINT uiColumnNum,
FLMBOOL bDescending);
RCODE setIndex(
FLMUINT uiTableNum,
FLMUINT uiIndexNum);
RCODE getNext(
F_Row ** ppRow);
RCODE getPrev(
F_Row ** ppRow);
RCODE getFirst(
F_Row ** ppRow);
RCODE getLast(
F_Row ** ppRow);
RCODE reduceTree(
FLMBOOL bFlattenTree);
private:
RCODE allocValueNode(
FLMUINT uiValLen,
eSQLValTypes eValType,
SQL_NODE ** ppSQLNode);
RCODE intersectPredicates(
SQL_PRED * pPred,
eSQLQueryOperators eOperator,
FLMUINT uiCompareRules,
FLMBOOL bNotted,
SQL_VALUE * pValue,
FLMBOOL * pbAlwaysFalse,
FLMBOOL * pbIntersected);
RCODE addPredicate(
SQL_SUBQUERY * pSubQuery,
FLMUINT * puiOperand,
SQL_TABLE * pSQLTable,
FLMUINT uiColumnNum,
eSQLQueryOperators eOperator,
FLMUINT uiCompareRules,
FLMBOOL bNotted,
SQL_VALUE * pValue);
RCODE convertOperandsToPredicates( void);
RCODE convertToDNF( void);
RCODE getPredKeys(
F_TABLE * pTable,
FLMUINT uiForceIndexNum,
SQL_PRED * pPred,
SQL_INDEX ** ppFirstSQLIndex,
SQL_INDEX ** ppLastSQLIndex);
RCODE chooseBestIndex(
F_TABLE * pTable,
SQL_INDEX * pFirstSQLIndex,
SQL_INDEX ** ppBestSQLIndex);
RCODE mergeKeys(
SQL_TABLE * pSQLTable,
SQL_INDEX * pSQLIndex);
RCODE optimizeTable(
SQL_SUBQUERY * pSubQuery,
SQL_TABLE * pSQLTable);
RCODE optimizeSubQueries( void);
RCODE addIndexToTable(
SQL_TABLE * pSQLTable,
FLMUINT uiIndexNum,
SQL_INDEX ** ppSQLIndex);
RCODE addKeyToIndex(
SQL_INDEX * pSQLIndex,
SQL_KEY ** ppSQLKey);
RCODE setupIndexScan(
SQL_TABLE * pSQLTable);
RCODE setupTableScan(
SQL_TABLE * pSQLTable);
RCODE setupScans( void);
RCODE optimize( void);
F_Pool m_pool;
FLMUINT m_uiLanguage;
SQL_NODE * m_pQuery;
SQL_NODE * m_pCurOperatorNode;
SQL_NODE * m_pLastNode;
FLMUINT m_uiNestLevel;
FLMBOOL m_bExpectingOperator;
SQL_SUBQUERY * m_pFirstSubQuery;
SQL_SUBQUERY * m_pLastSubQuery;
SQL_TABLE * m_pFirstSQLTable;
SQL_TABLE * m_pLastSQLTable;
SQL_ORDER_BY * m_pFirstOrderBy;
SQL_ORDER_BY * m_pLastOrderBy;
FLMBOOL m_bResolveNames;
FLMBOOL m_bOptimized;
F_Database * m_pDatabase;
F_Db * m_pDb;
FLMBOOL m_bEmpty;
SQLQuery * m_pNext;
SQLQuery * m_pPrev;
friend class F_Db;
friend class F_Database;
};
typedef struct SQL_KEYPOS
{
FLMBYTE ucKey [SFLM_MAX_KEY_SIZE];
FLMUINT uiKeyLen;
} SQL_KEYPOS;
RCODE sqlCompare( // sqleval.cpp
SQL_VALUE * pValue1,
SQL_VALUE * pValue2,
FLMUINT uiCompareRules,
FLMUINT uiLanguage,
FLMINT * piCmp);
RCODE sqlEvalArithOperator( // sqleval.cpp
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
eSQLQueryOperators eOperator,
SQL_VALUE * pResult);
RCODE sqlEvalCriteria( // sqleval.cpp
F_Db * pDb,
SQL_NODE * pQueryExpr,
SQL_VALUE ** ppSqlValue,
F_Pool * pPool,
F_Row * pRow,
FLMUINT uiLanguage);
void freeIndexKeys( // whereclause.cpp
SQL_INDEX * pSQLIndex);
void freeTableIndexes( // whereclause.cpp
SQL_TABLE * pSQLTable);
#endif // #ifndef SQLQUERY_H