|
|
//***************************************************************************
//
// (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
//
// wqltosql.cpp
//
// cvadai 19-Mar-99 Created as prototype for Quasar.
//
//***************************************************************************
#define _WQLTOSQL_CPP_
#pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
#include "precomp.h"
#include <windows.h>
#include <comutil.h>
#include <flexarry.h>
#include <wstring.h>
#include <wqlnode.h>
#include <reposit.h>
#include <time.h>
#include <map>
#include <vector>
#include <wbemcli.h>
#include <wbemint.h>
#include <wqltosql.h>
#include <repcache.h>
#include <reputils.h>
#include <smrtptr.h>
#include <sqlcache.h>
#include <wqllex.h>
#define WMIDB_PROPERTY_THIS 0x1000
//***************************************************************************
//
// TempQL Lex Table
//
//***************************************************************************
/*----------------------------------------------------
References of {objpath} where ResultClass=XXX Role=YYY RequiredQualifier=QualifierName ClassDefsOnly
Associators of {objpath} where ResultClass=XXX AssocClass=YYY Role=PPP RequiredQualifier=QualifierName RequiredAssocQualifier=QualifierName ClassDefsOnly
------------------------------------------------------*/
#define QUERY_TYPE_CLASSDEFS_ONLY 0x1
#define QUERY_TYPE_GETREFS 0x2
#define QUERY_TYPE_GETASSOCS 0x4
#define QUERY_TYPE_SCHEMA_ONLY 0x8
#define QASSOC_TOK_STRING 101
#define QASSOC_TOK_IDENT 102
#define QASSOC_TOK_DOT 103
#define QASSOC_TOK_EQU 104
#define QASSOC_TOK_COLON 105
#define QASSOC_TOK_ERROR 1
#define QASSOC_TOK_EOF 0
#define ST_IDENT 13
#define ST_STRING 19
#define ST_QSTRING 26
#define ST_QSTRING_ESC 30
//***************************************************************************
//
// CSQLBuilder::FormatSQL
//
//***************************************************************************
HRESULT CSQLBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope, IWbemQuery *pQuery, _bstr_t &sSQL, DWORD dwFlags, DWORD dwHandleType, SQL_ID *dClassId, BOOL *bHierarchyQuery, BOOL bTmpTblOK, BOOL *bDeleteQuery, BOOL *bDefault) {
// This needs to convert an entire query
// into SQL. We assume that any attempt to get
// a specific object will be done through GetObject.
// This is strictly to return the ObjectIds of heterogenous
// query results.
HRESULT hr = WBEM_S_NO_ERROR;
if (!m_pSchema) return WBEM_E_NOT_FOUND;
char szTmpNum[25]; BOOL bPartialFailure = FALSE; m_dwTableCount = 1; m_bClassSpecified = false;
m_dNamespace = dScopeId;
if (bHierarchyQuery) *bHierarchyQuery = FALSE; _bstr_t sColList, sFrom, sWhere;
sColList = L"select a.ObjectId, a.ClassId, a.ObjectScopeId "; sFrom = L" from ObjectMap as a "; sWhere = L" where a.ObjectState <> 2"; // Query types:
// ===========
// WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_SCOPE : ObjectScopeId = %I64d
// WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_CONTAINER: inner join ContainerObjs as b on b.ContaineeId = a.ObjectId
// and b.ContainerId = %I64d
// WMIDB_FLAG_QUERY_DEEP + <any> : inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != %I64d))
if (m_dNamespace) { sprintf(szTmpNum, "%I64d", m_dNamespace);
// Scope is an __Instances container
// This is shallow by definition.
if (dScopeClassId == INSTANCESCLASSID) { sWhere += L" and a.ObjectKey != 'root' and a.ClassId = "; sWhere += szTmpNum; char szTmp[25]; sprintf(szTmp, "%I64d", dSuperScope); sWhere += L" and a.ObjectScopeId in (0, "; sWhere += szTmp; sWhere += L")"; } else { // Shallow enumeration
if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP)) { if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) { sFrom += L" inner join ContainerObjs as z on z.ContaineeId = a.ObjectId " L" and z.ContainerId = "; sFrom += szTmpNum; } else { sWhere += L" and a.ObjectKey != 'root' and a.ObjectScopeId in (0,"; sWhere += szTmpNum; sWhere += L")"; } } // Deep enumeration, we enumerate all contained and subscope objects.
else { if (bTmpTblOK) { sFrom += L" inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != "; sFrom += szTmpNum; sFrom += L"))"; } else hr = E_NOTIMPL; } } }
if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) m_dNamespace = dSuperScope; // Containers are not valid scopes.
sSQL = "";
if (pQuery) { SWQLNode *pTop = NULL, *pRoot = NULL; pQuery->GetAnalysis(WMIQ_ANALYSIS_RESERVED, 0, (void **)&pTop); if (pTop && pTop->m_pLeft) { pRoot = pTop->m_pLeft;
if (bDeleteQuery) { if (pRoot->m_dwNodeType == TYPE_SWQLNode_Delete) *bDeleteQuery = TRUE; else *bDeleteQuery = FALSE; }
// *** WARNING ***
// This is phase I of this formatting code.
// In the future, we will need to also support
// joins, counts, order by, group by, having,
// qualifier queries, and lots of other stuff
// that has yet to be defined.
// For now, this will just return a single
// ObjectId for any query that is passed in.
// Reject any query with Where options (order by, group by)
if (pRoot->m_pRight != NULL) { if (pRoot->m_pRight->m_pRight != NULL) { bPartialFailure = TRUE; } }
// No counts, or multi-table queries.
if (pRoot->m_pLeft != NULL) { hr = GetClassFromNode(pRoot->m_pLeft, bDefault); if (SUCCEEDED(hr)) { if (m_dClassID == 1) { sWhere += L" and a.ClassId = 1"; if (bDefault) *bDefault = TRUE; } else if (m_dClassID == INSTANCESCLASSID) { wchar_t wTemp[128]; swprintf(wTemp, L" select a.ObjectId, %I64d, a.ObjectScopeId ", INSTANCESCLASSID); sColList = wTemp;
sWhere += L" and a.ClassId = 1"; // Classes only
if (bDefault) *bDefault = TRUE; } } }
if (SUCCEEDED(hr)) { // Now we parse the where clause.
if (pRoot->m_pRight && pRoot->m_pRight->m_pLeft) { _bstr_t sNewSQL; bool bSys = false; hr = FormatWhereClause((SWQLNode_RelExpr *)pRoot->m_pRight->m_pLeft, sNewSQL, L"a", bSys); if (SUCCEEDED(hr)) { if (bSys) { sFrom += L" inner join vSystemProperties as av on av.ObjectId = a.ObjectId "; } sWhere += L" AND "; sWhere += sNewSQL;
// Make sure the results are limited to instances of the requested class
// (Safeguard)
if (!m_bClassSpecified) { wchar_t wTemp[256]; if (bSys) { swprintf(wTemp, L" and exists (select * from ClassData as j where av.ObjectId = j.ObjectId" L" and j.ClassId= %I64d) ", m_dClassID); } else { // __Instances is automatically a shallow hierarchy query
if (m_dClassID != INSTANCESCLASSID) { // Until we figure out how to do this in Jet,
// we will only select instances of the requested class.
if (bTmpTblOK) wcscpy(wTemp, L" AND EXISTS (select b.ClassId from #Children as b " L" where b.ClassId = a.ClassId )"); else swprintf(wTemp, L" AND a.ClassId = %I64d", m_dClassID);
if (bHierarchyQuery) *bHierarchyQuery = TRUE; } }
sWhere += wTemp; } }
} else { // __Instances is automatically a shallow hierarchy query
if (m_dClassID != INSTANCESCLASSID) { wchar_t wTemp[256]; // If no criteria, make sure we only get the class we asked for.
if (bTmpTblOK) wcscpy(wTemp, L" AND EXISTS (select b.ClassId from #Children as b " L" where b.ClassId = a.ClassId)"); else swprintf(wTemp, L" AND a.ClassId = %I64d", m_dClassID);
if (bHierarchyQuery) *bHierarchyQuery = TRUE; sWhere += wTemp; } }
sSQL = sColList + sFrom + sWhere;
if (dClassId) *dClassId = m_dClassID; } } } else hr = WBEM_E_INVALID_PARAMETER;
if ((SUCCEEDED(hr) && bPartialFailure)) hr = WBEM_E_PROVIDER_NOT_CAPABLE;
return hr; }
//***************************************************************************
//
// CSQLBuilder::FormatSQL
//
//***************************************************************************
HRESULT CSQLBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope, SQL_ID dTargetObjID, LPWSTR pResultClass, LPWSTR pAssocClass, LPWSTR pRole, LPWSTR pResultRole, LPWSTR pRequiredQualifier, LPWSTR pRequiredAssocQualifier, DWORD dwQueryType, _bstr_t &sSQL, DWORD dwFlags, DWORD dwHandleType, SQL_ID *_dAssocClass, SQL_ID *_dResultClass, BOOL bIsClass) { // Query types:
// ===========
// WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_SCOPE : ObjectScopeId = %I64d
// WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_CONTAINER: inner join ContainerObjs as b on b.ContaineeId = a.ObjectId
// and b.ContainerId = %I64d
// WMIDB_FLAG_QUERY_DEEP + <any> : inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != %I64d))
// Scope = __Instances=<Class>: and ClassId = %I64d
HRESULT hr = WBEM_S_NO_ERROR; DWORD dwRoleID = 0, dwResultRole = 0, dwAssocQfr = 0; SQL_ID dAssocClass = 0, dTargetObj = 0, dThisClassId = 0; bool bWhereReq = true; _bstr_t sRole = "", sAssocQfr = "", sAssocClass = "", sResultRole = ""; _bstr_t sName; SQL_ID dwSuperClassID; SQL_ID dwScopeID; DWORD dwTemp; _bstr_t sJoin = L"RefId";
hr = m_pSchema->GetClassInfo(dTargetObjID, sName, dwSuperClassID, dwScopeID, dwTemp); if (SUCCEEDED(hr)) { dThisClassId = dTargetObjID; sJoin = L"RefClassId"; } hr = WBEM_S_NO_ERROR;
m_dNamespace = dScopeId;
if (dwQueryType & QUERY_TYPE_CLASSDEFS_ONLY) sSQL = L"select distinct a.ClassId, 1, 0 "; else sSQL = L"select a.ObjectId, a.ClassId, a.ObjectScopeId ";
sSQL += L" from ObjectMap as a "; if (m_dNamespace) { char szTmp[25]; sprintf(szTmp, "%I64d", m_dNamespace);
if (dScopeClassId == INSTANCESCLASSID) { sSQL += L" WHERE a.ClassId = "; sSQL += szTmp; sprintf(szTmp, "%I64d", dSuperScope); sSQL += L" and a.ObjectScopeId = "; sSQL += szTmp; } else { if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP)) { if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) { sSQL += L" inner join ContainerObjs as z on z.ContaineeId = a.ObjectId " L" WHERE z.ContainerId = "; sSQL += szTmp; } else { sSQL += " WHERE a.ObjectScopeId = "; sSQL += szTmp; } } else { sSQL += L" inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != "; sSQL += szTmp; sSQL += L" )) "; } }
sSQL += L" AND ";
} else sSQL += " WHERE "; sSQL += " a.ObjectState <> 2 AND ";
// Containers are not valid scopes.
if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) m_dNamespace = dSuperScope;
// RESULTCLASS
if (pResultClass != NULL) { wchar_t wTemp[100];
// Get the class ID of this class
hr = m_pSchema->GetClassID(pResultClass, m_dNamespace, dThisClassId); if (FAILED(hr)) goto Exit;
swprintf(wTemp, L" a.ClassId = %I64d", dThisClassId); bWhereReq = false; sSQL += wTemp; if (_dResultClass) *_dResultClass = dThisClassId; } // REQUIREDQUALIFIER
if (pRequiredQualifier != NULL) { /*
wchar_t wTemp[255]; DWORD dwPropId = 0; hr = m_pSchema->GetPropertyID(pRequiredQualifier, dThisClassId, REPDRVR_FLAG_QUALIFIER, REPDRVR_IGNORE_CIMTYPE, dwPropId, NULL, NULL, NULL, TRUE); if (FAILED(hr)) goto Exit;
if (!bWhereReq) sSQL += L" AND ";
// FIXME: This will only work on class-level qualifiers.
// It will not work on instance qualifiers.
swprintf(wTemp, L"EXISTS (select ClassId from ClassData as c where a.ClassId = c.ObjectId and c.PropertyId = %ld)", dwPropId); bWhereReq = false; sSQL += wTemp; */ }
if (!bWhereReq) sSQL += " AND ";
// ROLE
if (pRole) { wchar_t wTemp[512]; swprintf(wTemp, L" and b.PropertyId in (select PropertyId from PropertyMap where PropertyName = '%s')", pRole); sRole = wTemp; }
// RESULTROLE
if (pResultRole) { wchar_t wTemp[512]; swprintf(wTemp, L" and b.PropertyId in (select PropertyId from PropertyMap where PropertyName = '%s')", pResultRole); sResultRole = wTemp; }
// REQUIREDASSOCQUALIFIER
if (pRequiredAssocQualifier) { /*
wchar_t wTemp[256]; hr = m_pSchema->GetPropertyID(pRequiredAssocQualifier, dThisClassId, REPDRVR_FLAG_QUALIFIER, REPDRVR_IGNORE_CIMTYPE, dwAssocQfr, NULL, NULL, NULL, TRUE); if (FAILED(hr)) goto Exit; swprintf(wTemp, L" AND EXISTS (select ObjectId from ClassData as d where b.ClassId = d.ObjectId and d.PropertyId = %ld)", dwAssocQfr); sAssocQfr = wTemp; */ }
// ASSOCCLASS
if (pAssocClass) { wchar_t wTemp[256]; hr = m_pSchema->GetClassID(pAssocClass, m_dNamespace, dAssocClass); if (FAILED(hr)) goto Exit; swprintf(wTemp, L" AND b.ClassId = %I64d", dAssocClass); sAssocClass = wTemp; if (_dAssocClass) *_dAssocClass = dAssocClass; }
if (dwQueryType & QUERY_TYPE_GETREFS) { wchar_t wTemp[1024];
if (!bIsClass) { swprintf(wTemp, L" EXISTS (select ObjectId from ClassData as b where a.ObjectId = b.ObjectId " L" %s and b.%s = %I64d)", (const wchar_t *)sRole, (const wchar_t *)sJoin, dTargetObjID); } else { swprintf(wTemp, L" a.ClassId = 1 AND EXISTS (select r.ClassId from ReferenceProperties as r " L" where r.ClassId = a.ObjectId and r.RefClassId = %I64d)", dTargetObjID); }
sSQL += wTemp; } else { wchar_t wTemp[2048]; if (!bIsClass) { swprintf(wTemp, L" EXISTS (select b.RefId from ClassData as b inner join ClassData as c on c.ObjectId = b.ObjectId " L" where c.RefId = a.ObjectId and b.%s = %I64d and c.RefId <> b.RefId %s%s%s%s)", (const wchar_t *)sJoin, dTargetObjID, (const wchar_t *)sRole, (const wchar_t *)sResultRole, (const wchar_t *)sAssocClass, (const wchar_t *)sAssocQfr); } else { swprintf(wTemp, L" a.ClassId = 1 AND EXISTS (select r.ClassId from ReferenceProperties as r " L" INNER JOIN ReferenceProperties as r2 on r.ClassId = r2.ClassId and r.PropertyId <> r2.PropertyId" L" where r.ClassId = a.ObjectId and r2.RefClassId = %I64d)", dTargetObjID);
} sSQL += wTemp; }
Exit:
return hr;
} //***************************************************************************
//
// CSQLBuilder::FormatWhereClause
//
//***************************************************************************
HRESULT CSQLBuilder::FormatWhereClause (SWQLNode_RelExpr *pNode, _bstr_t &sSQL, LPCWSTR lpJoinAlias, bool &bSysPropsUsed) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bDone = FALSE; SQL_ID dClassId = 0;
// For each node, we need to
// 1. Look at the node type (and, or, not or typed)
// 2. If not typed, group and continue
// 3. If typed, construct the clause based on the property ID of the
// property, the value and the operator.
if (pNode) { DWORD dwType = pNode->m_dwExprType; _bstr_t sTemp;
switch(dwType) { case WQL_TOK_OR: case WQL_TOK_AND: if (pNode->m_pLeft) { sTemp = "("; hr |= FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, sTemp, lpJoinAlias, bSysPropsUsed); } if (dwType == WQL_TOK_OR) sTemp += " OR "; else sTemp += " AND ";
if (pNode->m_pRight) { hr |= FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pRight, sTemp, lpJoinAlias, bSysPropsUsed); sTemp += ")"; }
sSQL += sTemp;
break; case WQL_TOK_NOT: sSQL += " NOT ";
// Supposedly, only a left clause follows not...
if (pNode->m_pLeft) { hr = FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, sTemp, lpJoinAlias, bSysPropsUsed); sSQL += sTemp; } m_bClassSpecified = false; // whatever we've done probably negated the class qualifier.
break;
default: // Typed expression
m_dwTableCount++; SWQLTypedExpr *pExpr = ((SWQLNode_RelExpr *)pNode)->m_pTypedExpr; if (pExpr != NULL) { DWORD dwProp1 = 0, dwProp2 = 0, dwOp = 0; DWORD dwStorage1 = 0, dwStorage2 = 0; DWORD dwKey1, dwKey2; _bstr_t sPropName, sValue, sSrc; wchar_t sAlias[256]; swprintf(sAlias, L"%s%ld", lpJoinAlias, m_dwTableCount);
_bstr_t sColName; if (pExpr->m_pColRef) sColName = pExpr->m_pColRef; else if (pExpr->m_pIntrinsicFuncOnColRef && !_wcsicmp(pExpr->m_pIntrinsicFuncOnColRef, L"datepart") && pExpr->m_pLeftFunction) { sColName = ((SWQLNode_Datepart *)pExpr->m_pLeftFunction)->m_pColRef->m_pColName; } hr = GetPropertyID(m_dClassID, pExpr->m_pQNLeft, sColName, dwProp1, dwStorage1, dwKey1);
if (SUCCEEDED(hr)) { if (dwStorage1 == WMIDB_PROPERTY_THIS) { // Special-case: the __this property.
hr = m_pSchema->GetClassID(pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace, dClassId); if (SUCCEEDED(hr) && dClassId != 1) { sSQL += L" a.ObjectId in (";
SQL_ID *pIDs = NULL; int iNumChildren = 0; hr = m_pSchema->GetDerivedClassList(dClassId, &pIDs, iNumChildren); if (SUCCEEDED(hr)) { char szTmp[25]; sprintf(szTmp, "%I64d", dClassId); sSQL += szTmp;
for (int i = 0; i < iNumChildren; i++) { sSQL += L","; sprintf(szTmp, "%I64d", pIDs[i]); sSQL += szTmp; } delete pIDs; sSQL += L")"; } }
} else { GetStorageTable(dwStorage1, dwKey1, sSrc);
if (dwStorage1 == WMIDB_STORAGE_COMPACT) swprintf(sAlias, L"%sv", lpJoinAlias);
// Can't query anything stored as image
if (dwStorage1 == WMIDB_STORAGE_IMAGE || dwStorage2 == WMIDB_STORAGE_IMAGE) return WBEM_E_QUERY_NOT_IMPLEMENTED;
dwOp = pExpr->m_dwRelOperator;
hr = FunctionalizeProperty (sAlias, dwStorage1, pExpr->m_pIntrinsicFuncOnColRef, pExpr->m_pLeftFunction, pExpr->m_pColRef, sPropName);
if (SUCCEEDED(hr)) { if (pExpr->m_pConstValue != NULL) { CIMTYPE ct=0; m_pSchema->GetPropertyInfo(dwProp1, NULL, NULL, NULL, (DWORD *)&ct); if (ct != CIM_DATETIME) hr = FunctionalizeValue (pExpr->m_pConstValue, dwStorage1, pExpr->m_pIntrinsicFuncOnConstValue, sValue); else { // Skip this token...
// The core will post-filter.
bDone = TRUE; sSQL += L" 1=1 "; } } else if (pExpr->m_pJoinColRef != NULL) { // SPECIAL CASE. To compare two properties, we deliberately cause a join to happen.
m_dwTableCount++; wchar_t sAlias2[256]; _bstr_t sSrc2; _bstr_t sPropName2, sExtra = L"";
if (pExpr->m_pJoinColRef) sColName = pExpr->m_pJoinColRef; else if (pExpr->m_pIntrinsicFuncOnJoinColRef && !_wcsicmp(pExpr->m_pIntrinsicFuncOnJoinColRef, L"datepart") && pExpr->m_pRightFunction) { sColName = ((SWQLNode_Datepart *)pExpr->m_pRightFunction)->m_pColRef->m_pColName; }
hr = GetPropertyID(m_dClassID, pExpr->m_pQNRight, sColName, dwProp2, dwStorage2, dwKey2); GetStorageTable(dwStorage2, dwKey2, sSrc2); if (dwStorage2 == WMIDB_STORAGE_COMPACT) swprintf(sAlias2, L"%sv", lpJoinAlias); else swprintf(sAlias2, L"%s%ld", lpJoinAlias, m_dwTableCount);
hr = FunctionalizeProperty (sAlias2, dwStorage2, pExpr->m_pIntrinsicFuncOnJoinColRef, pExpr->m_pRightFunction, pExpr->m_pJoinColRef, sPropName2);
if (pExpr->m_pQNRight) { SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNRight->m_aFields[0]; hr = FormatPositionQuery(pNF, pExpr->m_dwRightArrayIndex, sAlias2, sTemp); if (SUCCEEDED(hr)) sExtra = sTemp; } if (pExpr->m_pQNLeft) { SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNLeft->m_aFields[0]; hr = FormatPositionQuery(pNF, pExpr->m_dwLeftArrayIndex, sAlias, sTemp); if (SUCCEEDED(hr)) sExtra += sTemp; }
if (SUCCEEDED(hr)) { wchar_t wTempSQL[2048];
// If the right side is a system property, we just treat this
// like a regular comparison.
if (dwStorage2 == WMIDB_STORAGE_COMPACT) { bSysPropsUsed = true; bDone = false; sValue = sPropName2; } // If the left side is a system property, we need to reverse the
// values and let it through...
else if (dwStorage1 == WMIDB_STORAGE_COMPACT) { sValue = sPropName; sPropName = sPropName2; wcscpy(sAlias,sAlias2); dwProp1 = dwProp2; bSysPropsUsed = true; dwStorage1 = dwStorage2; sSrc = sSrc2; } // Otherwise, we create a new join and wrap up.
else { LPWSTR lpOp = GetOperator(dwOp); CDeleteMe <wchar_t> r (lpOp);
swprintf(wTempSQL, L" EXISTS " L" (select %s.ObjectId from %s as %s inner join %s as %s on %s%s%s and %s.ObjectId = %s.ObjectId " L" where %s.ObjectId=%s.ObjectId and %s.PropertyId = %ld and %s.PropertyId = %ld%s)", sAlias, (const wchar_t *)sSrc, sAlias, (const wchar_t *)sSrc2, sAlias2, (const wchar_t *)sPropName, lpOp,(const wchar_t *)sPropName2, sAlias, sAlias2, lpJoinAlias, sAlias, sAlias, dwProp1, sAlias2, dwProp2, (const wchar_t *)sExtra); bDone = TRUE; sSQL += wTempSQL; }
} }
if (SUCCEEDED(hr) && !bDone) { _bstr_t sPrefix = ""; LPWSTR lpOp = GetOperator(dwOp);
if (!lpOp || !wcslen(lpOp)) { switch (dwOp) { case WQL_TOK_NULL: case WQL_TOK_ISNULL: sPrefix = " NOT "; sValue = ""; break; case WQL_TOK_NOT_NULL: sValue = ""; break; case WQL_TOK_ISA: sPropName = sAlias; sPropName += L".RefClassId"; delete lpOp; lpOp = new wchar_t [10]; if (lpOp) { hr = m_pSchema->GetClassID(pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace, dClassId); if (SUCCEEDED(hr) && dClassId != 1) { wcscpy(lpOp, L" in "); sValue = L"("; SQL_ID *pIDs = NULL; int iNumChildren = 0; hr = m_pSchema->GetDerivedClassList(dClassId, &pIDs, iNumChildren); if (SUCCEEDED(hr)) { char szTmp[25]; sprintf(szTmp, "%I64d", dClassId); sValue += szTmp;
for (int i = 0; i < iNumChildren; i++) { sValue += L","; sprintf(szTmp, "%I64d", pIDs[i]); sValue += szTmp; } delete pIDs; sValue += L")"; } if (dwStorage1 == WMIDB_STORAGE_COMPACT) dwStorage1 = WMIDB_STORAGE_REFERENCE; } else { wcscpy(lpOp, L" <> "); sValue = L"0"; } } else hr = WBEM_E_OUT_OF_MEMORY; break; case WQL_TOK_BETWEEN: delete lpOp; lpOp = new wchar_t [10]; if (lpOp) { wcscpy(lpOp, L" between "); sValue += " and "; hr = FunctionalizeValue (pExpr->m_pConstValue2, dwStorage2, pExpr->m_pIntrinsicFuncOnConstValue, sTemp); sValue += sTemp; } else hr = WBEM_E_OUT_OF_MEMORY; break; case WQL_TOK_NOT_IN: case WQL_TOK_IN: case WQL_TOK_IN_SUBSELECT: case WQL_TOK_NOT_IN_SUBSELECT: case WQL_TOK_IN_CONST_LIST: case WQL_TOK_NOT_IN_CONST_LIST: delete lpOp; lpOp = new wchar_t [10]; if (lpOp) { wcscpy(lpOp, L""); if (pExpr->m_dwRelOperator == WQL_TOK_NOT_IN || pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_SUBSELECT || pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_CONST_LIST) { wcscpy(lpOp, L" not "); } wcscat(lpOp, L" in "); sValue = "(";
if (pExpr->m_dwRelOperator == WQL_TOK_IN_SUBSELECT || pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_SUBSELECT) { // If a subselect, we need to construct an entirely new tree, passing
// in the current alias.
_bstr_t sTemp; m_dwTableCount++; wchar_t wAlias3[256]; swprintf(wAlias3, L"%s%ld", lpJoinAlias, m_dwTableCount);
wchar_t *pColName = sPropName; pColName += wcslen(sAlias)+1;
hr = FormatSimpleSelect (wAlias3, pColName, pExpr->m_pSubSelect, sTemp); if (SUCCEEDED(hr)) sValue += sTemp; } else { // If a const list, behaves as normal
if (pExpr->m_pConstList) { for (int iPos = 0; iPos < pExpr->m_pConstList->m_aValues.Size(); iPos++) { if (iPos > 0) sValue += ",";
hr = FunctionalizeValue(((SWQLTypedConst *)pExpr->m_pConstList->m_aValues.GetAt(iPos)), dwStorage1, pExpr->m_pIntrinsicFuncOnConstValue, sTemp); sValue += sTemp; } } }
sValue += ")"; } else hr = WBEM_E_OUT_OF_MEMORY; break; default: break; } }
if (SUCCEEDED(hr)) { long lLen = wcslen(sValue) + 512;
wchar_t *pTempSQL = new wchar_t[lLen]; CDeleteMe <wchar_t> r (pTempSQL); if (pTempSQL) { if (sValue.length() != 0) { if (dwStorage1 != WMIDB_STORAGE_COMPACT) sTemp = L" and ";
sTemp += sPropName + lpOp + sValue; sValue = sTemp; } // Set array position (for left value only)
if (pExpr->m_dwLeftFlags & WQL_FLAG_COMPLEX_NAME) { if (pExpr->m_pQNLeft) { SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNLeft->m_aFields[0]; hr = FormatPositionQuery(pNF, pExpr->m_dwLeftArrayIndex, sAlias, sTemp); if (SUCCEEDED(hr)) sValue + sTemp;
} }
if (dwStorage1 != WMIDB_STORAGE_COMPACT) { swprintf(pTempSQL, L"%s EXISTS (select %s.ObjectId from %s as %s where %s.ObjectId=%s.ObjectId and %s.PropertyId = %ld %s)", (const wchar_t *)sPrefix, sAlias, (const wchar_t *)sSrc, sAlias, sAlias, lpJoinAlias, sAlias, dwProp1, (const wchar_t *)sValue); } else { bSysPropsUsed = true; // This is a straight comparison on a system property...
swprintf(pTempSQL, L" %s", (const wchar_t *)sValue); } sSQL += pTempSQL; } else hr = WBEM_E_OUT_OF_MEMORY; delete lpOp; } } } } }
} break; } }
return hr; }
//***************************************************************************
//
// CSQLBuilder::GetStorageTable
//
//***************************************************************************
HRESULT CSQLBuilder::GetStorageTable(DWORD dwStorage, DWORD dwKey, _bstr_t &sTable) { if (dwStorage == WMIDB_STORAGE_COMPACT) sTable = L"vSystemProperties"; else { sTable = L"ClassData";
if (dwKey & 4 || dwKey & 8) { switch(dwStorage) { case WMIDB_STORAGE_STRING: sTable = L"IndexStringData"; break; case WMIDB_STORAGE_NUMERIC: sTable = L"IndexNumericData"; break; case WMIDB_STORAGE_REAL: sTable = L"IndexRealData"; break; case WMIDB_STORAGE_REFERENCE: sTable = L"IndexRefData"; break; } } } return WBEM_S_NO_ERROR; }
//***************************************************************************
//
// CSQLBuilder::GetPropertyID
//
//***************************************************************************
HRESULT CSQLBuilder::GetPropertyID (SQL_ID dClassID, SWQLQualifiedName *pQN, LPCWSTR pColRef, DWORD &PropID, DWORD &Storage, DWORD &Flags) {
// If this is an embedded object property,
// we need the actual class ID. The only way
// to do that is the walk through all the properties,
// and reconcile each layer.
BOOL bThis = FALSE;
HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dRefClassId = dClassID;
if (pQN != NULL) { /*
for (int i = pQN->GetNumNames() - 1; i >= 0; i--) { SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pQN->m_aFields[i]; if (pNF) { hr = m_pSchema->GetPropertyID(pNF->m_pName, dRefClassId, 0, REPDRVR_IGNORE_CIMTYPE, PropID, &dClassID, NULL, NULL, TRUE); if (SUCCEEDED(hr)) { // Look up the property ID for this class.
hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage, NULL, &Flags); } } } */ hr = WBEM_E_PROVIDER_NOT_CAPABLE; } else if (pColRef != NULL) { wchar_t wName[1024]; if (!_wcsicmp(pColRef, L"__this")) { Storage = WMIDB_PROPERTY_THIS; bThis = TRUE; m_bClassSpecified = true; // they are specifying which classes they want...
} else { wcscpy(wName, pColRef);
// Look up the property ID for this class.
hr = m_pSchema->GetPropertyID(wName, m_dClassID, 0, REPDRVR_IGNORE_CIMTYPE, PropID, &dClassID, NULL, NULL, TRUE); if (SUCCEEDED(hr)) hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage, NULL, &Flags); } } else hr = WBEM_E_INVALID_PARAMETER;
if (!bThis) { if (m_dClassID == dClassID) m_bClassSpecified = true;
if (Flags & REPDRVR_FLAG_SYSTEM) Storage = WMIDB_STORAGE_COMPACT; }
return hr;
}
//***************************************************************************
//
// CSQLBuilder::FunctionalizeProperty
//
//***************************************************************************
HRESULT CSQLBuilder::FunctionalizeProperty (LPCWSTR lpAlias, DWORD dwType, LPWSTR lpFuncName, SWQLNode *pFunction, LPWSTR lpColName, _bstr_t &sProp) { // Apply any functions to the appropriate column of ClassData
HRESULT hr = WBEM_S_NO_ERROR; bool bRef = false;
_bstr_t sTemp;
if (lpFuncName != NULL) { if (!_wcsicmp(lpFuncName, L"datepart")) sTemp = L"substring"; else sTemp = lpFuncName;
sTemp += "("; }
sTemp += lpAlias; sTemp += L".";
switch(dwType) { case WMIDB_STORAGE_STRING: // Unicode
sTemp += L"PropertyStringValue"; break; case WMIDB_STORAGE_NUMERIC: // SQL_ID
sTemp += L"PropertyNumericValue"; break; case WMIDB_STORAGE_REAL: // real
sTemp += L"PropertyRealValue"; break; case WMIDB_STORAGE_REFERENCE: // REF: Since this is stored as a number, we have to
// subselect to get the real path, and apply all
// functions to it.
bRef = true; sTemp = L"(select ObjectPath from ObjectMap where ObjectId = "; sTemp += lpAlias; sTemp += ".RefId)"; break; case WMIDB_STORAGE_COMPACT: // System property, using vSystemProperties
sTemp += lpColName; break; default: hr = WBEM_E_INVALID_QUERY; break; }
if (pFunction) { if (pFunction->m_dwNodeType == TYPE_SWQLNode_Datepart) { sTemp += ",";
switch(((SWQLNode_Datepart *)pFunction)->m_nDatepart) { case WQL_TOK_YEAR: sTemp += L"1,4"; break; case WQL_TOK_MONTH: sTemp += L"5,2"; break; case WQL_TOK_DAY: sTemp += L"7,2"; break; case WQL_TOK_HOUR: sTemp += L"9,2"; break; case WQL_TOK_MINUTE: sTemp += L"11,2"; break; case WQL_TOK_SECOND: sTemp += L"13,2"; break; case WQL_TOK_MILLISECOND: sTemp += L"16,6"; break; default: hr = WBEM_E_INVALID_QUERY; break; } } }
if (lpFuncName != NULL) { sTemp += ")"; }
if (SUCCEEDED(hr)) sProp = sTemp;
return hr; }
//***************************************************************************
//
// CSQLBuilder::FunctionalizeValue
//
//***************************************************************************
HRESULT CSQLBuilder::FunctionalizeValue(SWQLTypedConst *pValue, DWORD dwType, LPWSTR lpFuncName, _bstr_t &sValue) { // Apply any functions to the data, and add quotes as appropriate.
HRESULT hr = WBEM_S_NO_ERROR; _bstr_t sTemp;
if (lpFuncName) { sTemp = lpFuncName; sTemp += L"("; }
if (pValue->m_dwType == VT_LPWSTR) { sTemp += L"'"; LPWSTR lpTemp = StripQuotes(pValue->m_Value.m_pString); CDeleteMe <wchar_t> r (lpTemp); LPWSTR lpTemp2 = StripQuotes(lpTemp, '%'); CDeleteMe <wchar_t> r2 (lpTemp2);
if (dwType == WMIDB_STORAGE_COMPACT && !wcslen(lpTemp2)) sTemp += L"meta_class"; else sTemp += lpTemp2; sTemp += L"'"; } else if(pValue->m_dwType == VT_NULL) { hr = WBEM_E_INVALID_QUERY; } else if (pValue->m_dwType == VT_I4) { char szTmp[25]; sprintf(szTmp, "%ld", pValue->m_Value.m_lValue); sTemp += szTmp; } else if (pValue->m_dwType == VT_BOOL) { if (pValue->m_Value.m_bValue) sTemp += L"1"; else sTemp += L"0"; } else if (pValue->m_dwType == VT_R8) { char szTmp[25]; sprintf(szTmp, "%lG", pValue->m_Value.m_dblValue); sTemp += szTmp; }
if (lpFuncName) { sTemp += L")"; }
if (SUCCEEDED(hr)) sValue = sTemp;
return hr; }
//***************************************************************************
//
// CSQLBuilder::FormatSimpleSelect
//
//***************************************************************************
HRESULT CSQLBuilder::FormatSimpleSelect (LPCWSTR lpUseAlias,LPCWSTR lpColName, SWQLNode *pTop, _bstr_t &sSQL) { // Internal use only: This is to format subselects, so it should
// consist of a single column select from a known class.
HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dClassID; DWORD dwPropID = 0, dwStorage = 0, dwFlags = 0; _bstr_t sSrc = L""; _bstr_t sExtra=L""; _bstr_t sSubCol = lpColName;
if (pTop) { if (pTop->m_pLeft) { if (pTop->m_pLeft->m_pRight) { SWQLNode_TableRef *pRef = (SWQLNode_TableRef *)pTop->m_pLeft->m_pRight->m_pLeft; hr = m_pSchema->GetClassID(pRef->m_pTableName, m_dNamespace, dClassID); if (FAILED(hr)) hr = WBEM_E_INVALID_QUERY; } else hr = WBEM_E_INVALID_QUERY; if (pTop->m_pLeft->m_pLeft) { SWQLNode_ColumnList *pList = (SWQLNode_ColumnList *)pTop->m_pLeft->m_pLeft; SWQLColRef *pCol = (SWQLColRef *)pList->m_aColumnRefs[0]; if (pCol) { _bstr_t sName = pCol->m_pColName; if (pCol->m_dwFlags & WQL_FLAG_COMPLEX_NAME) { SWQLQualifiedName *pQN = pCol->m_pQName; if (pQN) { hr = FormatPositionQuery((SWQLQualifiedNameField *)pQN->m_aFields[0], pCol->m_dwArrayIndex, lpUseAlias, sExtra); } } hr = GetPropertyID(dClassID, pCol->m_pQName, pCol->m_pColName, dwPropID, dwStorage, dwFlags); if (SUCCEEDED(hr)) { GetStorageTable(dwStorage, dwFlags, sSrc); // If we are comparing different types,
// or using a system property, get the new col name
FunctionalizeProperty (lpUseAlias, dwStorage, NULL, NULL, pCol->m_pColName, sSubCol); }
} } } else hr = WBEM_E_INVALID_QUERY; } else hr = WBEM_E_INVALID_QUERY;
if (SUCCEEDED(hr)) { wchar_t wTemp[256]; wchar_t wWhere[512]; _bstr_t sTemp, sTempSQL;
// Construct the *simple* where clause....
// If there is any where element at all, we need to ditch the
// simple approach and revert to the subselect set...
// ==========================================================
swprintf(wTemp, L"select %s from %s as %s", (const wchar_t *)sSubCol, (const wchar_t *)sSrc, lpUseAlias);
sTemp = wTemp;
if (dwStorage == WMIDB_STORAGE_COMPACT) swprintf(wWhere, L" where %s.ClassId = %I64d", lpUseAlias, dClassID); else swprintf(wWhere, L" where PropertyId = %ld%s", dwPropID, (const wchar_t *)sExtra);
if (pTop->m_pRight) { bool bSysPropsUsed = false; hr = FormatWhereClause((SWQLNode_RelExpr *)pTop->m_pRight->m_pLeft, sTempSQL, lpUseAlias, bSysPropsUsed); if (SUCCEEDED(hr) && sTempSQL.length() > 0) { if (bSysPropsUsed && !(dwStorage == WMIDB_STORAGE_COMPACT)) { wchar_t NewSQL[1024]; swprintf(NewSQL, L" inner join vSystemProperties as %sv on %sv.ObjectId = %s.ObjectId and %sv.ClassId = %I64d", lpUseAlias, lpUseAlias, lpUseAlias, lpUseAlias, dClassID); sTemp += NewSQL; } sTemp += wWhere; sTemp += L" AND "; sTemp += sTempSQL; } else sTemp += wWhere; }
sSQL = sTemp; }
return hr; }
//***************************************************************************
//
// CSQLBuilder::FormatPositionQuery
//
//***************************************************************************
HRESULT CSQLBuilder::FormatPositionQuery (SWQLQualifiedNameField *pQNF, int iPos, LPCWSTR lpAlias, _bstr_t &sQuery) { HRESULT hr = WBEM_S_NO_ERROR; wchar_t wTemp[128]; int iTemp;
if (pQNF) { if (pQNF->m_bArrayRef) { iTemp = (int)pQNF->m_dwArrayIndex; } } else iTemp = iPos;
swprintf(wTemp, L"and %s.ArrayPos = %ld", lpAlias, iTemp);
sQuery = wTemp;
return hr;
}
//***************************************************************************
//
// CSQLBuilder::GetClassFromNode
//
//***************************************************************************
HRESULT CSQLBuilder::GetClassFromNode (SWQLNode *pNode, BOOL *bDefaultStorage) { HRESULT hr = WBEM_S_NO_ERROR;
LPWSTR lpTableName = NULL;
switch(pNode->m_dwNodeType) { case TYPE_SWQLNode_TableRefs:
if (((SWQLNode_TableRefs *)pNode)->m_nSelectType == WQL_FLAG_COUNT) return WBEM_E_PROVIDER_NOT_CAPABLE; if (pNode->m_pRight != NULL) { if (pNode->m_pRight->m_pLeft->m_dwNodeType != TYPE_SWQLNode_TableRef) hr = WBEM_E_PROVIDER_NOT_CAPABLE; else { SWQLNode_TableRef *pRef = (SWQLNode_TableRef *)pNode->m_pRight->m_pLeft; lpTableName = pRef->m_pTableName; } } else return WBEM_E_INVALID_SYNTAX;
break; case TYPE_SWQLNode_TableRef: if (pNode->m_dwNodeType != TYPE_SWQLNode_TableRef) hr = WBEM_E_INVALID_SYNTAX; else lpTableName = ((SWQLNode_TableRef *)pNode)->m_pTableName; break; default: return WBEM_E_NOT_SUPPORTED; break; } // Query = "select * from __Instances" : fudge it so they get all classes in this namespace.
hr = m_pSchema->GetClassID(lpTableName, m_dNamespace, m_dClassID); if (FAILED(hr)) hr = WBEM_E_INVALID_QUERY;
// System classes are always default.
if (bDefaultStorage) { if (lpTableName[0] == L'_') *bDefaultStorage = TRUE; else *bDefaultStorage = FALSE; }
return hr; }
|