//*************************************************************************** // // WQL.CPP // // WQL Parser // // Implements the LL(1) syntax described in WQL.BNF via a recursive // descent parser. // // raymcc 14-Sep-97 Created for WMI/SMS. // raymcc 18-Oct-97 Additional extensions for SMS team. // raymcc 20-Apr-00 Whistler RPN extensions // raymcc 19-May-00 Whistler delete/insert/update extensions // //*************************************************************************** // TO DO: #include "precomp.h" #include #include #include #include #include #include #include #include "wmiquery.h" #include #include #include #include #include void __stdcall _com_issue_error(long hResult) { throw hResult;}; POLARITY BOOL ReadI64(LPCWSTR wsz, UNALIGNED __int64& ri64); POLARITY BOOL ReadUI64(LPCWSTR wsz, UNALIGNED unsigned __int64& rui64); //*************************************************************************** // // Misc // //*************************************************************************** // static DWORD FlipOperator(DWORD dwOp); #define trace(x) printf x void StrArrayDelete(ULONG, LPWSTR *); HRESULT StrArrayCopy( ULONG uSize, LPWSTR *pSrc, LPWSTR **pDest ); //*************************************************************************** // // CloneLPWSTR // //*************************************************************************** // ok static LPWSTR CloneLPWSTR(LPCWSTR pszSrc) { if (pszSrc == 0) return 0; size_t cchTmp = wcslen(pszSrc) + 1; LPWSTR pszTemp = new wchar_t[cchTmp]; if (pszTemp ) memcpy(pszTemp, pszSrc,cchTmp*sizeof(wchar_t)); return pszTemp; } static LPWSTR Clone(LPCWSTR pszSrc) { if (pszSrc == 0) return 0; size_t cchTmp = wcslen(pszSrc) + 1; LPWSTR pszTemp = new wchar_t[cchTmp]; if (pszTemp ) memcpy(pszTemp, pszSrc,cchTmp*sizeof(wchar_t)); else throw CX_MemoryException(); return pszTemp; } //*************************************************************************** // // CloneFailed // //*************************************************************************** bool inline CloneFailed(LPCWSTR p1, LPCWSTR p2) { if (0 == p1 && 0 == p2 ) return false; if (p1 && p2) return false; return true; } //*************************************************************************** // // CWQLParser::CWQLParser // // Constructor // // Parameters: // A source from which to lex from. // //*************************************************************************** // CWQLParser::CWQLParser( LPWSTR pszQueryText, CGenLexSource *pSrc ) { if (pszQueryText == 0 || pSrc == 0) throw CX_Exception(); m_pLexer = new CGenLexer(WQL_LexTable, pSrc); if (m_pLexer == 0) throw CX_Exception(); m_pszQueryText = CloneLPWSTR(pszQueryText); if (m_pszQueryText == 0 && pszQueryText!=0 ) { delete m_pLexer; m_pLexer = 0; throw CX_Exception(); } m_nLine = 0; m_pTokenText = 0; m_nCurrentToken = 0; m_uFeatures = 0I64; m_pQueryRoot = 0; m_pRootWhere = 0; m_pRootColList = 0; m_pRootFrom = 0; m_pRootWhereOptions = 0; m_nParseContext = Ctx_Default; m_bAllowPromptForConstant = false; } //*************************************************************************** // // CWQLParser::~CWQLParser // //*************************************************************************** // CWQLParser::~CWQLParser() { Empty(); delete m_pLexer; } //*************************************************************************** // // CWQLParser::Empty // //*************************************************************************** // ok void CWQLParser::Empty() { m_aReferencedTables.Empty(); m_aReferencedAliases.Empty(); m_pTokenText = 0; // We don't delete this, it was never allocated m_nLine = 0; m_nCurrentToken = 0; m_uFeatures = 0I64; delete m_pQueryRoot; // Clean up previous query, if any m_pQueryRoot = 0; m_pRootWhere = 0; m_pRootColList = 0; m_pRootFrom = 0; m_pRootWhereOptions = 0; m_nParseContext = Ctx_Default; // For the next two, we don't delete the pointers since they // were copies of structs elsewhere in the tree. // ========================================================= m_aSelAliases.Empty(); m_aSelColumns.Empty(); delete [] m_pszQueryText; } //*************************************************************************** // // CWQLParser::GetTokenLong // // Converts the current token to a 32/64 bit integer. Returns info // about the size of the constant. // //*************************************************************************** // ok BOOL CWQLParser::GetIntToken( OUT BOOL *bSigned, OUT BOOL *b64Bit, OUT unsigned __int64 *pVal ) { BOOL bRes; if (m_pTokenText == 0 || *m_pTokenText == 0) return FALSE; if (*m_pTokenText == L'-') { __int64 Temp; bRes = ReadI64(m_pTokenText, Temp); if (bRes == FALSE) return FALSE; *bSigned = TRUE; if (Temp < -2147483648I64) { *b64Bit = TRUE; } else { *b64Bit = FALSE; } *pVal = (unsigned __int64) Temp; } else { bRes = ReadUI64(m_pTokenText, *pVal); if (bRes == FALSE) return FALSE; *bSigned = FALSE; if (*pVal >> 32) { *b64Bit = TRUE; if (*pVal <= 0x7FFFFFFFFFFFFFFFI64) { *bSigned = TRUE; } } else { *b64Bit = FALSE; // See if we can dumb down to 32-bit VT_I4 for simplicity. // Much code recognizes VT_I4 and doesn't recognize VT_UI4 // because it can't be packed into a VARIANT. So, if there // are only 31 bits used, let's convert to VT_I4. We do this // by returning this as a 'signed' value (the positive sign :). if (*pVal <= 0x7FFFFFFF) { *bSigned = TRUE; } } } return TRUE; } //*************************************************************************** // // CWQLParser::GetReferencedTables // // Creates an array of the names of the tables referenced in this query // //*************************************************************************** // ok BOOL CWQLParser::GetReferencedTables(OUT CWStringArray& Tables) { Tables = m_aReferencedTables; return TRUE; } //*************************************************************************** // // CWQLParser::GetReferencedAliases // //*************************************************************************** // ok BOOL CWQLParser::GetReferencedAliases(OUT CWStringArray & Aliases) { Aliases = m_aReferencedAliases; return TRUE; } //*************************************************************************** // // Next() // // Advances to the next token and recognizes keywords, etc. // //*************************************************************************** // ok struct WqlKeyword { LPWSTR m_pKeyword; int m_nTokenCode; }; static WqlKeyword KeyWords[] = // Keep this alphabetized for binary search { L"ALL", WQL_TOK_ALL, L"AND", WQL_TOK_AND, L"AS", WQL_TOK_AS, L"ASC", WQL_TOK_ASC, L"ASSOCIATORS", WQL_TOK_ASSOCIATORS, L"BETWEEN", WQL_TOK_BETWEEN, L"BY", WQL_TOK_BY, L"COUNT", WQL_TOK_COUNT, L"DATEPART", WQL_TOK_DATEPART, L"DELETE", WQL_TOK_DELETE, L"DESC", WQL_TOK_DESC, L"DISTINCT", WQL_TOK_DISTINCT, L"FROM", WQL_TOK_FROM, L"FULL", WQL_TOK_FULL, L"GROUP", WQL_TOK_GROUP, L"HAVING", WQL_TOK_HAVING, L"IN", WQL_TOK_IN, L"INNER", WQL_TOK_INNER, L"INSERT", WQL_TOK_INSERT, L"IS", WQL_TOK_IS, L"ISA", WQL_TOK_ISA, L"ISNULL", WQL_TOK_ISNULL, L"JOIN", WQL_TOK_JOIN, L"LEFT", WQL_TOK_LEFT, L"LIKE", WQL_TOK_LIKE, L"LOWER", WQL_TOK_LOWER, L"NOT", WQL_TOK_NOT, L"NULL", WQL_TOK_NULL, L"ON", WQL_TOK_ON, L"OR", WQL_TOK_OR, L"ORDER", WQL_TOK_ORDER, L"OUTER", WQL_TOK_OUTER, L"__QUALIFIER", WQL_TOK_QUALIFIER, L"REFERENCES", WQL_TOK_REFERENCES, L"RIGHT", WQL_TOK_RIGHT, L"SELECT", WQL_TOK_SELECT, L"__THIS", WQL_TOK_THIS, L"UPDATE", WQL_TOK_UPDATE, L"UPPER", WQL_TOK_UPPER, L"WHERE", WQL_TOK_WHERE }; const int NumKeywords = sizeof(KeyWords)/sizeof(WqlKeyword); BOOL CWQLParser::Next() { m_nCurrentToken = m_pLexer->NextToken(); if (m_nCurrentToken == WQL_TOK_ERROR || (m_nCurrentToken == WQL_TOK_PROMPT && !m_bAllowPromptForConstant)) return FALSE; m_nLine = m_pLexer->GetLineNum(); m_pTokenText = m_pLexer->GetTokenText(); if (m_nCurrentToken == WQL_TOK_EOF) m_pTokenText = L""; // Keyword check. Do a binary search // on the keyword table. // ================================= if (m_nCurrentToken == WQL_TOK_IDENT) { int l = 0, u = NumKeywords - 1; while (l <= u) { int m = (l + u) / 2; if (wbem_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) < 0) u = m - 1; else if (wbem_wcsicmp(m_pTokenText, KeyWords[m].m_pKeyword) > 0) l = m + 1; else // Match { m_nCurrentToken = KeyWords[m].m_nTokenCode; break; } } } return TRUE; } //*************************************************************************** // // ::= SELECT ; // ::= DELETE ; // ::= INSERT ; // ::= UPDATE ; // // Precondition: All cleanup has been performed from previous parse // by a call to Empty() // //*************************************************************************** // ok HRESULT CWQLParser::Parse() { HRESULT hRes = WBEM_E_INVALID_SYNTAX; m_pQueryRoot = new SWQLNode_QueryRoot; if (!m_pQueryRoot) return WBEM_E_OUT_OF_MEMORY; try { m_pLexer->Reset(); if (!Next()) return WBEM_E_INVALID_SYNTAX; // See which kind of query we have. // ================================ switch (m_nCurrentToken) { case WQL_TOK_SELECT: { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_Select *pSelStmt = 0; hRes = select_stmt(&pSelStmt); if (FAILED(hRes)) return hRes; m_pQueryRoot->m_pLeft = pSelStmt; m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eSelect; } break; case WQL_TOK_ASSOCIATORS: case WQL_TOK_REFERENCES: { SWQLNode_AssocQuery *pAQ = 0; hRes = assocquery(&pAQ); if (FAILED(hRes)) return hRes; m_pQueryRoot->m_pLeft = pAQ; m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eAssoc; } break; case WQL_TOK_INSERT: { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_Insert *pIns = 0; hRes = insert_stmt(&pIns); if (FAILED(hRes)) return hRes; m_pQueryRoot->m_pLeft = pIns; m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eInsert; } break; case WQL_TOK_DELETE: { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_Delete *pDel = 0; hRes = delete_stmt(&pDel); if (FAILED(hRes)) return hRes; m_pQueryRoot->m_pLeft = pDel; m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eDelete; } break; case WQL_TOK_UPDATE: { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_Update *pUpd = 0; hRes = update_stmt(&pUpd); if (FAILED(hRes)) return hRes; m_pQueryRoot->m_pLeft = pUpd; m_pQueryRoot->m_dwQueryType = SWQLNode_QueryRoot::eUpdate; } break; default: return WBEM_E_INVALID_SYNTAX; } } catch (CX_MemoryException) { hRes = WBEM_E_OUT_OF_MEMORY; } catch (...) { hRes = WBEM_E_CRITICAL_ERROR; } return hRes; } //*************************************************************************** // // ::= // // // // // //*************************************************************************** // ok int CWQLParser::select_stmt(OUT SWQLNode_Select **pSelStmt) { int nRes = 0; int nType = 0; SWQLNode_FromClause *pFrom = 0; SWQLNode_Select *pSel = 0; SWQLNode_TableRefs *pTblRefs = 0; SWQLNode_WhereClause *pWhere = 0; *pSelStmt = 0; // Set up the basic AST. // ===================== pSel = new SWQLNode_Select; if (!pSel) return WBEM_E_OUT_OF_MEMORY; pTblRefs = new SWQLNode_TableRefs; if (!pTblRefs) { delete pSel; return WBEM_E_OUT_OF_MEMORY; } pSel->m_pLeft = pTblRefs; // Get the select type. // ==================== nRes = select_type(nType); if (nRes) goto Exit; pTblRefs->m_nSelectType = nType; // ALL, DISTINCT // Get the selected list of columns. // ================================= nRes = col_ref_list(pTblRefs); if (nRes) goto Exit; m_pRootColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft; // Get the FROM clause and patch it into the AST. // =============================================== nRes = from_clause(&pFrom); if (nRes) goto Exit; m_pRootFrom = pFrom; pTblRefs->m_pRight = pFrom; // Get the WHERE clause. // ===================== nRes = where_clause(&pWhere); if (nRes) goto Exit; m_pRootWhere = pWhere; pSel->m_pRight = pWhere; // Verify we are at the end of the query. // ====================================== if (m_nCurrentToken != WQL_TOK_EOF) { nRes = WBEM_E_INVALID_SYNTAX; goto Exit; } nRes = NO_ERROR; Exit: if (nRes) delete pSel; else { *pSelStmt = pSel; } return nRes; } //*************************************************************************** // // CWQLParser::delete_stmt // //*************************************************************************** // ok int CWQLParser::delete_stmt(OUT SWQLNode_Delete **pDelStmt) { int nRes = 0; int nType = 0; SWQLNode_TableRef *pTblRef = 0; SWQLNode_WhereClause *pWhere = 0; // Default in case of error. // ========================= *pDelStmt = 0; if (m_nCurrentToken != WQL_TOK_FROM) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // Otherwise, traditional SQL. // =========================== nRes = single_table_decl(&pTblRef); if (nRes) return nRes; // Get the WHERE clause. // ===================== nRes = where_clause(&pWhere); if (nRes) { delete pTblRef; return nRes; } // Verify we are at the end of the query. // ====================================== if (m_nCurrentToken != WQL_TOK_EOF) { nRes = WBEM_E_INVALID_SYNTAX; delete pTblRef; delete pWhere; } else { // If here, everything is wonderful. // ================================== SWQLNode_Delete *pDel = new SWQLNode_Delete; if (!pDel) { // Except that we might have just run out of memory... // ==================================================== delete pTblRef; delete pWhere; return WBEM_E_OUT_OF_MEMORY; } // Patch in the new node. // ===================== pDel->m_pLeft = pTblRef; pDel->m_pRight = pWhere; *pDelStmt = pDel; nRes = WBEM_S_NO_ERROR; } return nRes; } //*************************************************************************** // // ::= ALL; // ::= DISTINCT; // ::= <>; // // Returns type through nSelType : // WQL_TOK_ALL or WQL_TOK_DISTINCT // //*************************************************************************** // done int CWQLParser::select_type(int & nSelType) { nSelType = WQL_FLAG_ALL; // Default if (m_nCurrentToken == WQL_TOK_ALL) { nSelType = WQL_FLAG_ALL; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_DISTINCT) { nSelType = WQL_FLAG_DISTINCT; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; } return NO_ERROR; } //*************************************************************************** // // ::= ; // ::= ASTERISK; // ::= COUNT ; // //*************************************************************************** // ? int CWQLParser::col_ref_list( IN OUT SWQLNode_TableRefs *pTblRefs ) { int nRes; DWORD dwFuncFlags = 0; // Allocate a new left node of type SWQLNode_ColumnList and patch it in // if it doesn't already exist. // ===================================================================== SWQLNode_ColumnList *pColList = (SWQLNode_ColumnList *) pTblRefs->m_pLeft; if (pColList == NULL) { pColList = new SWQLNode_ColumnList; if (!pColList) return WBEM_E_OUT_OF_MEMORY; pTblRefs->m_pLeft = pColList; } // If here, it is a "select *..." query. // ===================================== if (m_nCurrentToken == WQL_TOK_ASTERISK) { // Allocate a new column list which has a single asterisk. // ======================================================= SWQLColRef *pColRef = new SWQLColRef; if (!pColRef) return WBEM_E_OUT_OF_MEMORY; pColRef->m_pColName = CloneLPWSTR(L"*"); if (pColRef->m_pColName == 0) { delete pColRef; return WBEM_E_OUT_OF_MEMORY; } m_uFeatures |= WMIQ_RPNF_FEATURE_SELECT_STAR; pColRef->m_dwFlags = WQL_FLAG_ASTERISK; if (pColList->m_aColumnRefs.Add(pColRef) != CFlexArray::no_error) { delete pColRef; return WBEM_E_OUT_OF_MEMORY; }; if (!Next()) { return WBEM_E_INVALID_SYNTAX; } return NO_ERROR; } // If here, we have a "select COUNT..." operation. // =============================================== if (m_nCurrentToken == WQL_TOK_COUNT) { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLQualifiedName *pQN = 0; nRes = count_clause(&pQN); if (!nRes) { pTblRefs->m_nSelectType |= WQL_FLAG_COUNT; SWQLColRef *pCR = 0; if (SUCCEEDED(nRes = QNameToSWQLColRef(pQN, &pCR))) { if (pColList->m_aColumnRefs.Add(pCR)) { delete pCR; return WBEM_E_OUT_OF_MEMORY; } } return nRes; } else { // This may be a column named count // in which case the current token is // either an ident or "from" if (m_nCurrentToken == WQL_TOK_FROM || m_nCurrentToken == WQL_TOK_COMMA) { wmilib::auto_ptr pCR = wmilib::auto_ptr(new SWQLColRef); if (pCR.get()) { pCR->m_pColName = CloneLPWSTR(L"count"); if (pCR->m_pColName == 0) return WBEM_E_OUT_OF_MEMORY; if (pColList->m_aColumnRefs.Add(pCR.get()) != CFlexArray::no_error) return WBEM_E_OUT_OF_MEMORY; pCR.release(); } else return WBEM_E_OUT_OF_MEMORY; if (WQL_TOK_FROM == m_nCurrentToken) return 0; else { return col_ref_rest(pTblRefs); } } else return WBEM_E_INVALID_SYNTAX; } } // Make a provision for wrapping the // column in a function all UPPER or LOWER // ======================================= if (m_nCurrentToken == WQL_TOK_UPPER) dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_UPPER; else if (m_nCurrentToken == WQL_TOK_LOWER) dwFuncFlags = WQL_FLAG_FUNCTIONIZED | WQL_FLAG_LOWER; if (dwFuncFlags) { // Common procedure for cases where UPPER or LOWER are used. if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; } // If here, must be an identifier. // =============================== if (m_nCurrentToken != WQL_TOK_IDENT) return WBEM_E_INVALID_SYNTAX; SWQLQualifiedName *pInitCol = 0; nRes = col_ref(&pInitCol); if (nRes) return nRes; wmilib::auto_ptr initCol(pInitCol); SWQLColRef *pCR = 0; nRes = QNameToSWQLColRef(initCol.get(), &pCR); if (nRes) return nRes; initCol.release(); pCR->m_dwFlags |= dwFuncFlags; if (dwFuncFlags) { // If a function call was invoked, remove the trailing paren. // ========================================================== if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; } pColList->m_aColumnRefs.Add(pCR); m_uFeatures |= WMIQ_RPNF_PROJECTION; return col_ref_rest(pTblRefs); } //*************************************************************************** // // ::= OPEN_PAREN CLOSE_PAREN; // ::= ASTERISK; // ::= IDENT; // // On NO_ERROR returns: // set to TRUE if a * occurred in the COUNT clause, // or set to FALSE and set to point to the // qualified name of the column referenced. // //*************************************************************************** // ok int CWQLParser::count_clause( OUT SWQLQualifiedName **pQualName ) { int nRes; *pQualName = 0; // Syntax check. // ============= if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // Determine whether an asterisk was used COUNT(*) or // a col-ref COUNT(col-ref) // ================================================== if (m_nCurrentToken == WQL_TOK_ASTERISK) { SWQLQualifiedName *pQN = new SWQLQualifiedName; if (!pQN) return WBEM_E_OUT_OF_MEMORY; SWQLQualifiedNameField *pQF = new SWQLQualifiedNameField; if (!pQF) { delete pQN; return WBEM_E_OUT_OF_MEMORY; } pQF->m_pName = CloneLPWSTR(L"*"); if (pQF->m_pName == 0) { delete pQN; delete pQF; return WBEM_E_OUT_OF_MEMORY; } pQN->Add(pQF); *pQualName = pQN; if (!Next()) return WBEM_E_INVALID_SYNTAX; m_uFeatures |= WMIQ_RPNF_COUNT_STAR; } else if (m_nCurrentToken == WQL_TOK_IDENT) { SWQLQualifiedName *pQN = 0; nRes = col_ref(&pQN); if (nRes) return nRes; *pQualName = pQN; } // Check for errors in syntax and clean up // if so. // ======================================= if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) { if (*pQualName) delete *pQualName; *pQualName = 0; return WBEM_E_INVALID_SYNTAX; } if (!Next()) { if (*pQualName) delete *pQualName; *pQualName = 0; return WBEM_E_INVALID_SYNTAX; } return NO_ERROR; } //*************************************************************************** // // ::= COMMA ; // ::= <>; // //*************************************************************************** int CWQLParser::col_ref_rest(IN OUT SWQLNode_TableRefs *pTblRefs) { int nRes; if (m_nCurrentToken != WQL_TOK_COMMA) return NO_ERROR; if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = col_ref_list(pTblRefs); return nRes; } //*************************************************************************** // // ::= ; // ::= ; // // ::= ; // // ::= ; // ::= ; // // ::= <>; // Unary query // //*************************************************************************** int CWQLParser::from_clause(OUT SWQLNode_FromClause **pFrom) { int nRes = 0; SWQLNode_TableRef *pTbl = 0; std::auto_ptr pFC (new SWQLNode_FromClause); if (pFC.get() == 0) return WBEM_E_OUT_OF_MEMORY; if (m_nCurrentToken != WQL_TOK_FROM) { return WBEM_E_INVALID_SYNTAX; } if (!Next()) { return WBEM_E_INVALID_SYNTAX; } // Special case for WMI scope selections. // ====================================== if (m_nCurrentToken == WQL_TOK_BRACKETED_STRING) { nRes = wmi_scoped_select (pFC.get ()); *pFrom = pFC.release(); return nRes; } // Otherwise, traditional SQL. // =========================== nRes = single_table_decl(&pTbl); if (nRes) { return nRes; } // Check for joins. // =============== if (m_nCurrentToken == WQL_TOK_COMMA) { SWQLNode_Sql89Join *pJoin = 0; nRes = sql89_join_entry(pTbl, &pJoin); if (nRes) { return nRes; } pFC->m_pLeft = pJoin; } else { if (m_nCurrentToken == WQL_TOK_INNER || m_nCurrentToken == WQL_TOK_FULL || m_nCurrentToken == WQL_TOK_LEFT || m_nCurrentToken == WQL_TOK_RIGHT || m_nCurrentToken == WQL_TOK_JOIN ) { SWQLNode_Join *pJoin = 0; nRes = sql92_join_entry(pTbl, &pJoin); if (nRes) { return nRes; } pFC->m_pLeft = pJoin; } // Single table select (unary query). // ================================== else { pFC->m_pLeft = pTbl; } } *pFrom = pFC.release(); return NO_ERROR; } //*************************************************************************** // // wmi_scoped_select // // '[' objectpath ']' // // ::= CLASS // ::= '{' class1, class2, ...classn '}' // //*************************************************************************** // int CWQLParser::wmi_scoped_select(SWQLNode_FromClause *pFC) { // Strip all input up to the next closing bracket. // =============================================== SWQLNode_WmiScopedSelect *pSS = new SWQLNode_WmiScopedSelect; if (!pSS) throw CX_MemoryException(); pSS->m_pszScope = CloneLPWSTR(m_pTokenText); if (!pSS->m_pszScope) { delete pSS; throw CX_MemoryException(); } if (!Next()) goto Error; if (m_nCurrentToken == WQL_TOK_IDENT) { // Get simple class name. // ====================== LPWSTR pszTmp = CloneLPWSTR(m_pTokenText); if (pszTmp == 0) { delete pSS; return WBEM_E_OUT_OF_MEMORY; } pSS->m_aTables.Add(pszTmp); if (!Next()) goto Error; } else if (m_nCurrentToken == WQL_TOK_OPEN_BRACE) { while(1) { if (!Next()) goto Error; if (m_nCurrentToken == WQL_TOK_IDENT) { LPWSTR pszTmp = CloneLPWSTR(m_pTokenText); if (pszTmp == 0) { delete pSS; return WBEM_E_OUT_OF_MEMORY; } pSS->m_aTables.Add(pszTmp); } else goto Error; if (!Next()) goto Error; if (m_nCurrentToken == WQL_TOK_CLOSE_BRACE) break; if (m_nCurrentToken == WQL_TOK_COMMA) continue; } if (!Next()) goto Error; } // Patch in the node. // ================== pFC->m_pRight = pSS; return NO_ERROR; Error: delete pSS; return WBEM_E_INVALID_SYNTAX; } //*************************************************************************** // // ::= COMMA ; // //*************************************************************************** int CWQLParser::sql89_join_entry(IN SWQLNode_TableRef *pInitialTblRef, OUT SWQLNode_Sql89Join **pJoin ) { if (m_nCurrentToken != WQL_TOK_COMMA) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; return sql89_join_list(pInitialTblRef, pJoin); } //*************************************************************************** // // ::= ; // // ::= COMMA ; // ::= <>; // //*************************************************************************** int CWQLParser::sql89_join_list(IN SWQLNode_TableRef *pInitialTblRef, OUT SWQLNode_Sql89Join **pJoin ) { int nRes; SWQLNode_Sql89Join *p89Join = new SWQLNode_Sql89Join; if (!p89Join) return WBEM_E_OUT_OF_MEMORY; p89Join->m_aValues.Add(pInitialTblRef); while (1) { SWQLNode_TableRef *pTR = 0; nRes = single_table_decl(&pTR); if (nRes) { delete p89Join; return nRes; } p89Join->m_aValues.Add(pTR); if (m_nCurrentToken != WQL_TOK_COMMA) break; if (!Next()) { delete p89Join; return WBEM_E_INVALID_SYNTAX; } } *pJoin = p89Join; return NO_ERROR; } //*************************************************************************** // // ::= WQL_TOK_WHERE ; // ::= <>; // 'where' is not required // //*************************************************************************** // done int CWQLParser::where_clause(OUT SWQLNode_WhereClause **pRetWhere) { SWQLNode_WhereClause *pWhere = new SWQLNode_WhereClause; if (!pWhere) return WBEM_E_OUT_OF_MEMORY; *pRetWhere = pWhere; SWQLNode_RelExpr *pRelExpr = 0; int nRes; // 'where' is optional. // ==================== if (m_nCurrentToken == WQL_TOK_WHERE) { if (!Next()) return WBEM_E_INVALID_SYNTAX; m_uFeatures |= WMIQ_RPNF_WHERE_CLAUSE_PRESENT; // Get the primary relational expression for the 'where' clause. // ============================================================= nRes = rel_expr(&pRelExpr); if (nRes) { delete pRelExpr; return nRes; } } // Get the options, such as ORDER BY, GROUP BY, etc. // ================================================= SWQLNode_WhereOptions *pWhereOpt = 0; nRes = where_options(&pWhereOpt); if (nRes) { delete pRelExpr; delete pWhereOpt; return nRes; } pWhere->m_pLeft = pRelExpr; pWhere->m_pRight = pWhereOpt; m_pRootWhereOptions = pWhereOpt; return NO_ERROR; } //*************************************************************************** // // ::= // // // //*************************************************************************** // done int CWQLParser::where_options(OUT SWQLNode_WhereOptions **pRetWhereOpt) { int nRes; *pRetWhereOpt = 0; SWQLNode_GroupBy *pGroupBy = 0; nRes = group_by_clause(&pGroupBy); if (nRes) { delete pGroupBy; return nRes; } SWQLNode_OrderBy *pOrderBy = 0; nRes = order_by_clause(&pOrderBy); if (nRes) { delete pOrderBy; delete pGroupBy; return nRes; } SWQLNode_WhereOptions *pWhereOpt = 0; if (pGroupBy || pOrderBy) { pWhereOpt = new SWQLNode_WhereOptions; if (!pWhereOpt) { delete pOrderBy; delete pGroupBy; return WBEM_E_OUT_OF_MEMORY; } pWhereOpt->m_pLeft = pGroupBy; pWhereOpt->m_pRight = pOrderBy; } *pRetWhereOpt = pWhereOpt; return NO_ERROR; } //*************************************************************************** // // ::= WQL_TOK_GROUP WQL_TOK_BY ; // ::= <>; // //*************************************************************************** // done int CWQLParser::group_by_clause(OUT SWQLNode_GroupBy **pRetGroupBy) { int nRes; *pRetGroupBy = 0; if (m_nCurrentToken != WQL_TOK_GROUP) return NO_ERROR; if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_BY) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // Get the guts of the GROUP BY. // ============================= SWQLNode_GroupBy *pGroupBy = new SWQLNode_GroupBy; if (!pGroupBy) { return WBEM_E_OUT_OF_MEMORY; } SWQLNode_ColumnList *pColList = 0; nRes = col_list(&pColList); if (nRes) { delete pGroupBy; delete pColList; return nRes; } pGroupBy->m_pLeft = pColList; // Check for the HAVING clause. // ============================ SWQLNode_Having *pHaving = 0; nRes = having_clause(&pHaving); if (pHaving) pGroupBy->m_pRight = pHaving; *pRetGroupBy = pGroupBy; m_uFeatures |= WMIQ_RPNF_GROUP_BY_HAVING; return NO_ERROR; } //*************************************************************************** // // ::= WQL_TOK_HAVING ; // ::= <>; // //*************************************************************************** // done int CWQLParser::having_clause(OUT SWQLNode_Having **pRetHaving) { int nRes; *pRetHaving = 0; if (m_nCurrentToken != WQL_TOK_HAVING) return NO_ERROR; if (!Next()) return WBEM_E_INVALID_SYNTAX; // If here, we have a HAVING clause. // ================================= SWQLNode_RelExpr *pRelExpr = 0; nRes = rel_expr(&pRelExpr); if (nRes) { delete pRelExpr; return nRes; } SWQLNode_Having *pHaving = new SWQLNode_Having; if (!pHaving) { delete pRelExpr; return WBEM_E_OUT_OF_MEMORY; } pHaving->m_pLeft = pRelExpr; *pRetHaving = pHaving; return NO_ERROR; } //*************************************************************************** // // ::= WQL_TOK_ORDER WQL_TOK_BY ; // ::= <>; // //*************************************************************************** // done int CWQLParser::order_by_clause(OUT SWQLNode_OrderBy **pRetOrderBy) { int nRes; if (m_nCurrentToken != WQL_TOK_ORDER) return NO_ERROR; if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_BY) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // If here, we have an ORDER BY clause. // ==================================== m_uFeatures |= WMIQ_RPNF_ORDER_BY; SWQLNode_ColumnList *pColList = 0; nRes = col_list(&pColList); if (nRes) { delete pColList; return nRes; } SWQLNode_OrderBy *pOrderBy = new SWQLNode_OrderBy; if (!pOrderBy) { delete pColList; return WBEM_E_OUT_OF_MEMORY; } pOrderBy->m_pLeft = pColList; *pRetOrderBy = pOrderBy; return NO_ERROR; } //*************************************************************************** // // ::= ; // // ::= IDENT; // ::= ; // ::= <>; // ::= IDENT; // // ::= AS; // ::= <>; // //*************************************************************************** // done; no cleanup int CWQLParser::single_table_decl(OUT SWQLNode_TableRef **pTblRef) { if (pTblRef == 0) return WBEM_E_CRITICAL_ERROR; *pTblRef = 0; if (m_nCurrentToken != WQL_TOK_IDENT) return WBEM_E_INVALID_SYNTAX; SWQLNode_TableRef *pTR = new SWQLNode_TableRef; if (!pTR) return WBEM_E_OUT_OF_MEMORY; pTR->m_pTableName = CloneLPWSTR(m_pTokenText); if (pTR->m_pTableName == 0) { delete pTR; return WBEM_E_OUT_OF_MEMORY; } m_aReferencedTables.Add(m_pTokenText); if (!Next()) { delete pTR; return WBEM_E_INVALID_SYNTAX; } if (m_nCurrentToken == WQL_TOK_AS) { // Here we have a redundant AS and an alias. // ========================================= if (!Next()) { delete pTR; return WBEM_E_INVALID_SYNTAX; } } // If no Alias was used, we simply copy the table name into // the alias slot. // ======================================================== else { pTR->m_pAlias = CloneLPWSTR(pTR->m_pTableName); if (pTR->m_pAlias == 0) { delete pTR; return WBEM_E_OUT_OF_MEMORY; } m_aReferencedAliases.Add(pTR->m_pTableName); } // For the primary select, we are keeping a list of tables // we are selecting from. // ======================================================= if ((m_nParseContext & Ctx_Subselect) == 0) m_aSelAliases.Add(pTR); // Return the pointer to the caller. // ================================= *pTblRef = pTR; return NO_ERROR; } //*************************************************************************** // // SQL-92 Joins. // // We support: // 1. [INNER] JOIN // 2. LEFT [OUTER] JOIN // 3. RIGHT [OUTER] JOIN // 4. FULL [OUTER] JOIN // // // ::= ; // ::= INNER ; // ::= FULL ; // ::= LEFT ; // ::= RIGHT ; // // ::= WQL_TOK_OUTER; // ::= <>; // // ::= // JOIN // // // // // ::= ; // ::= <>; // //*************************************************************************** int CWQLParser::sql92_join_entry( IN SWQLNode_TableRef *pInitialTblRef, // inherited OUT SWQLNode_Join **pJoin // synthesized ) { int nRes; /* Build a nested join tree bottom up. Currently, the tree is always left-heavy: JN = Join Noe JP = Join Pair OC = On Clause TR = Table Ref JN / \ JP OC / \ JN TR / \ JP OC / \ TR TR */ // State 1: Attempting to build a new JOIN node. // ============================================= std::auto_ptr pCurrentLeftNode; SWQLNode_JoinPair *pBottomJP = 0; while (1) { std::auto_ptr pJN (new SWQLNode_Join); if (pJN.get() == 0) return WBEM_E_OUT_OF_MEMORY; // Join-type. // ========== pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN; // Default if (m_nCurrentToken == WQL_TOK_INNER) { if (!Next()) return WBEM_E_INVALID_SYNTAX; pJN->m_dwJoinType = WQL_FLAG_INNER_JOIN; } else if (m_nCurrentToken == WQL_TOK_FULL) { if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken == WQL_TOK_OUTER) if (!Next()) return WBEM_E_INVALID_SYNTAX; pJN->m_dwJoinType = WQL_FLAG_FULL_OUTER_JOIN; } else if (m_nCurrentToken == WQL_TOK_LEFT) { if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken == WQL_TOK_OUTER) if (!Next()) return WBEM_E_INVALID_SYNTAX; pJN->m_dwJoinType = WQL_FLAG_LEFT_OUTER_JOIN; } else if (m_nCurrentToken == WQL_TOK_RIGHT) { if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken == WQL_TOK_OUTER) if (!Next()) return WBEM_E_INVALID_SYNTAX; pJN->m_dwJoinType = WQL_FLAG_RIGHT_OUTER_JOIN; } // // ===================== if (m_nCurrentToken != WQL_TOK_JOIN) { return WBEM_E_INVALID_SYNTAX; } if (!Next()) return WBEM_E_INVALID_SYNTAX; std::auto_ptr pJP (new SWQLNode_JoinPair); if (pJP.get() == 0) return WBEM_E_OUT_OF_MEMORY; // Determine the table to which to join. // ===================================== SWQLNode_TableRef *pTR = 0; nRes = single_table_decl(&pTR); if (nRes) return nRes; pJP->m_pRight = pTR; pJP->m_pLeft = pCurrentLeftNode.release(); pCurrentLeftNode = pJN; if (pBottomJP==0) pBottomJP = pJP.get(); // If FIRSTROW is used, add it in. // =============================== if (m_nCurrentToken == WQL_TOK_IDENT) { if (wbem_wcsicmp(L"FIRSTROW", m_pTokenText) != 0) return WBEM_E_INVALID_SYNTAX; pCurrentLeftNode/*pJN*/->m_dwFlags |= WQL_FLAG_FIRSTROW; if (!Next()) return WBEM_E_INVALID_SYNTAX; } // Get the ON clause. // ================== SWQLNode_OnClause *pOC = 0; nRes = on_clause(&pOC); if (nRes) return nRes; pCurrentLeftNode/*pJN*/->m_pRight = pOC; // On clause pCurrentLeftNode/*pJN*/->m_pLeft = pJP.release(); // sql92_join_continuator(); // ========================= if (m_nCurrentToken == WQL_TOK_INNER || m_nCurrentToken == WQL_TOK_FULL || m_nCurrentToken == WQL_TOK_LEFT || m_nCurrentToken == WQL_TOK_RIGHT || m_nCurrentToken == WQL_TOK_JOIN ) continue; break; } // Return the join node to the caller. // ==================================== // Set pBottomJP->m_pLeft = pInitialTblRef; *pJoin = pCurrentLeftNode.release(); return NO_ERROR; } //*************************************************************************** // // ::= ON ; // //*************************************************************************** int CWQLParser::on_clause(OUT SWQLNode_OnClause **pOC) { if (m_nCurrentToken != WQL_TOK_ON) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; wmilib::auto_ptr pNewOC( new SWQLNode_OnClause); if (NULL == pNewOC.get()) return WBEM_E_OUT_OF_MEMORY; SWQLNode_RelExpr *pRelExpr = 0; int nRes = rel_expr(&pRelExpr); if (nRes) { delete pRelExpr; return nRes; } pNewOC->m_pLeft = pRelExpr; *pOC = pNewOC.release(); return NO_ERROR; } //*************************************************************************** // // ::= ; // // We are creating a new expression or subexpression each time // we enter this recursively. No inherited attributes are // propagated to this production. // //*************************************************************************** int CWQLParser::rel_expr(OUT SWQLNode_RelExpr **pRelExpr) { int nRes; *pRelExpr = 0; // Get the new node. This becomes a temporary root. // ================================================= SWQLNode_RelExpr *pRE = 0; nRes = rel_term(&pRE); if (nRes) return nRes; // At this point, we have a possible root. If // there are OR operations, the root will be // replaced by the next function. Otherwise, // the call will pass through pRE into pNewRoot. // ============================================= SWQLNode_RelExpr *pNewRoot = 0; nRes = rel_expr2(pRE, &pNewRoot); if (nRes) return nRes; // Return the expression to the caller. // ==================================== *pRelExpr = pNewRoot; return NO_ERROR; } //*************************************************************************** // // ::= OR ; // ::= <>; // //*************************************************************************** // done! int CWQLParser::rel_expr2( IN OUT SWQLNode_RelExpr *pLeftSide, OUT SWQLNode_RelExpr **pNewRootRE ) { int nRes; *pNewRootRE = pLeftSide; // Default for the nullable production while (1) { // Build a series of OR subtrees bottom-up. We use iteration // and pointer juggling to simulate recursion. // ============================================================ if (m_nCurrentToken == WQL_TOK_OR) { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr; if (!pNewRoot) return WBEM_E_OUT_OF_MEMORY; pNewRoot->m_dwExprType = WQL_TOK_OR; pNewRoot->m_pLeft = pLeftSide; pLeftSide = pNewRoot; *pNewRootRE = pNewRoot; // Communicate this fact to the caller SWQLNode_RelExpr *pRight = 0; if (nRes = rel_term(&pRight)) return nRes; pNewRoot->m_pRight = pRight; // Right node becomes the new subexpr } else break; } return NO_ERROR; } //*************************************************************************** // // ::= ; // //*************************************************************************** // done! int CWQLParser::rel_term( OUT SWQLNode_RelExpr **pNewTerm ) { int nRes; SWQLNode_RelExpr *pNewSimple = 0; if (nRes = rel_simple_expr(&pNewSimple)) return nRes; SWQLNode_RelExpr *pNewRoot = 0; if (nRes = rel_term2(pNewSimple, &pNewRoot)) return nRes; *pNewTerm = pNewRoot; return NO_ERROR; } //*************************************************************************** // // ::= AND ; // ::= <>; // //*************************************************************************** // done! int CWQLParser::rel_term2( IN SWQLNode_RelExpr *pLeftSide, // Inherited OUT SWQLNode_RelExpr **pNewRootRE // Synthesized ) { int nRes; *pNewRootRE = pLeftSide; // Default for the nullable production while (1) { // Build a series of AND subtrees bottom-up. We use iteration // and pointer juggling to simulate recursion. // ============================================================ if (m_nCurrentToken == WQL_TOK_AND) { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_RelExpr *pNewRoot = new SWQLNode_RelExpr; if (!pNewRoot) { return WBEM_E_OUT_OF_MEMORY; } pNewRoot->m_dwExprType = WQL_TOK_AND; pNewRoot->m_pLeft = pLeftSide; pLeftSide = pNewRoot; *pNewRootRE = pNewRoot; // Communicate this fact to the caller SWQLNode_RelExpr *pRight = 0; if (nRes = rel_simple_expr(&pRight)) return nRes; pNewRoot->m_pRight = pRight; } else break; } return NO_ERROR; } //*************************************************************************** // // ::= NOT ; // ::= OPEN_PAREN CLOSE_PAREN; // ::= ; // //*************************************************************************** // done! int CWQLParser::rel_simple_expr(OUT SWQLNode_RelExpr **pRelExpr) { int nRes; *pRelExpr = 0; // Default // NOT // ============== if (m_nCurrentToken == WQL_TOK_NOT) { if (!Next()) return WBEM_E_INVALID_SYNTAX; // Allocate a NOT root and place the NOTed subexpr // under it. // =============================================== SWQLNode_RelExpr *pNotRoot = new SWQLNode_RelExpr; if (!pNotRoot) return WBEM_E_OUT_OF_MEMORY; pNotRoot->m_dwExprType = WQL_TOK_NOT; SWQLNode_RelExpr *pRelSubExpr = 0; if (nRes = rel_expr(&pRelSubExpr)) return nRes; pNotRoot->m_pLeft = pRelSubExpr; pNotRoot->m_pRight = NULL; // intentional *pRelExpr = pNotRoot; return NO_ERROR; } // OPEN_PAREN CLOSE_PAREN // ================================= else if (m_nCurrentToken == WQL_TOK_OPEN_PAREN) { if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLNode_RelExpr *pSubExpr = 0; if (rel_expr(&pSubExpr)) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; *pRelExpr = pSubExpr; return NO_ERROR; } // // ============ SWQLNode_RelExpr *pSubExpr = 0; nRes = typed_expr(&pSubExpr); if (nRes) return nRes; *pRelExpr = pSubExpr; return NO_ERROR; } //*************************************************************************** // // ::= ; // //*************************************************************************** // done int CWQLParser::typed_expr(OUT SWQLNode_RelExpr **pRelExpr) { int nRes; // Allocate a node for this typed expression. // There are no possible child nodes, so this becomes // a synthesized attribute. // ============================================================= SWQLNode_RelExpr *pRE = new SWQLNode_RelExpr; if (!pRE) return WBEM_E_OUT_OF_MEMORY; pRE->m_dwExprType = WQL_TOK_TYPED_EXPR; *pRelExpr = pRE; SWQLTypedExpr *pTE = new SWQLTypedExpr; if (!pTE) return WBEM_E_OUT_OF_MEMORY; // Look at the left hand side. // =========================== nRes = typed_subexpr(pTE); if (nRes) { delete pTE; return nRes; } int nOperator; // Get the operator. // ================= nRes = rel_op(nOperator); if (nRes) return nRes; pTE->m_dwRelOperator = DWORD(nOperator); if (nOperator == WQL_TOK_ISNULL || nOperator == WQL_TOK_NOT_NULL) { pRE->m_pTypedExpr = pTE; return NO_ERROR; } // Get the right-hand side. // ======================== nRes = typed_subexpr_rh(pTE); if (nRes) { delete pTE; return nRes; } // Check for IN, NOT IN and a const-list, to change the operator // to a more specific variety. // ============================================================= if (pTE->m_pConstList) { if (pTE->m_dwRelOperator == WQL_TOK_IN) pTE->m_dwRelOperator = WQL_TOK_IN_CONST_LIST; if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN) pTE->m_dwRelOperator = WQL_TOK_NOT_IN_CONST_LIST; } // Post-processing. If the left side is a const and the right // side is a col-ref, flip the operator and swap so that // such expressions are normalized with the constant on the // right hand side and the column on the left. // ============================================================ if (pTE->m_pConstValue && pTE->m_pJoinColRef) { pTE->m_dwRelOperator = FlipOperator(pTE->m_dwRelOperator); pTE->m_pColRef = pTE->m_pJoinColRef; pTE->m_pTableRef = pTE->m_pJoinTableRef; pTE->m_pJoinTableRef = 0; pTE->m_pJoinColRef = 0; DWORD dwTmp = pTE->m_dwRightFlags; pTE->m_dwRightFlags = pTE->m_dwLeftFlags; pTE->m_dwLeftFlags = dwTmp; // Interchange function references. // ================================ pTE->m_pIntrinsicFuncOnColRef = pTE->m_pIntrinsicFuncOnJoinColRef; pTE->m_pIntrinsicFuncOnJoinColRef = 0; } pRE->m_pTypedExpr = pTE; return NO_ERROR; } //*************************************************************************** // // ::= ; // ::= ; // ::= ; // //*************************************************************************** // ok int CWQLParser::typed_subexpr( SWQLTypedExpr *pTE ) { int nRes; BOOL bStripTrailingParen = FALSE; SWQLQualifiedName *pColRef = 0; wmilib::auto_buffer pFuncHolder; // Check for // ========================= if (m_nCurrentToken == WQL_TOK_UPPER) { pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED; pFuncHolder.reset(CloneLPWSTR(L"UPPER")); if (pFuncHolder.get() == 0) { return WBEM_E_OUT_OF_MEMORY; } if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; bStripTrailingParen = TRUE; } if (m_nCurrentToken == WQL_TOK_LOWER) { pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED; pFuncHolder.reset(CloneLPWSTR(L"LOWER")); if (pFuncHolder.get() == 0) { return WBEM_E_OUT_OF_MEMORY; } if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; bStripTrailingParen = TRUE; } if ( m_nCurrentToken == WQL_TOK_DATEPART || m_nCurrentToken == WQL_TOK_QUALIFIER || m_nCurrentToken == WQL_TOK_ISNULL ) { nRes = function_call(TRUE, pTE); if (nRes) return nRes; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_QSTRING || m_nCurrentToken == WQL_TOK_INT || m_nCurrentToken == WQL_TOK_HEX_CONST || m_nCurrentToken == WQL_TOK_REAL || m_nCurrentToken == WQL_TOK_CHAR || m_nCurrentToken == WQL_TOK_PROMPT || m_nCurrentToken == WQL_TOK_NULL ) { SWQLTypedConst *pTC = 0; nRes = typed_const(&pTC); if (nRes) return nRes; pTE->m_pConstValue = pTC; pTE->m_dwLeftFlags |= WQL_FLAG_CONST; // Intentional! pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder.release(); goto Exit; } // If here, must be a . // ============================= nRes = col_ref(&pColRef); // TBD if (nRes) return nRes; pTE->m_pIntrinsicFuncOnColRef = pFuncHolder.release(); // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the // qualified name and extract the table and col name. // ============================================================================ if (pColRef->m_aFields.Size() == 1) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0]; pTE->m_pColRef = CloneLPWSTR(pCol->m_pName); if (pTE->m_pColRef == 0 && pCol->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_dwLeftFlags |= WQL_FLAG_COLUMN; if (pCol->m_bArrayRef) { pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF; pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex; } } else if (pColRef->m_aFields.Size() == 2) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1]; SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0]; pTE->m_pColRef = CloneLPWSTR(pCol->m_pName); if (pTE->m_pColRef == 0 && pCol->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_pTableRef = CloneLPWSTR(pTbl->m_pName); if (pTE->m_pTableRef == 0 && pTbl->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_dwLeftFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN; if (pCol->m_bArrayRef) { pTE->m_dwLeftFlags |= WQL_FLAG_ARRAY_REF; pTE->m_dwLeftArrayIndex = pCol->m_dwArrayIndex; } } // If UPPER or LOWER was used, we have to strip a trailing // parenthesis. // ======================================================= Exit: delete pColRef; if (bStripTrailingParen) { if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; } return NO_ERROR; } //*************************************************************************** // // ::= ; // ::= ; // ::= ; // // ::= ; // Operator must be _IN or _NOT_IN // //*************************************************************************** int CWQLParser::typed_subexpr_rh(IN SWQLTypedExpr *pTE) { int nRes; BOOL bStripTrailingParen = FALSE; SWQLQualifiedName *pColRef = 0; wmilib::auto_buffer pFuncHolder; // Check for // ========================= if (m_nCurrentToken == WQL_TOK_UPPER) { pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED; pFuncHolder.reset(CloneLPWSTR(L"UPPER")); if (pFuncHolder.get() == 0) { return WBEM_E_OUT_OF_MEMORY; } if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; bStripTrailingParen = TRUE; } if (m_nCurrentToken == WQL_TOK_LOWER) { pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED; pFuncHolder.reset(CloneLPWSTR(L"LOWER")); if (pFuncHolder.get() == 0) { return WBEM_E_OUT_OF_MEMORY; } if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; bStripTrailingParen = TRUE; } if (m_nCurrentToken == WQL_TOK_DATEPART || m_nCurrentToken == WQL_TOK_QUALIFIER || m_nCurrentToken == WQL_TOK_ISNULL ) { nRes = function_call(FALSE, pTE); if (nRes) return nRes; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_QSTRING || m_nCurrentToken == WQL_TOK_INT || m_nCurrentToken == WQL_TOK_HEX_CONST || m_nCurrentToken == WQL_TOK_REAL || m_nCurrentToken == WQL_TOK_CHAR || m_nCurrentToken == WQL_TOK_PROMPT || m_nCurrentToken == WQL_TOK_NULL ) { // If we already have a typed constant, then the expression doesn't // really make sense, trying to do a relop around two constants, // so we'll fail the operation here if ( NULL != pTE->m_pConstValue ) { return WBEM_E_INVALID_SYNTAX; } SWQLTypedConst *pTC = 0; nRes = typed_const(&pTC); if (nRes) return nRes; pTE->m_pConstValue = pTC; pTE->m_dwRightFlags |= WQL_FLAG_CONST; pTE->m_pIntrinsicFuncOnConstValue = pFuncHolder.release(); // Check for BETWEEN operator, since we have // the other end of the range to parse. // ========================================= if (pTE->m_dwRelOperator == WQL_TOK_BETWEEN || pTE->m_dwRelOperator == WQL_TOK_NOT_BETWEEN) { if (m_nCurrentToken != WQL_TOK_AND) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLTypedConst *pTC2 = 0; nRes = typed_const(&pTC2); if (nRes) return nRes; pTE->m_pConstValue2 = pTC2; pTE->m_dwRightFlags |= WQL_FLAG_CONST_RANGE; } goto Exit; } if (m_nCurrentToken == WQL_TOK_OPEN_PAREN) { // IN clause. nRes = in_clause(pTE); if (nRes) return nRes; goto Exit; } // If here, must be a . // ============================= nRes = col_ref(&pColRef); if (nRes) return nRes; pTE->m_pIntrinsicFuncOnJoinColRef = pFuncHolder.release(); // Convert the col_ref to be part of the current SWQLTypedExpr. We analyze the // qualified name and extract the table and col name. // ============================================================================ if (pColRef->m_aFields.Size() == 1) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[0]; pTE->m_pJoinColRef = CloneLPWSTR(pCol->m_pName); if (pTE->m_pJoinColRef == 0 && pCol->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_dwRightFlags |= WQL_FLAG_COLUMN; if (pCol->m_bArrayRef) { pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF; pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex; } } else if (pColRef->m_aFields.Size() == 2) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pColRef->m_aFields[1]; SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pColRef->m_aFields[0]; pTE->m_pJoinColRef = CloneLPWSTR(pCol->m_pName); if (pTE->m_pJoinColRef == 0 && pCol->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_pJoinTableRef = CloneLPWSTR(pTbl->m_pName); if (pTE->m_pJoinTableRef == 0 && pTbl->m_pName != 0) { return WBEM_E_OUT_OF_MEMORY; } pTE->m_dwRightFlags |= WQL_FLAG_TABLE | WQL_FLAG_COLUMN; if (pCol->m_bArrayRef) { pTE->m_dwRightFlags |= WQL_FLAG_ARRAY_REF; pTE->m_dwRightArrayIndex = pCol->m_dwArrayIndex; } } Exit: delete pColRef; if (bStripTrailingParen) { if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; } return NO_ERROR; } //***************************************************************************************** // // ::= WQL_TOK_LE; // ::= WQL_TOK_LT; // ::= WQL_TOK_GE; // ::= WQL_TOK_GT; // ::= WQL_TOK_EQ; // ::= WQL_TOK_NE; // ::= WQL_TOK_LIKE; // ::= WQL_TOK_BETWEEN; // ::= WQL_TOK_IS ; // ::= WQL_TOK_ISA; // ::= WQL_TOK_IN; // ::= WQL_TOK_NOT ; // // Operator type is returned via // //***************************************************************************************** // done int CWQLParser::rel_op(OUT int & nReturnedOp) { int nRes; nReturnedOp = WQL_TOK_ERROR; switch (m_nCurrentToken) { case WQL_TOK_LE: nReturnedOp = WQL_TOK_LE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_LT: nReturnedOp = WQL_TOK_LT; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_GE: nReturnedOp = WQL_TOK_GE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_GT: nReturnedOp = WQL_TOK_GT; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_EQ: nReturnedOp = WQL_TOK_EQ; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_NE: nReturnedOp = WQL_TOK_NE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_LIKE: nReturnedOp = WQL_TOK_LIKE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_BETWEEN: nReturnedOp = WQL_TOK_BETWEEN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_IS: if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = is_continuator(nReturnedOp); return nRes; case WQL_TOK_ISA: nReturnedOp = WQL_TOK_ISA; if (!Next()) return WBEM_E_INVALID_SYNTAX; m_uFeatures |= WMIQ_RPNF_ISA_USED; return NO_ERROR; case WQL_TOK_IN: nReturnedOp = WQL_TOK_IN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_NOT: if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = not_continuator(nReturnedOp); return nRes; } return WBEM_E_INVALID_SYNTAX; } //***************************************************************************************** // // ::= WQL_TOK_QSTRING; // ::= WQL_TOK_HEX_CONST; // ::= WQL_TOK_INT; // ::= WQL_TOK_REAL; // ::= WQL_TOK_PROMPT; // ::= WQL_TOK_NULL; // //***************************************************************************************** // done int CWQLParser::typed_const(OUT SWQLTypedConst **pRetVal) { SWQLTypedConst *pNew = new SWQLTypedConst; if (!pNew) return WBEM_E_OUT_OF_MEMORY; *pRetVal = pNew; if (m_nCurrentToken == WQL_TOK_QSTRING || m_nCurrentToken == WQL_TOK_PROMPT) { pNew->m_dwType = VT_LPWSTR; pNew->m_bPrompt = (m_nCurrentToken == WQL_TOK_PROMPT); pNew->m_Value.m_pString = CloneLPWSTR(m_pTokenText); if (NULL == pNew->m_Value.m_pString) return WBEM_E_OUT_OF_MEMORY; if (!Next()) goto Error; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_INT || m_nCurrentToken == WQL_TOK_HEX_CONST) { unsigned __int64 val = 0; BOOL bSigned = FALSE; BOOL b64Bit = FALSE; if (!GetIntToken(&bSigned, &b64Bit, &val)) return WBEM_E_INVALID_SYNTAX; if (!b64Bit) { if (bSigned) pNew->m_dwType = VT_I4; else pNew->m_dwType = VT_UI4; pNew->m_Value.m_lValue = (LONG) val; } else // 64 bit moved into string { if (bSigned) pNew->m_dwType = VT_I8; else pNew->m_dwType = VT_UI8; pNew->m_Value.m_i64Value = val; } if (!Next()) goto Error; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_REAL) { pNew->m_dwType = VT_R8; wchar_t *pStopper = 0; BSTR bstrValue = SysAllocString(m_pTokenText); if (!bstrValue) return WBEM_E_OUT_OF_MEMORY; _variant_t varValue; V_VT(&varValue) = VT_BSTR; V_BSTR(&varValue) = bstrValue; if (FAILED(VariantChangeTypeEx(&varValue,&varValue, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), VARIANT_NOUSEROVERRIDE, VT_R8))) return WBEM_E_INVALID_SYNTAX; double d = varValue; pNew->m_Value.m_dblValue = d; if (!Next()) goto Error; return NO_ERROR; } if (m_nCurrentToken == WQL_TOK_NULL) { pNew->m_dwType = VT_NULL; if (!Next()) goto Error; return NO_ERROR; } // Unrecognized constant. // ====================== Error: *pRetVal = 0; delete pNew; return WBEM_E_INVALID_SYNTAX; } //***************************************************************************************** // // ::= // WQL_TOK_OPEN_PAREN // WQL_TOK_IDENT // yy, mm,dd, hh, mm, ss, year, month, etc. // WQL_TOK_COMMA // // WQL_TOK_CLOSE_PAREN // //***************************************************************************************** static WqlKeyword DateKeyWords[] = // Keep this alphabetized for binary search { L"DAY", WQL_TOK_DAY, L"DD", WQL_TOK_DAY, L"HH", WQL_TOK_HOUR, L"HOUR", WQL_TOK_HOUR, L"MI", WQL_TOK_MINUTE, L"MILLISECOND", WQL_TOK_MILLISECOND, L"MINUTE", WQL_TOK_MINUTE, L"MONTH", WQL_TOK_MONTH, L"MM", WQL_TOK_MONTH, L"MS", WQL_TOK_MILLISECOND, L"YEAR", WQL_TOK_YEAR, L"YY", WQL_TOK_YEAR }; const int NumDateKeywords = sizeof(DateKeyWords)/sizeof(WqlKeyword); int CWQLParser::datepart_call(OUT SWQLNode_Datepart **pRetDP) { DWORD dwDatepartTok = 0; int nRes; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_IDENT) return WBEM_E_INVALID_SYNTAX; // Ident must be one of the DATEPART identifiers. // ============================================== BOOL bFound = FALSE; int l = 0, u = NumDateKeywords - 1; while (l <= u) { int m = (l + u) / 2; if (wbem_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) < 0) u = m - 1; else if (wbem_wcsicmp(m_pTokenText, DateKeyWords[m].m_pKeyword) > 0) l = m + 1; else // Match { bFound = TRUE; dwDatepartTok = DateKeyWords[m].m_nTokenCode; break; } } if (!bFound) return WBEM_E_INVALID_SYNTAX; // If here, we know the date part. // =============================== if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_COMMA) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; SWQLQualifiedName *pQN = 0; nRes = col_ref(&pQN); if (nRes) return nRes; SWQLColRef *pCR = 0; nRes = QNameToSWQLColRef(pQN, &pCR); if (nRes) { delete pQN; return WBEM_E_INVALID_PARAMETER; } std::auto_ptr _1(pCR); if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // Return the new node. // ==================== SWQLNode_Datepart *pDP = new SWQLNode_Datepart; if (!pDP) return WBEM_E_OUT_OF_MEMORY; _1.release(); pDP->m_nDatepart = dwDatepartTok; pDP->m_pColRef = pCR; *pRetDP = pDP; return NO_ERROR; } //***************************************************************************************** // // ::= WQL_TOK_UPPER ; // ::= WQL_TOK_LOWER ; // ::= WQL_TOK_DATEPART ; // ::= WQL_TOK_QUALIFIER ; // ::= WQL_TOK_ISNULL ; // //***************************************************************************************** int CWQLParser::function_call( IN BOOL bLeftSide, IN SWQLTypedExpr *pTE ) { int nRes; SWQLNode_Datepart *pDP = 0; switch (m_nCurrentToken) { case WQL_TOK_DATEPART: { if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = datepart_call(&pDP); if (nRes) return nRes; if (bLeftSide) { pTE->m_dwLeftFlags |= WQL_FLAG_FUNCTIONIZED; pTE->m_pLeftFunction = pDP; pTE->m_pIntrinsicFuncOnColRef = CloneLPWSTR(L"DATEPART"); if (!pTE->m_pIntrinsicFuncOnColRef) return WBEM_E_OUT_OF_MEMORY; } else { pTE->m_dwRightFlags |= WQL_FLAG_FUNCTIONIZED; pTE->m_pRightFunction = pDP; pTE->m_pIntrinsicFuncOnJoinColRef = CloneLPWSTR(L"DATEPART"); if (!pTE->m_pIntrinsicFuncOnJoinColRef) return WBEM_E_OUT_OF_MEMORY; } return NO_ERROR; } case WQL_TOK_QUALIFIER: trace(("EMIT: QUALIFIER\n")); if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = function_call_parms(); return nRes; case WQL_TOK_ISNULL: trace(("EMIT: ISNULL\n")); if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = function_call_parms(); return nRes; } return WBEM_E_INVALID_SYNTAX; } //***************************************************************************************** // // ::= // WQL_TOK_OPEN_PAREN // // WQL_TOK_CLOSE_PAREN // //***************************************************************************************** int CWQLParser::function_call_parms() { if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; int nRes = func_args(); if (nRes) return nRes; if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; } //***************************************************************************************** // // ::= ; // ::= WQL_TOK_COMMA ; // ::= <>; // //***************************************************************************************** int CWQLParser::func_args() { int nRes; while (1) { nRes = func_arg(); if (nRes) return nRes; if (m_nCurrentToken != WQL_TOK_COMMA) break; if (!Next()) return WBEM_E_INVALID_SYNTAX; } return NO_ERROR; } //***************************************************************************************** // // ::= ; // ::= ; // //***************************************************************************************** int CWQLParser::func_arg() { SWQLQualifiedName *pColRef = 0; int nRes; if (m_nCurrentToken == WQL_TOK_IDENT) { nRes = col_ref(&pColRef); return nRes; } SWQLTypedConst *pTC = 0; return typed_const(&pTC); } // Tokens which can follow IS // =========================== //***************************************************************************************** // // ::= WQL_TOK_LIKE; // ::= WQL_TOK_BEFORE; // ::= WQL_TOK_AFTER; // ::= WQL_TOK_BETWEEN; // ::= WQL_TOK_NULL; // ::= WQL_TOK_NOT ; // ::= WQL_TOK_IN; // ::= WQL_TOK_A; // //***************************************************************************************** // done int CWQLParser::is_continuator(int & nReturnedOp) { int nRes; nReturnedOp = WQL_TOK_ERROR; switch (m_nCurrentToken) { case WQL_TOK_LIKE: nReturnedOp = WQL_TOK_LIKE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_BEFORE: nReturnedOp = WQL_TOK_BEFORE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_AFTER: nReturnedOp = WQL_TOK_AFTER; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_BETWEEN: nReturnedOp = WQL_TOK_BETWEEN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_NULL: nReturnedOp = WQL_TOK_ISNULL; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_NOT: if (!Next()) return WBEM_E_INVALID_SYNTAX; nRes = not_continuator(nReturnedOp); return nRes; case WQL_TOK_IN: nReturnedOp = WQL_TOK_IN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_A: nReturnedOp = WQL_TOK_ISA; if (!Next()) return WBEM_E_INVALID_SYNTAX; m_uFeatures |= WMIQ_RPNF_ISA_USED; return NO_ERROR; } return WBEM_E_INVALID_SYNTAX; } //***************************************************************************************** // // ::= WQL_TOK_LIKE; // ::= WQL_TOK_BEFORE; // ::= WQL_TOK_AFTER; // ::= WQL_TOK_BETWEEN; // ::= WQL_TOK_NULL; // ::= WQL_TOK_IN; // // Returns WQL_TOK_NOT_LIKE, WQL_TOK_NOT_BEFORE, WQL_TOK_NOT_AFTER, WQL_TOK_NOT_BETWEEN // WQL_TOK_NOT_NULL, WQL_TOK_NOT_IN // //***************************************************************************************** // done int CWQLParser::not_continuator(int & nReturnedOp) { nReturnedOp = WQL_TOK_ERROR; switch (m_nCurrentToken) { case WQL_TOK_LIKE: nReturnedOp = WQL_TOK_NOT_LIKE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_BEFORE: nReturnedOp = WQL_TOK_NOT_BEFORE; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_AFTER: nReturnedOp = WQL_TOK_NOT_AFTER; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_BETWEEN: nReturnedOp = WQL_TOK_NOT_BETWEEN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_NULL: nReturnedOp = WQL_TOK_NOT_NULL; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_IN: nReturnedOp = WQL_TOK_NOT_IN; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; case WQL_TOK_A: nReturnedOp = WQL_TOK_NOT_A; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; } return WBEM_E_INVALID_SYNTAX; } //***************************************************************************************** // // ::= WQL_TOK_OPEN_PAREN WQL_TOK_CLOSE_PAREN; // ::= ; // ::= ; // ::= ; // //***************************************************************************************** int CWQLParser::in_clause(IN SWQLTypedExpr *pTE) { int nRes; if (m_nCurrentToken != WQL_TOK_OPEN_PAREN) return WBEM_E_INVALID_SYNTAX; //int nStPos = m_pLexer->GetCurPos(); if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken == WQL_TOK_SELECT) { SWQLNode_Select *pSel = 0; nRes = subselect_stmt(&pSel); if (nRes) return nRes; // pSel->m_nStPos = nStPos; // pSel->m_nEndPos = m_pLexer->GetCurPos() - 1; // Translate the IN / NOT IN operator to the specific // case of subselects. // ================================================== if (pTE->m_dwRelOperator == WQL_TOK_IN) pTE->m_dwRelOperator = WQL_TOK_IN_SUBSELECT; else if (pTE->m_dwRelOperator == WQL_TOK_NOT_IN) pTE->m_dwRelOperator = WQL_TOK_NOT_IN_SUBSELECT; pTE->m_pSubSelect = pSel; } else if (m_nCurrentToken == WQL_TOK_IDENT) { nRes = qualified_name(0); if (nRes) return nRes; } // If here, we must have a const-list. // =================================== else { SWQLConstList *pCL = 0; nRes = const_list(&pCL); if (nRes) return nRes; pTE->m_pConstList = pCL; } if (m_nCurrentToken != WQL_TOK_CLOSE_PAREN) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; return NO_ERROR; } //***************************************************************************************** // // ::= ; // ::= WQL_TOK_COMMA ; // ::= <>; // //***************************************************************************************** // done int CWQLParser::const_list(SWQLConstList **pRetVal) { int nRes; SWQLConstList *pCL = new SWQLConstList; if (!pCL) return WBEM_E_OUT_OF_MEMORY; *pRetVal = 0; while (1) { if (m_nCurrentToken == WQL_TOK_QSTRING || m_nCurrentToken == WQL_TOK_INT || m_nCurrentToken == WQL_TOK_HEX_CONST || m_nCurrentToken == WQL_TOK_REAL || m_nCurrentToken == WQL_TOK_CHAR || m_nCurrentToken == WQL_TOK_PROMPT || m_nCurrentToken == WQL_TOK_NULL ) { SWQLTypedConst *pTC = 0; nRes = typed_const(&pTC); if (nRes) { delete pCL; return nRes; } pCL->Add(pTC); } if (m_nCurrentToken != WQL_TOK_COMMA) break; // If here, a comma, indicating a following constant. // ================================================== if (!Next()) { delete pCL; return WBEM_E_INVALID_SYNTAX; } } *pRetVal = pCL; return NO_ERROR; } //***************************************************************************************** // // QUALIFIED_NAME // // This recognizes a name separated by dots, and recognizes any array references which // may occur with those names: // a // a.b // a[n].b[n] // a.b.c.d // a.b[2].c.d.e[3].f // ...etc. // // ::= WQL_TOK_IDENT ; // ::= WQL_TOK_DOT WQL_TOK_IDENT ; // // ::= // WQL_TOK_OPEN_BRACKET // WQL_TOK_INT // WQL_TOK_CLOSEBRACKET // // ; // // ::= <>; // Dummy to enforce array semantics // // ::= <>; // //***************************************************************************************** // done int CWQLParser::qualified_name(OUT SWQLQualifiedName **pRetVal) { if (pRetVal == 0) return WBEM_E_INVALID_PARAMETER; *pRetVal = 0; if (m_nCurrentToken != WQL_TOK_IDENT && m_nCurrentToken != WQL_TOK_COUNT) return WBEM_E_INVALID_SYNTAX; SWQLQualifiedName QN; SWQLQualifiedNameField *pQNF; pQNF = new SWQLQualifiedNameField; if (!pQNF) return WBEM_E_OUT_OF_MEMORY; pQNF->m_pName = CloneLPWSTR(m_pTokenText); if (pQNF->m_pName == 0 || QN.Add(pQNF)) { delete pQNF; return WBEM_E_OUT_OF_MEMORY; } if (wbem_wcsicmp(m_pTokenText, L"__CLASS") == 0) m_uFeatures |= WMIQ_RPNF_SYSPROP_CLASS_USED; if (!Next()) return WBEM_E_INVALID_SYNTAX; while (1) { if (m_nCurrentToken == WQL_TOK_DOT) { // Move past dot // ============== if (!Next()) return WBEM_E_INVALID_SYNTAX; if (!(m_nCurrentToken == WQL_TOK_IDENT || m_nCurrentToken == WQL_TOK_ASTERISK)) return WBEM_E_INVALID_SYNTAX; m_uFeatures |= WMIQ_RPNF_QUALIFIED_NAMES_USED; pQNF = new SWQLQualifiedNameField; if (!pQNF) return WBEM_E_OUT_OF_MEMORY; pQNF->m_pName = CloneLPWSTR(m_pTokenText); if (!pQNF->m_pName) return WBEM_E_OUT_OF_MEMORY; QN.Add(pQNF); if (wbem_wcsicmp(m_pTokenText, L"__CLASS") == 0) m_uFeatures |= WMIQ_RPNF_SYSPROP_CLASS_USED; if (!Next()) return WBEM_E_INVALID_SYNTAX; continue; } if (m_nCurrentToken == WQL_TOK_OPEN_BRACKET) { if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_INT) return WBEM_E_INVALID_SYNTAX; unsigned __int64 ArrayIndex = 0; BOOL bRes, b64Bit, bSigned; m_uFeatures |= WMIQ_RPNF_ARRAY_ACCESS_USED; bRes = GetIntToken(&bSigned, &b64Bit, &ArrayIndex); if (!bRes || b64Bit || bSigned) return WBEM_E_INVALID_SYNTAX; pQNF->m_bArrayRef = TRUE; pQNF->m_dwArrayIndex = (DWORD) ArrayIndex; if (!Next()) return WBEM_E_INVALID_SYNTAX; if (m_nCurrentToken != WQL_TOK_CLOSE_BRACKET) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; continue; } break; } // Copy the object and return it. We worked with the copy QN // throughout to avoid complicated cleanup problems on errors, since // we take advantage of the auto destructor of in cases // above where we return errors. // ================================================================== SWQLQualifiedName *pRetCopy = new SWQLQualifiedName(QN); if (!pRetCopy) return WBEM_E_OUT_OF_MEMORY; *pRetVal = pRetCopy; return NO_ERROR; } //***************************************************************************************** // // col_ref // //***************************************************************************************** // done int CWQLParser::col_ref(OUT SWQLQualifiedName **pRetVal) { return qualified_name(pRetVal); } //***************************************************************************************** // // ::= ; // ::= WQL_TOK_COMMA ; // ::= <>; // //***************************************************************************************** // int CWQLParser::col_list(OUT SWQLNode_ColumnList **pRetColList) { *pRetColList = 0; SWQLNode_ColumnList *pColList = new SWQLNode_ColumnList; if (!pColList) return WBEM_E_OUT_OF_MEMORY; while (1) { SWQLQualifiedName *pColRef = 0; int nRes = col_ref(&pColRef); if (nRes) { delete pColList; return nRes; } // If here, we have a legit column to add to the node. // =================================================== SWQLColRef *pCRef = 0; QNameToSWQLColRef(pColRef, &pCRef); pColList->m_aColumnRefs.Add(pCRef); // Check for sortation indication // ============================== if (m_nCurrentToken == WQL_TOK_ASC) { pCRef->m_dwFlags |= WQL_FLAG_SORT_ASC; if (!Next()) { delete pColList; return WBEM_E_INVALID_SYNTAX; } } else if (m_nCurrentToken == WQL_TOK_DESC) { pCRef->m_dwFlags |= WQL_FLAG_SORT_DESC; if (!Next()) { delete pColList; return WBEM_E_INVALID_SYNTAX; } } // Check for a continuation. // ========================= if (m_nCurrentToken != WQL_TOK_COMMA) break; if (!Next()) { delete pColList; return WBEM_E_INVALID_SYNTAX; } } *pRetColList = pColList; return NO_ERROR; } //***************************************************************************************** // // ::= // WQL_TOK_SELECT // // // Must not be an asterisk // // // //***************************************************************************************** int CWQLParser::subselect_stmt(OUT SWQLNode_Select **pRetSel) { int nSelType; int nRes = 0; SWQLNode_FromClause *pFrom = 0; SWQLNode_Select *pSel = 0; SWQLNode_TableRefs *pTblRefs = 0; SWQLNode_WhereClause *pWhere = 0; *pRetSel = 0; // Verify that we are in a subselect. // ================================== if (m_nCurrentToken != WQL_TOK_SELECT) return WBEM_E_INVALID_SYNTAX; if (!Next()) return WBEM_E_INVALID_SYNTAX; // This affects some of the productions, since they behave differently // in subselects than in primary selects. // =================================================================== m_nParseContext = Ctx_Subselect; // If here, we are definitely in a subselect, so // allocate a new node. // ============================================== pSel = new SWQLNode_Select; if (!pSel) return WBEM_E_OUT_OF_MEMORY; pTblRefs = new SWQLNode_TableRefs; if (!pTblRefs) { delete pSel; return WBEM_E_OUT_OF_MEMORY; } pSel->m_pLeft = pTblRefs; // Find the select type. // ===================== nRes = select_type(nSelType); if (nRes) return nRes; pTblRefs->m_nSelectType = nSelType; // ALL, DISTINCT // Get the column list. In this case // it must be a single column and not // an asterisk. // ==================================== nRes = col_ref_list(pTblRefs); if (nRes) return nRes; // Get the FROM clause and patch it in. // ===================================== nRes = from_clause(&pFrom); if (nRes) return nRes; pTblRefs->m_pRight = pFrom; // Get the WHERE clause. // ===================== nRes = where_clause(&pWhere); if (nRes) return nRes; pSel->m_pRight = pWhere; *pRetSel = pSel; m_nParseContext = Ctx_Default; // No longer in a subselect return NO_ERROR; } ///////////////////////////////////////////////////////////////////////////// // // Containers // ///////////////////////////////////////////////////////////////////////////// //*************************************************************************** // // SWQLTypedConst constructor // //*************************************************************************** // done SWQLTypedConst::SWQLTypedConst() { m_dwType = VT_NULL; m_bPrompt = false; memset(&m_Value, 0, sizeof(m_Value)); } //*************************************************************************** // // SWQLTypedConst::operator = // //*************************************************************************** // done SWQLTypedConst & SWQLTypedConst::operator = (SWQLTypedConst &Src) { Empty(); if (Src.m_dwType == VT_LPWSTR) { m_Value.m_pString = CloneLPWSTR(Src.m_Value.m_pString); if (CloneFailed(m_Value.m_pString,Src.m_Value.m_pString)) throw CX_MemoryException(); } else { m_Value = Src.m_Value; } m_dwType = Src.m_dwType; m_bPrompt = Src.m_bPrompt; return *this; } //*************************************************************************** // // SWQLTypedConst::Empty() // //*************************************************************************** // done void SWQLTypedConst::Empty() { if (m_dwType == VT_LPWSTR) delete [] m_Value.m_pString; m_bPrompt = false; } //*************************************************************************** // // SWQLConstList::operator = // //*************************************************************************** // done SWQLConstList & SWQLConstList::operator = (SWQLConstList & Src) { Empty(); for (int i = 0; i < Src.m_aValues.Size(); i++) { SWQLTypedConst *pC = (SWQLTypedConst *) Src.m_aValues[i]; m_aValues.Add(new SWQLTypedConst(*pC)); } return *this; } //*************************************************************************** // // SWQLConstList::Empty // //*************************************************************************** // done void SWQLConstList::Empty() { for (int i = 0; i < m_aValues.Size(); i++) delete (SWQLTypedConst *) m_aValues[i]; m_aValues.Empty(); } //*************************************************************************** // // SWQLQualifiedName::operator = // //*************************************************************************** // done SWQLQualifiedName & SWQLQualifiedName::operator = (SWQLQualifiedName &Src) { Empty(); for (int i = 0; i < Src.m_aFields.Size(); i++) { SWQLQualifiedNameField *pQN = new SWQLQualifiedNameField; if (!pQN) throw CX_MemoryException(); *pQN = *(SWQLQualifiedNameField *) Src.m_aFields[i]; m_aFields.Add(pQN); } return *this; } //*************************************************************************** // // SWQLQualifiedNameField::operator = // //*************************************************************************** // done SWQLQualifiedNameField & SWQLQualifiedNameField::operator =(SWQLQualifiedNameField &Src) { Empty(); m_bArrayRef = Src.m_bArrayRef; m_pName = CloneLPWSTR(Src.m_pName); if (CloneFailed(m_pName,Src.m_pName)) throw CX_MemoryException(); m_dwArrayIndex = Src.m_dwArrayIndex; return *this; } //*************************************************************************** // // SWQLNode_ColumnList destructor // //*************************************************************************** // tbd //*************************************************************************** // // QNameToSWQLColRef // // Translates a qualified name to a SWQLColRef structure and embeds // the q-name into the struct (since that is a field). // //*************************************************************************** int CWQLParser::QNameToSWQLColRef( IN SWQLQualifiedName *pQName, OUT SWQLColRef **pRetVal ) { *pRetVal = 0; if (pQName == 0 || pRetVal == 0) return WBEM_E_INVALID_PARAMETER; SWQLColRef *pCR = new SWQLColRef; if (!pCR) return WBEM_E_OUT_OF_MEMORY; // Algorithm: With a two name sequence, assume that the first name is // the table and that the second name is the column. If multiple // names occur, then we set the SWQLColRef type to WQL_FLAG_COMPLEX // and just take the last name for the column. // ================================================================== if (pQName->m_aFields.Size() == 2) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[1]; SWQLQualifiedNameField *pTbl = (SWQLQualifiedNameField *) pQName->m_aFields[0]; pCR->m_pColName = CloneLPWSTR(pCol->m_pName); pCR->m_pTableRef = CloneLPWSTR(pTbl->m_pName); if (!pCR->m_pColName || !pCR->m_pTableRef) return WBEM_E_OUT_OF_MEMORY; pCR->m_dwFlags = WQL_FLAG_TABLE | WQL_FLAG_COLUMN; if (wbem_wcsicmp(L"*", pCol->m_pName) == 0) pCR->m_dwFlags |= WQL_FLAG_ASTERISK; if (pCol->m_bArrayRef) { pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF; pCR->m_dwArrayIndex = pCol->m_dwArrayIndex; } } else if (pQName->m_aFields.Size() == 1) { SWQLQualifiedNameField *pCol = (SWQLQualifiedNameField *) pQName->m_aFields[0]; pCR->m_pColName = CloneLPWSTR(pCol->m_pName); if (!pCR->m_pColName) return WBEM_E_OUT_OF_MEMORY; pCR->m_dwFlags |= WQL_FLAG_COLUMN; if (wbem_wcsicmp(L"*", pCol->m_pName) == 0) pCR->m_dwFlags |= WQL_FLAG_ASTERISK; if (pCol->m_bArrayRef) { pCR->m_dwFlags |= WQL_FLAG_ARRAY_REF; pCR->m_dwArrayIndex = pCol->m_dwArrayIndex; } } // Complex case. // ============= else { pCR->m_dwFlags = WQL_FLAG_COMPLEX_NAME; } // Copy the qualified name. // ======================== pCR->m_pQName = pQName; *pRetVal = pCR; return NO_ERROR;; } //*************************************************************************** // // SWQLNode_ColumnList::DebugDump // //*************************************************************************** void SWQLNode_ColumnList::DebugDump() { printf("---SWQLNode_ColumnList---\n"); for (int i = 0; i < m_aColumnRefs.Size(); i++) { SWQLColRef *pCR = (SWQLColRef *) m_aColumnRefs[i]; if (pCR) pCR->DebugDump(); } printf("---End SWQLNode_ColumnList---\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_TableRefs::DebugDump() { printf("********** BEGIN SWQLNode_TableRefs *************\n"); printf("Select type = "); if (m_nSelectType & WQL_FLAG_COUNT) printf("WQL_FLAG_COUNT "); if (m_nSelectType & WQL_FLAG_ALL) printf("WQL_FLAG_ALL "); if (m_nSelectType & WQL_FLAG_DISTINCT) printf("WQL_FLAG_DISTINCT "); printf("\n"); if (m_pLeft) m_pLeft->DebugDump(); if (m_pRight) m_pRight->DebugDump(); printf("********** END SWQLNode_TableRefs *************\n\n\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_FromClause::DebugDump() { printf("---SWQLNode_FromClause---\n"); if (m_pLeft == 0) return; m_pLeft->DebugDump(); printf("---End SWQLNode_FromClause---\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_Select::DebugDump() { printf("********** BEGIN SWQLNode_Select *************\n"); if (m_pLeft) m_pLeft->DebugDump(); if (m_pRight) m_pRight->DebugDump(); printf("********** END SWQLNode_Select *************\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_WmiScopedSelect::DebugDump() { printf("********** BEGIN SWQLNode_WmiScopedSelect *************\n"); printf("Scope = %S\n", m_pszScope); for (int i = 0; i < m_aTables.Size(); i++) { printf("Selected table = %S\n", LPWSTR(m_aTables[i])); } printf("********** END SWQLNode_WmiScopedSelect *************\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_TableRef::DebugDump() { printf(" ---TableRef---\n"); printf(" TableName = %S\n", m_pTableName); printf(" Alias = %S\n", m_pAlias); printf(" ---End TableRef---\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_Join::DebugDump() { printf("---SWQLNode_Join---\n"); printf("Join type = "); switch (m_dwJoinType) { case WQL_FLAG_INNER_JOIN : printf("WQL_FLAG_INNER_JOIN "); break; case WQL_FLAG_FULL_OUTER_JOIN : printf("WQL_FLAG_FULL_OUTER_JOIN "); break; case WQL_FLAG_LEFT_OUTER_JOIN : printf("WQL_FLAG_LEFT_OUTER_JOIN "); break; case WQL_FLAG_RIGHT_OUTER_JOIN : printf("WQL_FLAG_RIGHT_OUTER_JOIN "); break; default: printf(" "); } if (m_dwFlags & WQL_FLAG_FIRSTROW) printf(" (FIRSTROW)"); printf("\n"); if (m_pRight) m_pRight->DebugDump(); if (m_pLeft) m_pLeft->DebugDump(); printf("---End SWQLNode_Join---\n"); } //*************************************************************************** // // SWQLNode_Sql89Join::Empty // //*************************************************************************** void SWQLNode_Sql89Join::Empty() { for (int i = 0; i < m_aValues.Size(); i++) delete (SWQLNode_TableRef *) m_aValues[i]; m_aValues.Empty(); } //*************************************************************************** // // SWQLNode_Sql89Join::DebugDump // //*************************************************************************** void SWQLNode_Sql89Join::DebugDump() { printf("\n========== SQL 89 JOIN =================================\n"); for (int i = 0; i < m_aValues.Size(); i++) { SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) m_aValues[i]; if (pTR) pTR->DebugDump(); } printf("\n========== END SQL 89 JOIN =============================\n"); } //*************************************************************************** // // SWQLNode_WhereClause::DebugDump // //*************************************************************************** void SWQLNode_WhereClause::DebugDump() { printf("\n========== WHERE CLAUSE ================================\n"); if (m_pLeft) m_pLeft->DebugDump(); else printf(" \n"); if (m_pRight) m_pRight->DebugDump(); printf("============= END WHERE CLAUSE ============================\n"); } //*************************************************************************** // // SWQLNode_WhereOptions::DebugDump // //*************************************************************************** void SWQLNode_WhereOptions::DebugDump() { printf("---- Where Options ----\n"); if (m_pLeft) m_pLeft->DebugDump(); if (m_pRight) m_pRight->DebugDump(); printf("---- End Where Options ----\n"); } //*************************************************************************** // // SWQLNode_Having::DebugDump // //*************************************************************************** void SWQLNode_Having::DebugDump() { printf("---- Having ----\n"); if (m_pLeft) m_pLeft->DebugDump(); if (m_pRight) m_pRight->DebugDump(); printf("---- End Having ----\n"); } //*************************************************************************** // // SWQLNode_GroupBy::DebugDump // //*************************************************************************** void SWQLNode_GroupBy::DebugDump() { printf("---- Group By ----\n"); if (m_pLeft) m_pLeft->DebugDump(); if (m_pRight) m_pRight->DebugDump(); printf("---- End Group By ----\n"); } //*************************************************************************** // // SWQLNode_RelExpr::DebugDump // //*************************************************************************** void SWQLNode_RelExpr::DebugDump() { if (m_pRight) m_pRight->DebugDump(); printf(" --- SWQLNode_RelExpr ---\n"); switch (m_dwExprType) { case WQL_TOK_OR: printf(" \n"); break; case WQL_TOK_AND: printf(" \n"); break; case WQL_TOK_NOT: printf(" \n"); break; case WQL_TOK_TYPED_EXPR: printf(" \n"); m_pTypedExpr->DebugDump(); break; default: printf(" \n"); } printf(" --- END SWQLNode_RelExpr ---\n\n"); if (m_pLeft) m_pLeft->DebugDump(); } //*************************************************************************** // //*************************************************************************** static LPWSTR OpToStr(DWORD dwOp) { LPWSTR pRet = 0; switch (dwOp) { case WQL_TOK_EQ: pRet = L" '=' "; break; case WQL_TOK_NE: pRet = L" '!=' "; break; case WQL_TOK_GT: pRet = L" '>' "; break; case WQL_TOK_LT: pRet = L" '<' "; break; case WQL_TOK_GE: pRet = L" '>=' "; break; case WQL_TOK_LE: pRet = L" '<=' "; break; case WQL_TOK_IN_CONST_LIST : pRet = L" IN "; break; case WQL_TOK_NOT_IN_CONST_LIST : pRet = L" NOT IN "; break; case WQL_TOK_IN_SUBSELECT : pRet = L" IN "; break; case WQL_TOK_NOT_IN_SUBSELECT : pRet = L" NOT IN "; break; case WQL_TOK_ISNULL: pRet = L""; break; case WQL_TOK_NOT_NULL: pRet = L""; break; case WQL_TOK_BETWEEN: pRet = L""; break; case WQL_TOK_NOT_BETWEEN: pRet = L""; break; default: pRet = L" "; break; } return pRet; } //*************************************************************************** // //*************************************************************************** void SWQLTypedExpr::DebugDump() { printf(" === BEGIN SWQLTypedExpr ===\n"); printf(" m_pTableRef = %S\n", m_pTableRef); printf(" m_pColRef = %S\n", m_pColRef); printf(" m_pJoinTableRef = %S\n", m_pJoinTableRef); printf(" m_pJoinColRef = %S\n", m_pJoinColRef); printf(" m_dwRelOperator = %S\n", OpToStr(m_dwRelOperator)); // printf(" m_pSubSelect = 0x%X\n", m_pSubSelect); printf(" m_dwLeftArrayIndex = %d\n", m_dwLeftArrayIndex); printf(" m_dwRightArrayIndex = %d\n", m_dwRightArrayIndex); printf(" m_pConstValue = "); if (m_pConstValue) m_pConstValue->DebugDump(); else printf(" NULL ptr \n"); printf(" m_pConstValue2 = "); if (m_pConstValue2) m_pConstValue2->DebugDump(); else printf(" NULL ptr \n"); printf(" m_dwLeftFlags = (0x%X)", m_dwLeftFlags); if (m_dwLeftFlags & WQL_FLAG_COLUMN) printf(" WQL_FLAG_COLUMN"); if (m_dwLeftFlags & WQL_FLAG_TABLE) printf(" WQL_FLAG_TABLE"); if (m_dwLeftFlags & WQL_FLAG_CONST) printf(" WQL_FLAG_CONST"); if (m_dwLeftFlags & WQL_FLAG_COMPLEX_NAME) printf(" WQL_FLAG_COMPLEX_NAME"); if (m_dwLeftFlags & WQL_FLAG_SORT_ASC) printf(" WQL_FLAG_SORT_ASC"); if (m_dwLeftFlags & WQL_FLAG_SORT_DESC) printf(" WQL_FLAG_SORT_DESC"); if (m_dwLeftFlags & WQL_FLAG_FUNCTIONIZED) printf(" WQL_FLAG_FUNCTIONIZED (Function=%S)", m_pIntrinsicFuncOnColRef); if (m_dwLeftFlags & WQL_FLAG_ARRAY_REF) printf(" WQL_FLAG_ARRAY_REF"); printf("\n"); printf(" m_dwRightFlags = (0x%X)", m_dwRightFlags); if (m_dwRightFlags & WQL_FLAG_COLUMN) printf(" WQL_FLAG_COLUMN"); if (m_dwRightFlags & WQL_FLAG_TABLE) printf(" WQL_FLAG_TABLE"); if (m_dwRightFlags & WQL_FLAG_CONST) printf(" WQL_FLAG_CONST"); if (m_dwRightFlags & WQL_FLAG_COMPLEX_NAME) printf(" WQL_FLAG_COMPLEX_NAME"); if (m_dwLeftFlags & WQL_FLAG_SORT_ASC) printf(" WQL_FLAG_SORT_ASC"); if (m_dwLeftFlags & WQL_FLAG_SORT_DESC) printf(" WQL_FLAG_SORT_DESC"); if (m_dwRightFlags & WQL_FLAG_FUNCTIONIZED) { printf(" WQL_FLAG_FUNCTIONIZED"); if (m_pIntrinsicFuncOnJoinColRef) printf("(On join col: Function=%S)", m_pIntrinsicFuncOnJoinColRef); if (m_pIntrinsicFuncOnConstValue) printf("(On const: Function=%S)", m_pIntrinsicFuncOnConstValue); } if (m_dwRightFlags & WQL_FLAG_ARRAY_REF) printf(" WQL_FLAG_ARRAY_REF"); if (m_dwRightFlags & WQL_FLAG_CONST_RANGE) printf(" WQL_FLAG_CONST_RANGE"); printf("\n"); if (m_pLeftFunction) { printf("m_pLeftFunction: \n"); m_pLeftFunction->DebugDump(); } if (m_pRightFunction) { printf("m_pRightFunction: \n"); m_pRightFunction->DebugDump(); } if (m_pConstList) { printf(" ---Const List---\n"); for (int i = 0; i < m_pConstList->m_aValues.Size(); i++) { SWQLTypedConst *pConst = (SWQLTypedConst *) m_pConstList->m_aValues.GetAt(i); printf(" "); pConst->DebugDump(); } printf(" ---End Const List---\n"); } // Subselects // ========== if (m_pSubSelect) { printf(" ------- Begin Subselect ------\n"); m_pSubSelect->DebugDump(); printf(" ------- End Subselect ------\n"); } printf("\n"); printf(" === END SWQLTypedExpr ===\n"); } //*************************************************************************** // //*************************************************************************** SWQLTypedExpr::SWQLTypedExpr() { m_pTableRef = 0; m_pColRef = 0; m_dwRelOperator = 0; m_pConstValue = 0; m_pConstValue2 = 0; m_pJoinTableRef = 0; m_pJoinColRef = 0; m_pIntrinsicFuncOnColRef = 0; m_pIntrinsicFuncOnJoinColRef = 0; m_pIntrinsicFuncOnConstValue = 0; m_pLeftFunction = 0; m_pRightFunction = 0; m_pQNRight = 0; m_pQNLeft = 0; m_dwLeftFlags = 0; m_dwRightFlags = 0; m_pSubSelect = 0; m_dwLeftArrayIndex = 0; m_dwRightArrayIndex = 0; m_pConstList = 0; } //*************************************************************************** // //*************************************************************************** void SWQLTypedExpr::Empty() { delete [] m_pTableRef; delete [] m_pColRef; delete m_pConstValue; delete m_pConstValue2; delete m_pConstList; delete [] m_pJoinTableRef; delete [] m_pJoinColRef; delete [] m_pIntrinsicFuncOnColRef; delete [] m_pIntrinsicFuncOnJoinColRef; delete [] m_pIntrinsicFuncOnConstValue; delete m_pLeftFunction; delete m_pRightFunction; delete m_pQNRight; delete m_pQNLeft; delete m_pSubSelect; } //*************************************************************************** // //*************************************************************************** // void SWQLNode_Delete::DebugDump() { printf("Delete Node\n"); printf("FROM:"); if (m_pLeft) m_pLeft->DebugDump(); printf("WHERE:"); if (m_pRight) m_pRight->DebugDump(); } //*************************************************************************** // //*************************************************************************** SWQLNode_Delete::~SWQLNode_Delete() { // nothing for now } //*************************************************************************** // //*************************************************************************** void SWQLTypedConst::DebugDump() { printf(" Typed Const <"); switch (m_dwType) { case VT_LPWSTR: printf("%S", m_Value.m_pString); break; case VT_I4: printf("%d (0x%X)", m_Value.m_lValue, m_Value.m_lValue); break; case VT_R8: printf("%f", m_Value.m_dblValue); break; case VT_BOOL: printf("(bool) %d", m_Value.m_bValue); break; case VT_NULL: printf(" NULL"); break; default: printf(" unknown"); } printf(">\n"); } //*************************************************************************** // //*************************************************************************** static DWORD FlipOperator(DWORD dwOp) { switch (dwOp) { case WQL_TOK_LT: return WQL_TOK_GT; case WQL_TOK_LE: return WQL_TOK_GE; case WQL_TOK_GT: return WQL_TOK_LT; case WQL_TOK_GE: return WQL_TOK_LE; } return dwOp; // Echo original } //*************************************************************************** // //*************************************************************************** void SWQLNode_JoinPair::DebugDump() { printf("---SWQLNode_JoinPair---\n"); if (m_pRight) m_pRight->DebugDump(); if (m_pLeft) m_pLeft->DebugDump(); printf("---End SWQLNode_JoinPair---\n"); } void SWQLNode_OnClause::DebugDump() { printf("---SWQLNode_OnClause---\n"); if (m_pLeft) m_pLeft->DebugDump(); printf("---END SWQLNode_OnClause---\n"); } //*************************************************************************** // //*************************************************************************** void SWQLNode_OrderBy::DebugDump() { printf("\n\n---- 'ORDER BY' Clause ----\n"); if (m_pLeft) m_pLeft->DebugDump(); printf("---- End 'ORDER BY' Clause ----\n\n"); } //*************************************************************************** // //*************************************************************************** const LPWSTR CWQLParser::AliasToTable(IN LPWSTR pAlias) { const CFlexArray *pAliases = GetSelectedAliases(); for (int i = 0; i < pAliases->Size(); i++) { SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) pAliases->GetAt(i); if (wbem_wcsicmp(pTR->m_pAlias, pAlias) == 0) return pTR->m_pTableName; } return NULL; // Not found } //*************************************************************************** // //*************************************************************************** // void SWQLNode_Datepart::DebugDump() { printf(" ----Begin SWQLNode_Datepart----\n"); switch (m_nDatepart) { case WQL_TOK_YEAR: printf(" WQL_TOK_YEAR"); break; case WQL_TOK_MONTH: printf(" WQL_TOK_MONTH"); break; case WQL_TOK_DAY: printf(" WQL_TOK_DAY"); break; case WQL_TOK_HOUR: printf(" WQL_TOK_HOUR"); break; case WQL_TOK_MINUTE: printf(" WQL_TOK_MINUTE"); break; case WQL_TOK_SECOND: printf(" WQL_TOK_SECOND"); break; case WQL_TOK_MILLISECOND: printf(" WQL_TOK_MILLISECOND"); break; default: printf(" -> No datepart specified\n"); } printf("\n"); if (m_pColRef) m_pColRef->DebugDump(); printf(" ----End SWQLNode_Datepart----\n"); } //*************************************************************************** // //*************************************************************************** // void SWQLNode_ColumnList::Empty() { for (int i = 0; i < m_aColumnRefs.Size(); i++) delete (SWQLColRef *) m_aColumnRefs[i]; m_aColumnRefs.Empty(); } //*************************************************************************** // //*************************************************************************** // void StrArrayDelete( ULONG uSize, LPWSTR *pszArray ) { if (!pszArray) return; for (unsigned u = 0; u < uSize; u++) delete pszArray[u]; delete pszArray; } //*************************************************************************** // //*************************************************************************** // HRESULT StrArrayCopy( ULONG uSize, LPWSTR *pSrc, LPWSTR **pDest ) { HRESULT hr = WBEM_S_NO_ERROR; LPWSTR *pFinal = new LPWSTR[uSize]; if (pFinal) { for (ULONG u = 0; u < uSize; u++) { pFinal[u] = CloneLPWSTR(pSrc[u]); if (!pFinal[u]) { hr = WBEM_E_OUT_OF_MEMORY; break; } } if (SUCCEEDED(hr)) { *pDest = pFinal; } else { for (ULONG u2 = 0; u2 < u; u2++) { delete pFinal[u]; } delete [] pFinal; } } else hr = WBEM_E_OUT_OF_MEMORY; return hr; } //*************************************************************************** // //*************************************************************************** // CWbemQueryQualifiedName::CWbemQueryQualifiedName() { Init(); } //*************************************************************************** // //*************************************************************************** // void CWbemQueryQualifiedName::Init() { m_uVersion = 1; m_uTokenType = 1; m_uNameListSize = 0; m_ppszNameList = 0; m_bArraysUsed = 0; m_pbArrayElUsed = 0; m_puArrayIndex = 0; } ////////////////////////////////////////////////////////////////////////////////// // * CWbemQueryQualifiedName::~CWbemQueryQualifiedName() { DeleteAll(); } void CWbemQueryQualifiedName::DeleteAll() { StrArrayDelete(m_uNameListSize, (LPWSTR *) m_ppszNameList); delete [] m_pbArrayElUsed; delete [] m_puArrayIndex; } ////////////////////////////////////////////////////////////////////////////////// // CWbemQueryQualifiedName::CWbemQueryQualifiedName(CWbemQueryQualifiedName &Src) { Init(); *this = Src; } ////////////////////////////////////////////////////////////////////////////////// // CWbemQueryQualifiedName& CWbemQueryQualifiedName::operator =(CWbemQueryQualifiedName &Src) { DeleteAll(); m_uVersion = Src.m_uVersion; m_uTokenType = Src.m_uTokenType; m_uNameListSize = Src.m_uNameListSize; m_ppszNameList = new LPCWSTR[m_uNameListSize]; m_pbArrayElUsed = new BOOL[m_uNameListSize]; m_puArrayIndex = new ULONG[m_uNameListSize]; if (!m_ppszNameList || !m_pbArrayElUsed || !m_puArrayIndex) throw CX_MemoryException(); for (unsigned u = 0; u < m_uNameListSize; u++) { m_pbArrayElUsed[u] = Src.m_pbArrayElUsed[u]; m_puArrayIndex[u] = Src.m_puArrayIndex[u]; } if (FAILED(StrArrayCopy(m_uNameListSize, (LPWSTR *) Src.m_ppszNameList, (LPWSTR **) &m_ppszNameList))) throw CX_MemoryException(); return *this; }; ////////////////////////////////////////////////////////////////////////////////// // void CWbemRpnQueryToken::Init() { m_uVersion = 1; m_uTokenType = 0; m_uSubexpressionShape = 0; m_uOperator = 0; m_pRightIdent = 0; m_pLeftIdent = 0; m_uConstApparentType = 0; // VT_ type m_uConst2ApparentType = 0; m_Const.m_uVal64 = 0; m_Const2.m_uVal64 = 0; m_pszLeftFunc = 0; m_pszRightFunc = 0; } /////////////////////////////////////////////////////////////////////////////////// // // CWbemRpnQueryToken::CWbemRpnQueryToken() { Init(); } /////////////////////////////////////////////////////////////////////////////////// // // void CWbemRpnEncodedQuery::DeleteAll() { unsigned u = 0; for (u = 0; u < m_uSelectListSize; u++) { SWbemQueryQualifiedName *pQN = m_ppSelectList[u]; CWbemQueryQualifiedName *pTmp = (CWbemQueryQualifiedName*) pQN; delete pTmp; } delete [] m_puDetectedFeatures; delete [] m_ppSelectList; delete LPWSTR(m_pszOptionalFromPath); StrArrayDelete(m_uFromListSize, (LPWSTR *) m_ppszFromList); for (u = 0; u < m_uWhereClauseSize; u++) { CWbemRpnQueryToken *pTmp = (CWbemRpnQueryToken *) m_ppRpnWhereClause[u]; delete pTmp; } m_uWhereClauseSize = 0; delete [] m_ppRpnWhereClause; StrArrayDelete(m_uOrderByListSize, (LPWSTR *) m_ppszOrderByList); } ////////////////////////////////////////////////////////////////////////////////// // CWbemRpnQueryToken::~CWbemRpnQueryToken() { DeleteAll(); } void CWbemRpnQueryToken::DeleteAll() { delete (CWbemQueryQualifiedName *) m_pRightIdent; delete (CWbemQueryQualifiedName *) m_pLeftIdent; if (m_uConstApparentType == VT_LPWSTR) { delete (LPWSTR) m_Const.m_pszStrVal; } if (m_uConst2ApparentType == VT_LPWSTR) { delete (LPWSTR) m_Const2.m_pszStrVal; } delete LPWSTR(m_pszLeftFunc); delete LPWSTR(m_pszRightFunc); } ////////////////////////////////////////////////////////////////////////////////// // CWbemRpnQueryToken::CWbemRpnQueryToken(CWbemRpnQueryToken &Src) { Init(); *this = Src; } ////////////////////////////////////////////////////////////////////////////////// // CWbemRpnQueryToken& CWbemRpnQueryToken::operator =(CWbemRpnQueryToken &Src) { // Kill old stuff. DeleteAll(); // Copy new stuff. m_pRightIdent = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName( *(CWbemQueryQualifiedName *) Src.m_pRightIdent ); m_pLeftIdent = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName( *(CWbemQueryQualifiedName *) Src.m_pLeftIdent ); if (!m_pRightIdent || !m_pLeftIdent) throw CX_MemoryException(); m_uConstApparentType = Src.m_uConstApparentType; m_uConst2ApparentType = Src.m_uConst2ApparentType; if (m_uConstApparentType == VT_LPWSTR) { m_Const.m_pszStrVal = CloneLPWSTR(Src.m_Const.m_pszStrVal);\ if (!m_Const.m_pszStrVal) throw CX_MemoryException(); } else m_Const = Src.m_Const; if (m_uConst2ApparentType == VT_LPWSTR) { m_Const2.m_pszStrVal = CloneLPWSTR(Src.m_Const2.m_pszStrVal); if (!m_Const2.m_pszStrVal) throw CX_MemoryException(); } else m_Const2 = Src.m_Const2; m_pszLeftFunc = CloneLPWSTR(Src.m_pszLeftFunc); if (CloneFailed(m_pszLeftFunc,Src.m_pszLeftFunc)) throw CX_MemoryException(); m_pszRightFunc = CloneLPWSTR(Src.m_pszRightFunc); if (CloneFailed(m_pszRightFunc,Src.m_pszRightFunc)) throw CX_MemoryException(); return *this; }; ////////////////////////////////////////////////////////////////////////////////// void CWbemRpnEncodedQuery::Init() { m_uVersion = 1; m_uTokenType = 0; m_uParsedFeatureMask = 0I64; m_uDetectedArraySize = 0; m_puDetectedFeatures = 0; m_uSelectListSize = 0; m_ppSelectList = 0; // FROM clause // =========== m_uFromTargetType = 0; m_pszOptionalFromPath = 0; m_uFromListSize = 0; m_ppszFromList = 0; // Where clause // ============ m_uWhereClauseSize = 0; m_ppRpnWhereClause = 0; // WITHIN value // ============ m_dblWithinPolling = 0.0; m_dblWithinWindow = 0.0; // ORDER BY // ======== m_uOrderByListSize = 0; m_ppszOrderByList = 0; m_uOrderDirectionEl = 0; } /////////////////////////////////////////////////////////////////////////////////// // // CWbemRpnEncodedQuery::CWbemRpnEncodedQuery() { Init(); } /////////////////////////////////////////////////////////////////////////////////// // // CWbemRpnEncodedQuery::~CWbemRpnEncodedQuery() { DeleteAll(); } /////////////////////////////////////////////////////////////////////////////////// // // CWbemRpnEncodedQuery::CWbemRpnEncodedQuery(CWbemRpnEncodedQuery &Src) { Init(); *this = Src; } /////////////////////////////////////////////////////////////////////////////////// // // CWbemRpnEncodedQuery& CWbemRpnEncodedQuery::operator=(CWbemRpnEncodedQuery &Src) { unsigned u; // Kill old stuff. DeleteAll(); // Clone new stuff. m_uVersion = Src.m_uVersion; m_uTokenType = Src.m_uTokenType; // General query features // ====================== m_uParsedFeatureMask = Src.m_uParsedFeatureMask; m_uDetectedArraySize = Src.m_uDetectedArraySize; m_puDetectedFeatures = new ULONG[Src.m_uDetectedArraySize]; if (!m_puDetectedFeatures) throw CX_MemoryException(); memcpy(m_puDetectedFeatures, Src.m_puDetectedFeatures, sizeof(ULONG) * Src.m_uDetectedArraySize); // Values being selected if WMIQ_RPNF_PROJECTION is set // ===================================================== m_uSelectListSize = Src.m_uSelectListSize; m_ppSelectList = (SWbemQueryQualifiedName **) new CWbemQueryQualifiedName *[m_uSelectListSize]; if (!m_ppSelectList) throw CX_MemoryException(); for (u = 0; u < m_uSelectListSize; u++) { CWbemQueryQualifiedName *p = new CWbemQueryQualifiedName(*(CWbemQueryQualifiedName *) Src.m_ppSelectList[u]); if (!p) throw CX_MemoryException(); m_ppSelectList[u] = (SWbemQueryQualifiedName *) p; } // FROM m_uFromTargetType = Src.m_uFromTargetType; m_pszOptionalFromPath = CloneLPWSTR(Src.m_pszOptionalFromPath);// NULL if not used if (CloneFailed(m_pszOptionalFromPath,Src.m_pszOptionalFromPath)) throw CX_MemoryException(); if (FAILED(StrArrayCopy(Src.m_uFromListSize, (LPWSTR *) Src.m_ppszFromList, (LPWSTR **) &m_ppszFromList))) throw CX_MemoryException(); m_uFromListSize = Src.m_uFromListSize; // Where clause // ============ m_uWhereClauseSize = Src.m_uWhereClauseSize; m_ppRpnWhereClause = new SWbemRpnQueryToken *[m_uWhereClauseSize]; if (!m_ppRpnWhereClause) throw CX_MemoryException(); for (u = 0; u < m_uWhereClauseSize; u++) { CWbemRpnQueryToken *pTmp = new CWbemRpnQueryToken(* (CWbemRpnQueryToken *) Src.m_ppRpnWhereClause[u]); if (!pTmp) throw CX_MemoryException(); m_ppRpnWhereClause[u] = (SWbemRpnQueryToken *) pTmp; } // WITHIN value // ============ m_dblWithinPolling = Src.m_dblWithinPolling; m_dblWithinWindow = Src.m_dblWithinWindow; // ORDER BY // ======== if (FAILED(StrArrayCopy(Src.m_uOrderByListSize, (LPWSTR *) Src.m_ppszOrderByList, (LPWSTR **) &m_ppszOrderByList))) throw CX_MemoryException(); m_uOrderByListSize = Src.m_uOrderByListSize; m_uOrderDirectionEl = new ULONG[m_uOrderByListSize]; if (!m_uOrderDirectionEl) throw CX_MemoryException(); memcpy(m_uOrderDirectionEl, Src.m_uOrderDirectionEl, sizeof(ULONG) * m_uOrderByListSize); return *this; } /////////////////////////////////////////////////////////////////////////////////// // // Recursively rearranges the tokens from AST to RPN. // Nondestructive to the query itself; only stores the pointers. // // HRESULT CWQLParser::BuildRpnWhereClause( SWQLNode *pCurrent, CFlexArray &aRpnReorg ) { if (pCurrent == 0) return WBEM_S_NO_ERROR; BuildRpnWhereClause(pCurrent->m_pLeft, aRpnReorg); BuildRpnWhereClause(pCurrent->m_pRight, aRpnReorg); aRpnReorg.Add(pCurrent); return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // int CWQLParser::update_stmt(OUT SWQLNode_Update **pUpdStmt) { return WBEM_E_INVALID_SYNTAX; } //*************************************************************************** // //*************************************************************************** // int CWQLParser::insert_stmt(OUT SWQLNode_Insert **pInsStmt) { return WBEM_E_INVALID_SYNTAX; } //*************************************************************************** // //*************************************************************************** // HRESULT CWQLParser::BuildSelectList(CWbemRpnEncodedQuery *pQuery) { SWQLNode_ColumnList *pCL = (SWQLNode_ColumnList *) GetColumnList(); if (pCL == 0) return WBEM_E_INVALID_QUERY; ULONG uSize = (ULONG) pCL->m_aColumnRefs.Size(); pQuery->m_uSelectListSize = uSize; pQuery->m_ppSelectList = (SWbemQueryQualifiedName **) new CWbemQueryQualifiedName *[uSize]; if (!pQuery->m_ppSelectList) { throw CX_MemoryException(); } for (ULONG u = 0; u < uSize; u++) { SWQLColRef *pCol = (SWQLColRef *) pCL->m_aColumnRefs[u]; SWbemQueryQualifiedName *pTemp = (SWbemQueryQualifiedName *) new CWbemQueryQualifiedName; if (!pTemp) throw CX_MemoryException(); unsigned uNameListSize = 1; if (pCol->m_pTableRef) uNameListSize = 2; pTemp->m_uNameListSize = uNameListSize; pTemp->m_ppszNameList = (LPCWSTR *) new LPWSTR[uNameListSize]; if (!pTemp->m_ppszNameList) { delete pTemp; throw CX_MemoryException(); } if (uNameListSize == 1) { pTemp->m_ppszNameList[0] = CloneLPWSTR(pCol->m_pColName); if (!pTemp->m_ppszNameList[0]) { delete pTemp; throw CX_MemoryException(); } } else { pTemp->m_ppszNameList[0] = CloneLPWSTR(pCol->m_pTableRef); if (!pTemp->m_ppszNameList[0]) { delete pTemp; throw CX_MemoryException(); } pTemp->m_ppszNameList[1] = CloneLPWSTR(pCol->m_pColName); if (!pTemp->m_ppszNameList[1]) { delete pTemp; throw CX_MemoryException(); } } pQuery->m_ppSelectList[u] = pTemp; } return 0; } //*************************************************************************** // //*************************************************************************** // HRESULT CWQLParser::BuildFromClause(CWbemRpnEncodedQuery *pQuery) { SWQLNode_FromClause *pFrom = (SWQLNode_FromClause *) GetFromClause(); if (pFrom == NULL) return WBEM_E_INVALID_QUERY; // Check left node for traditional SQL // Check right node for WMI scoped select if (pFrom->m_pLeft) { SWQLNode_TableRef *pTR = (SWQLNode_TableRef *) pFrom->m_pLeft; pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_UNARY; pQuery->m_uFromListSize = 1; pQuery->m_ppszFromList = (LPCWSTR *) new LPWSTR[1]; if (!pQuery->m_ppszFromList) throw CX_MemoryException(); pQuery->m_ppszFromList[0] = CloneLPWSTR(pTR->m_pTableName); if (!pQuery->m_ppszFromList[0]) { delete pQuery->m_ppszFromList; throw CX_MemoryException(); } } else if (pFrom->m_pRight) { SWQLNode_WmiScopedSelect *pSS = (SWQLNode_WmiScopedSelect *) pFrom->m_pRight; pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_PATH; pQuery->m_pszOptionalFromPath = CloneLPWSTR(pSS->m_pszScope); if (pQuery->m_pszOptionalFromPath) { throw CX_MemoryException(); } int nSz = pSS->m_aTables.Size(); if (nSz == 1) pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_UNARY; else if (nSz > 1) pQuery->m_uFromTargetType |= WMIQ_RPN_FROM_CLASS_LIST; pQuery->m_uFromListSize = (ULONG) nSz; pQuery->m_ppszFromList = (LPCWSTR *) new LPWSTR[nSz]; if (!pQuery->m_ppszFromList) throw CX_MemoryException(); for (int n = 0; n < nSz; n++) { pQuery->m_ppszFromList[n] = CloneLPWSTR(LPWSTR(pSS->m_aTables[n])); if (!pQuery->m_ppszFromList[n]) throw CX_MemoryException(); } } else return WBEM_E_INVALID_QUERY; return 0; } //*************************************************************************** // //*************************************************************************** // HRESULT CWQLParser::GetRpnSequence(OUT SWbemRpnEncodedQuery **pRpn) { HRESULT hRes; try { CWbemRpnEncodedQuery *pNewRpn = new CWbemRpnEncodedQuery; if (!pNewRpn) return WBEM_E_OUT_OF_MEMORY; wmilib::auto_ptr delNewRpn(pNewRpn); // Copy detected features. // ======================= pNewRpn->m_uParsedFeatureMask = m_uFeatures; // Do the SELECT LIST. // =================== BuildSelectList(pNewRpn); // Do the FROM list. // ================= BuildFromClause(pNewRpn); // Do the WHERE clause. // ==================== CFlexArray aRpn; SWQLNode *pWhereRoot = GetWhereClauseRoot(); SWQLNode_RelExpr *pExprRoot = (SWQLNode_RelExpr *) pWhereRoot->m_pLeft; SWQLNode_WhereOptions *pOp = (SWQLNode_WhereOptions *) pWhereRoot->m_pRight; // ORDER BY, etc. if (pExprRoot) hRes = BuildRpnWhereClause(pExprRoot, aRpn); // Now traverse the RPN form of the WHERE clause, if any. // ====================================================== if (aRpn.Size()) { pNewRpn->m_uWhereClauseSize = aRpn.Size(); pNewRpn->m_ppRpnWhereClause = (SWbemRpnQueryToken **) new CWbemRpnQueryToken*[aRpn.Size()]; if (!pNewRpn->m_ppRpnWhereClause) return WBEM_E_OUT_OF_MEMORY; } BOOL b_Test_AllEqualityTests = TRUE; BOOL b_Test_Disjunctive = FALSE; BOOL b_AtLeastOneTest = FALSE; for (int i = 0; i < aRpn.Size(); i++) { SWQLNode_RelExpr *pSrc = (SWQLNode_RelExpr *) aRpn[i]; SWbemRpnQueryToken *pDest = (SWbemRpnQueryToken *) new CWbemRpnQueryToken; if (!pDest) return WBEM_E_OUT_OF_MEMORY; wmilib::auto_ptr delDest(pDest); hRes = BuildCurrentWhereToken(pSrc, pDest); delDest.release(); pNewRpn->m_ppRpnWhereClause[i] = pDest; // Add in stats. // ============= if (pDest->m_uTokenType == WMIQ_RPN_TOKEN_EXPRESSION) { if (pDest->m_uOperator != WMIQ_RPN_OP_EQ) b_Test_AllEqualityTests = FALSE; b_AtLeastOneTest = TRUE; } else if (pDest->m_uTokenType != WMIQ_RPN_TOKEN_AND) { b_Test_Disjunctive = TRUE; } if (pDest->m_pRightIdent != 0 && pDest->m_pLeftIdent != 0) { pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_PROP_TO_PROP_TESTS; } } if (b_Test_AllEqualityTests && b_AtLeastOneTest) pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_EQUALITY_TESTS_ONLY; if (b_Test_Disjunctive) pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_QUERY_IS_DISJUNCTIVE; else pNewRpn->m_uParsedFeatureMask |= WMIQ_RPNF_QUERY_IS_CONJUNCTIVE; *pRpn = pNewRpn; delNewRpn.release(); } catch (CX_MemoryException) { return WBEM_E_OUT_OF_MEMORY; } catch (...) { return WBEM_E_CRITICAL_ERROR; } return WBEM_S_NO_ERROR; } //*************************************************************************** // //*************************************************************************** // ULONG RpnTranslateExprFlags(SWQLTypedExpr *pTE) { return 0; } //*************************************************************************** // //*************************************************************************** // ULONG RpnTranslateOperator(SWQLTypedExpr *pTE) { ULONG uRes = WMIQ_RPN_OP_UNDEFINED; switch (pTE->m_dwRelOperator) { case WQL_TOK_LE: uRes = WMIQ_RPN_OP_LE; break; case WQL_TOK_LT: uRes = WMIQ_RPN_OP_LT; break; case WQL_TOK_GE: uRes = WMIQ_RPN_OP_GE; break; case WQL_TOK_GT: uRes = WMIQ_RPN_OP_GT; break; case WQL_TOK_EQ: uRes = WMIQ_RPN_OP_EQ; break; case WQL_TOK_NE: uRes = WMIQ_RPN_OP_NE; break; case WQL_TOK_LIKE: uRes = WMIQ_RPN_OP_LIKE; break; case WQL_TOK_ISA: uRes = WMIQ_RPN_OP_ISA; break; case WQL_TOK_ISNULL: uRes = WMIQ_RPN_OP_ISNULL; break; case WQL_TOK_NOT_NULL: uRes = WMIQ_RPN_OP_ISNOTNULL; break; } return uRes; } //*************************************************************************** // //*************************************************************************** // SWbemQueryQualifiedName *RpnTranslateIdent(ULONG uWhichSide, SWQLTypedExpr *pTE) { SWQLQualifiedName *pQN = 0; if (uWhichSide == WMIQ_RPN_LEFT_PROPERTY_NAME) { pQN = pTE->m_pQNLeft; } else { pQN = pTE->m_pQNRight; } if (pQN) { CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName; if (!pNew) throw CX_MemoryException(); pNew->m_uNameListSize = (ULONG) pQN->m_aFields.Size(); pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[pNew->m_uNameListSize]; if (!pNew->m_ppszNameList) { delete pNew; throw CX_MemoryException(); } for (int i = 0; i < pQN->m_aFields.Size(); i++) { SWQLQualifiedNameField *pField = (SWQLQualifiedNameField *) pQN->m_aFields[i]; LPWSTR pszNewName = CloneLPWSTR(pField->m_pName); if (!pszNewName) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[i] = pszNewName; } return (SWbemQueryQualifiedName *) pNew; } else if (pTE->m_pColRef && WMIQ_RPN_LEFT_PROPERTY_NAME == uWhichSide) { CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName; if (!pNew) throw CX_MemoryException(); if (pTE->m_pTableRef) { pNew->m_uNameListSize = 2; pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[2]; if (!pNew->m_ppszNameList) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pTableRef); if (!pNew->m_ppszNameList[0]) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[1] = CloneLPWSTR(pTE->m_pColRef); if (!pNew->m_ppszNameList[1]) { delete pNew; throw CX_MemoryException(); } } else { pNew->m_uNameListSize = 1; pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[1]; if (!pNew->m_ppszNameList) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pColRef); if (!pNew->m_ppszNameList[0]) { delete pNew; throw CX_MemoryException(); } } return (SWbemQueryQualifiedName *) pNew; } else if (pTE->m_pJoinColRef && WMIQ_RPN_RIGHT_PROPERTY_NAME == uWhichSide) { CWbemQueryQualifiedName *pNew = new CWbemQueryQualifiedName; if (!pNew) throw CX_MemoryException(); if (pTE->m_pJoinTableRef) { pNew->m_uNameListSize = 2; pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[2]; if (!pNew->m_ppszNameList) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pJoinTableRef); if (!pNew->m_ppszNameList[0]) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[1] = CloneLPWSTR(pTE->m_pJoinColRef); if (!pNew->m_ppszNameList[1]) { delete pNew; throw CX_MemoryException(); } } else { pNew->m_uNameListSize = 1; pNew->m_ppszNameList = (LPCWSTR *) new LPWSTR *[1]; if (!pNew->m_ppszNameList) { delete pNew; throw CX_MemoryException(); } pNew->m_ppszNameList[0] = CloneLPWSTR(pTE->m_pJoinColRef); if (!pNew->m_ppszNameList[0]) { delete pNew; throw CX_MemoryException(); } } return (SWbemQueryQualifiedName *) pNew; } else return 0; } //*************************************************************************** // //*************************************************************************** // SWbemQueryQualifiedName *RpnTranslateRightIdent(SWQLTypedExpr *pTE) { return 0; } //*************************************************************************** // //*************************************************************************** // SWbemRpnConst RpnTranslateConst(SWQLTypedConst *pSrc) { SWbemRpnConst c; memset(&c, 0, sizeof(c)); if (!pSrc) return c; switch (pSrc->m_dwType) { case VT_LPWSTR: c.m_pszStrVal = CloneLPWSTR(pSrc->m_Value.m_pString); // this will fail with an "empty" struct returned break; case VT_I4: c.m_lLongVal = pSrc->m_Value.m_lValue; break; case VT_R8: c.m_dblVal = pSrc->m_Value.m_dblValue; break; case VT_BOOL: c.m_bBoolVal = pSrc->m_Value.m_bValue; break; case VT_UI4: c.m_uLongVal = (unsigned) pSrc->m_Value.m_lValue; break; case VT_I8: c.m_lVal64 = pSrc->m_Value.m_i64Value; break; case VT_UI8: c.m_uVal64 = (unsigned __int64) pSrc->m_Value.m_i64Value; break; } return c; } //*************************************************************************** // //*************************************************************************** // ULONG RpnTranslateConstType(SWQLTypedConst *pSrc) { if (pSrc) return pSrc->m_dwType; else return VT_NULL; } //*************************************************************************** // //*************************************************************************** // LPCWSTR RpnTranslateLeftFunc(SWQLTypedExpr *pTE) { return Clone(pTE->m_pIntrinsicFuncOnColRef); } //*************************************************************************** // //*************************************************************************** // LPCWSTR RpnTranslateRightFunc(SWQLTypedExpr *pTE) { if (pTE->m_pIntrinsicFuncOnJoinColRef == 0) return Clone(pTE->m_pIntrinsicFuncOnConstValue); else return Clone(pTE->m_pIntrinsicFuncOnJoinColRef); } //*************************************************************************** // //*************************************************************************** // HRESULT CWQLParser::BuildCurrentWhereToken( SWQLNode_RelExpr *pSrc, SWbemRpnQueryToken *pDest ) { HRESULT hRes = WBEM_E_INVALID_QUERY; if (pSrc->m_dwExprType == WQL_TOK_OR) { pDest->m_uTokenType = WMIQ_RPN_TOKEN_OR; } else if (pSrc->m_dwExprType == WQL_TOK_AND) { pDest->m_uTokenType = WMIQ_RPN_TOKEN_AND; } else if (pSrc->m_dwExprType == WQL_TOK_NOT) { pDest->m_uTokenType = WMIQ_RPN_TOKEN_NOT; } else if (pSrc->m_dwExprType == WQL_TOK_TYPED_EXPR) { pDest->m_uTokenType = WMIQ_RPN_TOKEN_EXPRESSION; SWQLTypedExpr *pTmp = pSrc->m_pTypedExpr; pDest->m_uSubexpressionShape = RpnTranslateExprFlags(pTmp); pDest->m_uOperator = RpnTranslateOperator(pTmp); pDest->m_pLeftIdent = RpnTranslateIdent(WMIQ_RPN_LEFT_PROPERTY_NAME, pTmp); pDest->m_pRightIdent = RpnTranslateIdent(WMIQ_RPN_RIGHT_PROPERTY_NAME, pTmp); pDest->m_uConstApparentType = RpnTranslateConstType(pTmp->m_pConstValue); pDest->m_Const = RpnTranslateConst(pTmp->m_pConstValue); pDest->m_uConst2ApparentType = RpnTranslateConstType(pTmp->m_pConstValue2); pDest->m_Const2 = RpnTranslateConst(pTmp->m_pConstValue2); pDest->m_pszLeftFunc = RpnTranslateLeftFunc(pTmp); pDest->m_pszRightFunc = RpnTranslateRightFunc(pTmp); if (pDest->m_pLeftIdent) pDest->m_uSubexpressionShape |= WMIQ_RPN_LEFT_PROPERTY_NAME; if (pDest->m_pRightIdent) pDest->m_uSubexpressionShape |= WMIQ_RPN_RIGHT_PROPERTY_NAME; // Special case NULL if there really is a const value with a type of NULL if ( (pDest->m_uConstApparentType != VT_NULL) || ( NULL != pTmp->m_pConstValue && pTmp->m_pConstValue->m_dwType == VT_NULL ) ) pDest->m_uSubexpressionShape |= WMIQ_RPN_CONST; // Do the same for CONST2 if ( (pDest->m_uConst2ApparentType != VT_NULL) || ( NULL != pTmp->m_pConstValue2 && pTmp->m_pConstValue2->m_dwType == VT_NULL ) ) pDest->m_uSubexpressionShape |= WMIQ_RPN_CONST2; if (pDest->m_pszLeftFunc) pDest->m_uSubexpressionShape |= WMIQ_RPN_LEFT_FUNCTION; if (pDest->m_pszRightFunc) pDest->m_uSubexpressionShape |= WMIQ_RPN_RIGHT_FUNCTION; if (pDest->m_uOperator != 0) pDest->m_uSubexpressionShape |= WMIQ_RPN_RELOP; } return hRes; } //*************************************************************************** // //*************************************************************************** // int CWQLParser::assocquery(OUT SWQLNode_AssocQuery **pAssocQuery) { HRESULT hRes; CAssocQueryParser AP; *pAssocQuery = 0; hRes = AP.Parse(m_pszQueryText); if (FAILED(hRes)) return hRes; // If here, extract the info and put it into a new node. // ===================================================== wmilib::auto_ptr pTmp(new SWQLNode_AssocQuery); if (0 == pTmp.get()) return WBEM_E_OUT_OF_MEMORY; pTmp->m_pAQInf = new CWbemAssocQueryInf; if (NULL == pTmp->m_pAQInf) return WBEM_E_OUT_OF_MEMORY; hRes = pTmp->m_pAQInf->CopyFrom((SWbemAssocQueryInf *) &AP); if (FAILED(hRes)) return hRes; *pAssocQuery = pTmp.release(); return S_OK; } //*************************************************************************** // //*************************************************************************** // void SWQLNode_QueryRoot::DebugDump() { if (m_pLeft) m_pLeft->DebugDump(); } //*************************************************************************** // //*************************************************************************** // void SWQLNode_AssocQuery::DebugDump() { printf("Association query info\n"); printf("Version = %u\n", m_pAQInf->m_uVersion); printf("Analysis Type = %u\n", m_pAQInf->m_uAnalysisType); printf("Feature Mask = 0x%X\n", m_pAQInf->m_uFeatureMask); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ASSOCIATORS) printf(" WMIQ_ASSOCQ_ASSOCIATORS\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REFERENCES) printf(" WMIQ_ASSOCQ_REFERENCES\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_RESULTCLASS) printf(" WMIQ_ASSOCQ_RESULTCLASS\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ASSOCCLASS) printf(" WMIQ_ASSOCQ_ASSOCCLASS\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_ROLE) printf(" WMIQ_ASSOCQ_ROLE\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_RESULTROLE) printf(" WMIQ_ASSOCQ_RESULTROLE\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REQUIREDQUALIFIER) printf(" WMIQ_ASSOCQ_REQUIREDQUALIFIER\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER) printf(" WMIQ_ASSOCQ_REQUIREDASSOCQUALIFIER\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_CLASSDEFSONLY) printf(" WMIQ_ASSOCQ_CLASSDEFSONLY\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_KEYSONLY) printf(" WMIQ_ASSOCQ_KEYSONLY\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_SCHEMAONLY) printf(" WMIQ_ASSOCQ_SCHEMAONLY\n"); if (m_pAQInf->m_uFeatureMask & WMIQ_ASSOCQ_CLASSREFSONLY) printf(" WMIQ_ASSOCQ_CLASSREFSONLY\n"); printf("IWbemPath pointer = 0x%I64X\n", (unsigned __int64) m_pAQInf->m_pPath); if (m_pAQInf->m_pPath) { printf("Path object has "); wchar_t Buf[256]; ULONG uLen = 256; m_pAQInf->m_pPath->GetText(0, &uLen, Buf); printf("<%S>\n", Buf); } printf("m_pszQueryText = %S\n", m_pAQInf->m_pszQueryText); printf("m_pszResultClass = %S\n", m_pAQInf->m_pszResultClass); printf("m_pszAssocClass = %S\n", m_pAQInf->m_pszAssocClass); printf("m_pszRole = %S\n", m_pAQInf->m_pszRole); printf("m_pszResultRole = %S\n", m_pAQInf->m_pszResultRole); printf("m_pszRequiredQualifier = %S\n", m_pAQInf->m_pszRequiredQualifier); printf("m_pszRequiredAssocQualifier = %S\n", m_pAQInf->m_pszRequiredAssocQualifier); printf("---end---\n"); } //*************************************************************************** // //*************************************************************************** // CWbemAssocQueryInf::CWbemAssocQueryInf() { Init(); } //*************************************************************************** // //*************************************************************************** // CWbemAssocQueryInf::~CWbemAssocQueryInf() { Empty(); } //*************************************************************************** // //*************************************************************************** // void CWbemAssocQueryInf::Empty() { if (m_pPath) m_pPath->Release(); delete [] m_pszPath; delete [] m_pszQueryText; delete [] m_pszResultClass; delete [] m_pszAssocClass; delete [] m_pszRole; delete [] m_pszResultRole; delete [] m_pszRequiredQualifier; delete [] m_pszRequiredAssocQualifier; Init(); } //*************************************************************************** // //*************************************************************************** // void CWbemAssocQueryInf::Init() { m_uVersion = 0; m_uAnalysisType = 0; m_uFeatureMask = 0; m_pPath = 0; m_pszPath = 0; m_pszQueryText = 0; m_pszResultClass = 0; m_pszAssocClass = 0; m_pszRole = 0; m_pszResultRole = 0; m_pszRequiredQualifier = 0; m_pszRequiredAssocQualifier = 0; } //*************************************************************************** // //*************************************************************************** // HRESULT CWbemAssocQueryInf::CopyFrom(SWbemAssocQueryInf *pSrc) { m_uVersion = pSrc->m_uVersion; m_uAnalysisType = pSrc->m_uAnalysisType; m_uFeatureMask = pSrc->m_uFeatureMask; m_pszPath = CloneLPWSTR(pSrc->m_pszPath); if (CloneFailed(m_pszPath,pSrc->m_pszPath)) return WBEM_E_OUT_OF_MEMORY; if (m_pszPath) { HRESULT hRes= CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &m_pPath); if (SUCCEEDED(hRes)) { hRes = m_pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, m_pszPath); if (FAILED(hRes)) { m_pPath->Release(); m_pPath = 0; return hRes; } } else return hRes; } m_pszQueryText = CloneLPWSTR(pSrc->m_pszQueryText); if (CloneFailed(m_pszQueryText,pSrc->m_pszQueryText)) return WBEM_E_OUT_OF_MEMORY; m_pszResultClass = CloneLPWSTR(pSrc->m_pszResultClass); if (CloneFailed(m_pszResultClass,pSrc->m_pszResultClass)) return WBEM_E_OUT_OF_MEMORY; m_pszAssocClass = CloneLPWSTR(pSrc->m_pszAssocClass); if (CloneFailed(m_pszAssocClass,pSrc->m_pszAssocClass)) return WBEM_E_OUT_OF_MEMORY; m_pszRole = CloneLPWSTR(pSrc->m_pszRole); if (CloneFailed(m_pszRole,pSrc->m_pszRole)) return WBEM_E_OUT_OF_MEMORY; m_pszResultRole = CloneLPWSTR(pSrc->m_pszResultRole); if (CloneFailed(m_pszResultRole,pSrc->m_pszResultRole)) return WBEM_E_OUT_OF_MEMORY; m_pszRequiredQualifier = CloneLPWSTR(pSrc->m_pszRequiredQualifier); if (CloneFailed(m_pszRequiredQualifier,pSrc->m_pszRequiredQualifier)) return WBEM_E_OUT_OF_MEMORY; m_pszRequiredAssocQualifier = CloneLPWSTR(pSrc->m_pszRequiredAssocQualifier); if (CloneFailed(m_pszRequiredAssocQualifier,pSrc->m_pszRequiredAssocQualifier)) return WBEM_E_OUT_OF_MEMORY; return WBEM_S_NO_ERROR; }