Added code for evaluating query expressions against a row.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@635 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
dsandersoremutah
2006-07-06 15:47:13 +00:00
parent 30bd367a3d
commit 3e8e003050
6 changed files with 946 additions and 333 deletions

View File

@@ -4411,7 +4411,7 @@ private:
// More includes
#include "flaimodbc.h"
#include "sqlquery.h"
#include "fscursor.h"
#endif // FLAIMSYS_H

View File

@@ -34,6 +34,11 @@ FSTATIC RCODE sqlCompareText(
FLMUINT uiLanguage,
FLMINT * piResult);
FSTATIC RCODE sqlApproxCompare(
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
FLMINT * piResult);
FSTATIC RCODE sqlCompareBinary(
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
@@ -154,6 +159,27 @@ FSTATIC void sqlArithOpSUMinus(
SQL_VALUE * pRValue,
SQL_VALUE * pResult);
FSTATIC RCODE sqlCompareOperands(
FLMUINT uiLanguage,
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
eSQLQueryOperators eOperator,
FLMUINT uiCompareRules,
FLMBOOL bNotted,
SQLBoolType * peBool);
FSTATIC RCODE sqlGetColumnValue(
F_Db * pDb,
F_Row * pRow,
FLMUINT uiTableNum,
FLMUINT uiColumnNum,
F_Pool * pPool,
SQL_VALUE * pSqlValue);
FSTATIC RCODE sqlEvalOperator(
FLMUINT uiLanguage,
SQL_NODE * pQNode);
typedef void SQL_ARITH_OP(
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
@@ -210,34 +236,20 @@ FSTATIC RCODE sqlCompareText(
// Open the streams
if( !(pLValue->uiFlags & SQL_VAL_IS_STREAM))
if (RC_BAD( rc = bufferLStream.open( (const char *)pLValue->val.str.pszStr,
pLValue->val.str.uiByteLen)))
{
if (RC_BAD( rc = bufferLStream.open( (const char *)pLValue->val.str.pszStr,
pLValue->val.str.uiByteLen)))
{
goto Exit;
}
pLStream = &bufferLStream;
}
else
{
pLStream = pLValue->val.pIStream;
goto Exit;
}
if( !(pRValue->uiFlags & SQL_VAL_IS_STREAM))
pLStream = &bufferLStream;
if( RC_BAD( rc = bufferRStream.open( (const char *)pRValue->val.str.pszStr,
pRValue->val.str.uiByteLen)))
{
if( RC_BAD( rc = bufferRStream.open( (const char *)pRValue->val.str.pszStr,
pRValue->val.str.uiByteLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
}
else
{
pRStream = pRValue->val.pIStream;
goto Exit;
}
pRStream = &bufferRStream;
if( RC_BAD( rc = f_compareUTF8Streams(
pLStream,
@@ -254,9 +266,142 @@ Exit:
return( rc);
}
//-------------------------------------------------------------------------
// Desc: Performs approximate compare on two strings.
//-------------------------------------------------------------------------
FSTATIC RCODE sqlApproxCompare(
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
FLMINT * piResult)
{
RCODE rc = NE_SFLM_OK;
FLMUINT uiLMeta;
FLMUINT uiRMeta;
FLMUINT64 ui64StartPos;
F_BufferIStream bufferLStream;
IF_PosIStream * pLStream;
F_BufferIStream bufferRStream;
IF_PosIStream * pRStream;
// Types must be text
if (pLValue->eValType != SQL_UTF8_VAL ||
pRValue->eValType != SQL_UTF8_VAL)
{
rc = RC_SET_AND_ASSERT( NE_SFLM_NOT_IMPLEMENTED);
goto Exit;
}
// Open the streams
if (RC_BAD( rc = bufferLStream.open(
(const char *)pLValue->val.str.pszStr, pLValue->val.str.uiByteLen)))
{
goto Exit;
}
pLStream = &bufferLStream;
if( RC_BAD( rc = bufferRStream.open(
(const char *)pRValue->val.str.pszStr, pRValue->val.str.uiByteLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
if ((pLValue->uiFlags & SQL_VAL_IS_CONSTANT) ||
!(pRValue->uiFlags & SQL_VAL_IS_CONSTANT))
{
for( ;;)
{
if (RC_BAD( rc = f_getNextMetaphone( pLStream, &uiLMeta)))
{
if( rc == NE_FLM_EOF_HIT)
{
*piResult = 0;
rc = NE_SFLM_OK;
}
goto Exit;
}
ui64StartPos = pRStream->getCurrPosition();
for( ;;)
{
if( RC_BAD( rc = f_getNextMetaphone( pRStream, &uiRMeta)))
{
if( rc == NE_FLM_EOF_HIT)
{
rc = NE_SFLM_OK;
*piResult = -1;
}
goto Exit;
}
if( uiLMeta == uiRMeta)
{
break;
}
}
if( RC_BAD( rc = pRStream->positionTo( ui64StartPos)))
{
goto Exit;
}
}
}
else
{
for( ;;)
{
if( RC_BAD( rc = f_getNextMetaphone( pRStream, &uiRMeta)))
{
if( rc == NE_FLM_EOF_HIT)
{
*piResult = 0;
rc = NE_SFLM_OK;
}
goto Exit;
}
ui64StartPos = pLStream->getCurrPosition();
for( ;;)
{
if( RC_BAD( rc = f_getNextMetaphone( pLStream, &uiLMeta)))
{
if( rc == NE_FLM_EOF_HIT)
{
rc = NE_SFLM_OK;
*piResult = 1;
}
goto Exit;
}
if( uiLMeta == uiRMeta)
{
break;
}
}
if( RC_BAD( rc = pLStream->positionTo( ui64StartPos)))
{
goto Exit;
}
}
}
Exit:
return( rc);
}
//-------------------------------------------------------------------------
// Desc: Performs binary comparison on two streams - may be text or binary,
// it really doesn't matter. Returns XFLM_TRUE or XFLM_FALSE.
// it really doesn't matter. Returns SQL_TRUE or SQL_FALSE.
//-------------------------------------------------------------------------
FSTATIC RCODE sqlCompareBinary(
SQL_VALUE * pLValue,
@@ -286,34 +431,19 @@ FSTATIC RCODE sqlCompareBinary(
// Open the streams
if( !(pLValue->uiFlags & SQL_VAL_IS_STREAM))
if (RC_BAD( rc = bufferLStream.open( (const char *)pLValue->val.str.pszStr,
pLValue->val.str.uiByteLen)))
{
if (RC_BAD( rc = bufferLStream.open( (const char *)pLValue->val.str.pszStr,
pLValue->val.str.uiByteLen)))
{
goto Exit;
}
goto Exit;
}
pLStream = &bufferLStream;
pLStream = &bufferLStream;
}
else
if( RC_BAD( rc = bufferRStream.open( (const char *)pRValue->val.str.pszStr,
pRValue->val.str.uiByteLen)))
{
pLStream = pLValue->val.pIStream;
}
if( !(pRValue->uiFlags & SQL_VAL_IS_STREAM))
{
if( RC_BAD( rc = bufferRStream.open( (const char *)pRValue->val.str.pszStr,
pRValue->val.str.uiByteLen)))
{
goto Exit;
}
pRStream = &bufferRStream;
}
else
{
pRStream = pRValue->val.pIStream;
goto Exit;
}
pRStream = &bufferRStream;
for (;;)
{
@@ -1416,6 +1546,122 @@ FSTATIC void sqlArithOpSUMinus(
}
}
/***************************************************************************
Desc: Do a comparison operator.
***************************************************************************/
FSTATIC RCODE sqlCompareOperands(
FLMUINT uiLanguage,
SQL_VALUE * pLValue,
SQL_VALUE * pRValue,
eSQLQueryOperators eOperator,
FLMUINT uiCompareRules,
FLMBOOL bNotted,
SQLBoolType * peBool)
{
RCODE rc = NE_SFLM_OK;
FLMINT iCmp;
if (!pLValue || pLValue->eValType == SQL_MISSING_VAL ||
!pRValue || pRValue->eValType == SQL_MISSING_VAL ||
!sqlCanCompare( pLValue, pRValue))
{
*peBool = SQL_UNKNOWN;
}
// At this point, both operands are known to be present and are of
// types that can be compared. The comparison
// will therefore be performed according to the
// operator specified.
else
{
switch (eOperator)
{
case SQL_EQ_OP:
case SQL_NE_OP:
if (pLValue->eValType == SQL_UTF8_VAL ||
pRValue->eValType == SQL_UTF8_VAL)
{
if (RC_BAD( rc = sqlCompareText( pLValue, pRValue,
uiCompareRules, TRUE, uiLanguage, &iCmp)))
{
goto Exit;
}
}
else
{
if (RC_BAD( rc = sqlCompare( pLValue, pRValue,
uiCompareRules, uiLanguage, &iCmp)))
{
goto Exit;
}
}
if (eOperator == SQL_EQ_OP)
{
*peBool = (iCmp == 0 ? SQL_TRUE : SQL_FALSE);
}
else
{
*peBool = (iCmp != 0 ? SQL_TRUE : SQL_FALSE);
}
break;
case SQL_APPROX_EQ_OP:
if (RC_BAD( rc = sqlApproxCompare( pLValue, pRValue, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp == 0 ? SQL_TRUE : SQL_FALSE);
break;
case SQL_LT_OP:
if (RC_BAD( rc = sqlCompare( pLValue, pRValue,
uiCompareRules, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp < 0 ? SQL_TRUE : SQL_FALSE);
break;
case SQL_LE_OP:
if (RC_BAD( rc = sqlCompare( pLValue, pRValue,
uiCompareRules, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp <= 0 ? SQL_TRUE : SQL_FALSE);
break;
case SQL_GT_OP:
if (RC_BAD( rc = sqlCompare( pLValue, pRValue,
uiCompareRules, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp > 0 ? SQL_TRUE : SQL_FALSE);
break;
case SQL_GE_OP:
if (RC_BAD( rc = sqlCompare( pLValue, pRValue,
uiCompareRules, uiLanguage, &iCmp)))
{
goto Exit;
}
*peBool = (iCmp >= 0 ? SQL_TRUE : SQL_FALSE);
break;
default:
*peBool = SQL_UNKNOWN;
rc = RC_SET_AND_ASSERT( NE_SFLM_QUERY_SYNTAX);
goto Exit;
}
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Do an arithmetic operator.
***************************************************************************/
@@ -1484,3 +1730,513 @@ Exit:
return( rc);
}
/***************************************************************************
Desc: Get a column's value from the passed in row. Return it in pSqlValue.
***************************************************************************/
FSTATIC RCODE sqlGetColumnValue(
F_Db * pDb,
F_Row * pRow,
FLMUINT uiTableNum,
FLMUINT uiColumnNum,
F_Pool * pPool,
SQL_VALUE * pSqlValue)
{
RCODE rc = NE_SFLM_OK;
F_TABLE * pTable = pDb->getDict()->getTable( uiTableNum);
F_COLUMN * pColumn = pDb->getDict()->getColumn( pTable, uiColumnNum);
FLMBOOL bNeg;
FLMUINT64 ui64Value;
FLMBOOL bIsNull;
FLMUINT uiDataLen;
const FLMBYTE * pucColumnData;
const FLMBYTE * pucEnd;
flmAssert( pTable->uiTableNum == uiTableNum);
pRow->getDataLen( pDb, uiColumnNum, &uiDataLen, &bIsNull);
if (bIsNull)
{
pSqlValue->eValType = SQL_MISSING_VAL;
goto Exit;
}
pucColumnData = (const FLMBYTE *)pRow->getColumnDataPtr( uiColumnNum);
switch (pColumn->eDataTyp)
{
case SFLM_STRING_TYPE:
// Decode the number of characters directly from the column's
// data buffer. Then copy only whatever part remains after that.
pSqlValue->eValType = SQL_UTF8_VAL;
pucEnd = pucColumnData + uiDataLen;
if (RC_BAD( rc = f_decodeSEN( &pucColumnData, pucEnd,
&pSqlValue->val.str.uiNumChars)))
{
goto Exit;
}
uiDataLen = (FLMUINT)(pucEnd - pucColumnData);
pSqlValue->val.str.uiByteLen = uiDataLen;
if (RC_BAD( rc = pPool->poolAlloc( uiDataLen,
(void **)&pSqlValue->val.str.pszStr)))
{
goto Exit;
}
f_memcpy( pSqlValue->val.str.pszStr, pucColumnData, uiDataLen);
break;
case SFLM_NUMBER_TYPE:
if (RC_BAD( rc = flmStorageNumberToNumber( pucColumnData, uiDataLen,
&ui64Value, &bNeg)))
{
goto Exit;
}
if (!bNeg)
{
if (ui64Value <= (FLMUINT64)(FLM_MAX_UINT))
{
pSqlValue->eValType = SQL_UINT_VAL;
pSqlValue->val.uiVal = (FLMUINT)ui64Value;
}
else
{
pSqlValue->eValType = SQL_UINT64_VAL;
pSqlValue->val.ui64Val = ui64Value;
}
}
else
{
if (-((FLMINT64)ui64Value) <= (FLMINT64)(FLM_MIN_INT))
{
pSqlValue->eValType = SQL_INT_VAL;
pSqlValue->val.iVal = (FLMINT)(-((FLMINT64)ui64Value));
}
else
{
pSqlValue->eValType = SQL_INT64_VAL;
pSqlValue->val.i64Val = -((FLMINT64)ui64Value);
}
}
break;
case SFLM_BINARY_TYPE:
pSqlValue->eValType = SQL_BINARY_VAL;
if (RC_BAD( rc = pPool->poolAlloc( uiDataLen,
(void **)&pSqlValue->val.bin.pucValue)))
{
goto Exit;
}
pSqlValue->val.bin.uiByteLen = uiDataLen;
f_memcpy( pSqlValue->val.bin.pucValue, pucColumnData, uiDataLen);
break;
default:
flmAssert( 0);
rc = RC_SET( NE_SFLM_FAILURE);
goto Exit;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Evaluate a simple operator.
***************************************************************************/
FSTATIC RCODE sqlEvalOperator(
FLMUINT uiLanguage,
SQL_NODE * pQNode)
{
RCODE rc = NE_SFLM_OK;
SQL_NODE * pLeftOperand;
SQL_NODE * pRightOperand;
SQLBoolType eBool;
// Right now we are only able to do operator nodes.
flmAssert( pQNode->eNodeType == SQL_OPERATOR_NODE);
pLeftOperand = pQNode->pFirstChild;
pRightOperand = pQNode->pLastChild;
pQNode->currVal.eValType = SQL_MISSING_VAL;
switch (pQNode->nd.op.eOperator)
{
case SQL_AND_OP:
case SQL_OR_OP:
pQNode->currVal.eValType = SQL_BOOL_VAL;
// There may be multiple operands here. We have already looked
// at all of the operands. If this is an AND we know that all
// of them were either TRUE or UNKNOWN. If this is an OR, we know
// that all of the previous operands were either FALSE or UNKNOWN.
// If we had hit a FALSE for an AND or a TRUE for an OR, we would
// not have come to this point. Now we just need to determine if
// any of the operands are UNKNOWN. If so, that is what we will
// set this node's value to. Otherwise, we will set it to TRUE for
// AND and FALSE for OR.
while (pLeftOperand)
{
// Get the left operand
if (pLeftOperand->eNodeType == SQL_OPERATOR_NODE)
{
// This operator may not have been evaluated because of missing
// column values in one or both operands, in which case
// its state will be SQL_MISSING_VALUE. If it was evaluated,
// its state should show a boolean value.
if (pLeftOperand->currVal.eValType == SQL_MISSING_VAL)
{
eBool = (pLeftOperand->bNotted ? SQL_TRUE : SQL_FALSE);
}
else
{
flmAssert( pLeftOperand->currVal.eValType == SQL_BOOL_VAL);
eBool = pLeftOperand->currVal.val.eBool;
}
}
else if (pLeftOperand->eNodeType == SQL_COLUMN_NODE)
{
if (!pLeftOperand->bNotted)
{
eBool = (pLeftOperand->currVal.eValType != SQL_MISSING_VAL)
? SQL_TRUE
: SQL_FALSE;
}
else
{
eBool = (pLeftOperand->currVal.eValType != SQL_MISSING_VAL)
? SQL_FALSE
: SQL_TRUE;
}
}
else
{
flmAssert( pLeftOperand->eNodeType == SQL_VALUE_NODE);
flmAssert( pLeftOperand->currVal.eValType == SQL_BOOL_VAL);
eBool = pLeftOperand->currVal.val.eBool;
}
// eBool better not have FALSE for an AND operator or
// TRUE for an OR operator.
flmAssert( (pQNode->nd.op.eOperator == SQL_AND_OP &&
eBool != SQL_FALSE) ||
(pQNode->nd.op.eOperator == SQL_OR_OP &&
eBool != SQL_TRUE));
if (eBool == SQL_UNKNOWN)
{
pQNode->currVal.val.eBool = SQL_UNKNOWN;
break;
}
pLeftOperand = pLeftOperand->pNextSib;
}
// If we didn't hit an UNKNOWN, set the node's value to TRUE for
// an AND operator and FALSE for an OR operator.
if (!pLeftOperand)
{
pQNode->currVal.val.eBool = pQNode->nd.op.eOperator == SQL_AND_OP
? SQL_TRUE
: SQL_FALSE;
}
break;
case SQL_EQ_OP:
case SQL_APPROX_EQ_OP:
case SQL_NE_OP:
case SQL_LT_OP:
case SQL_LE_OP:
case SQL_GT_OP:
case SQL_GE_OP:
pQNode->currVal.eValType = SQL_BOOL_VAL;
if (RC_BAD( rc = sqlCompareOperands( uiLanguage,
&pLeftOperand->currVal,
&pRightOperand->currVal,
pQNode->nd.op.eOperator,
pQNode->nd.op.uiCompareRules,
pQNode->bNotted,
&pQNode->currVal.val.eBool)))
{
goto Exit;
}
break;
case SQL_BITAND_OP:
case SQL_BITOR_OP:
case SQL_BITXOR_OP:
case SQL_MULT_OP:
case SQL_DIV_OP:
case SQL_MOD_OP:
case SQL_PLUS_OP:
case SQL_MINUS_OP:
case SQL_NEG_OP:
if (RC_BAD( rc = sqlEvalArithOperator( &pLeftOperand->currVal,
&pRightOperand->currVal,
pQNode->nd.op.eOperator,
&pQNode->currVal)))
{
goto Exit;
}
break;
default:
break;
}
Exit:
return( rc);
}
/***************************************************************************
Desc: Evaluate a query expression.
***************************************************************************/
RCODE sqlEvalCriteria(
F_Db * pDb,
SQL_NODE * pQueryExpr,
SQL_VALUE ** ppSqlValue,
F_Pool * pPool,
F_Row * pRow,
FLMUINT uiLanguage)
{
RCODE rc = NE_SFLM_OK;
SQL_NODE * pCurrNode;
SQL_VALUE * pSqlValue;
SQLBoolType eBoolVal;
SQLBoolType eBoolPartialEval;
// If the query is empty, return a value of SQL_TRUE.
if (!pQueryExpr)
{
if (RC_BAD( rc = pPool->poolAlloc( sizeof( SQL_VALUE),
(void **)ppSqlValue)))
{
goto Exit;
}
pSqlValue = *ppSqlValue;
pSqlValue->eValType = SQL_BOOL_VAL;
pSqlValue->uiFlags = SQL_VAL_IS_CONSTANT;
pSqlValue->val.eBool = SQL_TRUE;
goto Exit;
}
// If the query is a constant, return pointer to its value.
if (pQueryExpr->eNodeType == SQL_VALUE_NODE)
{
*ppSqlValue = &pQueryExpr->currVal;
goto Exit;
}
// If the query is a column, get the column's value from the
// row that was passed in.
if (pQueryExpr->eNodeType == SQL_COLUMN_NODE)
{
*ppSqlValue = &pQueryExpr->currVal;
rc = sqlGetColumnValue( pDb, pRow,
pQueryExpr->nd.column.pTable->uiTableNum,
pQueryExpr->nd.column.uiColumnNum,
pPool, *ppSqlValue);
goto Exit;
}
// Perform the evaluation
pCurrNode = pQueryExpr;
for (;;)
{
while (pCurrNode->pFirstChild)
{
pCurrNode = pCurrNode->pFirstChild;
}
// We should be positioned on a leaf node that is either a
// value or a column
if (pCurrNode->eNodeType == SQL_COLUMN_NODE)
{
if (RC_BAD( rc = sqlGetColumnValue( pDb, pRow,
pCurrNode->nd.column.pTable->uiTableNum,
pCurrNode->nd.column.uiColumnNum,
pPool, &pCurrNode->currVal)))
{
goto Exit;
}
}
else
{
// Better be a constant
flmAssert( pCurrNode->eNodeType == SQL_VALUE_NODE);
}
// When we get to this point, we have at least one leaf
// level operand in hand - pCurrNode.
// See if we can evaluate the operator of pCurrNode.
// This will take care of any short-circuiting evaluation
// that can be done.
for (;;)
{
if (pCurrNode == pQueryExpr)
{
*ppSqlValue = &pQueryExpr->currVal;
goto Exit;
}
// If the current node's parent is an AND or OR
// operator, see if we even need to go to the next
// sibling.
flmAssert( pCurrNode->pParent->eNodeType == SQL_OPERATOR_NODE);
if (isSQLLogicalOp( pCurrNode->pParent->nd.op.eOperator))
{
// All NOT operators should have been weeded out of the tree
// by now.
flmAssert( pCurrNode->pParent->nd.op.eOperator != SQL_NOT_OP);
eBoolVal = SQL_UNKNOWN;
eBoolPartialEval = pCurrNode->pParent->nd.op.eOperator == SQL_AND_OP
? SQL_FALSE
: SQL_TRUE;
if (pCurrNode->eNodeType == SQL_OPERATOR_NODE)
{
// It may not have been evaluated because of missing
// values in one or both operands, in which case
// its state will be SQL_MISSING_VALUE. If it was
// evaluated, its state should show a boolean value.
if (pCurrNode->currVal.eValType == SQL_MISSING_VAL)
{
eBoolVal = (pCurrNode->bNotted ? SQL_TRUE : SQL_FALSE);
}
else
{
flmAssert( pCurrNode->currVal.eValType == SQL_BOOL_VAL);
eBoolVal = pCurrNode->currVal.val.eBool;
}
}
else if (pCurrNode->eNodeType == SQL_COLUMN_NODE)
{
if (!pCurrNode->bNotted)
{
eBoolVal = (pCurrNode->currVal.eValType == SQL_MISSING_VAL)
? SQL_FALSE
: SQL_TRUE;
}
else
{
eBoolVal = (pCurrNode->currVal.eValType == SQL_MISSING_VAL)
? SQL_TRUE
: SQL_FALSE;
}
}
else
{
flmAssert( pCurrNode->eNodeType == SQL_VALUE_NODE);
// Only allowed value node underneath a logical operator is
// a boolean value that has a value of SQL_UNKNOWN.
// SQL_FALSE and SQL_TRUE will already have been weeded out.
flmAssert( pCurrNode->currVal.eValType == SQL_BOOL_VAL &&
pCurrNode->currVal.val.eBool == SQL_UNKNOWN);
// No need to set eBoolVal to SQL_UNKNOWN, because it will never
// match eBoolPartialEval in the test below. eBoolPartialEval
// is always either SQL_FALSE or SQL_TRUE.
// eBoolVal = SQL_UNKNOWN;
}
if (eBoolVal == eBoolPartialEval)
{
pCurrNode = pCurrNode->pParent;
pCurrNode->currVal.eValType = SQL_BOOL_VAL;
pCurrNode->currVal.val.eBool = eBoolVal;
}
else
{
goto Check_Sibling_Operand;
}
}
else if (isSQLCompareOp( pCurrNode->pParent->nd.op.eOperator))
{
// We can short-circuit the comparison - avoid getting the
// sibling operand - if the current node is a missing value.
// If the value is missing, the comparison operator will
// return a boolean SQL_UNKNOWN, regardless of what the
// other operand is.
if (pCurrNode->currVal.eValType == SQL_MISSING_VAL)
{
pCurrNode = pCurrNode->pParent;
pCurrNode->currVal.eValType = SQL_BOOL_VAL;
pCurrNode->currVal.val.eBool = SQL_UNKNOWN;
}
else
{
goto Check_Sibling_Operand;
}
}
else if (isSQLArithOp( pCurrNode->pParent->nd.op.eOperator))
{
// We can short-circuit the arithmetic operation - avoid getting the
// sibling operand - if the current node is a missing value.
// If the value is missing, the arithmetic operation will
// return a missing value, regardless of what the
// other operand is.
if (pCurrNode->currVal.eValType == SQL_MISSING_VAL)
{
pCurrNode = pCurrNode->pParent;
pCurrNode->currVal.eValType = SQL_MISSING_VAL;
}
else
{
goto Check_Sibling_Operand;
}
}
else
{
Check_Sibling_Operand:
if (pCurrNode->pNextSib)
{
pCurrNode = pCurrNode->pNextSib;
break;
}
pCurrNode = pCurrNode->pParent;
// All operands are now present - do evaluation
if (RC_BAD( rc = sqlEvalOperator( uiLanguage, pCurrNode)))
{
goto Exit;
}
}
}
}
Exit:
return( rc);
}

View File

@@ -975,13 +975,13 @@ RCODE SQLQuery::convertOperandsToPredicates( void)
{
pTable = pSQLNode->pFirstChild->nd.column.pTable;
uiColumnNum = pSQLNode->pFirstChild->nd.column.uiColumnNum;
pValue = &pSQLNode->pLastChild->nd.value;
pValue = &pSQLNode->pLastChild->currVal;
}
else
{
pTable = pSQLNode->pFirstChild->nd.column.pTable;
uiColumnNum = pSQLNode->pFirstChild->nd.column.uiColumnNum;
pValue = &pSQLNode->pFirstChild->nd.value;
pTable = pSQLNode->pLastChild->nd.column.pTable;
uiColumnNum = pSQLNode->pLastChild->nd.column.uiColumnNum;
pValue = &pSQLNode->pFirstChild->currVal;
// Need to invert the operator in this case.
@@ -1061,7 +1061,7 @@ FSTATIC SQL_NODE * sqlEvalLogicalOperands(
{
if (isSQLNodeBool( pChildNode))
{
eChildBoolVal = pChildNode->nd.value.val.eBool;
eChildBoolVal = pChildNode->currVal.val.eBool;
}
else
{
@@ -1209,11 +1209,14 @@ FSTATIC SQL_NODE * sqlClipNotNode(
}
//-------------------------------------------------------------------------
// Desc: Flatten the query tree. This coalesces AND and OR nodes so that
// they can have multiple operands. This will also strip out NOT nodes
// and resolve constant expressions to a single node.
// Desc: Reduce the query tree. This will strip out NOT nodes and
// resolve constant expressions to a single node. It also weeds
// out all boolean constants that are operands of AND or OR operators.
// Finally, if the bFlattenTree parameter is TRUE, it will coalesce
// AND and OR nodes so that they can have multiple operands.
//-------------------------------------------------------------------------
RCODE SQLQuery::flattenTree( void)
RCODE SQLQuery::reduceTree(
FLMBOOL bFlattenTree)
{
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode = m_pQuery;
@@ -1266,7 +1269,7 @@ RCODE SQLQuery::flattenTree( void)
rc = RC_SET( NE_SFLM_Q_ILLEGAL_OPERAND);
goto Exit;
}
if (pParentNode->nd.op.eOperator == eOperator)
if (bFlattenTree && pParentNode->nd.op.eOperator == eOperator)
{
// Move all of pSQLNode's children become the immediate
@@ -1401,15 +1404,15 @@ RCODE SQLQuery::flattenTree( void)
// If bNotted is TRUE and we have a boolean value, change
// the value: FALSE ==> TRUE, TRUE ==> FALSE.
if (bNotted && pSQLNode->nd.value.eValType == SQL_BOOL_VAL)
if (bNotted && pSQLNode->currVal.eValType == SQL_BOOL_VAL)
{
if (pSQLNode->nd.value.val.eBool == SQL_TRUE)
if (pSQLNode->currVal.val.eBool == SQL_TRUE)
{
pSQLNode->nd.value.val.eBool = SQL_FALSE;
pSQLNode->currVal.val.eBool = SQL_FALSE;
}
else if (pSQLNode->nd.value.val.eBool == SQL_FALSE)
else if (pSQLNode->currVal.val.eBool == SQL_FALSE)
{
pSQLNode->nd.value.val.eBool = SQL_TRUE;
pSQLNode->currVal.val.eBool = SQL_TRUE;
}
}
@@ -1419,7 +1422,7 @@ RCODE SQLQuery::flattenTree( void)
if (pParentNode)
{
if (pSQLNode->nd.value.eValType == SQL_BOOL_VAL)
if (pSQLNode->currVal.eValType == SQL_BOOL_VAL)
{
if (!isSQLLogicalOp( pParentNode->nd.op.eOperator))
{
@@ -1475,15 +1478,15 @@ RCODE SQLQuery::flattenTree( void)
pSQLNode->pLastChild->eNodeType == SQL_VALUE_NODE)
{
if (RC_BAD( rc = sqlEvalArithOperator(
&pSQLNode->pFirstChild->nd.value,
&pSQLNode->pLastChild->nd.value,
&pSQLNode->pFirstChild->currVal,
&pSQLNode->pLastChild->currVal,
pSQLNode->nd.op.eOperator,
&pSQLNode->nd.value)))
&pSQLNode->currVal)))
{
goto Exit;
}
pSQLNode->eNodeType = SQL_VALUE_NODE;
pSQLNode->nd.value.uiFlags = SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.uiFlags = SQL_VAL_IS_CONSTANT;
pSQLNode->pFirstChild = NULL;
pSQLNode->pLastChild = NULL;
}
@@ -2668,10 +2671,6 @@ RCODE SQLQuery::optimize( void)
rc = RC_SET( NE_SFLM_Q_INCOMPLETE_QUERY_EXPR);
goto Exit;
}
else if (m_pCurrParseState)
{
m_pQuery = m_pCurrParseState->pRootNode;
}
m_uiLanguage = m_pDb->getDefaultLanguage();
@@ -2695,8 +2694,8 @@ RCODE SQLQuery::optimize( void)
if (m_pQuery->eNodeType == SQL_VALUE_NODE)
{
if (m_pQuery->nd.value.eValType == SQL_BOOL_VAL &&
m_pQuery->nd.value.val.eBool == SQL_TRUE)
if (m_pQuery->currVal.eValType == SQL_BOOL_VAL &&
m_pQuery->currVal.val.eBool == SQL_TRUE)
{
m_bScan = TRUE;
}
@@ -2720,9 +2719,11 @@ RCODE SQLQuery::optimize( void)
goto Exit;
}
// Flatten the AND and OR operators in the query tree.
// Flatten the AND and OR operators in the query tree. Strip out
// NOT operators, resolve constant arithmetic expressions, and
// weed out boolean constants.
if (RC_BAD( rc = flattenTree()))
if (RC_BAD( rc = reduceTree( TRUE)))
{
goto Exit;
}

View File

@@ -152,21 +152,18 @@ typedef struct SQL_VALUE
{
eSQLValTypes eValType;
FLMUINT uiFlags;
#define SQL_VAL_IS_STREAM 0x0001
#define SQL_VAL_IS_CONSTANT 0x0002 // During query evaluation, this indicates
#define SQL_VAL_IS_CONSTANT 0x0001 // During query evaluation, this indicates
// that this value is a constant. If it
// is a FLM_UTF8_VAL, then asterisks will
// 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 0x0004 // This is only set if the value is a
// constant, FLM_UTF8_VAL, that has
#define SQL_VAL_HAS_WILDCARDS 0x0002 // This is only set if the value is a
// constant, SQL_UTF8_VAL, that has
// wildcards.
FLMUINT uiDataLen; // Length in bytes if the type is text
// or binary
union
{
SQLBoolType eBool;
@@ -176,7 +173,6 @@ typedef struct SQL_VALUE
FLMINT64 i64Val;
SQL_STRING_VALUE str;
SQL_BINARY_VALUE bin;
IF_PosIStream * pIStream;
} val; // Holds or points to the atom value.
} SQL_VALUE;
@@ -259,8 +255,10 @@ typedef struct SQL_NODE
eSQLNodeTypes eNodeType; // Type of node this is
FLMUINT uiNestLevel; // Nesting level of node - only used when
// setting up the query
FLMBOOL bUsedValue; // Used during evaluation
FLMBOOL bLastValue; // Used during evaluation
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
@@ -271,31 +269,17 @@ typedef struct SQL_NODE
{
SQL_OP op;
SQL_COLUMN column;
SQL_VALUE value;
SQL_PRED pred;
} nd;
} SQL_NODE;
FINLINE FLMBOOL isSQLNodeBool(
SQL_NODE * pNode
)
SQL_NODE * pNode)
{
return( (pNode->eNodeType == SQL_VALUE_NODE &&
pNode->nd.value.eValType == SQL_BOOL_VAL) ? TRUE : FALSE);
pNode->currVal.eValType == SQL_BOOL_VAL) ? TRUE : FALSE);
}
typedef struct SQL_PARSE_STATE
{
SQL_NODE * pRootNode;
SQL_NODE * pCurOperatorNode;
SQL_NODE * pLastNode;
FLMUINT uiNestLevel;
FLMBOOL bExpectingOperator;
FLMBOOL bExpectingLParen;
SQL_PARSE_STATE * pPrev;
SQL_PARSE_STATE * pNext;
} SQL_PARSE_STATE;
typedef struct SQL_SUBQUERY
{
FLMUINT uiOperandCount;
@@ -328,12 +312,12 @@ public:
FINLINE FLMBOOL expectingOperand( void)
{
return( !m_pCurrParseState->bExpectingOperator);
return( !m_bExpectingOperator);
}
FINLINE FLMBOOL expectingOperator( void)
{
return( m_pCurrParseState->bExpectingOperator);
return( m_bExpectingOperator);
}
RCODE addOperator(
@@ -409,17 +393,10 @@ public:
{
// Make sure we have a completed expression
if (m_pCurrParseState)
{
if (m_pCurrParseState->pPrev ||
m_pCurrParseState->uiNestLevel ||
(m_pCurrParseState->pLastNode &&
m_pCurrParseState->pLastNode->eNodeType == SQL_OPERATOR_NODE))
{
return( FALSE);
}
}
return( TRUE);
return( (m_uiNestLevel ||
(m_pLastNode && m_pLastNode->eNodeType == SQL_OPERATOR_NODE))
? FALSE
: TRUE);
}
RCODE getNext(
@@ -434,15 +411,11 @@ public:
RCODE getLast(
F_Row ** ppRow);
RCODE evalCriteria(
SQL_VALUE * pSqlValue,
F_Pool * pPool,
F_Row * pRow);
RCODE reduceTree(
FLMBOOL bFlattenTree);
private:
RCODE allocParseState( void);
RCODE allocValueNode(
FLMUINT uiValLen,
eSQLValTypes eValType,
@@ -477,8 +450,6 @@ private:
RCODE convertOperandsToPredicates( void);
RCODE flattenTree( void);
RCODE convertToDNF( void);
RCODE getPredKeys(
@@ -508,13 +479,16 @@ private:
F_Pool m_pool;
FLMUINT m_uiLanguage;
SQL_PARSE_STATE * m_pCurrParseState;
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_pFirstTable;
SQL_TABLE * m_pLastTable;
FLMBOOL m_bOptimized;
SQL_NODE * m_pQuery;
F_Database * m_pDatabase;
F_Db * m_pDb;
FLMBOOL m_bScan;
@@ -547,5 +521,13 @@ RCODE sqlEvalArithOperator( // sqleval.cpp
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);
#endif // #ifndef FLAIMODBC_H

View File

@@ -769,6 +769,15 @@ FSTATIC RCODE convertValueToStorageFormat(
{
RCODE rc = NE_SFLM_OK;
// Check for a missing value - return a NULL.
if (pSqlValue->eValType == SQL_MISSING_VAL)
{
pColValue->uiValueLen = 0;
pColValue->pucColumnValue = NULL;
goto Exit;
}
switch (pColumn->eDataTyp)
{
case SFLM_STRING_TYPE:
@@ -823,7 +832,7 @@ RCODE F_Db::updateSelectedRows(
F_COLUMN_VALUE * pColValue;
F_COLUMN_ITEM * pColItem;
COLUMN_SET * pColSet;
SQL_VALUE sqlValue;
SQL_VALUE * pSqlValue;
F_Pool tmpPool;
FLMBOOL bValueChanged;
@@ -899,14 +908,17 @@ Set_Null_Value:
}
else
{
if (RC_BAD( rc = pColSet->pSqlQuery->evalCriteria( &sqlValue,
&tmpPool, pRow)))
if (RC_BAD( rc = sqlEvalCriteria( this,
pSqlQuery->m_pQuery,
&pSqlValue,
&tmpPool, pRow,
m_pDatabase->m_uiDefaultLanguage)))
{
goto Exit;
}
pColumn = m_pDict->getColumn( pTable, pColSet->uiColumnNum);
if (RC_BAD( rc = convertValueToStorageFormat( &sqlValue,
if (RC_BAD( rc = convertValueToStorageFormat( pSqlValue,
pColumn, pColValue, &tmpPool)))
{
goto Exit;
@@ -1125,6 +1137,15 @@ RCODE SQLStatement::parseSetColumns(
{
goto Exit;
}
// Strip out NOT operators, resolve constant arithmetic expressions,
// and weed out boolean constants, but do not flatten the AND
// and OR operators in the query tree.
if (RC_BAD( rc = pSqlQuery->reduceTree( FALSE)))
{
goto Exit;
}
}
// Next token should either be a comma or the WHERE keyword, or we

View File

@@ -118,49 +118,6 @@ SQLQuery::~SQLQuery()
}
}
//-------------------------------------------------------------------------
// Desc: Allocate a structure for keeping track of the state of the
// current SQL query.
//-------------------------------------------------------------------------
RCODE SQLQuery::allocParseState( void)
{
RCODE rc = NE_SFLM_OK;
SQL_PARSE_STATE * pParseState;
if (!m_pCurrParseState || !m_pCurrParseState->pNext)
{
if (RC_BAD( rc = m_pool.poolCalloc( sizeof( SQL_PARSE_STATE),
(void **)&pParseState)))
{
goto Exit;
}
if ((pParseState->pPrev = m_pCurrParseState) != NULL)
{
m_pCurrParseState->pNext = pParseState;
}
m_pCurrParseState = pParseState;
}
else
{
SQL_PARSE_STATE * pSaveNext;
SQL_PARSE_STATE * pSavePrev;
m_pCurrParseState = m_pCurrParseState->pNext;
// Zero out everything except for the prev and next pointers
pSaveNext = m_pCurrParseState->pNext;
pSavePrev = m_pCurrParseState->pPrev;
f_memset( m_pCurrParseState, 0, sizeof( SQL_PARSE_STATE));
m_pCurrParseState->pNext = pSaveNext;
m_pCurrParseState->pPrev = pSavePrev;
}
Exit:
return( rc);
}
//-------------------------------------------------------------------------
// Desc: Unlinks a node from its parent and siblings. This routine assumes
// that the test has already been made that the node has a parent.
@@ -235,20 +192,6 @@ RCODE SQLQuery::allocValueNode(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
if (m_pCurrParseState->bExpectingLParen)
{
rc = RC_SET( NE_SFLM_Q_EXPECTING_LPAREN);
goto Exit;
}
if (!expectingOperand())
{
rc = RC_SET( NE_SFLM_Q_UNEXPECTED_VALUE);
@@ -262,8 +205,8 @@ RCODE SQLQuery::allocValueNode(
}
pSQLNode = *ppSQLNode;
pSQLNode->eNodeType = SQL_VALUE_NODE;
pSQLNode->nd.value.eValType = eValType;
pSQLNode->nd.value.uiFlags = SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.eValType = eValType;
pSQLNode->currVal.uiFlags = SQL_VAL_IS_CONSTANT;
// For string and binary data, allocate a buffer.
@@ -272,33 +215,33 @@ RCODE SQLQuery::allocValueNode(
if (eValType == SQL_UTF8_VAL)
{
if (RC_BAD( rc = m_pool.poolAlloc( uiValLen,
(void **)&pSQLNode->nd.value.val.str.pszStr)))
(void **)&pSQLNode->currVal.val.str.pszStr)))
{
goto Exit;
}
pSQLNode->nd.value.val.str.uiByteLen = uiValLen;
pSQLNode->currVal.val.str.uiByteLen = uiValLen;
}
else if (eValType == SQL_BINARY_VAL)
{
if (RC_BAD( rc = m_pool.poolAlloc( uiValLen,
(void **)&pSQLNode->nd.value.val.bin.pucValue)))
(void **)&pSQLNode->currVal.val.bin.pucValue)))
{
goto Exit;
}
pSQLNode->nd.value.val.bin.uiByteLen = uiValLen;
pSQLNode->currVal.val.bin.uiByteLen = uiValLen;
}
}
if (m_pCurrParseState->pRootNode)
if (m_pQuery)
{
sqlLinkLastChild( m_pCurrParseState->pCurOperatorNode, pSQLNode);
sqlLinkLastChild( m_pCurOperatorNode, pSQLNode);
}
else
{
m_pCurrParseState->pRootNode = pSQLNode;
m_pQuery = pSQLNode;
}
m_pCurrParseState->bExpectingOperator = TRUE;
m_pCurrParseState->pLastNode = pSQLNode;
m_bExpectingOperator = TRUE;
m_pLastNode = pSQLNode;
Exit:
@@ -316,23 +259,6 @@ RCODE SQLQuery::addOperator(
SQL_NODE * pSQLNode;
SQL_NODE * pParentNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// If we are expecting a left paren (for a function), that is
// the only thing that is acceptable at this point.
if (m_pCurrParseState->bExpectingLParen && eOperator != SQL_LPAREN_OP)
{
rc = RC_SET( NE_SFLM_Q_EXPECTING_LPAREN);
goto Exit;
}
if (eOperator == SQL_MINUS_OP && expectingOperand())
{
eOperator = SQL_NEG_OP;
@@ -349,8 +275,7 @@ RCODE SQLQuery::addOperator(
rc = RC_SET( NE_SFLM_Q_UNEXPECTED_LPAREN);
goto Exit;
}
m_pCurrParseState->uiNestLevel++;
m_pCurrParseState->bExpectingLParen = FALSE;
m_uiNestLevel++;
goto Exit;
case SQL_RPAREN_OP:
@@ -359,12 +284,12 @@ RCODE SQLQuery::addOperator(
rc = RC_SET( NE_SFLM_Q_UNEXPECTED_RPAREN);
goto Exit;
}
if (!m_pCurrParseState->uiNestLevel)
if (!m_uiNestLevel)
{
rc = RC_SET( NE_SFLM_Q_UNMATCHED_RPAREN);
goto Exit;
}
m_pCurrParseState->uiNestLevel--;
m_uiNestLevel--;
goto Exit;
@@ -416,12 +341,12 @@ RCODE SQLQuery::addOperator(
pSQLNode->eNodeType = SQL_OPERATOR_NODE;
pSQLNode->nd.op.eOperator = eOperator;
pSQLNode->nd.op.uiCompareRules = uiCompareRules;
pSQLNode->uiNestLevel = m_pCurrParseState->uiNestLevel;
pSQLNode->uiNestLevel = m_uiNestLevel;
// Go up the stack until an operator whose nest level or precedence is <
// this one's is encountered, then link this one in as the last child
pParentNode = m_pCurrParseState->pCurOperatorNode;
pParentNode = m_pCurOperatorNode;
while (pParentNode &&
(pParentNode->uiNestLevel > pSQLNode->uiNestLevel ||
(pParentNode->uiNestLevel == pSQLNode->uiNestLevel &&
@@ -432,11 +357,11 @@ RCODE SQLQuery::addOperator(
}
if (!pParentNode)
{
if (m_pCurrParseState->pRootNode)
if (m_pQuery)
{
sqlLinkLastChild( pSQLNode, m_pCurrParseState->pRootNode);
sqlLinkLastChild( pSQLNode, m_pQuery);
}
m_pCurrParseState->pRootNode = pSQLNode;
m_pQuery = pSQLNode;
}
else if (eOperator == SQL_NOT_OP || eOperator == SQL_NEG_OP)
{
@@ -466,7 +391,7 @@ RCODE SQLQuery::addOperator(
#endif
sqlLinkLastChild( pParentNode, pSQLNode);
flmAssert( !m_pCurrParseState->bExpectingOperator);
flmAssert( !m_bExpectingOperator);
}
else
{
@@ -502,9 +427,9 @@ RCODE SQLQuery::addOperator(
sqlLinkLastChild( pParentNode, pSQLNode);
}
m_pCurrParseState->pCurOperatorNode = pSQLNode;
m_pCurrParseState->bExpectingOperator = FALSE;
m_pCurrParseState->pLastNode = pSQLNode;
m_pCurOperatorNode = pSQLNode;
m_bExpectingOperator = FALSE;
m_pLastNode = pSQLNode;
Exit:
@@ -528,16 +453,16 @@ RCODE SQLQuery::allocOperandNode(
}
pSQLNode->eNodeType = eNodeType;
if (m_pCurrParseState->pRootNode)
if (m_pQuery)
{
sqlLinkLastChild( m_pCurrParseState->pCurOperatorNode, pSQLNode);
sqlLinkLastChild( m_pCurOperatorNode, pSQLNode);
}
else
{
m_pCurrParseState->pRootNode = pSQLNode;
m_pQuery = pSQLNode;
}
m_pCurrParseState->bExpectingOperator = TRUE;
m_pCurrParseState->pLastNode = *ppSQLNode = pSQLNode;
m_bExpectingOperator = TRUE;
m_pLastNode = *ppSQLNode = pSQLNode;
Exit:
@@ -554,14 +479,6 @@ RCODE SQLQuery::addTable(
RCODE rc = NE_SFLM_OK;
SQL_TABLE * pTable;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Add or find the table structure for the node.
pTable = m_pFirstTable;
@@ -608,14 +525,6 @@ RCODE SQLQuery::addColumn(
SQL_NODE * pSQLNode;
SQL_TABLE * pTable;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -652,14 +561,6 @@ RCODE SQLQuery::addUINT64(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -674,9 +575,9 @@ RCODE SQLQuery::addUINT64(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_UINT64_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.ui64Val = ui64Num;
pSQLNode->currVal.eValType = SQL_UINT64_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.ui64Val = ui64Num;
Exit:
@@ -692,14 +593,6 @@ RCODE SQLQuery::addUINT(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -714,9 +607,9 @@ RCODE SQLQuery::addUINT(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_UINT_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.uiVal = uiNum;
pSQLNode->currVal.eValType = SQL_UINT_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.uiVal = uiNum;
Exit:
@@ -732,14 +625,6 @@ RCODE SQLQuery::addINT64(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -754,9 +639,9 @@ RCODE SQLQuery::addINT64(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_INT64_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.i64Val = i64Num;
pSQLNode->currVal.eValType = SQL_INT64_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.i64Val = i64Num;
Exit:
@@ -772,14 +657,6 @@ RCODE SQLQuery::addINT(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -794,9 +671,9 @@ RCODE SQLQuery::addINT(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_INT_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.iVal = iNum;
pSQLNode->currVal.eValType = SQL_INT_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.iVal = iNum;
Exit:
@@ -813,14 +690,6 @@ RCODE SQLQuery::addBoolean(
RCODE rc = NE_SFLM_OK;
SQL_NODE * pSQLNode;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -835,19 +704,19 @@ RCODE SQLQuery::addBoolean(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_BOOL_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.eValType = SQL_BOOL_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
if (bUnknown)
{
pSQLNode->nd.value.val.eBool = SQL_UNKNOWN;
pSQLNode->currVal.val.eBool = SQL_UNKNOWN;
}
else if (bValue)
{
pSQLNode->nd.value.val.eBool = SQL_TRUE;
pSQLNode->currVal.val.eBool = SQL_TRUE;
}
else
{
pSQLNode->nd.value.val.eBool = SQL_FALSE;
pSQLNode->currVal.val.eBool = SQL_FALSE;
}
Exit:
@@ -867,14 +736,6 @@ RCODE SQLQuery::addUTF8String(
SQL_NODE * pSQLNode;
FLMBYTE * pszTmp;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -898,11 +759,11 @@ RCODE SQLQuery::addUTF8String(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_UTF8_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.str.pszStr = pszTmp;
pSQLNode->nd.value.val.str.uiByteLen = uiStrLen + 1;
pSQLNode->nd.value.val.str.uiNumChars = uiNumChars;
pSQLNode->currVal.eValType = SQL_UTF8_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.str.pszStr = pszTmp;
pSQLNode->currVal.val.str.uiByteLen = uiStrLen + 1;
pSQLNode->currVal.val.str.uiNumChars = uiNumChars;
f_memcpy( pszTmp, pszUTF8Str, uiStrLen);
pszTmp [uiStrLen] = 0;
@@ -912,7 +773,7 @@ RCODE SQLQuery::addUTF8String(
{
if (*pszTmp == '*')
{
pSQLNode->nd.value.uiFlags |= SQL_VAL_HAS_WILDCARDS;
pSQLNode->currVal.uiFlags |= SQL_VAL_HAS_WILDCARDS;
break;
}
else if (*pszTmp == '\\')
@@ -946,14 +807,6 @@ RCODE SQLQuery::addBinary(
SQL_NODE * pSQLNode;
FLMBYTE * pucTmp;
if (!m_pCurrParseState)
{
if (RC_BAD( rc = allocParseState()))
{
goto Exit;
}
}
// Must be expecting an operand
if (!expectingOperand())
@@ -972,10 +825,10 @@ RCODE SQLQuery::addBinary(
{
goto Exit;
}
pSQLNode->nd.value.eValType = SQL_BINARY_VAL;
pSQLNode->nd.value.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->nd.value.val.bin.uiByteLen = uiValueLen;
pSQLNode->nd.value.val.bin.pucValue = pucTmp;
pSQLNode->currVal.eValType = SQL_BINARY_VAL;
pSQLNode->currVal.uiFlags |= SQL_VAL_IS_CONSTANT;
pSQLNode->currVal.val.bin.uiByteLen = uiValueLen;
pSQLNode->currVal.val.bin.pucValue = pucTmp;
f_memcpy( pucTmp, pucValue, uiValueLen);
Exit: