Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1499 lines
55 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. // wqltosql.cpp
  6. //
  7. // cvadai 19-Mar-99 Created as prototype for Quasar.
  8. //
  9. //***************************************************************************
  10. #define _WQLTOSQL_CPP_
  11. #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
  12. #include "precomp.h"
  13. #include <windows.h>
  14. #include <comutil.h>
  15. #include <flexarry.h>
  16. #include <wstring.h>
  17. #include <wqlnode.h>
  18. #include <reposit.h>
  19. #include <time.h>
  20. #include <map>
  21. #include <vector>
  22. #include <wbemcli.h>
  23. #include <wbemint.h>
  24. #include <wqltosql.h>
  25. #include <repcache.h>
  26. #include <reputils.h>
  27. #include <smrtptr.h>
  28. #include <sqlcache.h>
  29. #include <wqllex.h>
  30. #define WMIDB_PROPERTY_THIS 0x1000
  31. //***************************************************************************
  32. //
  33. // TempQL Lex Table
  34. //
  35. //***************************************************************************
  36. /*----------------------------------------------------
  37. References of {objpath} where
  38. ResultClass=XXX
  39. Role=YYY
  40. RequiredQualifier=QualifierName
  41. ClassDefsOnly
  42. Associators of {objpath} where
  43. ResultClass=XXX
  44. AssocClass=YYY
  45. Role=PPP
  46. RequiredQualifier=QualifierName
  47. RequiredAssocQualifier=QualifierName
  48. ClassDefsOnly
  49. ------------------------------------------------------*/
  50. #define QUERY_TYPE_CLASSDEFS_ONLY 0x1
  51. #define QUERY_TYPE_GETREFS 0x2
  52. #define QUERY_TYPE_GETASSOCS 0x4
  53. #define QUERY_TYPE_SCHEMA_ONLY 0x8
  54. #define QASSOC_TOK_STRING 101
  55. #define QASSOC_TOK_IDENT 102
  56. #define QASSOC_TOK_DOT 103
  57. #define QASSOC_TOK_EQU 104
  58. #define QASSOC_TOK_COLON 105
  59. #define QASSOC_TOK_ERROR 1
  60. #define QASSOC_TOK_EOF 0
  61. #define ST_IDENT 13
  62. #define ST_STRING 19
  63. #define ST_QSTRING 26
  64. #define ST_QSTRING_ESC 30
  65. //***************************************************************************
  66. //
  67. // CSQLBuilder::FormatSQL
  68. //
  69. //***************************************************************************
  70. HRESULT CSQLBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope,
  71. IWbemQuery *pQuery, _bstr_t &sSQL, DWORD dwFlags,
  72. DWORD dwHandleType, SQL_ID *dClassId,
  73. BOOL *bHierarchyQuery, BOOL bTmpTblOK, BOOL *bDeleteQuery,
  74. BOOL *bDefault)
  75. {
  76. // This needs to convert an entire query
  77. // into SQL. We assume that any attempt to get
  78. // a specific object will be done through GetObject.
  79. // This is strictly to return the ObjectIds of heterogenous
  80. // query results.
  81. HRESULT hr = WBEM_S_NO_ERROR;
  82. if (!m_pSchema)
  83. return WBEM_E_NOT_FOUND;
  84. char szTmpNum[25];
  85. BOOL bPartialFailure = FALSE;
  86. m_dwTableCount = 1;
  87. m_bClassSpecified = false;
  88. m_dNamespace = dScopeId;
  89. if (bHierarchyQuery)
  90. *bHierarchyQuery = FALSE;
  91. _bstr_t sColList, sFrom, sWhere;
  92. sColList = L"select a.ObjectId, a.ClassId, a.ObjectScopeId ";
  93. sFrom = L" from ObjectMap as a ";
  94. sWhere = L" where a.ObjectState <> 2";
  95. // Query types:
  96. // ===========
  97. // WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_SCOPE : ObjectScopeId = %I64d
  98. // WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_CONTAINER: inner join ContainerObjs as b on b.ContaineeId = a.ObjectId
  99. // and b.ContainerId = %I64d
  100. // WMIDB_FLAG_QUERY_DEEP + <any> : inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != %I64d))
  101. if (m_dNamespace)
  102. {
  103. sprintf(szTmpNum, "%I64d", m_dNamespace);
  104. // Scope is an __Instances container
  105. // This is shallow by definition.
  106. if (dScopeClassId == INSTANCESCLASSID)
  107. {
  108. sWhere += L" and a.ObjectKey != 'root' and a.ClassId = ";
  109. sWhere += szTmpNum;
  110. char szTmp[25];
  111. sprintf(szTmp, "%I64d", dSuperScope);
  112. sWhere += L" and a.ObjectScopeId in (0, ";
  113. sWhere += szTmp;
  114. sWhere += L")";
  115. }
  116. else
  117. {
  118. // Shallow enumeration
  119. if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP))
  120. {
  121. if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)
  122. {
  123. sFrom += L" inner join ContainerObjs as z on z.ContaineeId = a.ObjectId "
  124. L" and z.ContainerId = ";
  125. sFrom += szTmpNum;
  126. }
  127. else
  128. {
  129. sWhere += L" and a.ObjectKey != 'root' and a.ObjectScopeId in (0,";
  130. sWhere += szTmpNum;
  131. sWhere += L")";
  132. }
  133. }
  134. // Deep enumeration, we enumerate all contained and subscope objects.
  135. else
  136. {
  137. if (bTmpTblOK)
  138. {
  139. sFrom += L" inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != ";
  140. sFrom += szTmpNum;
  141. sFrom += L"))";
  142. }
  143. else
  144. hr = E_NOTIMPL;
  145. }
  146. }
  147. }
  148. if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)
  149. m_dNamespace = dSuperScope; // Containers are not valid scopes.
  150. sSQL = "";
  151. if (pQuery)
  152. {
  153. SWQLNode *pTop = NULL, *pRoot = NULL;
  154. pQuery->GetAnalysis(WMIQ_ANALYSIS_RESERVED, 0, (void **)&pTop);
  155. if (pTop && pTop->m_pLeft)
  156. {
  157. pRoot = pTop->m_pLeft;
  158. if (bDeleteQuery)
  159. {
  160. if (pRoot->m_dwNodeType == TYPE_SWQLNode_Delete)
  161. *bDeleteQuery = TRUE;
  162. else
  163. *bDeleteQuery = FALSE;
  164. }
  165. // *** WARNING ***
  166. // This is phase I of this formatting code.
  167. // In the future, we will need to also support
  168. // joins, counts, order by, group by, having,
  169. // qualifier queries, and lots of other stuff
  170. // that has yet to be defined.
  171. // For now, this will just return a single
  172. // ObjectId for any query that is passed in.
  173. // Reject any query with Where options (order by, group by)
  174. if (pRoot->m_pRight != NULL)
  175. {
  176. if (pRoot->m_pRight->m_pRight != NULL)
  177. {
  178. bPartialFailure = TRUE;
  179. }
  180. }
  181. // No counts, or multi-table queries.
  182. if (pRoot->m_pLeft != NULL)
  183. {
  184. hr = GetClassFromNode(pRoot->m_pLeft, bDefault);
  185. if (SUCCEEDED(hr))
  186. {
  187. if (m_dClassID == 1)
  188. {
  189. sWhere += L" and a.ClassId = 1";
  190. if (bDefault)
  191. *bDefault = TRUE;
  192. }
  193. else if (m_dClassID == INSTANCESCLASSID)
  194. {
  195. wchar_t wTemp[128];
  196. swprintf(wTemp, L" select a.ObjectId, %I64d, a.ObjectScopeId ", INSTANCESCLASSID);
  197. sColList = wTemp;
  198. sWhere += L" and a.ClassId = 1"; // Classes only
  199. if (bDefault)
  200. *bDefault = TRUE;
  201. }
  202. }
  203. }
  204. if (SUCCEEDED(hr))
  205. {
  206. // Now we parse the where clause.
  207. if (pRoot->m_pRight && pRoot->m_pRight->m_pLeft)
  208. {
  209. _bstr_t sNewSQL;
  210. bool bSys = false;
  211. hr = FormatWhereClause((SWQLNode_RelExpr *)pRoot->m_pRight->m_pLeft, sNewSQL, L"a", bSys);
  212. if (SUCCEEDED(hr))
  213. {
  214. if (bSys)
  215. {
  216. sFrom += L" inner join vSystemProperties as av on av.ObjectId = a.ObjectId ";
  217. }
  218. sWhere += L" AND ";
  219. sWhere += sNewSQL;
  220. // Make sure the results are limited to instances of the requested class
  221. // (Safeguard)
  222. if (!m_bClassSpecified)
  223. {
  224. wchar_t wTemp[256];
  225. if (bSys)
  226. {
  227. swprintf(wTemp, L" and exists (select * from ClassData as j where av.ObjectId = j.ObjectId"
  228. L" and j.ClassId= %I64d) ", m_dClassID);
  229. }
  230. else
  231. {
  232. // __Instances is automatically a shallow hierarchy query
  233. if (m_dClassID != INSTANCESCLASSID)
  234. {
  235. // Until we figure out how to do this in Jet,
  236. // we will only select instances of the requested class.
  237. if (bTmpTblOK)
  238. wcscpy(wTemp, L" AND EXISTS (select b.ClassId from #Children as b "
  239. L" where b.ClassId = a.ClassId )");
  240. else
  241. swprintf(wTemp, L" AND a.ClassId = %I64d", m_dClassID);
  242. if (bHierarchyQuery)
  243. *bHierarchyQuery = TRUE;
  244. }
  245. }
  246. sWhere += wTemp;
  247. }
  248. }
  249. }
  250. else
  251. {
  252. // __Instances is automatically a shallow hierarchy query
  253. if (m_dClassID != INSTANCESCLASSID)
  254. {
  255. wchar_t wTemp[256];
  256. // If no criteria, make sure we only get the class we asked for.
  257. if (bTmpTblOK)
  258. wcscpy(wTemp, L" AND EXISTS (select b.ClassId from #Children as b "
  259. L" where b.ClassId = a.ClassId)");
  260. else
  261. swprintf(wTemp, L" AND a.ClassId = %I64d", m_dClassID);
  262. if (bHierarchyQuery)
  263. *bHierarchyQuery = TRUE;
  264. sWhere += wTemp;
  265. }
  266. }
  267. sSQL = sColList + sFrom + sWhere;
  268. if (dClassId)
  269. *dClassId = m_dClassID;
  270. }
  271. }
  272. }
  273. else
  274. hr = WBEM_E_INVALID_PARAMETER;
  275. if ((SUCCEEDED(hr) && bPartialFailure))
  276. hr = WBEM_E_PROVIDER_NOT_CAPABLE;
  277. return hr;
  278. }
  279. //***************************************************************************
  280. //
  281. // CSQLBuilder::FormatSQL
  282. //
  283. //***************************************************************************
  284. HRESULT CSQLBuilder::FormatSQL (SQL_ID dScopeId, SQL_ID dScopeClassId, SQL_ID dSuperScope,
  285. SQL_ID dTargetObjID, LPWSTR pResultClass,
  286. LPWSTR pAssocClass, LPWSTR pRole, LPWSTR pResultRole, LPWSTR pRequiredQualifier,
  287. LPWSTR pRequiredAssocQualifier, DWORD dwQueryType, _bstr_t &sSQL, DWORD dwFlags,
  288. DWORD dwHandleType, SQL_ID *_dAssocClass, SQL_ID *_dResultClass, BOOL bIsClass)
  289. {
  290. // Query types:
  291. // ===========
  292. // WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_SCOPE : ObjectScopeId = %I64d
  293. // WMIDB_FLAG_QUERY_SHALLOW + WMIDB_HANDLE_TYPE_CONTAINER: inner join ContainerObjs as b on b.ContaineeId = a.ObjectId
  294. // and b.ContainerId = %I64d
  295. // WMIDB_FLAG_QUERY_DEEP + <any> : inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != %I64d))
  296. // Scope = __Instances=<Class>: and ClassId = %I64d
  297. HRESULT hr = WBEM_S_NO_ERROR;
  298. DWORD dwRoleID = 0, dwResultRole = 0, dwAssocQfr = 0;
  299. SQL_ID dAssocClass = 0, dTargetObj = 0, dThisClassId = 0;
  300. bool bWhereReq = true;
  301. _bstr_t sRole = "", sAssocQfr = "", sAssocClass = "", sResultRole = "";
  302. _bstr_t sName;
  303. SQL_ID dwSuperClassID;
  304. SQL_ID dwScopeID;
  305. DWORD dwTemp;
  306. _bstr_t sJoin = L"RefId";
  307. hr = m_pSchema->GetClassInfo(dTargetObjID, sName, dwSuperClassID, dwScopeID, dwTemp);
  308. if (SUCCEEDED(hr))
  309. {
  310. dThisClassId = dTargetObjID;
  311. sJoin = L"RefClassId";
  312. }
  313. hr = WBEM_S_NO_ERROR;
  314. m_dNamespace = dScopeId;
  315. if (dwQueryType & QUERY_TYPE_CLASSDEFS_ONLY)
  316. sSQL = L"select distinct a.ClassId, 1, 0 ";
  317. else
  318. sSQL = L"select a.ObjectId, a.ClassId, a.ObjectScopeId ";
  319. sSQL += L" from ObjectMap as a ";
  320. if (m_dNamespace)
  321. {
  322. char szTmp[25];
  323. sprintf(szTmp, "%I64d", m_dNamespace);
  324. if (dScopeClassId == INSTANCESCLASSID)
  325. {
  326. sSQL += L" WHERE a.ClassId = ";
  327. sSQL += szTmp;
  328. sprintf(szTmp, "%I64d", dSuperScope);
  329. sSQL += L" and a.ObjectScopeId = ";
  330. sSQL += szTmp;
  331. }
  332. else
  333. {
  334. if (!(dwFlags & WMIDB_FLAG_QUERY_DEEP))
  335. {
  336. if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)
  337. {
  338. sSQL += L" inner join ContainerObjs as z on z.ContaineeId = a.ObjectId "
  339. L" WHERE z.ContainerId = ";
  340. sSQL += szTmp;
  341. }
  342. else
  343. {
  344. sSQL += " WHERE a.ObjectScopeId = ";
  345. sSQL += szTmp;
  346. }
  347. }
  348. else
  349. {
  350. sSQL += L" inner join #SubScopeIds on (ID = a.ObjectScopeId OR (ID = a.ObjectId AND a.ObjectId != ";
  351. sSQL += szTmp;
  352. sSQL += L" )) ";
  353. }
  354. }
  355. sSQL += L" AND ";
  356. }
  357. else
  358. sSQL += " WHERE ";
  359. sSQL += " a.ObjectState <> 2 AND ";
  360. // Containers are not valid scopes.
  361. if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER)
  362. m_dNamespace = dSuperScope;
  363. // RESULTCLASS
  364. if (pResultClass != NULL)
  365. {
  366. wchar_t wTemp[100];
  367. // Get the class ID of this class
  368. hr = m_pSchema->GetClassID(pResultClass, m_dNamespace, dThisClassId);
  369. if (FAILED(hr))
  370. goto Exit;
  371. swprintf(wTemp, L" a.ClassId = %I64d", dThisClassId);
  372. bWhereReq = false;
  373. sSQL += wTemp;
  374. if (_dResultClass)
  375. *_dResultClass = dThisClassId;
  376. }
  377. // REQUIREDQUALIFIER
  378. if (pRequiredQualifier != NULL)
  379. {
  380. /*
  381. wchar_t wTemp[255];
  382. DWORD dwPropId = 0;
  383. hr = m_pSchema->GetPropertyID(pRequiredQualifier, dThisClassId, REPDRVR_FLAG_QUALIFIER,
  384. REPDRVR_IGNORE_CIMTYPE, dwPropId, NULL, NULL, NULL, TRUE);
  385. if (FAILED(hr))
  386. goto Exit;
  387. if (!bWhereReq)
  388. sSQL += L" AND ";
  389. // FIXME: This will only work on class-level qualifiers.
  390. // It will not work on instance qualifiers.
  391. swprintf(wTemp, L"EXISTS (select ClassId from ClassData as c where a.ClassId = c.ObjectId and c.PropertyId = %ld)",
  392. dwPropId);
  393. bWhereReq = false;
  394. sSQL += wTemp;
  395. */
  396. }
  397. if (!bWhereReq)
  398. sSQL += " AND ";
  399. // ROLE
  400. if (pRole)
  401. {
  402. wchar_t wTemp[512];
  403. swprintf(wTemp, L" and b.PropertyId in (select PropertyId from PropertyMap where PropertyName = '%s')", pRole);
  404. sRole = wTemp;
  405. }
  406. // RESULTROLE
  407. if (pResultRole)
  408. {
  409. wchar_t wTemp[512];
  410. swprintf(wTemp, L" and b.PropertyId in (select PropertyId from PropertyMap where PropertyName = '%s')", pResultRole);
  411. sResultRole = wTemp;
  412. }
  413. // REQUIREDASSOCQUALIFIER
  414. if (pRequiredAssocQualifier)
  415. {
  416. /*
  417. wchar_t wTemp[256];
  418. hr = m_pSchema->GetPropertyID(pRequiredAssocQualifier, dThisClassId, REPDRVR_FLAG_QUALIFIER,
  419. REPDRVR_IGNORE_CIMTYPE, dwAssocQfr, NULL, NULL, NULL, TRUE);
  420. if (FAILED(hr))
  421. goto Exit;
  422. swprintf(wTemp, L" AND EXISTS (select ObjectId from ClassData as d where b.ClassId = d.ObjectId and d.PropertyId = %ld)",
  423. dwAssocQfr);
  424. sAssocQfr = wTemp;
  425. */
  426. }
  427. // ASSOCCLASS
  428. if (pAssocClass)
  429. {
  430. wchar_t wTemp[256];
  431. hr = m_pSchema->GetClassID(pAssocClass, m_dNamespace, dAssocClass);
  432. if (FAILED(hr))
  433. goto Exit;
  434. swprintf(wTemp, L" AND b.ClassId = %I64d", dAssocClass);
  435. sAssocClass = wTemp;
  436. if (_dAssocClass)
  437. *_dAssocClass = dAssocClass;
  438. }
  439. if (dwQueryType & QUERY_TYPE_GETREFS)
  440. {
  441. wchar_t wTemp[1024];
  442. if (!bIsClass)
  443. {
  444. swprintf(wTemp, L" EXISTS (select ObjectId from ClassData as b where a.ObjectId = b.ObjectId "
  445. L" %s and b.%s = %I64d)", (const wchar_t *)sRole, (const wchar_t *)sJoin, dTargetObjID);
  446. }
  447. else
  448. {
  449. swprintf(wTemp, L" a.ClassId = 1 AND EXISTS (select r.ClassId from ReferenceProperties as r "
  450. L" where r.ClassId = a.ObjectId and r.RefClassId = %I64d)", dTargetObjID);
  451. }
  452. sSQL += wTemp;
  453. }
  454. else
  455. {
  456. wchar_t wTemp[2048];
  457. if (!bIsClass)
  458. {
  459. swprintf(wTemp, L" EXISTS (select b.RefId from ClassData as b inner join ClassData as c on c.ObjectId = b.ObjectId "
  460. L" where c.RefId = a.ObjectId and b.%s = %I64d and c.RefId <> b.RefId %s%s%s%s)", (const wchar_t *)sJoin,
  461. dTargetObjID, (const wchar_t *)sRole, (const wchar_t *)sResultRole, (const wchar_t *)sAssocClass,
  462. (const wchar_t *)sAssocQfr);
  463. }
  464. else
  465. {
  466. swprintf(wTemp, L" a.ClassId = 1 AND EXISTS (select r.ClassId from ReferenceProperties as r "
  467. L" INNER JOIN ReferenceProperties as r2 on r.ClassId = r2.ClassId and r.PropertyId <> r2.PropertyId"
  468. L" where r.ClassId = a.ObjectId and r2.RefClassId = %I64d)", dTargetObjID);
  469. }
  470. sSQL += wTemp;
  471. }
  472. Exit:
  473. return hr;
  474. }
  475. //***************************************************************************
  476. //
  477. // CSQLBuilder::FormatWhereClause
  478. //
  479. //***************************************************************************
  480. HRESULT CSQLBuilder::FormatWhereClause (SWQLNode_RelExpr *pNode, _bstr_t &sSQL, LPCWSTR lpJoinAlias, bool &bSysPropsUsed)
  481. {
  482. HRESULT hr = WBEM_S_NO_ERROR;
  483. BOOL bDone = FALSE;
  484. SQL_ID dClassId = 0;
  485. // For each node, we need to
  486. // 1. Look at the node type (and, or, not or typed)
  487. // 2. If not typed, group and continue
  488. // 3. If typed, construct the clause based on the property ID of the
  489. // property, the value and the operator.
  490. if (pNode)
  491. {
  492. DWORD dwType = pNode->m_dwExprType;
  493. _bstr_t sTemp;
  494. switch(dwType)
  495. {
  496. case WQL_TOK_OR:
  497. case WQL_TOK_AND:
  498. if (pNode->m_pLeft)
  499. {
  500. sTemp = "(";
  501. hr |= FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, sTemp, lpJoinAlias, bSysPropsUsed);
  502. }
  503. if (dwType == WQL_TOK_OR)
  504. sTemp += " OR ";
  505. else
  506. sTemp += " AND ";
  507. if (pNode->m_pRight)
  508. {
  509. hr |= FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pRight, sTemp, lpJoinAlias, bSysPropsUsed);
  510. sTemp += ")";
  511. }
  512. sSQL += sTemp;
  513. break;
  514. case WQL_TOK_NOT:
  515. sSQL += " NOT ";
  516. // Supposedly, only a left clause follows not...
  517. if (pNode->m_pLeft)
  518. {
  519. hr = FormatWhereClause((SWQLNode_RelExpr *)pNode->m_pLeft, sTemp, lpJoinAlias, bSysPropsUsed);
  520. sSQL += sTemp;
  521. }
  522. m_bClassSpecified = false; // whatever we've done probably negated the class qualifier.
  523. break;
  524. default: // Typed expression
  525. m_dwTableCount++;
  526. SWQLTypedExpr *pExpr = ((SWQLNode_RelExpr *)pNode)->m_pTypedExpr;
  527. if (pExpr != NULL)
  528. {
  529. DWORD dwProp1 = 0, dwProp2 = 0, dwOp = 0;
  530. DWORD dwStorage1 = 0, dwStorage2 = 0;
  531. DWORD dwKey1, dwKey2;
  532. _bstr_t sPropName, sValue, sSrc;
  533. wchar_t sAlias[256];
  534. swprintf(sAlias, L"%s%ld", lpJoinAlias, m_dwTableCount);
  535. _bstr_t sColName;
  536. if (pExpr->m_pColRef)
  537. sColName = pExpr->m_pColRef;
  538. else if (pExpr->m_pIntrinsicFuncOnColRef &&
  539. !_wcsicmp(pExpr->m_pIntrinsicFuncOnColRef, L"datepart") &&
  540. pExpr->m_pLeftFunction)
  541. {
  542. sColName = ((SWQLNode_Datepart *)pExpr->m_pLeftFunction)->m_pColRef->m_pColName;
  543. }
  544. hr = GetPropertyID(m_dClassID, pExpr->m_pQNLeft, sColName, dwProp1, dwStorage1, dwKey1);
  545. if (SUCCEEDED(hr))
  546. {
  547. if (dwStorage1 == WMIDB_PROPERTY_THIS)
  548. {
  549. // Special-case: the __this property.
  550. hr = m_pSchema->GetClassID(pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace, dClassId);
  551. if (SUCCEEDED(hr) && dClassId != 1)
  552. {
  553. sSQL += L" a.ObjectId in (";
  554. SQL_ID *pIDs = NULL;
  555. int iNumChildren = 0;
  556. hr = m_pSchema->GetDerivedClassList(dClassId, &pIDs, iNumChildren);
  557. if (SUCCEEDED(hr))
  558. {
  559. char szTmp[25];
  560. sprintf(szTmp, "%I64d", dClassId);
  561. sSQL += szTmp;
  562. for (int i = 0; i < iNumChildren; i++)
  563. {
  564. sSQL += L",";
  565. sprintf(szTmp, "%I64d", pIDs[i]);
  566. sSQL += szTmp;
  567. }
  568. delete pIDs;
  569. sSQL += L")";
  570. }
  571. }
  572. }
  573. else
  574. {
  575. GetStorageTable(dwStorage1, dwKey1, sSrc);
  576. if (dwStorage1 == WMIDB_STORAGE_COMPACT)
  577. swprintf(sAlias, L"%sv", lpJoinAlias);
  578. // Can't query anything stored as image
  579. if (dwStorage1 == WMIDB_STORAGE_IMAGE || dwStorage2 == WMIDB_STORAGE_IMAGE)
  580. return WBEM_E_QUERY_NOT_IMPLEMENTED;
  581. dwOp = pExpr->m_dwRelOperator;
  582. hr = FunctionalizeProperty (sAlias, dwStorage1, pExpr->m_pIntrinsicFuncOnColRef, pExpr->m_pLeftFunction, pExpr->m_pColRef, sPropName);
  583. if (SUCCEEDED(hr))
  584. {
  585. if (pExpr->m_pConstValue != NULL)
  586. {
  587. CIMTYPE ct=0;
  588. m_pSchema->GetPropertyInfo(dwProp1, NULL, NULL, NULL, (DWORD *)&ct);
  589. if (ct != CIM_DATETIME)
  590. hr = FunctionalizeValue (pExpr->m_pConstValue, dwStorage1, pExpr->m_pIntrinsicFuncOnConstValue, sValue);
  591. else
  592. {
  593. // Skip this token...
  594. // The core will post-filter.
  595. bDone = TRUE;
  596. sSQL += L" 1=1 ";
  597. }
  598. }
  599. else if (pExpr->m_pJoinColRef != NULL)
  600. {
  601. // SPECIAL CASE. To compare two properties, we deliberately cause a join to happen.
  602. m_dwTableCount++;
  603. wchar_t sAlias2[256];
  604. _bstr_t sSrc2;
  605. _bstr_t sPropName2, sExtra = L"";
  606. if (pExpr->m_pJoinColRef)
  607. sColName = pExpr->m_pJoinColRef;
  608. else if (pExpr->m_pIntrinsicFuncOnJoinColRef &&
  609. !_wcsicmp(pExpr->m_pIntrinsicFuncOnJoinColRef, L"datepart") &&
  610. pExpr->m_pRightFunction)
  611. {
  612. sColName = ((SWQLNode_Datepart *)pExpr->m_pRightFunction)->m_pColRef->m_pColName;
  613. }
  614. hr = GetPropertyID(m_dClassID, pExpr->m_pQNRight, sColName, dwProp2, dwStorage2, dwKey2);
  615. GetStorageTable(dwStorage2, dwKey2, sSrc2);
  616. if (dwStorage2 == WMIDB_STORAGE_COMPACT)
  617. swprintf(sAlias2, L"%sv", lpJoinAlias);
  618. else
  619. swprintf(sAlias2, L"%s%ld", lpJoinAlias, m_dwTableCount);
  620. hr = FunctionalizeProperty (sAlias2, dwStorage2, pExpr->m_pIntrinsicFuncOnJoinColRef, pExpr->m_pRightFunction, pExpr->m_pJoinColRef, sPropName2);
  621. if (pExpr->m_pQNRight)
  622. {
  623. SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNRight->m_aFields[0];
  624. hr = FormatPositionQuery(pNF, pExpr->m_dwRightArrayIndex, sAlias2, sTemp);
  625. if (SUCCEEDED(hr))
  626. sExtra = sTemp;
  627. }
  628. if (pExpr->m_pQNLeft)
  629. {
  630. SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNLeft->m_aFields[0];
  631. hr = FormatPositionQuery(pNF, pExpr->m_dwLeftArrayIndex, sAlias, sTemp);
  632. if (SUCCEEDED(hr))
  633. sExtra += sTemp;
  634. }
  635. if (SUCCEEDED(hr))
  636. {
  637. wchar_t wTempSQL[2048];
  638. // If the right side is a system property, we just treat this
  639. // like a regular comparison.
  640. if (dwStorage2 == WMIDB_STORAGE_COMPACT)
  641. {
  642. bSysPropsUsed = true;
  643. bDone = false;
  644. sValue = sPropName2;
  645. }
  646. // If the left side is a system property, we need to reverse the
  647. // values and let it through...
  648. else if (dwStorage1 == WMIDB_STORAGE_COMPACT)
  649. {
  650. sValue = sPropName;
  651. sPropName = sPropName2;
  652. wcscpy(sAlias,sAlias2);
  653. dwProp1 = dwProp2;
  654. bSysPropsUsed = true;
  655. dwStorage1 = dwStorage2;
  656. sSrc = sSrc2;
  657. }
  658. // Otherwise, we create a new join and wrap up.
  659. else
  660. {
  661. LPWSTR lpOp = GetOperator(dwOp);
  662. CDeleteMe <wchar_t> r (lpOp);
  663. swprintf(wTempSQL, L" EXISTS "
  664. L" (select %s.ObjectId from %s as %s inner join %s as %s on %s%s%s and %s.ObjectId = %s.ObjectId "
  665. L" where %s.ObjectId=%s.ObjectId and %s.PropertyId = %ld and %s.PropertyId = %ld%s)",
  666. sAlias, (const wchar_t *)sSrc, sAlias,
  667. (const wchar_t *)sSrc2, sAlias2, (const wchar_t *)sPropName,
  668. lpOp,(const wchar_t *)sPropName2, sAlias,
  669. sAlias2, lpJoinAlias, sAlias, sAlias,
  670. dwProp1, sAlias2, dwProp2, (const wchar_t *)sExtra);
  671. bDone = TRUE;
  672. sSQL += wTempSQL;
  673. }
  674. }
  675. }
  676. if (SUCCEEDED(hr) && !bDone)
  677. {
  678. _bstr_t sPrefix = "";
  679. LPWSTR lpOp = GetOperator(dwOp);
  680. if (!lpOp || !wcslen(lpOp))
  681. {
  682. switch (dwOp)
  683. {
  684. case WQL_TOK_NULL:
  685. case WQL_TOK_ISNULL:
  686. sPrefix = " NOT ";
  687. sValue = "";
  688. break;
  689. case WQL_TOK_NOT_NULL:
  690. sValue = "";
  691. break;
  692. case WQL_TOK_ISA:
  693. sPropName = sAlias;
  694. sPropName += L".RefClassId";
  695. delete lpOp;
  696. lpOp = new wchar_t [10];
  697. if (lpOp)
  698. {
  699. hr = m_pSchema->GetClassID(pExpr->m_pConstValue->m_Value.m_pString, m_dNamespace, dClassId);
  700. if (SUCCEEDED(hr) && dClassId != 1)
  701. {
  702. wcscpy(lpOp, L" in ");
  703. sValue = L"(";
  704. SQL_ID *pIDs = NULL;
  705. int iNumChildren = 0;
  706. hr = m_pSchema->GetDerivedClassList(dClassId, &pIDs, iNumChildren);
  707. if (SUCCEEDED(hr))
  708. {
  709. char szTmp[25];
  710. sprintf(szTmp, "%I64d", dClassId);
  711. sValue += szTmp;
  712. for (int i = 0; i < iNumChildren; i++)
  713. {
  714. sValue += L",";
  715. sprintf(szTmp, "%I64d", pIDs[i]);
  716. sValue += szTmp;
  717. }
  718. delete pIDs;
  719. sValue += L")";
  720. }
  721. if (dwStorage1 == WMIDB_STORAGE_COMPACT)
  722. dwStorage1 = WMIDB_STORAGE_REFERENCE;
  723. }
  724. else
  725. {
  726. wcscpy(lpOp, L" <> ");
  727. sValue = L"0";
  728. }
  729. }
  730. else
  731. hr = WBEM_E_OUT_OF_MEMORY;
  732. break;
  733. case WQL_TOK_BETWEEN:
  734. delete lpOp;
  735. lpOp = new wchar_t [10];
  736. if (lpOp)
  737. {
  738. wcscpy(lpOp, L" between ");
  739. sValue += " and ";
  740. hr = FunctionalizeValue (pExpr->m_pConstValue2, dwStorage2, pExpr->m_pIntrinsicFuncOnConstValue, sTemp);
  741. sValue += sTemp;
  742. }
  743. else
  744. hr = WBEM_E_OUT_OF_MEMORY;
  745. break;
  746. case WQL_TOK_NOT_IN:
  747. case WQL_TOK_IN:
  748. case WQL_TOK_IN_SUBSELECT:
  749. case WQL_TOK_NOT_IN_SUBSELECT:
  750. case WQL_TOK_IN_CONST_LIST:
  751. case WQL_TOK_NOT_IN_CONST_LIST:
  752. delete lpOp;
  753. lpOp = new wchar_t [10];
  754. if (lpOp)
  755. {
  756. wcscpy(lpOp, L"");
  757. if (pExpr->m_dwRelOperator == WQL_TOK_NOT_IN ||
  758. pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_SUBSELECT ||
  759. pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_CONST_LIST)
  760. {
  761. wcscpy(lpOp, L" not ");
  762. }
  763. wcscat(lpOp, L" in ");
  764. sValue = "(";
  765. if (pExpr->m_dwRelOperator == WQL_TOK_IN_SUBSELECT ||
  766. pExpr->m_dwRelOperator == WQL_TOK_NOT_IN_SUBSELECT)
  767. {
  768. // If a subselect, we need to construct an entirely new tree, passing
  769. // in the current alias.
  770. _bstr_t sTemp;
  771. m_dwTableCount++;
  772. wchar_t wAlias3[256];
  773. swprintf(wAlias3, L"%s%ld", lpJoinAlias, m_dwTableCount);
  774. wchar_t *pColName = sPropName;
  775. pColName += wcslen(sAlias)+1;
  776. hr = FormatSimpleSelect (wAlias3, pColName, pExpr->m_pSubSelect, sTemp);
  777. if (SUCCEEDED(hr))
  778. sValue += sTemp;
  779. }
  780. else
  781. {
  782. // If a const list, behaves as normal
  783. if (pExpr->m_pConstList)
  784. {
  785. for (int iPos = 0; iPos < pExpr->m_pConstList->m_aValues.Size(); iPos++)
  786. {
  787. if (iPos > 0)
  788. sValue += ",";
  789. hr = FunctionalizeValue(((SWQLTypedConst *)pExpr->m_pConstList->m_aValues.GetAt(iPos)), dwStorage1, pExpr->m_pIntrinsicFuncOnConstValue, sTemp);
  790. sValue += sTemp;
  791. }
  792. }
  793. }
  794. sValue += ")";
  795. }
  796. else
  797. hr = WBEM_E_OUT_OF_MEMORY;
  798. break;
  799. default:
  800. break;
  801. }
  802. }
  803. if (SUCCEEDED(hr))
  804. {
  805. long lLen = wcslen(sValue) + 512;
  806. wchar_t *pTempSQL = new wchar_t[lLen];
  807. CDeleteMe <wchar_t> r (pTempSQL);
  808. if (pTempSQL)
  809. {
  810. if (sValue.length() != 0)
  811. {
  812. if (dwStorage1 != WMIDB_STORAGE_COMPACT)
  813. sTemp = L" and ";
  814. sTemp += sPropName + lpOp + sValue;
  815. sValue = sTemp;
  816. }
  817. // Set array position (for left value only)
  818. if (pExpr->m_dwLeftFlags & WQL_FLAG_COMPLEX_NAME)
  819. {
  820. if (pExpr->m_pQNLeft)
  821. {
  822. SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pExpr->m_pQNLeft->m_aFields[0];
  823. hr = FormatPositionQuery(pNF, pExpr->m_dwLeftArrayIndex, sAlias, sTemp);
  824. if (SUCCEEDED(hr))
  825. sValue + sTemp;
  826. }
  827. }
  828. if (dwStorage1 != WMIDB_STORAGE_COMPACT)
  829. {
  830. swprintf(pTempSQL, L"%s EXISTS (select %s.ObjectId from %s as %s where %s.ObjectId=%s.ObjectId and %s.PropertyId = %ld %s)",
  831. (const wchar_t *)sPrefix, sAlias, (const wchar_t *)sSrc, sAlias,
  832. sAlias, lpJoinAlias, sAlias,
  833. dwProp1, (const wchar_t *)sValue);
  834. }
  835. else
  836. {
  837. bSysPropsUsed = true;
  838. // This is a straight comparison on a system property...
  839. swprintf(pTempSQL, L" %s",
  840. (const wchar_t *)sValue);
  841. }
  842. sSQL += pTempSQL;
  843. }
  844. else
  845. hr = WBEM_E_OUT_OF_MEMORY;
  846. delete lpOp;
  847. }
  848. }
  849. }
  850. }
  851. }
  852. }
  853. break;
  854. }
  855. }
  856. return hr;
  857. }
  858. //***************************************************************************
  859. //
  860. // CSQLBuilder::GetStorageTable
  861. //
  862. //***************************************************************************
  863. HRESULT CSQLBuilder::GetStorageTable(DWORD dwStorage, DWORD dwKey, _bstr_t &sTable)
  864. {
  865. if (dwStorage == WMIDB_STORAGE_COMPACT)
  866. sTable = L"vSystemProperties";
  867. else
  868. {
  869. sTable = L"ClassData";
  870. if (dwKey & 4 || dwKey & 8)
  871. {
  872. switch(dwStorage)
  873. {
  874. case WMIDB_STORAGE_STRING:
  875. sTable = L"IndexStringData";
  876. break;
  877. case WMIDB_STORAGE_NUMERIC:
  878. sTable = L"IndexNumericData";
  879. break;
  880. case WMIDB_STORAGE_REAL:
  881. sTable = L"IndexRealData";
  882. break;
  883. case WMIDB_STORAGE_REFERENCE:
  884. sTable = L"IndexRefData";
  885. break;
  886. }
  887. }
  888. }
  889. return WBEM_S_NO_ERROR;
  890. }
  891. //***************************************************************************
  892. //
  893. // CSQLBuilder::GetPropertyID
  894. //
  895. //***************************************************************************
  896. HRESULT CSQLBuilder::GetPropertyID (SQL_ID dClassID, SWQLQualifiedName *pQN, LPCWSTR pColRef, DWORD &PropID, DWORD &Storage, DWORD &Flags)
  897. {
  898. // If this is an embedded object property,
  899. // we need the actual class ID. The only way
  900. // to do that is the walk through all the properties,
  901. // and reconcile each layer.
  902. BOOL bThis = FALSE;
  903. HRESULT hr = WBEM_S_NO_ERROR;
  904. SQL_ID dRefClassId = dClassID;
  905. if (pQN != NULL)
  906. {
  907. /*
  908. for (int i = pQN->GetNumNames() - 1; i >= 0; i--)
  909. {
  910. SWQLQualifiedNameField *pNF = (SWQLQualifiedNameField *)pQN->m_aFields[i];
  911. if (pNF)
  912. {
  913. hr = m_pSchema->GetPropertyID(pNF->m_pName, dRefClassId, 0,
  914. REPDRVR_IGNORE_CIMTYPE, PropID, &dClassID, NULL, NULL, TRUE);
  915. if (SUCCEEDED(hr))
  916. {
  917. // Look up the property ID for this class.
  918. hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage,
  919. NULL, &Flags);
  920. }
  921. }
  922. }
  923. */
  924. hr = WBEM_E_PROVIDER_NOT_CAPABLE;
  925. }
  926. else if (pColRef != NULL)
  927. {
  928. wchar_t wName[1024];
  929. if (!_wcsicmp(pColRef, L"__this"))
  930. {
  931. Storage = WMIDB_PROPERTY_THIS;
  932. bThis = TRUE;
  933. m_bClassSpecified = true; // they are specifying which classes they want...
  934. }
  935. else
  936. {
  937. wcscpy(wName, pColRef);
  938. // Look up the property ID for this class.
  939. hr = m_pSchema->GetPropertyID(wName, m_dClassID, 0, REPDRVR_IGNORE_CIMTYPE,
  940. PropID, &dClassID, NULL, NULL, TRUE);
  941. if (SUCCEEDED(hr))
  942. hr = m_pSchema->GetPropertyInfo(PropID, NULL, NULL, &Storage,
  943. NULL, &Flags);
  944. }
  945. }
  946. else
  947. hr = WBEM_E_INVALID_PARAMETER;
  948. if (!bThis)
  949. {
  950. if (m_dClassID == dClassID)
  951. m_bClassSpecified = true;
  952. if (Flags & REPDRVR_FLAG_SYSTEM)
  953. Storage = WMIDB_STORAGE_COMPACT;
  954. }
  955. return hr;
  956. }
  957. //***************************************************************************
  958. //
  959. // CSQLBuilder::FunctionalizeProperty
  960. //
  961. //***************************************************************************
  962. HRESULT CSQLBuilder::FunctionalizeProperty (LPCWSTR lpAlias, DWORD dwType, LPWSTR lpFuncName, SWQLNode *pFunction, LPWSTR lpColName, _bstr_t &sProp)
  963. {
  964. // Apply any functions to the appropriate column of ClassData
  965. HRESULT hr = WBEM_S_NO_ERROR;
  966. bool bRef = false;
  967. _bstr_t sTemp;
  968. if (lpFuncName != NULL)
  969. {
  970. if (!_wcsicmp(lpFuncName, L"datepart"))
  971. sTemp = L"substring";
  972. else
  973. sTemp = lpFuncName;
  974. sTemp += "(";
  975. }
  976. sTemp += lpAlias;
  977. sTemp += L".";
  978. switch(dwType)
  979. {
  980. case WMIDB_STORAGE_STRING:
  981. // Unicode
  982. sTemp += L"PropertyStringValue";
  983. break;
  984. case WMIDB_STORAGE_NUMERIC:
  985. // SQL_ID
  986. sTemp += L"PropertyNumericValue";
  987. break;
  988. case WMIDB_STORAGE_REAL:
  989. // real
  990. sTemp += L"PropertyRealValue";
  991. break;
  992. case WMIDB_STORAGE_REFERENCE:
  993. // REF: Since this is stored as a number, we have to
  994. // subselect to get the real path, and apply all
  995. // functions to it.
  996. bRef = true;
  997. sTemp = L"(select ObjectPath from ObjectMap where ObjectId = ";
  998. sTemp += lpAlias;
  999. sTemp += ".RefId)";
  1000. break;
  1001. case WMIDB_STORAGE_COMPACT:
  1002. // System property, using vSystemProperties
  1003. sTemp += lpColName;
  1004. break;
  1005. default:
  1006. hr = WBEM_E_INVALID_QUERY;
  1007. break;
  1008. }
  1009. if (pFunction)
  1010. {
  1011. if (pFunction->m_dwNodeType == TYPE_SWQLNode_Datepart)
  1012. {
  1013. sTemp += ",";
  1014. switch(((SWQLNode_Datepart *)pFunction)->m_nDatepart)
  1015. {
  1016. case WQL_TOK_YEAR:
  1017. sTemp += L"1,4";
  1018. break;
  1019. case WQL_TOK_MONTH:
  1020. sTemp += L"5,2";
  1021. break;
  1022. case WQL_TOK_DAY:
  1023. sTemp += L"7,2";
  1024. break;
  1025. case WQL_TOK_HOUR:
  1026. sTemp += L"9,2";
  1027. break;
  1028. case WQL_TOK_MINUTE:
  1029. sTemp += L"11,2";
  1030. break;
  1031. case WQL_TOK_SECOND:
  1032. sTemp += L"13,2";
  1033. break;
  1034. case WQL_TOK_MILLISECOND:
  1035. sTemp += L"16,6";
  1036. break;
  1037. default:
  1038. hr = WBEM_E_INVALID_QUERY;
  1039. break;
  1040. }
  1041. }
  1042. }
  1043. if (lpFuncName != NULL)
  1044. {
  1045. sTemp += ")";
  1046. }
  1047. if (SUCCEEDED(hr))
  1048. sProp = sTemp;
  1049. return hr;
  1050. }
  1051. //***************************************************************************
  1052. //
  1053. // CSQLBuilder::FunctionalizeValue
  1054. //
  1055. //***************************************************************************
  1056. HRESULT CSQLBuilder::FunctionalizeValue(SWQLTypedConst *pValue, DWORD dwType, LPWSTR lpFuncName, _bstr_t &sValue)
  1057. {
  1058. // Apply any functions to the data, and add quotes as appropriate.
  1059. HRESULT hr = WBEM_S_NO_ERROR;
  1060. _bstr_t sTemp;
  1061. if (lpFuncName)
  1062. {
  1063. sTemp = lpFuncName;
  1064. sTemp += L"(";
  1065. }
  1066. if (pValue->m_dwType == VT_LPWSTR) {
  1067. sTemp += L"'";
  1068. LPWSTR lpTemp = StripQuotes(pValue->m_Value.m_pString);
  1069. CDeleteMe <wchar_t> r (lpTemp);
  1070. LPWSTR lpTemp2 = StripQuotes(lpTemp, '%');
  1071. CDeleteMe <wchar_t> r2 (lpTemp2);
  1072. if (dwType == WMIDB_STORAGE_COMPACT && !wcslen(lpTemp2))
  1073. sTemp += L"meta_class";
  1074. else
  1075. sTemp += lpTemp2;
  1076. sTemp += L"'";
  1077. }
  1078. else if(pValue->m_dwType == VT_NULL)
  1079. {
  1080. hr = WBEM_E_INVALID_QUERY;
  1081. }
  1082. else if (pValue->m_dwType == VT_I4)
  1083. {
  1084. char szTmp[25];
  1085. sprintf(szTmp, "%ld", pValue->m_Value.m_lValue);
  1086. sTemp += szTmp;
  1087. }
  1088. else if (pValue->m_dwType == VT_BOOL)
  1089. {
  1090. if (pValue->m_Value.m_bValue)
  1091. sTemp += L"1";
  1092. else
  1093. sTemp += L"0";
  1094. }
  1095. else if (pValue->m_dwType == VT_R8)
  1096. {
  1097. char szTmp[25];
  1098. sprintf(szTmp, "%lG", pValue->m_Value.m_dblValue);
  1099. sTemp += szTmp;
  1100. }
  1101. if (lpFuncName)
  1102. {
  1103. sTemp += L")";
  1104. }
  1105. if (SUCCEEDED(hr))
  1106. sValue = sTemp;
  1107. return hr;
  1108. }
  1109. //***************************************************************************
  1110. //
  1111. // CSQLBuilder::FormatSimpleSelect
  1112. //
  1113. //***************************************************************************
  1114. HRESULT CSQLBuilder::FormatSimpleSelect (LPCWSTR lpUseAlias,LPCWSTR lpColName, SWQLNode *pTop, _bstr_t &sSQL)
  1115. {
  1116. // Internal use only: This is to format subselects, so it should
  1117. // consist of a single column select from a known class.
  1118. HRESULT hr = WBEM_S_NO_ERROR;
  1119. SQL_ID dClassID;
  1120. DWORD dwPropID = 0, dwStorage = 0, dwFlags = 0;
  1121. _bstr_t sSrc = L"";
  1122. _bstr_t sExtra=L"";
  1123. _bstr_t sSubCol = lpColName;
  1124. if (pTop)
  1125. {
  1126. if (pTop->m_pLeft)
  1127. {
  1128. if (pTop->m_pLeft->m_pRight)
  1129. {
  1130. SWQLNode_TableRef *pRef = (SWQLNode_TableRef *)pTop->m_pLeft->m_pRight->m_pLeft;
  1131. hr = m_pSchema->GetClassID(pRef->m_pTableName, m_dNamespace, dClassID);
  1132. if (FAILED(hr))
  1133. hr = WBEM_E_INVALID_QUERY;
  1134. }
  1135. else
  1136. hr = WBEM_E_INVALID_QUERY;
  1137. if (pTop->m_pLeft->m_pLeft)
  1138. {
  1139. SWQLNode_ColumnList *pList = (SWQLNode_ColumnList *)pTop->m_pLeft->m_pLeft;
  1140. SWQLColRef *pCol = (SWQLColRef *)pList->m_aColumnRefs[0];
  1141. if (pCol)
  1142. {
  1143. _bstr_t sName = pCol->m_pColName;
  1144. if (pCol->m_dwFlags & WQL_FLAG_COMPLEX_NAME)
  1145. {
  1146. SWQLQualifiedName *pQN = pCol->m_pQName;
  1147. if (pQN)
  1148. {
  1149. hr = FormatPositionQuery((SWQLQualifiedNameField *)pQN->m_aFields[0], pCol->m_dwArrayIndex, lpUseAlias, sExtra);
  1150. }
  1151. }
  1152. hr = GetPropertyID(dClassID, pCol->m_pQName, pCol->m_pColName, dwPropID, dwStorage, dwFlags);
  1153. if (SUCCEEDED(hr))
  1154. {
  1155. GetStorageTable(dwStorage, dwFlags, sSrc);
  1156. // If we are comparing different types,
  1157. // or using a system property, get the new col name
  1158. FunctionalizeProperty (lpUseAlias, dwStorage, NULL, NULL, pCol->m_pColName, sSubCol);
  1159. }
  1160. }
  1161. }
  1162. }
  1163. else
  1164. hr = WBEM_E_INVALID_QUERY;
  1165. }
  1166. else
  1167. hr = WBEM_E_INVALID_QUERY;
  1168. if (SUCCEEDED(hr))
  1169. {
  1170. wchar_t wTemp[256];
  1171. wchar_t wWhere[512];
  1172. _bstr_t sTemp, sTempSQL;
  1173. // Construct the *simple* where clause....
  1174. // If there is any where element at all, we need to ditch the
  1175. // simple approach and revert to the subselect set...
  1176. // ==========================================================
  1177. swprintf(wTemp, L"select %s from %s as %s",
  1178. (const wchar_t *)sSubCol,
  1179. (const wchar_t *)sSrc, lpUseAlias);
  1180. sTemp = wTemp;
  1181. if (dwStorage == WMIDB_STORAGE_COMPACT)
  1182. swprintf(wWhere, L" where %s.ClassId = %I64d", lpUseAlias, dClassID);
  1183. else
  1184. swprintf(wWhere, L" where PropertyId = %ld%s", dwPropID, (const wchar_t *)sExtra);
  1185. if (pTop->m_pRight)
  1186. {
  1187. bool bSysPropsUsed = false;
  1188. hr = FormatWhereClause((SWQLNode_RelExpr *)pTop->m_pRight->m_pLeft, sTempSQL, lpUseAlias, bSysPropsUsed);
  1189. if (SUCCEEDED(hr) && sTempSQL.length() > 0)
  1190. {
  1191. if (bSysPropsUsed && !(dwStorage == WMIDB_STORAGE_COMPACT))
  1192. {
  1193. wchar_t NewSQL[1024];
  1194. swprintf(NewSQL, L" inner join vSystemProperties as %sv on %sv.ObjectId = %s.ObjectId and %sv.ClassId = %I64d",
  1195. lpUseAlias, lpUseAlias, lpUseAlias, lpUseAlias, dClassID);
  1196. sTemp += NewSQL;
  1197. }
  1198. sTemp += wWhere;
  1199. sTemp += L" AND ";
  1200. sTemp += sTempSQL;
  1201. }
  1202. else
  1203. sTemp += wWhere;
  1204. }
  1205. sSQL = sTemp;
  1206. }
  1207. return hr;
  1208. }
  1209. //***************************************************************************
  1210. //
  1211. // CSQLBuilder::FormatPositionQuery
  1212. //
  1213. //***************************************************************************
  1214. HRESULT CSQLBuilder::FormatPositionQuery (SWQLQualifiedNameField *pQNF, int iPos, LPCWSTR lpAlias, _bstr_t &sQuery)
  1215. {
  1216. HRESULT hr = WBEM_S_NO_ERROR;
  1217. wchar_t wTemp[128];
  1218. int iTemp;
  1219. if (pQNF)
  1220. {
  1221. if (pQNF->m_bArrayRef)
  1222. {
  1223. iTemp = (int)pQNF->m_dwArrayIndex;
  1224. }
  1225. }
  1226. else
  1227. iTemp = iPos;
  1228. swprintf(wTemp, L"and %s.ArrayPos = %ld", lpAlias, iTemp);
  1229. sQuery = wTemp;
  1230. return hr;
  1231. }
  1232. //***************************************************************************
  1233. //
  1234. // CSQLBuilder::GetClassFromNode
  1235. //
  1236. //***************************************************************************
  1237. HRESULT CSQLBuilder::GetClassFromNode (SWQLNode *pNode, BOOL *bDefaultStorage)
  1238. {
  1239. HRESULT hr = WBEM_S_NO_ERROR;
  1240. LPWSTR lpTableName = NULL;
  1241. switch(pNode->m_dwNodeType)
  1242. {
  1243. case TYPE_SWQLNode_TableRefs:
  1244. if (((SWQLNode_TableRefs *)pNode)->m_nSelectType == WQL_FLAG_COUNT)
  1245. return WBEM_E_PROVIDER_NOT_CAPABLE;
  1246. if (pNode->m_pRight != NULL)
  1247. {
  1248. if (pNode->m_pRight->m_pLeft->m_dwNodeType != TYPE_SWQLNode_TableRef)
  1249. hr = WBEM_E_PROVIDER_NOT_CAPABLE;
  1250. else
  1251. {
  1252. SWQLNode_TableRef *pRef = (SWQLNode_TableRef *)pNode->m_pRight->m_pLeft;
  1253. lpTableName = pRef->m_pTableName;
  1254. }
  1255. }
  1256. else
  1257. return WBEM_E_INVALID_SYNTAX;
  1258. break;
  1259. case TYPE_SWQLNode_TableRef:
  1260. if (pNode->m_dwNodeType != TYPE_SWQLNode_TableRef)
  1261. hr = WBEM_E_INVALID_SYNTAX;
  1262. else
  1263. lpTableName = ((SWQLNode_TableRef *)pNode)->m_pTableName;
  1264. break;
  1265. default:
  1266. return WBEM_E_NOT_SUPPORTED;
  1267. break;
  1268. }
  1269. // Query = "select * from __Instances" : fudge it so they get all classes in this namespace.
  1270. hr = m_pSchema->GetClassID(lpTableName, m_dNamespace, m_dClassID);
  1271. if (FAILED(hr))
  1272. hr = WBEM_E_INVALID_QUERY;
  1273. // System classes are always default.
  1274. if (bDefaultStorage)
  1275. {
  1276. if (lpTableName[0] == L'_')
  1277. *bDefaultStorage = TRUE;
  1278. else
  1279. *bDefaultStorage = FALSE;
  1280. }
  1281. return hr;
  1282. }