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:
@@ -4411,7 +4411,7 @@ private:
|
||||
|
||||
// More includes
|
||||
|
||||
#include "flaimodbc.h"
|
||||
#include "sqlquery.h"
|
||||
#include "fscursor.h"
|
||||
|
||||
#endif // FLAIMSYS_H
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user