Leaked source code of windows server 2003
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.

1509 lines
50 KiB

  1. //--------------------------------------------------------------------------
  2. // Query.cpp
  3. //--------------------------------------------------------------------------
  4. #include "pch.hxx"
  5. #include "database.h"
  6. #include "query.h"
  7. #include "shlwapi.h"
  8. #include "strconst.h"
  9. //--------------------------------------------------------------------------
  10. // OPERATORTYPE
  11. //--------------------------------------------------------------------------
  12. typedef enum tagOPERATORTYPE {
  13. OPERATOR_LEFTPAREN,
  14. OPERATOR_RIGHTPAREN,
  15. OPERATOR_EQUAL,
  16. OPERATOR_NOTEQUAL,
  17. OPERATOR_LESSTHANEQUAL,
  18. OPERATOR_LESSTHAN,
  19. OPERATOR_GREATERTHANEQUAL,
  20. OPERATOR_GREATERTHAN,
  21. OPERATOR_AND,
  22. OPERATOR_BITWISEAND,
  23. OPERATOR_OR,
  24. OPERATOR_BITWISEOR,
  25. OPERATOR_STRSTRI,
  26. OPERATOR_STRSTR,
  27. OPERATOR_LSTRCMPI,
  28. OPERATOR_LSTRCMP,
  29. OPERATOR_ADD,
  30. OPERATOR_SUBTRACT,
  31. OPERATOR_MULTIPLY,
  32. OPERATOR_DIVIDE,
  33. OPERATOR_MOD,
  34. OPERATOR_LAST
  35. } OPERATORTYPE;
  36. //--------------------------------------------------------------------------
  37. // TOKENTYPE
  38. //--------------------------------------------------------------------------
  39. typedef enum tagTOKENTYPE {
  40. TOKEN_INVALID,
  41. TOKEN_OPERATOR,
  42. TOKEN_OPERAND
  43. } TOKENTYPE;
  44. //--------------------------------------------------------------------------
  45. // OPERANDTYPE
  46. //--------------------------------------------------------------------------
  47. typedef enum tagOPERANDTYPE {
  48. OPERAND_INVALID,
  49. OPERAND_COLUMN,
  50. OPERAND_STRING,
  51. OPERAND_DWORD,
  52. OPERAND_METHOD,
  53. OPERAND_LAST
  54. } OPERANDTYPE;
  55. //--------------------------------------------------------------------------
  56. // OPERANDINFO
  57. //--------------------------------------------------------------------------
  58. typedef struct tagOPERANDINFO {
  59. OPERANDTYPE tyOperand;
  60. DWORD iSymbol;
  61. LPVOID pRelease;
  62. union {
  63. COLUMNORDINAL iColumn; // OPERAND_COLUMN
  64. LPSTR pszString; // OPERAND_STRING
  65. DWORD dwValue; // OPERAND_DWORD
  66. METHODID idMethod; // OPERAND_METHOD
  67. };
  68. DWORD dwReserved;
  69. } OPERANDINFO, *LPOPERANDINFO;
  70. //--------------------------------------------------------------------------
  71. // QUERYTOKEN
  72. //--------------------------------------------------------------------------
  73. typedef struct tagQUERYTOKEN *LPQUERYTOKEN;
  74. typedef struct tagQUERYTOKEN {
  75. TOKENTYPE tyToken;
  76. DWORD cRefs;
  77. union {
  78. OPERATORTYPE tyOperator; // TOKEN_OPERATOR
  79. OPERANDINFO Operand; // TOKEN_OPERAND
  80. };
  81. LPQUERYTOKEN pNext;
  82. LPQUERYTOKEN pPrevious;
  83. } QUERYTOKEN;
  84. //--------------------------------------------------------------------------
  85. // PFNCOMPAREOPERAND - Compares Two Operands of the same type
  86. //--------------------------------------------------------------------------
  87. typedef INT (APIENTRY *PFNCOMPAREOPERAND)(LPVOID pDataLeft, LPVOID pDataRight);
  88. #define PCOMPARE(_pfn) ((PFNCOMPAREOPERAND)_pfn)
  89. //--------------------------------------------------------------------------
  90. // CompareOperandString
  91. //--------------------------------------------------------------------------
  92. INT CompareOperandString(LPVOID pDataLeft, LPVOID pDataRight) {
  93. return(lstrcmpi((LPSTR)pDataLeft, (LPSTR)pDataRight));
  94. }
  95. //--------------------------------------------------------------------------
  96. // CompareOperandDword
  97. //--------------------------------------------------------------------------
  98. INT CompareOperandDword(LPVOID pDataLeft, LPVOID pDataRight) {
  99. return (INT)(*((DWORD *)pDataLeft) - *((DWORD *)pDataRight));
  100. }
  101. //--------------------------------------------------------------------------
  102. // g_rgpfnCompareOperand
  103. //--------------------------------------------------------------------------
  104. const static PFNCOMPAREOPERAND g_rgpfnCompareOperand[OPERAND_LAST] = {
  105. NULL, // OPERAND_INVALID
  106. NULL, // OPERAND_COLUMN
  107. PCOMPARE(CompareOperandString), // OPERAND_STRING
  108. PCOMPARE(CompareOperandDword) // OPERAND_DWORD
  109. };
  110. //--------------------------------------------------------------------------
  111. // CompareOperands
  112. //--------------------------------------------------------------------------
  113. #define CompareOperands(_tyOperand, _pDataLeft, _pDataRight) \
  114. (*(g_rgpfnCompareOperand[_tyOperand]))(_pDataLeft, _pDataRight)
  115. //--------------------------------------------------------------------------
  116. // PFNEVALUATEOPERATOR - Compares data in two flat records.
  117. //--------------------------------------------------------------------------
  118. typedef DWORD (APIENTRY *PFNEVALUATEOPERATOR)(OPERANDTYPE tyOperand,
  119. LPVOID pDataLeft, LPVOID pDataRight);
  120. #define PEVAL(_pfn) ((PFNEVALUATEOPERATOR)_pfn)
  121. //--------------------------------------------------------------------------
  122. // Evaluate Operator Prototypes
  123. //--------------------------------------------------------------------------
  124. DWORD EvaluateEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  125. DWORD EvaluateNotEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  126. DWORD EvaluateLessThanEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  127. DWORD EvaluateLessThan(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  128. DWORD EvaluateGreaterThanEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  129. DWORD EvaluateGreaterThan(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  130. DWORD EvaluateAnd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  131. DWORD EvaluateBitwiseAnd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  132. DWORD EvaluateOr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  133. DWORD EvaluateBitwiseOr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  134. DWORD EvaluateStrStrI(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  135. DWORD EvaluateStrStr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  136. DWORD EvaluateStrcmpi(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  137. DWORD EvaluateStrcmp(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  138. DWORD EvaluateAdd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  139. DWORD EvaluateSubtract(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  140. DWORD EvaluateMultiply(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  141. DWORD EvaluateDivide(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  142. DWORD EvaluateModula(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight);
  143. //--------------------------------------------------------------------------
  144. // OPERATORINFO
  145. //--------------------------------------------------------------------------
  146. typedef struct tagOPERATORINFO {
  147. LPCSTR pszName;
  148. BYTE bISP;
  149. BYTE bICP;
  150. PFNEVALUATEOPERATOR pfnEvaluate;
  151. } OPERATORINFO, *LPOPERATORINFO;
  152. //--------------------------------------------------------------------------
  153. // Operator Precedence Table
  154. //--------------------------------------------------------------------------
  155. static const OPERATORINFO g_rgOperator[OPERATOR_LAST] = {
  156. // Name ISP ICP Function
  157. { "(", 6, 0, NULL }, // OPERATOR_LEFTPAREN
  158. { ")", 1, 1, NULL }, // OPERATOR_RIGHTPAREN
  159. { "==", 5, 5, PEVAL(EvaluateEqual) }, // OPERATOR_EQUAL
  160. { "!=", 5, 5, PEVAL(EvaluateNotEqual) }, // OPERATOR_NOTEQUAL
  161. { "<=", 5, 5, PEVAL(EvaluateLessThanEqual) }, // OPERATOR_LESSTHANEQUAL
  162. { "<", 5, 5, PEVAL(EvaluateLessThan) }, // OPERATOR_LESSTHAN
  163. { ">=", 5, 5, PEVAL(EvaluateGreaterThanEqual) }, // OPERATOR_GREATERTHANEQUAL
  164. { ">", 5, 5, PEVAL(EvaluateGreaterThan) }, // OPERATOR_GREATERTHAN
  165. { "&&", 4, 4, PEVAL(EvaluateAnd) }, // OPERATOR_AND
  166. { "&", 3, 3, PEVAL(EvaluateBitwiseAnd) }, // OPERATOR_BITWISEAND
  167. { "||", 4, 4, PEVAL(EvaluateOr) }, // OPERATOR_OR
  168. { "|", 3, 3, PEVAL(EvaluateBitwiseOr) }, // OPERATOR_BITWISEOR
  169. { "containsi", 5, 5, PEVAL(EvaluateStrStrI) }, // OPERATOR_STRSTRI
  170. { "contains", 5, 5, PEVAL(EvaluateStrStr) }, // OPERATOR_STRSTR
  171. { "comparei", 5, 5, PEVAL(EvaluateStrcmpi) }, // OPERATOR_LSTRCMPI
  172. { "compare", 5, 5, PEVAL(EvaluateStrcmp) }, // OPERATOR_LSTRCMP
  173. { "+", 4, 4, PEVAL(EvaluateAdd) }, // OPERATOR_ADD,
  174. { "-", 4, 4, PEVAL(EvaluateSubtract) }, // OPERATOR_SUBTRACT,
  175. { "*", 3, 3, PEVAL(EvaluateMultiply) }, // OPERATOR_MULTIPLY,
  176. { "/", 3, 3, PEVAL(EvaluateDivide) }, // OPERATOR_DIVIDE,
  177. { "%", 3, 3, PEVAL(EvaluateModula) }, // OPERATOR_MOD,
  178. };
  179. //--------------------------------------------------------------------------
  180. // EvaluateOperator
  181. //--------------------------------------------------------------------------
  182. #define EvaluateOperator(_tyOperator, _tyOperand, _pDataLeft, _pDataRight) \
  183. (*(g_rgOperator[_tyOperator].pfnEvaluate))(_tyOperand, _pDataLeft, _pDataRight)
  184. //--------------------------------------------------------------------------
  185. // MAPCOLUMNTYPE
  186. //--------------------------------------------------------------------------
  187. typedef void (APIENTRY *PFNMAPCOLUMNTYPE)(LPOPERANDINFO pOperand,
  188. LPCTABLECOLUMN pColumn, LPVOID pBinding, LPVOID *ppValue);
  189. #define PMAP(_pfn) ((PFNMAPCOLUMNTYPE)_pfn)
  190. //--------------------------------------------------------------------------
  191. // MapColumnString
  192. //--------------------------------------------------------------------------
  193. void MapColumnString(LPOPERANDINFO pOperand, LPCTABLECOLUMN pColumn,
  194. LPVOID pBinding, LPVOID *ppValue) {
  195. (*ppValue) = *((LPSTR *)((LPBYTE)pBinding + pColumn->ofBinding));
  196. }
  197. //--------------------------------------------------------------------------
  198. // MapColumnByte
  199. //--------------------------------------------------------------------------
  200. void MapColumnByte(LPOPERANDINFO pOperand, LPCTABLECOLUMN pColumn,
  201. LPVOID pBinding, LPVOID *ppValue) {
  202. pOperand->dwReserved = *((BYTE *)((LPBYTE)pBinding + pColumn->ofBinding));
  203. (*ppValue) = (LPVOID)&pOperand->dwReserved;
  204. }
  205. //--------------------------------------------------------------------------
  206. // MapColumnDword
  207. //--------------------------------------------------------------------------
  208. void MapColumnDword(LPOPERANDINFO pOperand, LPCTABLECOLUMN pColumn,
  209. LPVOID pBinding, LPVOID *ppValue) {
  210. pOperand->dwReserved = *((DWORD *)((LPBYTE)pBinding + pColumn->ofBinding));
  211. (*ppValue) = (LPVOID)&pOperand->dwReserved;
  212. }
  213. //--------------------------------------------------------------------------
  214. // MapColumnWord
  215. //--------------------------------------------------------------------------
  216. void MapColumnWord(LPOPERANDINFO pOperand, LPCTABLECOLUMN pColumn,
  217. LPVOID pBinding, LPVOID *ppValue) {
  218. pOperand->dwReserved = *((WORD *)((LPBYTE)pBinding + pColumn->ofBinding));
  219. (*ppValue) = (LPVOID)&pOperand->dwReserved;
  220. }
  221. //--------------------------------------------------------------------------
  222. // COLUMNTYPEINFO
  223. //--------------------------------------------------------------------------
  224. typedef struct tagCOLUMNTYPEINFO {
  225. OPERANDTYPE tyOperand;
  226. PFNMAPCOLUMNTYPE pfnMapColumnType;
  227. } COLUMNTYPEINFO, *LPCOLUMNTYPEINFO;
  228. //--------------------------------------------------------------------------
  229. // g_rgColumnTypeInfo
  230. //--------------------------------------------------------------------------
  231. static const COLUMNTYPEINFO g_rgColumnTypeInfo[CDT_LASTTYPE] = {
  232. { OPERAND_INVALID, NULL }, // CDT_FILETIME,
  233. { OPERAND_STRING, PMAP(MapColumnString) }, // CDT_FIXSTRA,
  234. { OPERAND_STRING, PMAP(MapColumnString) }, // CDT_VARSTRA,
  235. { OPERAND_DWORD, PMAP(MapColumnByte) }, // CDT_BYTE,
  236. { OPERAND_DWORD, PMAP(MapColumnDword) }, // CDT_DWORD,
  237. { OPERAND_DWORD, PMAP(MapColumnWord) }, // CDT_WORD,
  238. { OPERAND_DWORD, PMAP(MapColumnDword) }, // CDT_STREAM,
  239. { OPERAND_INVALID, NULL }, // CDT_VARBLOB,
  240. { OPERAND_INVALID, NULL }, // CDT_FIXBLOB,
  241. { OPERAND_DWORD, PMAP(MapColumnDword) }, // CDT_FLAGS,
  242. { OPERAND_DWORD, PMAP(MapColumnDword) }, // CDT_UNIQUE
  243. };
  244. //--------------------------------------------------------------------------
  245. // MapColumnType
  246. //--------------------------------------------------------------------------
  247. #define MapColumnType(_tyColumn, _pOperand, _pColumn, _pBinding, _ppValue) \
  248. (*(g_rgColumnTypeInfo[_tyColumn].pfnMapColumnType))(_pOperand, _pColumn, _pBinding, _ppValue)
  249. //--------------------------------------------------------------------------
  250. // Prototypes
  251. //--------------------------------------------------------------------------
  252. HRESULT GetNextQueryToken(LPSTR *ppszT, LPCTABLESCHEMA pSchema, LPQUERYTOKEN *ppToken, CDatabase *pDB);
  253. HRESULT LinkToken(LPQUERYTOKEN pToken, LPQUERYTOKEN *ppHead, LPQUERYTOKEN *ppTail);
  254. HRESULT ReleaseTokenList(BOOL fReverse, LPQUERYTOKEN *ppHead, CDatabase *pDB);
  255. HRESULT ReleaseToken(LPQUERYTOKEN *ppToken, CDatabase *pDB);
  256. HRESULT ParseStringLiteral(LPCSTR pszStart, LPOPERANDINFO pOperand, LPSTR *ppszEnd, CDatabase *pDB);
  257. HRESULT ParseNumeric(LPCSTR pszT, LPOPERANDINFO pOperand, LPSTR *ppszEnd);
  258. HRESULT ParseSymbol(LPCSTR pszT, LPCTABLESCHEMA pSchema, LPOPERANDINFO pOperand, LPSTR *ppszEnd, CDatabase *pDB);
  259. HRESULT PushStackToken(LPQUERYTOKEN pToken, LPQUERYTOKEN *ppStackTop);
  260. HRESULT PopStackToken(LPQUERYTOKEN *ppToken, LPQUERYTOKEN *ppStackTop);
  261. HRESULT EvaluateClause(OPERATORTYPE tyOperator, LPVOID pBinding, LPCTABLESCHEMA pSchema, LPQUERYTOKEN *ppStackTop, CDatabase *pDB, IDatabaseExtension *pExtension);
  262. IF_DEBUG(HRESULT DebugDumpExpression(LPCSTR pszQuery, LPCTABLESCHEMA pSchema, LPQUERYTOKEN pPostfixHead));
  263. //--------------------------------------------------------------------------
  264. // ISP inline
  265. //--------------------------------------------------------------------------
  266. inline BYTE ISP(LPQUERYTOKEN pToken)
  267. {
  268. // Validate
  269. Assert(TOKEN_OPERATOR == pToken->tyToken && pToken->tyOperator < OPERATOR_LAST);
  270. // Return ISP
  271. return (g_rgOperator[pToken->tyOperator].bISP);
  272. }
  273. //--------------------------------------------------------------------------
  274. // ICP inline
  275. //--------------------------------------------------------------------------
  276. inline BYTE ICP(LPQUERYTOKEN pToken)
  277. {
  278. // Validate
  279. Assert(TOKEN_OPERATOR == pToken->tyToken && pToken->tyOperator < OPERATOR_LAST);
  280. // Return ISP
  281. return (g_rgOperator[pToken->tyOperator].bICP);
  282. }
  283. // --------------------------------------------------------------------------
  284. // DBIsDigit
  285. // --------------------------------------------------------------------------
  286. int DBIsDigit(LPSTR psz)
  287. {
  288. WORD wType;
  289. if (IsDBCSLeadByte(*psz))
  290. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType));
  291. else
  292. SideAssert(GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType));
  293. return(wType & C1_DIGIT);
  294. }
  295. //--------------------------------------------------------------------------
  296. // EvaluateQuery
  297. //--------------------------------------------------------------------------
  298. HRESULT EvaluateQuery(HQUERY hQuery, LPVOID pBinding, LPCTABLESCHEMA pSchema,
  299. CDatabase *pDB, IDatabaseExtension *pExtension)
  300. {
  301. // Locals
  302. HRESULT hr=S_OK;
  303. LPQUERYTOKEN pToken;
  304. LPQUERYTOKEN pResult=NULL;
  305. LPQUERYTOKEN pStackTop=NULL;
  306. // Trace
  307. TraceCall("EvaluateQuery");
  308. // Assert
  309. Assert(hQuery && pBinding && pSchema);
  310. // Walk through the tokens
  311. for (pToken=(LPQUERYTOKEN)hQuery; pToken!=NULL; pToken=pToken->pNext)
  312. {
  313. // If this is an operand, append to the stack
  314. if (TOKEN_OPERAND == pToken->tyToken)
  315. {
  316. // LinkStackToken
  317. PushStackToken(pToken, &pStackTop);
  318. }
  319. // Otherwise, must be an operator
  320. else
  321. {
  322. // Operator ?
  323. Assert(TOKEN_OPERATOR == pToken->tyToken && g_rgOperator[pToken->tyOperator].pfnEvaluate != NULL);
  324. // EvaluateOperator
  325. IF_FAILEXIT(hr = EvaluateClause(pToken->tyOperator, pBinding, pSchema, &pStackTop, pDB, pExtension));
  326. }
  327. }
  328. // Pop the stack
  329. PopStackToken(&pResult, &pStackTop);
  330. // No Token and Stack should now be empty..
  331. Assert(pResult && NULL == pStackTop && pResult->tyToken == TOKEN_OPERAND && pResult->Operand.tyOperand == OPERAND_DWORD);
  332. // 0 or not zero
  333. hr = (pResult->Operand.dwValue == 0) ? S_FALSE : S_OK;
  334. exit:
  335. // Cleanup
  336. ReleaseToken(&pResult, pDB);
  337. ReleaseTokenList(TRUE, &pStackTop, pDB);
  338. // Done
  339. return(SUCCEEDED(hr) ? hr : S_FALSE);
  340. }
  341. //--------------------------------------------------------------------------
  342. // ParseQuery
  343. //--------------------------------------------------------------------------
  344. HRESULT ParseQuery(LPCSTR pszQuery, LPCTABLESCHEMA pSchema, LPHQUERY phQuery,
  345. CDatabase *pDB)
  346. {
  347. // Locals
  348. HRESULT hr=S_OK;
  349. LPSTR pszT=(LPSTR)pszQuery;
  350. LPQUERYTOKEN pCurrent;
  351. LPQUERYTOKEN pPrevious;
  352. LPQUERYTOKEN pToken=NULL;
  353. LPQUERYTOKEN pPostfixHead=NULL;
  354. LPQUERYTOKEN pPostfixTail=NULL;
  355. LPQUERYTOKEN pStackTop=NULL;
  356. // Trace
  357. TraceCall("ParseQuery");
  358. // Invalid Args
  359. if (NULL == pszQuery || NULL == pSchema || NULL == phQuery)
  360. return TraceResult(E_INVALIDARG);
  361. // Initialize
  362. (*phQuery) = NULL;
  363. // Start the Parsing Loop
  364. while(1)
  365. {
  366. // Parse next Token
  367. IF_FAILEXIT(hr = GetNextQueryToken(&pszT, pSchema, &pToken, pDB));
  368. // Done
  369. if (S_FALSE == hr)
  370. break;
  371. // If this was an operand, append to postfix expression
  372. if (TOKEN_OPERAND == pToken->tyToken)
  373. {
  374. // LinkToken
  375. LinkToken(pToken, &pPostfixHead, &pPostfixTail);
  376. // Don't pToken
  377. ReleaseToken(&pToken, pDB);
  378. }
  379. // Otherwise, must be an operator
  380. else
  381. {
  382. // Must be an operator
  383. Assert(TOKEN_OPERATOR == pToken->tyToken);
  384. // If Right Paren
  385. if (OPERATOR_RIGHTPAREN == pToken->tyOperator)
  386. {
  387. // Pop all the items from the stack and link into the postfix expression
  388. while (pStackTop && OPERATOR_LEFTPAREN != pStackTop->tyOperator)
  389. {
  390. // Save pPrevious
  391. pPrevious = pStackTop->pPrevious;
  392. // Otherwise
  393. LinkToken(pStackTop, &pPostfixHead, &pPostfixTail);
  394. // Releae
  395. ReleaseToken(&pStackTop, pDB);
  396. // Goto Previuos
  397. pStackTop = pPrevious;
  398. }
  399. // If not a left parent was found, then we failed
  400. if (OPERATOR_LEFTPAREN != pStackTop->tyOperator)
  401. {
  402. hr = TraceResult(DB_E_UNMATCHINGPARENS);
  403. goto exit;
  404. }
  405. // Save pPrevious
  406. pPrevious = pStackTop->pPrevious;
  407. // Free pStackTop
  408. ReleaseToken(&pStackTop, pDB);
  409. // Reset pStackTop
  410. pStackTop = pPrevious;
  411. // Free pToken
  412. ReleaseToken(&pToken, pDB);
  413. }
  414. // Otherwise
  415. else
  416. {
  417. // Pop all the items into the postfix expression according to a cool little priority rule
  418. while (pStackTop && ISP(pStackTop) <= ICP(pToken))
  419. {
  420. // Save pPrevious
  421. pPrevious = pStackTop->pPrevious;
  422. // Otherwise
  423. LinkToken(pStackTop, &pPostfixHead, &pPostfixTail);
  424. // Releae
  425. ReleaseToken(&pStackTop, pDB);
  426. // Goto Previuos
  427. pStackTop = pPrevious;
  428. }
  429. // Append pToken to the Stack
  430. LinkToken(pToken, NULL, &pStackTop);
  431. // Don't pToken
  432. ReleaseToken(&pToken, pDB);
  433. }
  434. }
  435. }
  436. // Pop all the items from the stack and link into the postfix expression
  437. while (pStackTop)
  438. {
  439. // Save pPrevious
  440. pPrevious = pStackTop->pPrevious;
  441. // Append to Postfix Expression
  442. LinkToken(pStackTop, &pPostfixHead, &pPostfixTail);
  443. // Releae
  444. ReleaseToken(&pStackTop, pDB);
  445. // Goto Previuos
  446. pStackTop = pPrevious;
  447. }
  448. // lets write the postfix notation...
  449. //IF_DEBUG(DebugDumpExpression(pszQuery, pSchema, pPostfixHead));
  450. // Success
  451. (*phQuery) = (HQUERY)pPostfixHead;
  452. exit:
  453. // Cleanup On Failure
  454. if (FAILED(hr))
  455. {
  456. // Free pToken
  457. ReleaseToken(&pToken, pDB);
  458. // Free the Stack
  459. ReleaseTokenList(TRUE, &pStackTop, pDB);
  460. // Free the Postfix Expression
  461. ReleaseTokenList(FALSE, &pPostfixHead, pDB);
  462. }
  463. // Done
  464. return(hr);
  465. }
  466. //--------------------------------------------------------------------------
  467. // DebugDumpExpression
  468. //--------------------------------------------------------------------------
  469. #ifdef DEBUG
  470. HRESULT DebugDumpExpression(LPCSTR pszQuery, LPCTABLESCHEMA pSchema,
  471. LPQUERYTOKEN pPostfixHead)
  472. {
  473. // Locals
  474. LPQUERYTOKEN pToken;
  475. // Trace
  476. TraceCall("DebugDumpExpression");
  477. // Write Infix
  478. DebugTrace("ParseQuery (Infix) : %s\n", pszQuery);
  479. // Write Postfix header
  480. DebugTrace("ParseQuery (Postfix) : ");
  481. // Loop through the tokens
  482. for (pToken=pPostfixHead; pToken!=NULL; pToken=pToken->pNext)
  483. {
  484. // Operator
  485. if (TOKEN_OPERATOR == pToken->tyToken)
  486. {
  487. // Write the Operator
  488. DebugTrace("%s", g_rgOperator[pToken->tyOperator].pszName);
  489. }
  490. // Operand
  491. else if (TOKEN_OPERAND == pToken->tyToken)
  492. {
  493. // Column Operand
  494. if (OPERAND_COLUMN == pToken->Operand.tyOperand)
  495. {
  496. // Must have an iSymbol
  497. Assert(0xffffffff != pToken->Operand.iSymbol);
  498. // Write the Symbol
  499. DebugTrace("Column: %d (%s)", pToken->Operand.dwValue, pSchema->pSymbols->rgSymbol[pToken->Operand.iSymbol].pszName);
  500. }
  501. // String Operand
  502. else if (OPERAND_STRING == pToken->Operand.tyOperand)
  503. {
  504. // Write the Symbol
  505. DebugTrace("<%s>", pToken->Operand.pszString);
  506. }
  507. // Dword Operand
  508. else if (OPERAND_DWORD == pToken->Operand.tyOperand)
  509. {
  510. // Has a iSymbol
  511. if (0xffffffff != pToken->Operand.iSymbol)
  512. {
  513. // Write the Symbol
  514. DebugTrace("%d (%s)", pToken->Operand.dwValue, pSchema->pSymbols->rgSymbol[pToken->Operand.iSymbol].pszName);
  515. }
  516. // Otherwise, just write the value
  517. else
  518. {
  519. // Write the Symbol
  520. DebugTrace("%d", pToken->Operand.dwValue);
  521. }
  522. }
  523. // Method
  524. else if (OPERAND_METHOD == pToken->Operand.tyOperand)
  525. {
  526. // Validate Symbol Type
  527. Assert(SYMBOL_METHOD == pSchema->pSymbols->rgSymbol[pToken->Operand.iSymbol].tySymbol);
  528. // Write the Method
  529. DebugTrace("Method: %d (%s)", pToken->Operand.idMethod, pSchema->pSymbols->rgSymbol[pToken->Operand.iSymbol].pszName);
  530. }
  531. }
  532. // Bad
  533. else
  534. Assert(FALSE);
  535. // Write Delimiter
  536. DebugTrace(", ");
  537. }
  538. // Wrap the line
  539. DebugTrace("\n");
  540. // Done
  541. return(S_OK);
  542. }
  543. #endif // DEBUG
  544. //--------------------------------------------------------------------------
  545. // CompareSymbol
  546. //--------------------------------------------------------------------------
  547. HRESULT CompareSymbol(LPSTR pszT, LPCSTR pszName, LPSTR *ppszEnd)
  548. {
  549. // Locals
  550. LPSTR pszName1;
  551. LPSTR pszName2;
  552. // Trace
  553. TraceCall("CompareSymbol");
  554. // Set pszName
  555. pszName1 = (LPSTR)pszName;
  556. // Set pszName2
  557. pszName2 = pszT;
  558. // Compare pszTo to Operator pszName...
  559. while ('\0' != *pszName2 && *pszName1 == *pszName2)
  560. {
  561. // Increment
  562. pszName1++;
  563. pszName2++;
  564. // Reached the End of pszName1, must be a match
  565. if ('\0' == *pszName1)
  566. {
  567. // Set ppszEnd
  568. *ppszEnd = pszName2;
  569. // Done
  570. return(S_OK);
  571. }
  572. }
  573. // Done
  574. return(S_FALSE);
  575. }
  576. //--------------------------------------------------------------------------
  577. // GetNextQueryToken
  578. //--------------------------------------------------------------------------
  579. HRESULT GetNextQueryToken(LPSTR *ppszT, LPCTABLESCHEMA pSchema,
  580. LPQUERYTOKEN *ppToken, CDatabase *pDB)
  581. {
  582. // Locals
  583. HRESULT hr=S_FALSE;
  584. LPSTR pszT=(*ppszT);
  585. LPSTR pszEnd;
  586. DWORD i;
  587. LPQUERYTOKEN pToken=NULL;
  588. // Trace
  589. TraceCall("GetNextQueryToken");
  590. // Allocate a Token
  591. IF_NULLEXIT(pToken = (LPQUERYTOKEN)pDB->PHeapAllocate(HEAP_ZERO_MEMORY, sizeof(QUERYTOKEN)));
  592. // Set Reference Count
  593. pToken->cRefs = 1;
  594. // No Token foundyet
  595. pToken->tyToken = TOKEN_INVALID;
  596. // Invalid Symbol Index
  597. pToken->Operand.iSymbol = 0xffffffff;
  598. // Skip White Space...
  599. while(*pszT && (*pszT == ' ' || *pszT == '\t'))
  600. pszT++;
  601. // Done
  602. if ('\0' == *pszT)
  603. goto exit;
  604. // Check for the Start of an Operator...
  605. for (i=0; i<OPERATOR_LAST; i++)
  606. {
  607. // Does pszT point to the start of an operator ?
  608. if (S_OK == CompareSymbol(pszT, g_rgOperator[i].pszName, &pszEnd))
  609. {
  610. // Update pszT
  611. pszT = pszEnd;
  612. // We found an operator
  613. pToken->tyToken = TOKEN_OPERATOR;
  614. // Set the operator type
  615. pToken->tyOperator = (OPERATORTYPE)i;
  616. // Done
  617. break;
  618. }
  619. }
  620. // No Token Yet ?
  621. if (TOKEN_INVALID == pToken->tyToken)
  622. {
  623. // Start of a String Literal ?
  624. if ('"' == *pszT)
  625. {
  626. // ParseStringLiteral
  627. IF_FAILEXIT(hr = ParseStringLiteral(pszT, &pToken->Operand, &pszEnd, pDB));
  628. }
  629. // Otherwise, start of a number
  630. else if (DBIsDigit(pszT))
  631. {
  632. // ParseNumeric
  633. IF_FAILEXIT(hr = ParseNumeric(pszT, &pToken->Operand, &pszEnd));
  634. }
  635. // Start of a Symbol
  636. else
  637. {
  638. // ParseSymbol
  639. IF_FAILEXIT(hr = ParseSymbol(pszT, pSchema, &pToken->Operand, &pszEnd, pDB));
  640. }
  641. // Must have been an operand
  642. pToken->tyToken = TOKEN_OPERAND;
  643. // Set pszT
  644. pszT = pszEnd;
  645. }
  646. // Set ppszT
  647. *ppszT = pszT;
  648. // Success
  649. hr = S_OK;
  650. // Return the Token
  651. *ppToken = pToken;
  652. // Don't Free the Token
  653. pToken = NULL;
  654. exit:
  655. // Cleanup
  656. ReleaseToken(&pToken, pDB);
  657. // Done
  658. return(hr);
  659. }
  660. //--------------------------------------------------------------------------
  661. // ParseStringLiteral
  662. //--------------------------------------------------------------------------
  663. HRESULT ParseStringLiteral(LPCSTR pszStart, LPOPERANDINFO pOperand,
  664. LPSTR *ppszEnd, CDatabase *pDB)
  665. {
  666. // Locals
  667. HRESULT hr=S_OK;
  668. LPSTR pszValue;
  669. DWORD cchString;
  670. LPSTR pszT=(LPSTR)pszStart;
  671. // Trace
  672. TraceCall("ParseStringLiteral");
  673. // Validate Args
  674. Assert(*pszT == '"' && pOperand && ppszEnd);
  675. // Increment over "
  676. pszT++;
  677. // Find the End of the Quoted String
  678. while(*pszT)
  679. {
  680. // DBCS Lead Byte
  681. if (IsDBCSLeadByte(*pszT) || '\\' == *pszT)
  682. {
  683. pszT+=2;
  684. continue;
  685. }
  686. // If Escaped Quote..
  687. if ('"' == *pszT)
  688. {
  689. // Set ppszEnd
  690. *ppszEnd = pszT + 1;
  691. // Done
  692. break;
  693. }
  694. // Increment pszT
  695. pszT++;
  696. }
  697. // Not Found
  698. if ('\0' == *pszT)
  699. {
  700. hr = TraceResult(DB_E_UNMATCHINGQUOTES);
  701. goto exit;
  702. }
  703. // Get Size
  704. cchString = (DWORD)(pszT - (pszStart + 1));
  705. // Duplicate the String
  706. IF_NULLEXIT(pszValue = (LPSTR)pDB->PHeapAllocate(NOFLAGS, cchString + 1));
  707. // Copy the String
  708. CopyMemory(pszValue, pszStart + 1, cchString);
  709. // Set the Null
  710. pszValue[cchString] = '\0';
  711. // Set Operand Type
  712. pOperand->tyOperand = OPERAND_STRING;
  713. // Release
  714. pOperand->pRelease = (LPVOID)pszValue;
  715. // Set Value
  716. pOperand->pszString = pszValue;
  717. exit:
  718. // Done
  719. return(hr);
  720. }
  721. //--------------------------------------------------------------------------
  722. // ParseNumeric
  723. //--------------------------------------------------------------------------
  724. HRESULT ParseNumeric(LPCSTR pszStart, LPOPERANDINFO pOperand, LPSTR *ppszEnd)
  725. {
  726. // Locals
  727. HRESULT hr=S_OK;
  728. DWORD dwValue;
  729. CHAR szNumber[255];
  730. DWORD dwIncrement=0;
  731. LPSTR pszT=(LPSTR)pszStart;
  732. DWORD cchNumber;
  733. // Trace
  734. TraceCall("ParseNumeric");
  735. // Validate Args
  736. Assert(DBIsDigit(pszT) && pOperand && ppszEnd);
  737. // Is Hex: 0x
  738. if ('0' == *pszT && '\0' != *(pszT + 1) && 'X' == TOUPPERA(*(pszT + 1)))
  739. {
  740. // IsHex
  741. dwIncrement = 2;
  742. // Set pszT
  743. pszT += 2;
  744. }
  745. // Find the End of the Number
  746. while (*pszT && DBIsDigit(pszT))
  747. {
  748. // Increment
  749. pszT++;
  750. }
  751. // Get Length
  752. cchNumber = (DWORD)(pszT - (pszStart + dwIncrement));
  753. // Too Frickin Big
  754. if (cchNumber >= ARRAYSIZE(szNumber))
  755. {
  756. hr = TraceResult(DB_E_NUMBERTOOBIG);
  757. goto exit;
  758. }
  759. // Copy into szNumber
  760. CopyMemory(szNumber, pszStart + dwIncrement, cchNumber);
  761. // Set Null
  762. szNumber[cchNumber] = '\0';
  763. // If Is Hex, convert to integer
  764. if (FALSE == StrToIntEx(szNumber, dwIncrement ? STIF_SUPPORT_HEX : STIF_DEFAULT, (INT *)&dwValue))
  765. {
  766. hr = TraceResult(DB_E_BADNUMBER);
  767. goto exit;
  768. }
  769. // Set Operand Type
  770. pOperand->tyOperand = OPERAND_DWORD;
  771. // Set Value
  772. pOperand->dwValue = dwValue;
  773. // Return ppszEnd
  774. *ppszEnd = pszT;
  775. exit:
  776. // Done
  777. return(hr);
  778. }
  779. //--------------------------------------------------------------------------
  780. // ParseSymbol
  781. //--------------------------------------------------------------------------
  782. HRESULT ParseSymbol(LPCSTR pszT, LPCTABLESCHEMA pSchema, LPOPERANDINFO pOperand,
  783. LPSTR *ppszEnd, CDatabase *pDB)
  784. {
  785. // Locals
  786. HRESULT hr=S_OK;
  787. DWORD i;
  788. LPSYMBOLINFO pSymbol;
  789. LPSTR pszEnd;
  790. // Trace
  791. TraceCall("ParseSymbol");
  792. // No Symbols
  793. if (NULL == pSchema->pSymbols)
  794. {
  795. hr = TraceResult(DB_E_NOSYMBOLS);
  796. goto exit;
  797. }
  798. // Check for the Start of an Operator...
  799. for (i=0; i<pSchema->pSymbols->cSymbols; i++)
  800. {
  801. // Readability
  802. pSymbol = (LPSYMBOLINFO)&pSchema->pSymbols->rgSymbol[i];
  803. // Does pszT point to the start of an operator ?
  804. if (S_OK == CompareSymbol((LPSTR)pszT, pSymbol->pszName, &pszEnd))
  805. {
  806. // Update pszT
  807. *ppszEnd = pszEnd;
  808. // Save iSymbol
  809. pOperand->iSymbol = i;
  810. // Is Column Symbol
  811. if (SYMBOL_COLUMN == pSymbol->tySymbol)
  812. {
  813. // Validate the Ordinal
  814. if (pSymbol->dwValue > pSchema->cColumns)
  815. {
  816. hr = TraceResult(DB_E_INVALIDCOLUMN);
  817. goto exit;
  818. }
  819. // Convert to OPERANDTYPE
  820. pOperand->tyOperand = OPERAND_COLUMN;
  821. // Save the Column
  822. pOperand->iColumn = (COLUMNORDINAL)pSymbol->dwValue;
  823. }
  824. // Otherwise, is a method ?
  825. else if (SYMBOL_METHOD == pSymbol->tySymbol)
  826. {
  827. // Convert to OPERANDTYPE
  828. pOperand->tyOperand = OPERAND_METHOD;
  829. // Save the Column
  830. pOperand->idMethod = pSymbol->dwValue;
  831. }
  832. // Otherwise, just a dword value
  833. else
  834. {
  835. // Dword
  836. pOperand->tyOperand = OPERAND_DWORD;
  837. // Set the operator type
  838. pOperand->dwValue = pSymbol->dwValue;
  839. }
  840. // Done
  841. goto exit;
  842. }
  843. }
  844. // Not Found
  845. hr = TraceResult(DB_E_INVALIDSYMBOL);
  846. exit:
  847. // Done
  848. return(hr);
  849. }
  850. //--------------------------------------------------------------------------
  851. // CloseQuery
  852. //--------------------------------------------------------------------------
  853. HRESULT CloseQuery(LPHQUERY phQuery, CDatabase *pDB)
  854. {
  855. // Trace
  856. TraceCall("CloseQuery");
  857. // ReleaseTokenList
  858. ReleaseTokenList(FALSE, (LPQUERYTOKEN *)phQuery, pDB);
  859. // Done
  860. return(S_OK);
  861. }
  862. //--------------------------------------------------------------------------
  863. // PushStackToken
  864. //--------------------------------------------------------------------------
  865. HRESULT PushStackToken(LPQUERYTOKEN pToken, LPQUERYTOKEN *ppStackTop)
  866. {
  867. // Trace
  868. TraceCall("PushStackToken");
  869. // Set pStackPrevious
  870. pToken->pPrevious = (*ppStackTop);
  871. // Update Stack Top
  872. (*ppStackTop) = pToken;
  873. // AddRef the Token
  874. pToken->cRefs++;
  875. // Done
  876. return(S_OK);
  877. }
  878. //--------------------------------------------------------------------------
  879. // PopStackToken
  880. //--------------------------------------------------------------------------
  881. HRESULT PopStackToken(LPQUERYTOKEN *ppToken, LPQUERYTOKEN *ppStackTop)
  882. {
  883. // Trace
  884. TraceCall("PopStackToken");
  885. // Validate
  886. Assert(ppToken && ppStackTop);
  887. // No more tokens...
  888. if (NULL == *ppStackTop)
  889. return TraceResult(DB_E_BADEXPRESSION);
  890. // Set Token
  891. *ppToken = (*ppStackTop);
  892. // Goto Previous
  893. (*ppStackTop) = (*ppToken)->pPrevious;
  894. // Release the Token
  895. //(*ppToken)->cRefs--;
  896. // Done
  897. return(S_OK);
  898. }
  899. //--------------------------------------------------------------------------
  900. // LinkToken
  901. //--------------------------------------------------------------------------
  902. HRESULT LinkToken(LPQUERYTOKEN pToken, LPQUERYTOKEN *ppHead, LPQUERYTOKEN *ppTail)
  903. {
  904. // Trace
  905. TraceCall("LinkToken");
  906. // Invalid Args
  907. Assert(pToken && ppTail);
  908. // No Next and No Previous
  909. pToken->pNext = pToken->pPrevious = NULL;
  910. // No Head yet ?
  911. if (ppHead && NULL == *ppHead)
  912. {
  913. // Set the Head and Tail
  914. *ppHead = pToken;
  915. }
  916. // Otherwise, append to the end
  917. else if (*ppTail)
  918. {
  919. // Set ppTail->pNext
  920. (*ppTail)->pNext = pToken;
  921. // Set Previous
  922. pToken->pPrevious = (*ppTail);
  923. }
  924. // Update the Tail
  925. *ppTail = pToken;
  926. // AddRef the Token
  927. pToken->cRefs++;
  928. // Done
  929. return(S_OK);
  930. }
  931. //--------------------------------------------------------------------------
  932. // ReleaseToken
  933. //--------------------------------------------------------------------------
  934. HRESULT ReleaseToken(LPQUERYTOKEN *ppToken, CDatabase *pDB)
  935. {
  936. // Trace
  937. TraceCall("ReleaseToken");
  938. // Token
  939. if (*ppToken)
  940. {
  941. // Validate Reference Count
  942. Assert((*ppToken)->cRefs);
  943. // Decrement Reference Count
  944. (*ppToken)->cRefs--;
  945. // No more refs...
  946. if (0 == (*ppToken)->cRefs)
  947. {
  948. // Free pData
  949. pDB->HeapFree((*ppToken)->Operand.pRelease);
  950. // Free pElement
  951. pDB->HeapFree((*ppToken));
  952. }
  953. // Don't Release Again
  954. *ppToken = NULL;
  955. }
  956. // Done
  957. return(S_OK);
  958. }
  959. //--------------------------------------------------------------------------
  960. // ReleaseTokenList
  961. //--------------------------------------------------------------------------
  962. HRESULT ReleaseTokenList(BOOL fReverse, LPQUERYTOKEN *ppHead, CDatabase *pDB)
  963. {
  964. // Locals
  965. LPQUERYTOKEN pNext;
  966. LPQUERYTOKEN pToken=(*ppHead);
  967. // Trace
  968. TraceCall("ReleaseTokenList");
  969. // Walk the Linked List
  970. while (pToken)
  971. {
  972. // Save Next
  973. pNext = (fReverse ? pToken->pPrevious : pToken->pNext);
  974. // Free this token
  975. ReleaseToken(&pToken, pDB);
  976. // Goto Next
  977. pToken = pNext;
  978. }
  979. // Don't Free Again
  980. *ppHead = NULL;
  981. // Done
  982. return(S_OK);
  983. }
  984. //--------------------------------------------------------------------------
  985. // PGetOperandData
  986. //--------------------------------------------------------------------------
  987. LPVOID PGetOperandData(OPERANDTYPE tyOperand, LPOPERANDINFO pOperand,
  988. LPVOID pBinding, LPCTABLESCHEMA pSchema, CDatabase *pDB,
  989. IDatabaseExtension *pExtension)
  990. {
  991. // Locals
  992. LPVOID pValue=NULL;
  993. // Trace
  994. TraceCall("PGetOperandData");
  995. // OPERAND_COLUMN
  996. if (OPERAND_COLUMN == pOperand->tyOperand)
  997. {
  998. // Get the Tag
  999. LPCTABLECOLUMN pColumn = &pSchema->prgColumn[pOperand->iColumn];
  1000. // MapColumnType
  1001. MapColumnType(pColumn->type, pOperand, pColumn, pBinding, &pValue);
  1002. }
  1003. // OPERAND_STRING
  1004. else if (OPERAND_STRING == pOperand->tyOperand)
  1005. {
  1006. // Better want a string out
  1007. Assert(OPERAND_STRING == tyOperand);
  1008. // Return Data Pointer
  1009. pValue = pOperand->pszString;
  1010. }
  1011. // OPERAND_DWORD
  1012. else if (OPERAND_DWORD == pOperand->tyOperand)
  1013. {
  1014. // Better want a dword out
  1015. Assert(OPERAND_DWORD == tyOperand);
  1016. // Return Data Pointer
  1017. pValue = (LPVOID)&pOperand->dwValue;
  1018. }
  1019. // OPERAND_METHOD
  1020. else if (OPERAND_METHOD == pOperand->tyOperand && pExtension)
  1021. {
  1022. // Better want a dword out
  1023. Assert(OPERAND_DWORD == tyOperand);
  1024. // Call the Method on the Extension
  1025. pExtension->OnExecuteMethod(pOperand->idMethod, pBinding, &pOperand->dwReserved);
  1026. // Return Data Pointer
  1027. pValue = (LPVOID)&pOperand->dwReserved;
  1028. }
  1029. // No Data ?
  1030. if (NULL == pValue)
  1031. {
  1032. // What type of operand was wanted
  1033. switch(tyOperand)
  1034. {
  1035. case OPERAND_STRING:
  1036. pValue = (LPVOID)c_szEmpty;
  1037. break;
  1038. case OPERAND_DWORD:
  1039. pOperand->dwReserved = 0;
  1040. pValue = (LPVOID)&pOperand->dwReserved;
  1041. break;
  1042. default:
  1043. AssertSz(FALSE, "While go ahead and Jimmy my buffet..");
  1044. break;
  1045. }
  1046. }
  1047. // Done
  1048. return(pValue);
  1049. }
  1050. //--------------------------------------------------------------------------
  1051. // GetCommonOperandType
  1052. //--------------------------------------------------------------------------
  1053. OPERANDTYPE GetCommonOperandType(LPOPERANDINFO pLeft, LPOPERANDINFO pRight,
  1054. LPCTABLESCHEMA pSchema)
  1055. {
  1056. // Locals
  1057. OPERANDTYPE tyLeft = (OPERAND_STRING == pLeft->tyOperand ? OPERAND_STRING : OPERAND_DWORD);
  1058. OPERANDTYPE tyRight = (OPERAND_STRING == pRight->tyOperand ? OPERAND_STRING : OPERAND_DWORD);
  1059. // Trace
  1060. TraceCall("GetCommonOperandType");
  1061. // Left is a column
  1062. if (OPERAND_COLUMN == pLeft->tyOperand)
  1063. {
  1064. // Maps to a string
  1065. if (OPERAND_STRING == g_rgColumnTypeInfo[pSchema->prgColumn[pLeft->iColumn].type].tyOperand)
  1066. tyLeft = OPERAND_STRING;
  1067. }
  1068. // Right is a string
  1069. if (OPERAND_COLUMN == pRight->tyOperand)
  1070. {
  1071. // Maps to a String ?
  1072. if (OPERAND_STRING == g_rgColumnTypeInfo[pSchema->prgColumn[pRight->iColumn].type].tyOperand)
  1073. tyRight = OPERAND_STRING;
  1074. }
  1075. // Better be the Same
  1076. Assert(tyLeft == tyRight);
  1077. // Return tyLeft since they are the same
  1078. return(tyLeft);
  1079. }
  1080. //--------------------------------------------------------------------------
  1081. // EvaluateClause
  1082. //--------------------------------------------------------------------------
  1083. HRESULT EvaluateClause(OPERATORTYPE tyOperator, LPVOID pBinding,
  1084. LPCTABLESCHEMA pSchema, LPQUERYTOKEN *ppStackTop, CDatabase *pDB,
  1085. IDatabaseExtension *pExtension)
  1086. {
  1087. // Locals
  1088. HRESULT hr=S_OK;
  1089. LPVOID pDataLeft=NULL;
  1090. LPVOID pDataRight=NULL;
  1091. LPQUERYTOKEN pTokenResult=NULL;
  1092. LPQUERYTOKEN pTokenRight=NULL;
  1093. LPQUERYTOKEN pTokenLeft=NULL;
  1094. OPERANDTYPE tyOperand;
  1095. INT nCompare;
  1096. // Trace
  1097. TraceCall("EvaluateClause");
  1098. // Pop the right token
  1099. IF_FAILEXIT(hr = PopStackToken(&pTokenRight, ppStackTop));
  1100. // Pop the left token
  1101. IF_FAILEXIT(hr = PopStackToken(&pTokenLeft, ppStackTop));
  1102. // Better have Data
  1103. Assert(TOKEN_OPERAND == pTokenLeft->tyToken && TOKEN_OPERAND == pTokenRight->tyToken);
  1104. // Compute Operand type
  1105. tyOperand = GetCommonOperandType(&pTokenLeft->Operand, &pTokenRight->Operand, pSchema);
  1106. // Get Left Data
  1107. pDataLeft = PGetOperandData(tyOperand, &pTokenLeft->Operand, pBinding, pSchema, pDB, pExtension);
  1108. // Get Right Data
  1109. pDataRight = PGetOperandData(tyOperand, &pTokenRight->Operand, pBinding, pSchema, pDB, pExtension);
  1110. // Create new Token to push back onto the stack
  1111. IF_NULLEXIT(pTokenResult = (LPQUERYTOKEN)pDB->PHeapAllocate(HEAP_ZERO_MEMORY, sizeof(QUERYTOKEN)));
  1112. // Set Reference Count
  1113. pTokenResult->cRefs = 1;
  1114. // No Token foundyet
  1115. pTokenResult->tyToken = TOKEN_OPERAND;
  1116. // Invalid Symbol Index
  1117. pTokenResult->Operand.iSymbol = 0xffffffff;
  1118. // Set Result
  1119. pTokenResult->Operand.tyOperand = OPERAND_DWORD;
  1120. // EvaluateData
  1121. pTokenResult->Operand.dwValue = EvaluateOperator(tyOperator, tyOperand, pDataLeft, pDataRight);
  1122. // Push the result operand
  1123. PushStackToken(pTokenResult, ppStackTop);
  1124. exit:
  1125. // Cleanup
  1126. ReleaseToken(&pTokenLeft, pDB);
  1127. ReleaseToken(&pTokenRight, pDB);
  1128. ReleaseToken(&pTokenResult, pDB);
  1129. // Done
  1130. return(hr);
  1131. }
  1132. //--------------------------------------------------------------------------
  1133. // EvaluateEqual
  1134. //--------------------------------------------------------------------------
  1135. DWORD EvaluateEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1136. return (0 == CompareOperands(tyOperand, pDataLeft, pDataRight) ? TRUE : FALSE);
  1137. }
  1138. //--------------------------------------------------------------------------
  1139. // EvaluateNotEqual
  1140. //--------------------------------------------------------------------------
  1141. DWORD EvaluateNotEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1142. return (0 != CompareOperands(tyOperand, pDataLeft, pDataRight) ? TRUE : FALSE);
  1143. }
  1144. //--------------------------------------------------------------------------
  1145. // EvaluateLessThanEqual
  1146. //--------------------------------------------------------------------------
  1147. DWORD EvaluateLessThanEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1148. return (CompareOperands(tyOperand, pDataLeft, pDataRight) <= 0 ? TRUE : FALSE);
  1149. }
  1150. //--------------------------------------------------------------------------
  1151. // EvaluateLessThan
  1152. //--------------------------------------------------------------------------
  1153. DWORD EvaluateLessThan(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1154. return (CompareOperands(tyOperand, pDataLeft, pDataRight) < 0 ? TRUE : FALSE);
  1155. }
  1156. //--------------------------------------------------------------------------
  1157. // EvaluateGreaterThanEqual
  1158. //--------------------------------------------------------------------------
  1159. DWORD EvaluateGreaterThanEqual(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1160. return (CompareOperands(tyOperand, pDataLeft, pDataRight) >= 0 ? TRUE : FALSE);
  1161. }
  1162. //--------------------------------------------------------------------------
  1163. // EvaluateGreaterThan
  1164. //--------------------------------------------------------------------------
  1165. DWORD EvaluateGreaterThan(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1166. return (CompareOperands(tyOperand, pDataLeft, pDataRight) > 0 ? TRUE : FALSE);
  1167. }
  1168. //--------------------------------------------------------------------------
  1169. // EvaluateAnd
  1170. //--------------------------------------------------------------------------
  1171. DWORD EvaluateAnd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1172. return (INT)(*((DWORD *)pDataLeft) && *((DWORD *)pDataRight));
  1173. }
  1174. //--------------------------------------------------------------------------
  1175. // EvaluateBitwiseAnd
  1176. //--------------------------------------------------------------------------
  1177. DWORD EvaluateBitwiseAnd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1178. return (INT)(*((DWORD *)pDataLeft) & *((DWORD *)pDataRight));
  1179. }
  1180. //--------------------------------------------------------------------------
  1181. // EvaluateOr
  1182. //--------------------------------------------------------------------------
  1183. DWORD EvaluateOr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1184. return (INT)(*((DWORD *)pDataLeft) || *((DWORD *)pDataRight));
  1185. }
  1186. //--------------------------------------------------------------------------
  1187. // EvaluateBitwiseOr
  1188. //--------------------------------------------------------------------------
  1189. DWORD EvaluateBitwiseOr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1190. return (INT)(*((DWORD *)pDataLeft) | *((DWORD *)pDataRight));
  1191. }
  1192. //--------------------------------------------------------------------------
  1193. // EvaluateStrStrI
  1194. //--------------------------------------------------------------------------
  1195. DWORD EvaluateStrStrI(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1196. return (NULL == StrStrIA((LPCSTR)pDataLeft, (LPCSTR)pDataRight) ? FALSE : TRUE);
  1197. }
  1198. //--------------------------------------------------------------------------
  1199. // EvaluateStrStr
  1200. //--------------------------------------------------------------------------
  1201. DWORD EvaluateStrStr(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1202. return (NULL == StrStrA((LPCSTR)pDataLeft, (LPCSTR)pDataRight) ? FALSE : TRUE);
  1203. }
  1204. //--------------------------------------------------------------------------
  1205. // EvaluateStrcmpi
  1206. //--------------------------------------------------------------------------
  1207. DWORD EvaluateStrcmpi(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1208. return (lstrcmpi((LPCSTR)pDataLeft, (LPCSTR)pDataRight) == 0 ? TRUE : FALSE);
  1209. }
  1210. //--------------------------------------------------------------------------
  1211. // EvaluateStrcmp
  1212. //--------------------------------------------------------------------------
  1213. DWORD EvaluateStrcmp(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1214. return (lstrcmp((LPCSTR)pDataLeft, (LPCSTR)pDataRight) == 0 ? TRUE : FALSE);
  1215. }
  1216. //--------------------------------------------------------------------------
  1217. // EvaluateAdd
  1218. //--------------------------------------------------------------------------
  1219. DWORD EvaluateAdd(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1220. return (INT)(*((DWORD *)pDataLeft) + *((DWORD *)pDataRight));
  1221. }
  1222. //--------------------------------------------------------------------------
  1223. // EvaluateSubtract
  1224. //--------------------------------------------------------------------------
  1225. DWORD EvaluateSubtract(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1226. return (INT)(*((DWORD *)pDataLeft) - *((DWORD *)pDataRight));
  1227. }
  1228. //--------------------------------------------------------------------------
  1229. // EvaluateMultiply
  1230. //--------------------------------------------------------------------------
  1231. DWORD EvaluateMultiply(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1232. return (INT)(*((DWORD *)pDataLeft) * *((DWORD *)pDataRight));
  1233. }
  1234. //--------------------------------------------------------------------------
  1235. // EvaluateDivide
  1236. //--------------------------------------------------------------------------
  1237. DWORD EvaluateDivide(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1238. return (INT)(*((DWORD *)pDataLeft) / *((DWORD *)pDataRight));
  1239. }
  1240. //--------------------------------------------------------------------------
  1241. // EvaluateModula
  1242. //--------------------------------------------------------------------------
  1243. DWORD EvaluateModula(OPERANDTYPE tyOperand, LPVOID pDataLeft, LPVOID pDataRight) {
  1244. return (INT)(*((DWORD *)pDataLeft) % *((DWORD *)pDataRight));
  1245. }