//+--------------------------------------------------------------------------- // // 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; } LPWSTR szTemp = (LPWSTR)ReallocADsMem( (void*)_szString, _dwSizeMax*sizeof(WCHAR), dwNewSizeMax*sizeof(WCHAR) ); if (!szTemp) { return E_OUTOFMEMORY; } _szString = szTemp; 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; } LPWSTR szTemp = (LPWSTR)ReallocADsMem( (void*)_szString, _dwSizeMax*sizeof(WCHAR), dwNewSizeMax*sizeof(WCHAR) ); if (!szTemp) { return E_OUTOFMEMORY; } _szString = szTemp; // // 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; }