windows-nt/Source/XPSP1/NT/ds/adsi/router/sql/sqltree.cxx
2020-09-26 16:20:57 +08:00

437 lines
11 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: SqlTree.cxx
//
// Contents: Implementation of the SQL Query Tree to convert SQL queries
// to LDAP queries
//
// Functions:
//
// History: 12-Dec-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
#include "lexer.hxx"
#include "sqltree.hxx"
#include "sqlparse.hxx"
//+---------------------------------------------------------------------------
//
// Function: CSQLNode::CSQLNode
//
// Synopsis: Constructor of the CSQLNode
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
CSQLNode::CSQLNode()
{
_dwType = 0;
_szValue = NULL;
_pLQueryNode = NULL;
_pRQueryNode = NULL;
}
//+---------------------------------------------------------------------------
//
// Function: CSQLNode::CSQLNode
//
// Synopsis: Constructor of the CSQLNode
//
// Arguments: dwType type of node
// pLQueryNode pointer to left node
// pRQueryNode pointer to right node
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
CSQLNode::CSQLNode(
DWORD dwType,
CSQLNode *pLQueryNode,
CSQLNode *pRQueryNode
)
{
_dwType = dwType;
_pLQueryNode = pLQueryNode;
_pRQueryNode = pRQueryNode;
}
//+---------------------------------------------------------------------------
//
// Function: CSQLNode::SetToString
//
// Synopsis: Set the Node to be a String Node
//
// Arguments: szValue value of the string
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT CSQLNode::SetToString(
LPWSTR szValue
)
{
_szValue = szValue;
_dwType = QUERY_STRING;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: CSQLNode::~CSQLNode
//
// Synopsis: Destructor of the CSQLNode
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
CSQLNode::~CSQLNode()
{
if ((_dwType == QUERY_STRING) && _szValue) {
FreeADsStr(_szValue);
}
if (_pLQueryNode) {
delete _pLQueryNode;
}
if (_pRQueryNode) {
delete _pRQueryNode;
}
}
// Helper Functions for creating nodes using the CSQLNode Class
//+---------------------------------------------------------------------------
//
// Function: MakeNode
//
// Synopsis: Make a node with the input values
//
// Arguments: dwType type of node
// pLQueryNode pointer to left node
// pRQueryNode pointer to right node
// ppQueryNodeReturn pointer to Return Node
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT MakeNode(
DWORD dwType,
CSQLNode *pLQueryNode,
CSQLNode *pRQueryNode,
CSQLNode **ppQueryNodeReturn
)
{
CSQLNode *pQueryNode = new CSQLNode(
dwType,
pLQueryNode,
pRQueryNode
);
if (!pQueryNode)
return E_OUTOFMEMORY;
*ppQueryNodeReturn = pQueryNode;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: MakeLeaf
//
// Synopsis: Constructor of the CSQLNode
//
// Arguments: szValue value of the string
// ppQueryNodeReturn the return node
//
// Returns:
//
// Modifies:
//
// History: 11-12-96 Felix Wong Created.
//
//----------------------------------------------------------------------------
HRESULT MakeLeaf(
LPWSTR szValue,
CSQLNode **ppQueryNodeReturn
)
{
HRESULT hr = S_OK;
CSQLNode *pQueryNode = new CSQLNode();
if (!pQueryNode)
return E_OUTOFMEMORY;
hr = pQueryNode->SetToString(szValue);
BAIL_ON_FAILURE(hr);
*ppQueryNodeReturn = pQueryNode;
RRETURN(hr);
error:
delete pQueryNode;
RRETURN(hr);
}
typedef struct _TOKEN_TO_STRING {
DWORD dwToken;
LPWSTR szToken;
} TOKEN_TO_STRING, *LPTOKEN_TO_STRING;
TOKEN_TO_STRING SqlTokenMap[] =
{
{ TOKEN_EQ, L"="},
{ TOKEN_LT, L"<="},
{ TOKEN_GT, L">="},
{ TOKEN_LE, L"<="},
{ TOKEN_GE, L">="},
{ TOKEN_AND, L"&"},
{ TOKEN_OR, L"|"},
{ TOKEN_NOT, L"!"},
{ 0, 0}
};
HRESULT CSQLNode::MapTokenToChar(DWORD dwToken, LPWSTR *pszToken)
{
LPTOKEN_TO_STRING pTokenMap ;
pTokenMap = SqlTokenMap;
while (pTokenMap->dwToken)
{
if (pTokenMap->dwToken == dwToken) {
*pszToken = pTokenMap->szToken ;
return S_OK;
}
pTokenMap++ ;
}
return E_FAIL;
}
HRESULT CSQLNode::GenerateLDAPString(CSQLString* pString)
{
HRESULT hr = S_OK;
switch (_dwType) {
case QUERY_STRING:
BAIL_ON_FAILURE(hr = pString->Append(_szValue));
break;
case TOKEN_EQ:
case TOKEN_LE:
case TOKEN_GE:
{
BAIL_ON_FAILURE(hr = pString->Append(L"("));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
LPWSTR szToken;
MapTokenToChar(
_dwType,
&szToken
);
BAIL_ON_FAILURE(hr = pString->Append(szToken));
BAIL_ON_FAILURE(hr = _pRQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L")"));
break;
}
case TOKEN_LT:
case TOKEN_GT:
{
BAIL_ON_FAILURE(hr = pString->Append(L"(&("));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
LPWSTR szToken;
MapTokenToChar(
_dwType,
&szToken
);
BAIL_ON_FAILURE(hr = pString->Append(szToken));
BAIL_ON_FAILURE(hr = _pRQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L")(!("));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L"="));
BAIL_ON_FAILURE(hr = _pRQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L")))"));
break;
}
case TOKEN_NE:
{
BAIL_ON_FAILURE(hr = pString->Append(L"(!("));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L"="));
BAIL_ON_FAILURE(hr = _pRQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L"))"));
}
break;
case TOKEN_NOT:
{
BAIL_ON_FAILURE(hr = pString->Append(L"(!"));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L")"));
break;
}
case TOKEN_AND:
case TOKEN_OR:
{
BAIL_ON_FAILURE(hr = pString->Append(L"("));
LPWSTR szToken;
MapTokenToChar(
_dwType,
&szToken
);
BAIL_ON_FAILURE(hr = pString->Append(szToken));
BAIL_ON_FAILURE(hr = _pLQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = _pRQueryNode->GenerateLDAPString(pString));
BAIL_ON_FAILURE(hr = pString->Append(L")"));
break;
}
default:
return E_FAIL;
}
return S_OK;
error:
return hr;
}
#define SQLSTR_INC 255
CSQLString::CSQLString()
{
_dwSizeMax = SQLSTR_INC;
_szString = (LPWSTR)AllocADsMem(sizeof(WCHAR)*SQLSTR_INC);
_dwSize = 0;
}
CSQLString::~CSQLString()
{
FreeADsMem((void*)_szString);
}
HRESULT CSQLString::Append(LPWSTR szAppend)
{
DWORD dwAppendSize = wcslen(szAppend);
DWORD dwSizeCurrent = _dwSize + dwAppendSize + 1;
if (dwSizeCurrent <= _dwSizeMax) {
wcscat(
_szString,
szAppend
);
_dwSize +=dwAppendSize;
}
else {
DWORD dwNewSizeMax = _dwSizeMax + SQLSTR_INC;
while (dwSizeCurrent > dwNewSizeMax) {
dwNewSizeMax += SQLSTR_INC;
}
_szString = (LPWSTR)ReallocADsMem(
(void*)_szString,
_dwSizeMax*sizeof(WCHAR),
dwNewSizeMax*sizeof(WCHAR)
);
if (!_szString) {
return E_OUTOFMEMORY;
}
wcscat(
_szString,
szAppend
);
_dwSizeMax = dwNewSizeMax;
_dwSize +=dwAppendSize;
}
return S_OK;
}
HRESULT CSQLString::AppendAtBegin(LPWSTR szAppend)
{
DWORD dwAppendSize = wcslen(szAppend);
DWORD dwSizeCurrent = _dwSize + dwAppendSize + 1;
DWORD i = 0;
//
// Explicitly move the original string and copy the new string to the
// beginning
if (dwSizeCurrent <= _dwSizeMax) {
for (i=dwSizeCurrent - 1; i > dwAppendSize - 1; i--) {
_szString[i] = _szString[i-dwAppendSize];
}
wcsncpy(
_szString,
szAppend,
dwAppendSize
);
_dwSize +=dwAppendSize;
}
else {
DWORD dwNewSizeMax = _dwSizeMax + SQLSTR_INC;
while (dwSizeCurrent > dwNewSizeMax) {
dwNewSizeMax += SQLSTR_INC;
}
_szString = (LPWSTR)ReallocADsMem(
(void*)_szString,
_dwSizeMax*sizeof(WCHAR),
dwNewSizeMax*sizeof(WCHAR)
);
if (!_szString) {
return E_OUTOFMEMORY;
}
//
// Explicitly move the original string and copy the new string to the
// beginning
for (i=dwSizeCurrent - 1; i > dwAppendSize - 1; i--) {
_szString[i] = _szString[i-dwAppendSize];
}
wcsncpy(
_szString,
szAppend,
dwAppendSize
);
_dwSize +=dwAppendSize;
_dwSizeMax = dwNewSizeMax;
_dwSize +=dwAppendSize;
}
return S_OK;
}