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.

6565 lines
209 KiB

  1. /***************************************************************************/
  2. /* EVALUATE.C */
  3. /* Copyright (C) 1995-96 SYWARE Inc., All rights reserved */
  4. /***************************************************************************/
  5. // Commenting #define out - causing compiler error - not sure if needed, compiles
  6. // okay without it.
  7. //#define WINVER 0x0400
  8. #include "precomp.h"
  9. #include "wbemidl.h"
  10. #include <comdef.h>
  11. //smart pointer
  12. _COM_SMARTPTR_TYPEDEF(IWbemServices, IID_IWbemServices);
  13. _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, IID_IEnumWbemClassObject);
  14. //_COM_SMARTPTR_TYPEDEF(IWbemContext, IID_IWbemContext );
  15. _COM_SMARTPTR_TYPEDEF(IWbemLocator, IID_IWbemLocator);
  16. #include "drdbdr.h"
  17. #include <time.h>
  18. #include <memory.h>
  19. /***************************************************************************/
  20. #define SECONDS_PER_DAY (60L * 60L * 24L)
  21. typedef struct HFILE_BUFFERtag {
  22. HGLOBAL hGlobal;
  23. HFILE hfile;
  24. UWORD offset;
  25. LPSTR ptr;
  26. char buffer[32768];
  27. } HF_BUFFER, FAR * HFILE_BUFFER;
  28. HFILE_BUFFER _lcreat_buffer(LPCSTR szFilename, int arg)
  29. {
  30. HGLOBAL h;
  31. HFILE_BUFFER hf;
  32. h = GlobalAlloc(GMEM_MOVEABLE, sizeof(HF_BUFFER));
  33. if (h == NULL)
  34. return NULL;
  35. hf = (HFILE_BUFFER) GlobalLock(h);
  36. if (hf == NULL) {
  37. GlobalFree(h);
  38. return NULL;
  39. }
  40. hf->hGlobal = h;
  41. hf->hfile = _lcreat(szFilename, arg);
  42. if (hf->hfile == HFILE_ERROR) {
  43. GlobalUnlock(h);
  44. GlobalFree(h);
  45. return NULL;
  46. }
  47. hf->offset = 0;
  48. hf->ptr = hf->buffer;
  49. return hf;
  50. }
  51. HFILE _lclose_buffer(HFILE_BUFFER hf)
  52. {
  53. HGLOBAL h;
  54. if (hf->offset != 0) {
  55. if ((UINT) hf->offset !=
  56. _lwrite(hf->hfile, hf->buffer, (UINT) hf->offset)) {
  57. h = hf->hGlobal;
  58. _lclose(hf->hfile);
  59. GlobalUnlock(h);
  60. GlobalFree(h);
  61. return HFILE_ERROR;
  62. }
  63. }
  64. if (HFILE_ERROR == _lclose(hf->hfile)) {
  65. h = hf->hGlobal;
  66. GlobalUnlock(h);
  67. GlobalFree(h);
  68. return HFILE_ERROR;
  69. }
  70. h = hf->hGlobal;
  71. GlobalUnlock(h);
  72. GlobalFree(h);
  73. return 0;
  74. }
  75. UINT _lwrite_buffer(HFILE_BUFFER hf, LPSTR ptr, UINT len)
  76. {
  77. UWORD total;
  78. UWORD count;
  79. total = 0;
  80. while (TRUE) {
  81. if (len > sizeof(hf->buffer) - hf->offset)
  82. count = sizeof(hf->buffer) - hf->offset;
  83. else
  84. count = (UWORD) len;
  85. _fmemcpy(hf->ptr, ptr, count);
  86. hf->ptr += (count);
  87. ptr += (count);
  88. hf->offset += (count);
  89. total += (count);
  90. len -= (count);
  91. if (len == 0)
  92. break;
  93. if (sizeof(hf->buffer) !=
  94. _lwrite(hf->hfile, hf->buffer, sizeof(hf->buffer)))
  95. return ((UINT) HFILE_ERROR);
  96. hf->offset = 0;
  97. hf->ptr = hf->buffer;
  98. }
  99. return total;
  100. }
  101. /***************************************************************************/
  102. void INTFUNC DateAdd(DATE_STRUCT date, SWORD offset, DATE_STRUCT FAR *result)
  103. /* Adds specified number of days to a date */
  104. {
  105. static struct tm tm_time;
  106. time_t t;
  107. /* Create time structure */
  108. tm_time.tm_sec = 0;
  109. tm_time.tm_min = 0;
  110. tm_time.tm_hour = 0;
  111. tm_time.tm_mday = date.day + offset;
  112. tm_time.tm_mon = date.month - 1;
  113. tm_time.tm_year = (date.year >= 1900 ? date.year - 1900 : 0);
  114. tm_time.tm_wday = 0;
  115. tm_time.tm_yday = 0;
  116. tm_time.tm_isdst = 0;
  117. /* Correct values */
  118. t = mktime(&tm_time);
  119. if (t == -1) {
  120. result->year = 0;
  121. result->month = 0;
  122. result->day = 0;
  123. return;
  124. }
  125. /* Return answer */
  126. result->year = tm_time.tm_year + 1900;
  127. result->month = tm_time.tm_mon + 1;
  128. result->day = (WORD) tm_time.tm_mday;
  129. }
  130. /***************************************************************************/
  131. int INTFUNC DateDifference(DATE_STRUCT leftDate, DATE_STRUCT rightDate)
  132. /* Compares two dates. */
  133. {
  134. static struct tm tm_time;
  135. time_t left_t;
  136. time_t right_t;
  137. /* Create left value */
  138. tm_time.tm_sec = 0;
  139. tm_time.tm_min = 0;
  140. tm_time.tm_hour = 0;
  141. tm_time.tm_mday = leftDate.day;
  142. tm_time.tm_mon = leftDate.month-1;
  143. tm_time.tm_year = (leftDate.year >= 1900 ? leftDate.year - 1900 : 0);
  144. tm_time.tm_wday = 0;
  145. tm_time.tm_yday = 0;
  146. tm_time.tm_isdst = 0;
  147. left_t = mktime(&tm_time);
  148. /* Create right value */
  149. tm_time.tm_sec = 0;
  150. tm_time.tm_min = 0;
  151. tm_time.tm_hour = 0;
  152. tm_time.tm_mday = rightDate.day;
  153. tm_time.tm_mon = rightDate.month-1;
  154. tm_time.tm_year = (rightDate.year >= 1900 ? rightDate.year - 1900 : 0);
  155. tm_time.tm_wday = 0;
  156. tm_time.tm_yday = 0;
  157. tm_time.tm_isdst = 0;
  158. right_t = mktime(&tm_time);
  159. /* Return answer */
  160. return (int) ((left_t - right_t) / SECONDS_PER_DAY);
  161. }
  162. /***************************************************************************/
  163. int INTFUNC DateCompare(DATE_STRUCT leftDate, DATE_STRUCT rightDate)
  164. /* Compares two dates. */
  165. {
  166. if ( (leftDate.year - rightDate.year) != 0 )
  167. return (int) (leftDate.year -rightDate.year);
  168. else if ( (leftDate.month - rightDate.month) != 0 )
  169. return (int) (leftDate.month -rightDate.month);
  170. else
  171. return (int) (leftDate.day -rightDate.day);
  172. }
  173. /***************************************************************************/
  174. int INTFUNC TimeCompare(TIME_STRUCT leftTime, TIME_STRUCT rightTime)
  175. /* Compares two times. */
  176. {
  177. if ((leftTime.hour - rightTime.hour) != 0)
  178. return (int) (leftTime.hour - rightTime.hour);
  179. else if ((leftTime.minute - rightTime.minute) != 0)
  180. return (int) (leftTime.minute - rightTime.minute);
  181. else
  182. return (int) (leftTime.second - rightTime.second);
  183. }
  184. /***************************************************************************/
  185. int INTFUNC TimestampCompare(TIMESTAMP_STRUCT leftTimestamp,
  186. TIMESTAMP_STRUCT rightTimestamp)
  187. /* Compares two timestamp. */
  188. {
  189. if ((leftTimestamp.year - rightTimestamp.year) != 0)
  190. return (int) (leftTimestamp.year - rightTimestamp.year);
  191. else if ((leftTimestamp.month - rightTimestamp.month) != 0)
  192. return (int) (leftTimestamp.month - rightTimestamp.month);
  193. else if ((leftTimestamp.day - rightTimestamp.day) != 0)
  194. return (int) (leftTimestamp.day - rightTimestamp.day);
  195. else if ((leftTimestamp.hour - rightTimestamp.hour) != 0)
  196. return (int) (leftTimestamp.hour - rightTimestamp.hour);
  197. else if ((leftTimestamp.minute - rightTimestamp.minute) != 0)
  198. return (int) (leftTimestamp.minute - rightTimestamp.minute);
  199. else if ((leftTimestamp.second - rightTimestamp.second) != 0)
  200. return (int) (leftTimestamp.second - rightTimestamp.second);
  201. else if (leftTimestamp.fraction > rightTimestamp.fraction)
  202. return 1;//-1;
  203. else if (leftTimestamp.fraction < rightTimestamp.fraction)
  204. return -1;//1;
  205. else
  206. return 0;
  207. }
  208. /***************************************************************************/
  209. RETCODE INTFUNC NumericCompare(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
  210. UWORD Operator, LPSQLNODE lpSqlNodeRight)
  211. /* Compares two numerical valuesas follows: */
  212. /* lpSqlNode->value.Double = lpSqlNodeLeft Operator lpSqlNodeRight */
  213. {
  214. RETCODE err;
  215. UWORD op;
  216. SQLNODE sqlNode;
  217. UCHAR szBuffer[32];
  218. /* What is the type of the left side? */
  219. switch (lpSqlNodeLeft->sqlDataType) {
  220. case TYPE_DOUBLE:
  221. case TYPE_INTEGER:
  222. /* Left side is a double or integer. What is the right side? */
  223. switch (lpSqlNodeRight->sqlDataType) {
  224. case TYPE_DOUBLE:
  225. case TYPE_INTEGER:
  226. /* Right side is also a double or an integer. Compare them */
  227. switch (Operator) {
  228. case OP_EQ:
  229. if (lpSqlNodeLeft->value.Double ==
  230. lpSqlNodeRight->value.Double)
  231. lpSqlNode->value.Double = TRUE;
  232. else
  233. lpSqlNode->value.Double = FALSE;
  234. break;
  235. case OP_NE:
  236. if (lpSqlNodeLeft->value.Double !=
  237. lpSqlNodeRight->value.Double)
  238. lpSqlNode->value.Double = TRUE;
  239. else
  240. lpSqlNode->value.Double = FALSE;
  241. break;
  242. case OP_LE:
  243. if (lpSqlNodeLeft->value.Double <=
  244. lpSqlNodeRight->value.Double)
  245. lpSqlNode->value.Double = TRUE;
  246. else
  247. lpSqlNode->value.Double = FALSE;
  248. break;
  249. case OP_LT:
  250. if (lpSqlNodeLeft->value.Double <
  251. lpSqlNodeRight->value.Double)
  252. lpSqlNode->value.Double = TRUE;
  253. else
  254. lpSqlNode->value.Double = FALSE;
  255. break;
  256. case OP_GE:
  257. if (lpSqlNodeLeft->value.Double >=
  258. lpSqlNodeRight->value.Double)
  259. lpSqlNode->value.Double = TRUE;
  260. else
  261. lpSqlNode->value.Double = FALSE;
  262. break;
  263. case OP_GT:
  264. if (lpSqlNodeLeft->value.Double >
  265. lpSqlNodeRight->value.Double)
  266. lpSqlNode->value.Double = TRUE;
  267. else
  268. lpSqlNode->value.Double = FALSE;
  269. break;
  270. case OP_LIKE:
  271. case OP_NOTLIKE:
  272. default:
  273. return ERR_INTERNAL;
  274. }
  275. break;
  276. case TYPE_NUMERIC:
  277. /* Right side is a numeric. Is left side a double? */
  278. if (lpSqlNodeLeft->sqlDataType == TYPE_DOUBLE) {
  279. /* Yes. Promote the right side to a double */
  280. sqlNode = *lpSqlNodeRight;
  281. sqlNode.sqlDataType = TYPE_DOUBLE;
  282. sqlNode.sqlSqlType = SQL_DOUBLE;
  283. sqlNode.sqlPrecision = 15;
  284. sqlNode.sqlScale = NO_SCALE;
  285. err = CharToDouble(lpSqlNodeRight->value.String,
  286. s_lstrlen(lpSqlNodeRight->value.String), FALSE,
  287. -1.7E308, 1.7E308, &(sqlNode.value.Double));
  288. if (err != ERR_SUCCESS)
  289. return err;
  290. /* Compare the two doubles */
  291. err = NumericCompare(lpSqlNode, lpSqlNodeLeft, Operator,
  292. &sqlNode);
  293. if (err != ERR_SUCCESS)
  294. return err;
  295. }
  296. /* Right side is a numeric. Is left side an integer? */
  297. else { /* (lpSqlNodeLeft->sqlDataType == TYPE_INTEGER) */
  298. /* Yes. Promote the left side to a numeric */
  299. sqlNode = *lpSqlNodeLeft;
  300. sqlNode.sqlDataType = TYPE_NUMERIC;
  301. sqlNode.sqlSqlType = SQL_NUMERIC;
  302. sqlNode.sqlPrecision = 10;
  303. sqlNode.sqlScale = 0;
  304. if (lpSqlNodeLeft->value.Double != 0.0)
  305. wsprintf((LPSTR)szBuffer, "%ld", (long) lpSqlNodeLeft->value.Double);
  306. else
  307. s_lstrcpy((char*)szBuffer, "");
  308. sqlNode.value.String = (LPUSTR)szBuffer;
  309. /* Compare the two numerics */
  310. err = NumericCompare(lpSqlNode, &sqlNode, Operator,
  311. lpSqlNodeRight);
  312. if (err != ERR_SUCCESS)
  313. return err;
  314. }
  315. break;
  316. case TYPE_CHAR:
  317. case TYPE_BINARY:
  318. case TYPE_DATE:
  319. case TYPE_TIME:
  320. case TYPE_TIMESTAMP:
  321. return ERR_INTERNAL;
  322. default:
  323. return ERR_NOTSUPPORTED;
  324. }
  325. break;
  326. case TYPE_NUMERIC:
  327. /* Left side is a numeric. What is the right side? */
  328. switch (lpSqlNodeRight->sqlDataType) {
  329. case TYPE_DOUBLE:
  330. case TYPE_INTEGER:
  331. /* Right side is a double or integer. Swap left and right and */
  332. /* then do the comaprison */
  333. switch (Operator) {
  334. case OP_EQ:
  335. op = OP_EQ;
  336. break;
  337. case OP_NE:
  338. op = OP_NE;
  339. break;
  340. case OP_LE:
  341. op = OP_GE;
  342. break;
  343. case OP_LT:
  344. op = OP_GT;
  345. break;
  346. case OP_GE:
  347. op = OP_LE;
  348. break;
  349. case OP_GT:
  350. op = OP_LT;
  351. break;
  352. case OP_LIKE:
  353. case OP_NOTLIKE:
  354. default:
  355. return ERR_INTERNAL;
  356. }
  357. err = NumericCompare(lpSqlNode, lpSqlNodeRight, op,
  358. lpSqlNodeLeft);
  359. if (err != ERR_SUCCESS)
  360. return err;
  361. break;
  362. case TYPE_NUMERIC:
  363. /* Right side is also numeric. Compare them as numeric */
  364. err = BCDCompare(lpSqlNode, lpSqlNodeLeft, Operator, lpSqlNodeRight);
  365. if (err != ERR_SUCCESS)
  366. return err;
  367. break;
  368. case TYPE_CHAR:
  369. case TYPE_BINARY:
  370. case TYPE_DATE:
  371. case TYPE_TIME:
  372. case TYPE_TIMESTAMP:
  373. return ERR_INTERNAL;
  374. default:
  375. return ERR_NOTSUPPORTED;
  376. }
  377. break;
  378. case TYPE_CHAR:
  379. case TYPE_BINARY:
  380. case TYPE_DATE:
  381. case TYPE_TIME:
  382. case TYPE_TIMESTAMP:
  383. return ERR_INTERNAL;
  384. default:
  385. return ERR_NOTSUPPORTED;
  386. }
  387. return ERR_SUCCESS;
  388. }
  389. /***************************************************************************/
  390. SWORD INTFUNC ToInteger(LPSQLNODE lpSqlNode)
  391. /* Returns the value of the node (as an integer). If the data type of the */
  392. /* node is incompatible, zerois returned */
  393. {
  394. double dbl;
  395. RETCODE err;
  396. switch (lpSqlNode->sqlDataType) {
  397. case TYPE_DOUBLE:
  398. case TYPE_INTEGER:
  399. return ((SWORD) lpSqlNode->value.Double);
  400. case TYPE_NUMERIC:
  401. err = CharToDouble(lpSqlNode->value.String,
  402. s_lstrlen(lpSqlNode->value.String), FALSE,
  403. -1.7E308, 1.7E308, &dbl);
  404. if (err != ERR_SUCCESS)
  405. return 0;
  406. return ((SWORD) dbl);
  407. case TYPE_CHAR:
  408. case TYPE_BINARY:
  409. case TYPE_DATE:
  410. case TYPE_TIME:
  411. case TYPE_TIMESTAMP:
  412. default:
  413. return 0;
  414. }
  415. }
  416. /***************************************************************************/
  417. RETCODE INTFUNC NumericAlgebra(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
  418. UWORD Operator, LPSQLNODE lpSqlNodeRight,
  419. LPUSTR lpWorkBuffer1, LPUSTR lpWorkBuffer2,
  420. LPUSTR lpWorkBuffer3)
  421. /* Perfoms algebraic operation in two numerical or char values as follows: */
  422. /* lpSqlNode lpSqlNodeLeft Operator lpSqlNodeRight */
  423. {
  424. RETCODE err;
  425. SQLNODE sqlNode;
  426. UCHAR szBuffer[32];
  427. /* What is the type of the left side? */
  428. switch (lpSqlNodeLeft->sqlDataType) {
  429. case TYPE_DOUBLE:
  430. case TYPE_INTEGER:
  431. /* Left side is a double or integer. What is the right side? */
  432. switch (lpSqlNodeRight != NULL ? lpSqlNodeRight->sqlDataType :
  433. lpSqlNodeLeft->sqlDataType) {
  434. case TYPE_DOUBLE:
  435. case TYPE_INTEGER:
  436. /* Right side is also a double or an integer. Do the operation */
  437. switch (Operator) {
  438. case OP_NEG:
  439. lpSqlNode->value.Double = -(lpSqlNodeLeft->value.Double);
  440. break;
  441. case OP_PLUS:
  442. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double +
  443. lpSqlNodeRight->value.Double;
  444. break;
  445. case OP_MINUS:
  446. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double -
  447. lpSqlNodeRight->value.Double;
  448. break;
  449. case OP_TIMES:
  450. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double *
  451. lpSqlNodeRight->value.Double;
  452. break;
  453. case OP_DIVIDEDBY:
  454. if (lpSqlNodeRight->value.Double != 0.0)
  455. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double /
  456. lpSqlNodeRight->value.Double;
  457. else
  458. return ERR_ZERODIVIDE;
  459. break;
  460. default:
  461. return ERR_INTERNAL;
  462. break;
  463. }
  464. break;
  465. case TYPE_NUMERIC:
  466. /* Right side is a numeric. Is left side a double? */
  467. if (lpSqlNodeLeft->sqlDataType == TYPE_DOUBLE) {
  468. /* Yes. Promote the right side to a double */
  469. sqlNode = *lpSqlNodeRight;
  470. sqlNode.sqlDataType = TYPE_DOUBLE;
  471. sqlNode.sqlSqlType = SQL_DOUBLE;
  472. sqlNode.sqlPrecision = 15;
  473. sqlNode.sqlScale = NO_SCALE;
  474. err = CharToDouble(lpSqlNodeRight->value.String,
  475. s_lstrlen(lpSqlNodeRight->value.String), FALSE,
  476. -1.7E308, 1.7E308, &(sqlNode.value.Double));
  477. if (err != ERR_SUCCESS)
  478. return err;
  479. /* Compute the result */
  480. err = NumericAlgebra(lpSqlNode, lpSqlNodeLeft, Operator,
  481. &sqlNode, lpWorkBuffer1, lpWorkBuffer2,
  482. lpWorkBuffer3);
  483. if (err != ERR_SUCCESS)
  484. return err;
  485. }
  486. /* Right side is a numeric. Is left side an integer? */
  487. else { /* (lpSqlNodeLeft->sqlDataType == TYPE_INTEGER) */
  488. /* Yes. Promote the left side to a numeric */
  489. sqlNode = *lpSqlNodeLeft;
  490. sqlNode.sqlDataType = TYPE_NUMERIC;
  491. sqlNode.sqlSqlType = SQL_NUMERIC;
  492. sqlNode.sqlPrecision = 10;
  493. sqlNode.sqlScale = 0;
  494. if (lpSqlNodeLeft->value.Double != 0.0)
  495. wsprintf((LPSTR)szBuffer, "%ld", (long) lpSqlNodeLeft->value.Double);
  496. else
  497. s_lstrcpy((char*)szBuffer, "");
  498. sqlNode.value.String = (LPUSTR)szBuffer;
  499. /* Compute the result */
  500. err = NumericAlgebra(lpSqlNode, &sqlNode, Operator,
  501. lpSqlNodeRight, lpWorkBuffer1,
  502. lpWorkBuffer2, lpWorkBuffer3);
  503. if (err != ERR_SUCCESS)
  504. return err;
  505. }
  506. break;
  507. case TYPE_DATE:
  508. /* Right side is a date. Do the operation */
  509. switch (Operator) {
  510. case OP_PLUS:
  511. DateAdd(lpSqlNodeRight->value.Date,
  512. ToInteger(lpSqlNodeLeft),
  513. &(lpSqlNode->value.Date));
  514. break;
  515. case OP_NEG:
  516. case OP_MINUS:
  517. case OP_TIMES:
  518. case OP_DIVIDEDBY:
  519. default:
  520. return ERR_INTERNAL;
  521. }
  522. break;
  523. case TYPE_CHAR:
  524. case TYPE_BINARY:
  525. case TYPE_TIME:
  526. case TYPE_TIMESTAMP:
  527. return ERR_INTERNAL;
  528. default:
  529. return ERR_NOTSUPPORTED;
  530. }
  531. break;
  532. case TYPE_NUMERIC:
  533. /* Left side is a numeric. What is the right side? */
  534. switch (lpSqlNodeRight != NULL ? lpSqlNodeRight->sqlDataType :
  535. lpSqlNodeLeft->sqlDataType) {
  536. case TYPE_DOUBLE:
  537. /* Right side is a double. Promote the left side to a double */
  538. sqlNode = *lpSqlNodeLeft;
  539. sqlNode.sqlDataType = TYPE_DOUBLE;
  540. sqlNode.sqlSqlType = SQL_DOUBLE;
  541. sqlNode.sqlPrecision = 15;
  542. sqlNode.sqlScale = NO_SCALE;
  543. err = CharToDouble(lpSqlNodeLeft->value.String,
  544. s_lstrlen(lpSqlNodeLeft->value.String), FALSE,
  545. -1.7E308, 1.7E308, &(sqlNode.value.Double));
  546. if (err != ERR_SUCCESS)
  547. return err;
  548. /* Compute the result */
  549. err = NumericAlgebra(lpSqlNode, &sqlNode, Operator,
  550. lpSqlNodeRight, lpWorkBuffer1,
  551. lpWorkBuffer2, lpWorkBuffer3);
  552. if (err != ERR_SUCCESS)
  553. return err;
  554. break;
  555. case TYPE_INTEGER:
  556. /* Right side is an integer. Promote the right side to nuemric */
  557. sqlNode = *lpSqlNodeRight;
  558. sqlNode.sqlDataType = TYPE_NUMERIC;
  559. sqlNode.sqlSqlType = SQL_NUMERIC;
  560. sqlNode.sqlPrecision = 10;
  561. sqlNode.sqlScale = 0;
  562. if (lpSqlNodeRight->value.Double != 0.0)
  563. wsprintf((LPSTR)szBuffer, "%ld", (long) lpSqlNodeRight->value.Double);
  564. else
  565. s_lstrcpy((char*)szBuffer, "");
  566. sqlNode.value.String = szBuffer;
  567. /* Compute the result */
  568. err = NumericAlgebra(lpSqlNode, lpSqlNodeLeft, Operator,
  569. &sqlNode, lpWorkBuffer1, lpWorkBuffer2,
  570. lpWorkBuffer3);
  571. if (err != ERR_SUCCESS)
  572. return err;
  573. break;
  574. case TYPE_NUMERIC:
  575. /* Right side is also numeric. Do the operation */
  576. err = BCDAlgebra(lpSqlNode, lpSqlNodeLeft, Operator,
  577. lpSqlNodeRight, lpWorkBuffer1,
  578. lpWorkBuffer2, lpWorkBuffer3);
  579. if (err != ERR_SUCCESS)
  580. return err;
  581. break;
  582. case TYPE_CHAR:
  583. case TYPE_BINARY:
  584. case TYPE_DATE:
  585. case TYPE_TIME:
  586. case TYPE_TIMESTAMP:
  587. return ERR_INTERNAL;
  588. default:
  589. return ERR_NOTSUPPORTED;
  590. }
  591. break;
  592. case TYPE_DATE:
  593. /* Left side is a date. What operator? */
  594. switch (Operator) {
  595. case OP_NEG:
  596. return ERR_INTERNAL;
  597. break;
  598. case OP_PLUS:
  599. DateAdd(lpSqlNodeLeft->value.Date,
  600. ToInteger(lpSqlNodeRight),
  601. &(lpSqlNode->value.Date));
  602. break;
  603. case OP_MINUS:
  604. switch (lpSqlNodeRight->sqlDataType) {
  605. case TYPE_DOUBLE:
  606. case TYPE_INTEGER:
  607. case TYPE_NUMERIC:
  608. DateAdd(lpSqlNodeLeft->value.Date, (SWORD)
  609. -(ToInteger(lpSqlNodeRight)),
  610. &(lpSqlNode->value.Date));
  611. break;
  612. case TYPE_CHAR:
  613. case TYPE_BINARY:
  614. return ERR_INTERNAL;
  615. break;
  616. case TYPE_DATE:
  617. lpSqlNode->value.Double = DateDifference(
  618. lpSqlNodeLeft->value.Date,
  619. lpSqlNodeRight->value.Date);
  620. break;
  621. case TYPE_TIME:
  622. return ERR_INTERNAL;
  623. break;
  624. case TYPE_TIMESTAMP:
  625. return ERR_NOTSUPPORTED;
  626. break;
  627. }
  628. break;
  629. case OP_TIMES:
  630. case OP_DIVIDEDBY:
  631. default:
  632. return ERR_INTERNAL;
  633. break;
  634. }
  635. break;
  636. case TYPE_CHAR:
  637. /* Left side is character. Concatenate */
  638. if ((lpSqlNodeRight->sqlDataType != TYPE_CHAR) ||
  639. (Operator != OP_PLUS))
  640. return ERR_INTERNAL;
  641. if ((s_lstrlen(lpSqlNodeLeft->value.String) +
  642. s_lstrlen(lpSqlNodeRight->value.String)) > lpSqlNode->sqlPrecision)
  643. return ERR_CONCATOVERFLOW;
  644. s_lstrcpy(lpSqlNode->value.String, lpSqlNodeLeft->value.String);
  645. s_lstrcat(lpSqlNode->value.String, lpSqlNodeRight->value.String);
  646. break;
  647. case TYPE_BINARY:
  648. case TYPE_TIME:
  649. case TYPE_TIMESTAMP:
  650. return ERR_INTERNAL;
  651. default:
  652. return ERR_NOTSUPPORTED;
  653. }
  654. return ERR_SUCCESS;
  655. }
  656. /***************************************************************************/
  657. RETCODE INTFUNC SetParameterValue(LPSTMT lpstmt,
  658. LPSQLNODE lpSqlNodeParameter,
  659. SDWORD FAR *pcbOffset,
  660. SWORD fCType,
  661. PTR rgbValue,
  662. SDWORD cbValue)
  663. /* Sets the value of a parameter node to the value given. If fCType is */
  664. /* SQL_C_CHAR and the parameter is TYPE_CHAR (or if fCType is SQL_C_BINARY */
  665. /* and the parameter is TYPE_BINARY), the parameter is written at offset */
  666. /* (*pcbOffset) and (*pcbOffset) is incremented by the number of */
  667. /* of characters written. */
  668. {
  669. SWORD err;
  670. SDWORD cbOffset;
  671. DATE_STRUCT FAR *lpDate;
  672. TIME_STRUCT FAR *lpTime;
  673. TIMESTAMP_STRUCT FAR *lpTimestamp;
  674. static time_t t;
  675. struct tm *ts;
  676. UCHAR szValue[20];
  677. LPUSTR lpszValue;
  678. SDWORD cbVal;
  679. LPUSTR lpszVal;
  680. SDWORD i;
  681. UCHAR nibble;
  682. LPUSTR lpFrom;
  683. LPUSTR lpTo;
  684. /* Null data? */
  685. err = SQL_SUCCESS;
  686. if (cbValue == SQL_NULL_DATA) {
  687. /* Yes. Set the value to NULL */
  688. lpSqlNodeParameter->sqlIsNull = TRUE;
  689. switch (lpSqlNodeParameter->sqlDataType) {
  690. case TYPE_DOUBLE:
  691. case TYPE_INTEGER:
  692. lpSqlNodeParameter->value.Double = 0.0;
  693. break;
  694. case TYPE_NUMERIC:
  695. lpSqlNodeParameter->value.String = ToString(
  696. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  697. s_lstrcpy(lpSqlNodeParameter->value.String, "");
  698. break;
  699. case TYPE_CHAR:
  700. lpSqlNodeParameter->value.String = ToString(
  701. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  702. s_lstrcpy(lpSqlNodeParameter->value.String, "");
  703. break;
  704. case TYPE_DATE:
  705. lpSqlNodeParameter->value.Date.year = 0;
  706. lpSqlNodeParameter->value.Date.month = 0;
  707. lpSqlNodeParameter->value.Date.day = 0;
  708. break;
  709. case TYPE_TIME:
  710. lpSqlNodeParameter->value.Time.hour = 0;
  711. lpSqlNodeParameter->value.Time.minute = 0;
  712. lpSqlNodeParameter->value.Time.second = 0;
  713. break;
  714. case TYPE_TIMESTAMP:
  715. lpSqlNodeParameter->value.Timestamp.year = 0;
  716. lpSqlNodeParameter->value.Timestamp.month = 0;
  717. lpSqlNodeParameter->value.Timestamp.day = 0;
  718. lpSqlNodeParameter->value.Timestamp.hour = 0;
  719. lpSqlNodeParameter->value.Timestamp.minute = 0;
  720. lpSqlNodeParameter->value.Timestamp.second = 0;
  721. lpSqlNodeParameter->value.Timestamp.fraction = 0;
  722. break;
  723. case TYPE_BINARY:
  724. lpSqlNodeParameter->value.Binary = ToString(
  725. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  726. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 0;
  727. break;
  728. default:
  729. return ERR_NOTSUPPORTED;
  730. }
  731. }
  732. else {
  733. /* No. Set the value to not NULL */
  734. lpSqlNodeParameter->sqlIsNull = FALSE;
  735. /* Put the data value into the parse tree */
  736. switch (lpSqlNodeParameter->sqlDataType) {
  737. case TYPE_DOUBLE:
  738. case TYPE_INTEGER:
  739. if (fCType == SQL_C_BINARY) {
  740. switch (lpSqlNodeParameter->sqlSqlType) {
  741. case SQL_CHAR:
  742. case SQL_VARCHAR:
  743. case SQL_LONGVARCHAR:
  744. return ERR_INTERNAL;
  745. case SQL_BIT:
  746. fCType = SQL_C_BIT;
  747. break;
  748. case SQL_TINYINT:
  749. fCType = SQL_C_TINYINT;
  750. break;
  751. case SQL_SMALLINT:
  752. fCType = SQL_C_SHORT;
  753. break;
  754. case SQL_INTEGER:
  755. fCType = SQL_C_LONG;
  756. break;
  757. case SQL_REAL:
  758. fCType = SQL_C_FLOAT;
  759. break;
  760. case SQL_DECIMAL:
  761. case SQL_NUMERIC:
  762. case SQL_BIGINT:
  763. return ERR_INTERNAL;
  764. case SQL_FLOAT:
  765. case SQL_DOUBLE:
  766. fCType = SQL_C_DOUBLE;
  767. break;
  768. case SQL_BINARY:
  769. case SQL_VARBINARY:
  770. case SQL_LONGVARBINARY:
  771. case SQL_DATE:
  772. case SQL_TIME:
  773. case SQL_TIMESTAMP:
  774. default:
  775. return ERR_INTERNAL;
  776. }
  777. }
  778. switch (fCType) {
  779. case SQL_C_CHAR:
  780. err = CharToDouble((LPUSTR)rgbValue, cbValue, FALSE, -1.7E308,
  781. 1.7E308, &(lpSqlNodeParameter->value.Double));
  782. if (err != ERR_SUCCESS)
  783. return err;
  784. break;
  785. case SQL_C_SSHORT:
  786. lpSqlNodeParameter->value.Double = (double)
  787. *((short far *) rgbValue);
  788. break;
  789. case SQL_C_USHORT:
  790. lpSqlNodeParameter->value.Double = (double)
  791. *((unsigned short far *) rgbValue);
  792. break;
  793. case SQL_C_SLONG:
  794. lpSqlNodeParameter->value.Double = (double)
  795. *((long far *) rgbValue);
  796. break;
  797. case SQL_C_ULONG:
  798. lpSqlNodeParameter->value.Double = (double)
  799. *((unsigned long far *) rgbValue);
  800. break;
  801. case SQL_C_FLOAT:
  802. lpSqlNodeParameter->value.Double = (double)
  803. *((float far *) rgbValue);
  804. break;
  805. case SQL_C_DOUBLE:
  806. lpSqlNodeParameter->value.Double =
  807. *((double far *) rgbValue);
  808. break;
  809. case SQL_C_BIT:
  810. lpSqlNodeParameter->value.Double = (double)
  811. *((unsigned char far *) rgbValue);
  812. break;
  813. case SQL_C_STINYINT:
  814. lpSqlNodeParameter->value.Double = (double)
  815. *((char far *) rgbValue);
  816. break;
  817. case SQL_C_UTINYINT:
  818. lpSqlNodeParameter->value.Double = (double)
  819. *((unsigned char far *) rgbValue);
  820. break;
  821. case SQL_C_DATE:
  822. case SQL_C_TIME:
  823. case SQL_C_TIMESTAMP:
  824. return ERR_NOTCONVERTABLE;
  825. case SQL_C_BINARY:
  826. return ERR_INTERNAL;
  827. default:
  828. return ERR_NOTSUPPORTED;
  829. }
  830. break;
  831. case TYPE_NUMERIC:
  832. if (fCType == SQL_C_BINARY) {
  833. switch (lpSqlNodeParameter->sqlSqlType) {
  834. case SQL_CHAR:
  835. case SQL_VARCHAR:
  836. case SQL_LONGVARCHAR:
  837. case SQL_BIT:
  838. case SQL_TINYINT:
  839. case SQL_SMALLINT:
  840. case SQL_INTEGER:
  841. case SQL_REAL:
  842. return ERR_INTERNAL;
  843. case SQL_DECIMAL:
  844. case SQL_NUMERIC:
  845. case SQL_BIGINT:
  846. fCType = SQL_C_CHAR;
  847. break;
  848. case SQL_FLOAT:
  849. case SQL_DOUBLE:
  850. case SQL_BINARY:
  851. case SQL_VARBINARY:
  852. case SQL_LONGVARBINARY:
  853. case SQL_DATE:
  854. case SQL_TIME:
  855. case SQL_TIMESTAMP:
  856. default:
  857. return ERR_INTERNAL;
  858. }
  859. }
  860. lpSqlNodeParameter->value.String = ToString(
  861. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  862. switch (fCType) {
  863. case SQL_C_CHAR:
  864. /* Get true length of source string */
  865. lpszValue = (LPUSTR) rgbValue;
  866. if (cbValue == SQL_NTS)
  867. cbValue = s_lstrlen(lpszValue);
  868. else if (cbValue < 0)
  869. cbValue = 0;
  870. /* Make sure the number is well formed: Leading blanks... */
  871. lpszVal = lpszValue;
  872. cbVal = cbValue;
  873. while ((cbVal > 0) && (*lpszVal == ' ')) {
  874. lpszVal++;
  875. cbVal--;
  876. }
  877. /* ...a minus sign... */
  878. if ((cbVal > 0) && (*lpszVal == '-')) {
  879. lpszVal++;
  880. cbVal--;
  881. }
  882. /* ...some digits... */
  883. while ((cbVal > 0) && (*lpszVal >= '0')&&(*lpszVal <= '9')) {
  884. lpszVal++;
  885. cbVal--;
  886. }
  887. /* ...a decimal point... */
  888. if ((cbVal > 0) && (*lpszVal == '.')) {
  889. lpszVal++;
  890. cbVal--;
  891. }
  892. /* ...some more digits... */
  893. while ((cbVal > 0) && (*lpszVal >= '0')&&(*lpszVal <= '9')) {
  894. lpszVal++;
  895. cbVal--;
  896. }
  897. /* ...some trailing blanks. */
  898. while ((cbVal > 0) && (*lpszVal == ' ')) {
  899. lpszVal++;
  900. cbVal--;
  901. }
  902. /* If there is anything else, error */
  903. if (cbVal != 0) {
  904. if (cbValue <= MAX_TOKEN_SIZE) {
  905. _fmemcpy(lpstmt->szError, lpszValue, (SWORD) cbValue);
  906. lpstmt->szError[cbValue] = '\0';
  907. }
  908. else {
  909. _fmemcpy(lpstmt->szError, lpszValue, MAX_TOKEN_SIZE);
  910. lpstmt->szError[MAX_TOKEN_SIZE] = '\0';
  911. }
  912. return ERR_MALFORMEDNUMBER;
  913. }
  914. break;
  915. case SQL_C_SSHORT:
  916. wsprintf((LPSTR)szValue, "%d", *((short far *) rgbValue));
  917. lpszValue = szValue;
  918. cbValue = s_lstrlen((char*)szValue);
  919. break;
  920. case SQL_C_USHORT:
  921. wsprintf((LPSTR)szValue, "%u", *((unsigned short far *) rgbValue));
  922. lpszValue = szValue;
  923. cbValue = s_lstrlen((char*)szValue);
  924. break;
  925. case SQL_C_SLONG:
  926. wsprintf((LPSTR)szValue, "%ld", *((long far *) rgbValue));
  927. lpszValue = szValue;
  928. cbValue = lstrlen((char*)szValue);
  929. break;
  930. case SQL_C_ULONG:
  931. wsprintf((LPSTR)szValue, "%lu", *((unsigned long far *) rgbValue));
  932. lpszValue = szValue;
  933. cbValue = s_lstrlen((char*)szValue);
  934. break;
  935. case SQL_C_FLOAT:
  936. if (DoubleToChar((double) *((float far *) rgbValue),
  937. FALSE,
  938. lpSqlNodeParameter->value.String,
  939. lpSqlNodeParameter->sqlPrecision + 2 + 1))
  940. lpSqlNodeParameter->value.String[
  941. lpSqlNodeParameter->sqlPrecision + 2 + 1 - 1] = '\0';
  942. lpszValue = lpSqlNodeParameter->value.String;
  943. cbValue = s_lstrlen(lpSqlNodeParameter->value.String);
  944. break;
  945. case SQL_C_DOUBLE:
  946. if (DoubleToChar(*((double far *) rgbValue),
  947. FALSE,
  948. lpSqlNodeParameter->value.String,
  949. lpSqlNodeParameter->sqlPrecision + 2 + 1))
  950. lpSqlNodeParameter->value.String[
  951. lpSqlNodeParameter->sqlPrecision + 2 + 1 - 1] = '\0';
  952. lpszValue = lpSqlNodeParameter->value.String;
  953. cbValue = s_lstrlen(lpSqlNodeParameter->value.String);
  954. break;
  955. case SQL_C_BIT:
  956. wsprintf((LPSTR)szValue, "%d", (short)
  957. *((unsigned char far *) rgbValue));
  958. lpszValue = szValue;
  959. cbValue = s_lstrlen((char*)szValue);
  960. break;
  961. case SQL_C_STINYINT:
  962. wsprintf((LPSTR)szValue, "%d", (short)
  963. *((char far *) rgbValue));
  964. lpszValue = szValue;
  965. cbValue = s_lstrlen((char*)szValue);
  966. break;
  967. case SQL_C_UTINYINT:
  968. wsprintf((LPSTR)szValue, "%d", (short)
  969. *((unsigned char far *) rgbValue));
  970. lpszValue = szValue;
  971. cbValue = s_lstrlen((char*)szValue);
  972. break;
  973. case SQL_C_DATE:
  974. case SQL_C_TIME:
  975. case SQL_C_TIMESTAMP:
  976. return ERR_NOTCONVERTABLE;
  977. break;
  978. case SQL_C_BINARY:
  979. return ERR_INTERNAL;
  980. default:
  981. return ERR_NOTSUPPORTED;
  982. }
  983. /* Normalize the result */
  984. err = BCDNormalize(lpszValue, cbValue,
  985. lpSqlNodeParameter->value.String,
  986. lpSqlNodeParameter->sqlPrecision + 2 + 1,
  987. lpSqlNodeParameter->sqlPrecision,
  988. lpSqlNodeParameter->sqlScale);
  989. break;
  990. case TYPE_CHAR:
  991. lpSqlNodeParameter->value.String = ToString(
  992. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  993. switch (fCType) {
  994. case SQL_C_CHAR:
  995. /* Get true lengthof source string */
  996. if (cbValue == SQL_NTS)
  997. cbValue = s_lstrlen((char*)rgbValue);
  998. else if (cbValue < 0)
  999. cbValue = 0;
  1000. /* Figure out the offset to write at */
  1001. if (pcbOffset != NULL)
  1002. cbOffset = *pcbOffset;
  1003. else
  1004. cbOffset = 0;
  1005. /* Make sure we don't write past the end of the buffer */
  1006. if (cbValue > (MAX_CHAR_LITERAL_LENGTH - cbOffset)) {
  1007. cbValue = MAX_CHAR_LITERAL_LENGTH - cbOffset;
  1008. err = ERR_DATATRUNCATED;
  1009. }
  1010. /* Copy the data */
  1011. _fmemcpy(lpSqlNodeParameter->value.String + cbOffset,
  1012. rgbValue, (SWORD) cbValue);
  1013. lpSqlNodeParameter->value.String[cbValue + cbOffset] = '\0';
  1014. if (pcbOffset != NULL)
  1015. *pcbOffset += (cbValue);
  1016. break;
  1017. case SQL_C_SSHORT:
  1018. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%d",
  1019. *((short far *) rgbValue));
  1020. break;
  1021. case SQL_C_USHORT:
  1022. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%u",
  1023. *((unsigned short far *) rgbValue));
  1024. break;
  1025. case SQL_C_SLONG:
  1026. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%ld",
  1027. *((long far *) rgbValue));
  1028. break;
  1029. case SQL_C_ULONG:
  1030. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%lu",
  1031. *((unsigned long far *) rgbValue));
  1032. break;
  1033. case SQL_C_FLOAT:
  1034. if (DoubleToChar((double) *((float far *) rgbValue), TRUE,
  1035. lpSqlNodeParameter->value.String,
  1036. MAX_CHAR_LITERAL_LENGTH))
  1037. lpSqlNodeParameter->value.String[
  1038. MAX_CHAR_LITERAL_LENGTH - 1] = '\0';
  1039. break;
  1040. case SQL_C_DOUBLE:
  1041. if (DoubleToChar(*((double far *) rgbValue), TRUE,
  1042. lpSqlNodeParameter->value.String,
  1043. MAX_CHAR_LITERAL_LENGTH))
  1044. lpSqlNodeParameter->value.String[
  1045. MAX_CHAR_LITERAL_LENGTH - 1] = '\0';
  1046. break;
  1047. case SQL_C_BIT:
  1048. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%d", (short)
  1049. *((unsigned char far *) rgbValue));
  1050. break;
  1051. case SQL_C_STINYINT:
  1052. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%d", (short)
  1053. *((char far *) rgbValue));
  1054. break;
  1055. case SQL_C_UTINYINT:
  1056. wsprintf((LPSTR) lpSqlNodeParameter->value.String, "%d", (short)
  1057. *((unsigned char far *) rgbValue));
  1058. break;
  1059. case SQL_C_DATE:
  1060. DateToChar((DATE_STRUCT far *) rgbValue,
  1061. lpSqlNodeParameter->value.String);
  1062. break;
  1063. case SQL_C_TIME:
  1064. TimeToChar((TIME_STRUCT far *) rgbValue,
  1065. lpSqlNodeParameter->value.String);
  1066. break;
  1067. case SQL_C_TIMESTAMP:
  1068. TimestampToChar((TIMESTAMP_STRUCT far *) rgbValue,
  1069. lpSqlNodeParameter->value.String);
  1070. break;
  1071. case SQL_C_BINARY:
  1072. /* Get true lengthof source string */
  1073. if (cbValue < 0)
  1074. cbValue = 0;
  1075. /* Figure out the offset to write at */
  1076. if (pcbOffset != NULL)
  1077. cbOffset = *pcbOffset;
  1078. else
  1079. cbOffset = 0;
  1080. /* Make sure we don't write past the end of the buffer */
  1081. if (cbValue > (MAX_CHAR_LITERAL_LENGTH - cbOffset)) {
  1082. cbValue = MAX_CHAR_LITERAL_LENGTH - cbOffset;
  1083. err = ERR_DATATRUNCATED;
  1084. }
  1085. /* Copy the data */
  1086. _fmemcpy(lpSqlNodeParameter->value.String + cbOffset,
  1087. rgbValue, (SWORD) cbValue);
  1088. lpSqlNodeParameter->value.String[cbValue + cbOffset] = '\0';
  1089. if (pcbOffset != NULL)
  1090. *pcbOffset += (cbValue);
  1091. break;
  1092. default:
  1093. return ERR_NOTSUPPORTED;
  1094. }
  1095. break;
  1096. case TYPE_DATE:
  1097. switch (fCType) {
  1098. case SQL_C_CHAR:
  1099. err = CharToDate((LPUSTR)rgbValue, cbValue,
  1100. &(lpSqlNodeParameter->value.Date));
  1101. if (err != ERR_SUCCESS)
  1102. return err;
  1103. break;
  1104. case SQL_C_SSHORT:
  1105. case SQL_C_USHORT:
  1106. case SQL_C_SLONG:
  1107. case SQL_C_ULONG:
  1108. case SQL_C_FLOAT:
  1109. case SQL_C_DOUBLE:
  1110. case SQL_C_BIT:
  1111. case SQL_C_STINYINT:
  1112. case SQL_C_UTINYINT:
  1113. return ERR_NOTCONVERTABLE;
  1114. case SQL_C_DATE:
  1115. lpSqlNodeParameter->value.Date =
  1116. *((DATE_STRUCT far *) rgbValue);
  1117. break;
  1118. case SQL_C_TIME:
  1119. return ERR_NOTCONVERTABLE;
  1120. case SQL_C_TIMESTAMP:
  1121. lpTimestamp = (TIMESTAMP_STRUCT far *) rgbValue;
  1122. lpSqlNodeParameter->value.Date.year = lpTimestamp->year;
  1123. lpSqlNodeParameter->value.Date.month = lpTimestamp->month;
  1124. lpSqlNodeParameter->value.Date.day = lpTimestamp->day;
  1125. break;
  1126. case SQL_C_BINARY:
  1127. lpSqlNodeParameter->value.Date =
  1128. *((DATE_STRUCT far *) rgbValue);
  1129. break;
  1130. default:
  1131. return ERR_NOTSUPPORTED;
  1132. }
  1133. break;
  1134. case TYPE_TIME:
  1135. switch (fCType) {
  1136. case SQL_C_CHAR:
  1137. err = CharToTime((LPUSTR)rgbValue, cbValue,
  1138. &(lpSqlNodeParameter->value.Time));
  1139. if (err != ERR_SUCCESS)
  1140. return err;
  1141. break;
  1142. case SQL_C_SSHORT:
  1143. case SQL_C_USHORT:
  1144. case SQL_C_SLONG:
  1145. case SQL_C_ULONG:
  1146. case SQL_C_FLOAT:
  1147. case SQL_C_DOUBLE:
  1148. case SQL_C_BIT:
  1149. case SQL_C_STINYINT:
  1150. case SQL_C_UTINYINT:
  1151. return ERR_NOTCONVERTABLE;
  1152. case SQL_C_DATE:
  1153. return ERR_NOTCONVERTABLE;
  1154. case SQL_C_TIME:
  1155. lpSqlNodeParameter->value.Time =
  1156. *((TIME_STRUCT far *) rgbValue);
  1157. break;
  1158. case SQL_C_TIMESTAMP:
  1159. lpTimestamp = (TIMESTAMP_STRUCT far *) rgbValue;
  1160. lpSqlNodeParameter->value.Time.hour = lpTimestamp->hour;
  1161. lpSqlNodeParameter->value.Time.minute = lpTimestamp->minute;
  1162. lpSqlNodeParameter->value.Time.second = lpTimestamp->second;
  1163. break;
  1164. case SQL_C_BINARY:
  1165. lpSqlNodeParameter->value.Time =
  1166. *((TIME_STRUCT far *) rgbValue);
  1167. break;
  1168. default:
  1169. return ERR_NOTSUPPORTED;
  1170. }
  1171. break;
  1172. case TYPE_TIMESTAMP:
  1173. switch (fCType) {
  1174. case SQL_C_CHAR:
  1175. err = CharToTimestamp((LPUSTR)rgbValue, cbValue,
  1176. &(lpSqlNodeParameter->value.Timestamp));
  1177. if (err != ERR_SUCCESS)
  1178. return err;
  1179. break;
  1180. case SQL_C_SSHORT:
  1181. case SQL_C_USHORT:
  1182. case SQL_C_SLONG:
  1183. case SQL_C_ULONG:
  1184. case SQL_C_FLOAT:
  1185. case SQL_C_DOUBLE:
  1186. case SQL_C_BIT:
  1187. case SQL_C_STINYINT:
  1188. case SQL_C_UTINYINT:
  1189. return ERR_NOTCONVERTABLE;
  1190. case SQL_C_DATE:
  1191. lpDate = (DATE_STRUCT far *) rgbValue;
  1192. lpSqlNodeParameter->value.Timestamp.year = lpDate->year;
  1193. lpSqlNodeParameter->value.Timestamp.month = lpDate-> month;
  1194. lpSqlNodeParameter->value.Timestamp.day = lpDate-> day;
  1195. lpSqlNodeParameter->value.Timestamp.hour = 0;
  1196. lpSqlNodeParameter->value.Timestamp.minute = 0;
  1197. lpSqlNodeParameter->value.Timestamp.second = 0;
  1198. lpSqlNodeParameter->value.Timestamp.fraction = 0;
  1199. break;
  1200. case SQL_C_TIME:
  1201. lpTime = (TIME_STRUCT far *) rgbValue;
  1202. time(&t);
  1203. ts = localtime(&t);
  1204. lpSqlNodeParameter->value.Timestamp.year = ts->tm_year + 1900;
  1205. lpSqlNodeParameter->value.Timestamp.month = ts->tm_mon + 1;
  1206. lpSqlNodeParameter->value.Timestamp.day = (UWORD) ts->tm_mday;
  1207. lpSqlNodeParameter->value.Timestamp.hour = (WORD) lpTime->hour;
  1208. lpSqlNodeParameter->value.Timestamp.minute = lpTime->minute;
  1209. lpSqlNodeParameter->value.Timestamp.second = lpTime->second;
  1210. lpSqlNodeParameter->value.Timestamp.fraction = 0;
  1211. break;
  1212. case SQL_C_TIMESTAMP:
  1213. lpSqlNodeParameter->value.Timestamp =
  1214. *((TIMESTAMP_STRUCT far *) rgbValue);
  1215. break;
  1216. case SQL_C_BINARY:
  1217. lpSqlNodeParameter->value.Timestamp =
  1218. *((TIMESTAMP_STRUCT far *) rgbValue);
  1219. break;
  1220. default:
  1221. return ERR_NOTSUPPORTED;
  1222. }
  1223. break;
  1224. case TYPE_BINARY:
  1225. lpSqlNodeParameter->value.Binary = ToString(
  1226. lpstmt->lpSqlStmt, lpSqlNodeParameter->node.parameter.Value);
  1227. switch (fCType) {
  1228. case SQL_C_CHAR:
  1229. /* Get true length of source string */
  1230. if (cbValue == SQL_NTS)
  1231. cbValue = s_lstrlen((char*)rgbValue);
  1232. else if (cbValue < 0)
  1233. cbValue = 0;
  1234. /* If am odd numbe of characters, discard the last one */
  1235. if (((cbValue/2) * 2) != cbValue)
  1236. cbValue--;
  1237. /* Figure out the offset to write at */
  1238. if (pcbOffset != NULL)
  1239. cbOffset = *pcbOffset;
  1240. else
  1241. cbOffset = 0;
  1242. /* Make sure we don't write past the end of the buffer */
  1243. if (cbValue > ((MAX_BINARY_LITERAL_LENGTH - cbOffset) * 2)) {
  1244. cbValue = (MAX_BINARY_LITERAL_LENGTH - cbOffset) * 2;
  1245. err = ERR_DATATRUNCATED;
  1246. }
  1247. /* Copy the data */
  1248. lpFrom = (LPUSTR) rgbValue;
  1249. lpTo = BINARY_DATA(lpSqlNodeParameter->value.Binary) +
  1250. cbOffset;
  1251. for (i=0; i < cbValue; i++) {
  1252. /* Convert the next character to a binary digit */
  1253. if ((*lpFrom >= '0') && (*lpFrom <= '9'))
  1254. nibble = *lpFrom - '0';
  1255. else if ((*lpFrom >= 'A') && (*lpFrom <= 'F'))
  1256. nibble = *lpFrom - 'A';
  1257. else if ((*lpFrom >= 'a') && (*lpFrom <= 'f'))
  1258. nibble = *lpFrom - 'a';
  1259. else
  1260. return ERR_NOTCONVERTABLE;
  1261. /* Are we writing the left or right side of the byte? */
  1262. if (((i/2) * 2) != i) {
  1263. /* The left side. Shift the nibble over */
  1264. *lpTo = nibble << 4;
  1265. }
  1266. else {
  1267. /* The right side. Add the nibble in */
  1268. *lpTo |= (nibble);
  1269. /* Point at next binary byte */
  1270. lpTo++;
  1271. }
  1272. /* Look at next character */
  1273. lpFrom++;
  1274. }
  1275. /* Set the new length */
  1276. if (cbOffset == 0)
  1277. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) =
  1278. cbValue/2;
  1279. else
  1280. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) =
  1281. (cbValue/2)+
  1282. BINARY_LENGTH(lpSqlNodeParameter->value.Binary);
  1283. /* Return new offset */
  1284. if (pcbOffset != NULL)
  1285. *pcbOffset += (cbValue/2);
  1286. break;
  1287. case SQL_C_SSHORT:
  1288. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1289. rgbValue, 2);
  1290. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 2;
  1291. break;
  1292. case SQL_C_USHORT:
  1293. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1294. rgbValue, 2);
  1295. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 2;
  1296. break;
  1297. case SQL_C_SLONG:
  1298. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1299. rgbValue, 4);
  1300. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 4;
  1301. break;
  1302. case SQL_C_ULONG:
  1303. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1304. rgbValue, 4);
  1305. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 4;
  1306. break;
  1307. case SQL_C_FLOAT:
  1308. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1309. rgbValue, 4);
  1310. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 4;
  1311. break;
  1312. case SQL_C_DOUBLE:
  1313. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1314. rgbValue, 8);
  1315. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 8;
  1316. break;
  1317. case SQL_C_BIT:
  1318. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1319. rgbValue, 1);
  1320. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 1;
  1321. break;
  1322. case SQL_C_STINYINT:
  1323. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1324. rgbValue, 1);
  1325. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 1;
  1326. break;
  1327. case SQL_C_UTINYINT:
  1328. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1329. rgbValue, 1);
  1330. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 1;
  1331. break;
  1332. case SQL_C_DATE:
  1333. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1334. rgbValue, 6);
  1335. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 6;
  1336. break;
  1337. case SQL_C_TIME:
  1338. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1339. rgbValue, 6);
  1340. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 6;
  1341. break;
  1342. case SQL_C_TIMESTAMP:
  1343. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary),
  1344. rgbValue, 16);
  1345. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = 16;
  1346. break;
  1347. case SQL_C_BINARY:
  1348. /* Get true lengthof source string */
  1349. if (cbValue < 0)
  1350. cbValue = 0;
  1351. /* Figure out the offset to write at */
  1352. if (pcbOffset != NULL)
  1353. cbOffset = *pcbOffset;
  1354. else
  1355. cbOffset = 0;
  1356. /* Make sure we don't write past the end of the buffer */
  1357. if (cbValue > (MAX_BINARY_LITERAL_LENGTH - cbOffset)) {
  1358. cbValue = MAX_BINARY_LITERAL_LENGTH - cbOffset;
  1359. err = ERR_DATATRUNCATED;
  1360. }
  1361. /* Copy the data */
  1362. _fmemcpy(BINARY_DATA(lpSqlNodeParameter->value.Binary) +
  1363. cbOffset, rgbValue, (SWORD) cbValue);
  1364. if (cbOffset == 0)
  1365. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = cbValue;
  1366. else
  1367. BINARY_LENGTH(lpSqlNodeParameter->value.Binary) = cbValue+
  1368. BINARY_LENGTH(lpSqlNodeParameter->value.Binary);
  1369. if (pcbOffset != NULL)
  1370. *pcbOffset += (cbValue);
  1371. break;
  1372. default:
  1373. return ERR_NOTSUPPORTED;
  1374. }
  1375. break;
  1376. default:
  1377. return ERR_NOTSUPPORTED;
  1378. }
  1379. }
  1380. return err;
  1381. }
  1382. /***************************************************************************/
  1383. RETCODE INTFUNC Rewind(LPSTMT lpstmt, LPSQLNODE lpSqlNode,
  1384. BOOL fOuterJoinIsNull)
  1385. /* Rewinds the table or table list identified by lpSqlNode */
  1386. {
  1387. #define MAX_RESTRICTIONS 10
  1388. LPSQLTREE lpSql;
  1389. SWORD err;
  1390. LPSQLNODE lpSqlNodeComparison;
  1391. LPSQLNODE lpSqlNodeColumn;
  1392. LPSQLNODE lpSqlNodeValue;
  1393. LPSQLNODE lpSqlNodeTable;
  1394. LPSQLNODE lpSqlNodeTables;
  1395. SQLNODEIDX idxRestrict;
  1396. UWORD cRestrict;
  1397. UWORD fOperator[MAX_RESTRICTIONS];
  1398. SWORD fCType[MAX_RESTRICTIONS];
  1399. PTR rgbValue[MAX_RESTRICTIONS];
  1400. SDWORD cbValue[MAX_RESTRICTIONS];
  1401. UWORD icol[MAX_RESTRICTIONS];
  1402. lpSql = lpstmt->lpSqlStmt;
  1403. switch (lpSqlNode->sqlNodeType) {
  1404. case NODE_TYPE_TABLES:
  1405. /* Rewind this table */
  1406. lpSqlNodeTable = ToNode(lpSql, lpSqlNode->node.tables.Table);
  1407. err = Rewind(lpstmt, lpSqlNodeTable, fOuterJoinIsNull);
  1408. if (err != ERR_SUCCESS)
  1409. return err;
  1410. /* Are there other tables on the list? */
  1411. if (lpSqlNode->node.tables.Next != NO_SQLNODE) {
  1412. /* Yes. Find next record */
  1413. while (TRUE) {
  1414. /* Is this the right side of a NULL outer join? */
  1415. if ((lpSqlNodeTable->node.table.OuterJoinPredicate !=
  1416. NO_SQLNODE) && fOuterJoinIsNull)
  1417. /* Yes. This table has NULLs also */
  1418. err = ISAM_EOF;
  1419. else {
  1420. /* No. Position the current table to the next record */
  1421. err = ISAMNextRecord(lpSqlNodeTable->node.table.Handle, lpstmt);
  1422. if ((err == NO_ISAM_ERR) || (err == ISAM_EOF))
  1423. lpstmt->fISAMTxnStarted = TRUE;
  1424. }
  1425. /* End of file? */
  1426. if (err == ISAM_EOF) {
  1427. /* Yes. Is this table the right side of an outer join */
  1428. if (lpSqlNodeTable->node.table.OuterJoinPredicate ==
  1429. NO_SQLNODE) {
  1430. /* No. No more records */
  1431. return ERR_NODATAFOUND;
  1432. }
  1433. else {
  1434. /* Yes. Use a record of all nulls */
  1435. err = ERR_SUCCESS;
  1436. lpSqlNodeTable->node.table.AllNull = TRUE;
  1437. fOuterJoinIsNull = TRUE;
  1438. }
  1439. }
  1440. else if (err != NO_ISAM_ERR) {
  1441. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  1442. (LPUSTR)lpstmt->szISAMError);
  1443. return err;
  1444. }
  1445. /* Rewind the other tables */
  1446. lpSqlNodeTables = ToNode(lpSql, lpSqlNode->node.tables.Next);
  1447. err = Rewind(lpstmt, lpSqlNodeTables, fOuterJoinIsNull);
  1448. if (err == ERR_SUCCESS)
  1449. break;
  1450. if (err != ERR_NODATAFOUND)
  1451. return err;
  1452. }
  1453. }
  1454. break;
  1455. case NODE_TYPE_TABLE:
  1456. /* Did the optimizer find any restrictions? */
  1457. if (lpSqlNode->node.table.Restrict != 0) {
  1458. /* Yes. For each restriction found... */
  1459. cRestrict = 0;
  1460. idxRestrict = lpSqlNode->node.table.Restrict;
  1461. while (idxRestrict != NO_SQLNODE) {
  1462. /* Get the restriction */
  1463. lpSqlNodeComparison = ToNode(lpSql, idxRestrict);
  1464. /* Get the column */
  1465. lpSqlNodeColumn = ToNode(lpSql, lpSqlNodeComparison->node.comparison.Left);
  1466. icol[cRestrict] = lpSqlNodeColumn->node.column.Id;
  1467. /* Get the operator */
  1468. switch (lpSqlNodeComparison->node.comparison.Operator) {
  1469. case OP_EQ:
  1470. fOperator[cRestrict] = ISAM_OP_EQ;
  1471. break;
  1472. case OP_NE:
  1473. fOperator[cRestrict] = ISAM_OP_NE;
  1474. break;
  1475. case OP_LE:
  1476. fOperator[cRestrict] = ISAM_OP_LE;
  1477. break;
  1478. case OP_LT:
  1479. fOperator[cRestrict] = ISAM_OP_LT;
  1480. break;
  1481. case OP_GE:
  1482. fOperator[cRestrict] = ISAM_OP_GE;
  1483. break;
  1484. case OP_GT:
  1485. fOperator[cRestrict] = ISAM_OP_GT;
  1486. break;
  1487. default:
  1488. return ERR_INTERNAL;
  1489. }
  1490. /* Calculate the key value */
  1491. lpSqlNodeValue = ToNode(lpSql,
  1492. lpSqlNodeComparison->node.comparison.Right);
  1493. err = EvaluateExpression(lpstmt, lpSqlNodeValue);
  1494. if (err != ERR_SUCCESS)
  1495. return err;
  1496. /* Put restriction on the list */
  1497. switch (lpSqlNodeValue->sqlDataType) {
  1498. case TYPE_DOUBLE:
  1499. case TYPE_INTEGER:
  1500. fCType[cRestrict] = SQL_C_DOUBLE;
  1501. rgbValue[cRestrict] = &(lpSqlNodeValue->value.Double);
  1502. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ?
  1503. SQL_NULL_DATA : sizeof(double);
  1504. break;
  1505. case TYPE_NUMERIC:
  1506. fCType[cRestrict] = SQL_C_CHAR;
  1507. rgbValue[cRestrict] = lpSqlNodeValue->value.String;
  1508. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  1509. s_lstrlen(lpSqlNodeValue->value.String);
  1510. break;
  1511. case TYPE_CHAR:
  1512. fCType[cRestrict] = SQL_C_CHAR;
  1513. rgbValue[cRestrict] = lpSqlNodeValue->value.String;
  1514. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  1515. s_lstrlen(lpSqlNodeValue->value.String);
  1516. break;
  1517. case TYPE_DATE:
  1518. fCType[cRestrict] = SQL_C_DATE;
  1519. rgbValue[cRestrict] = &(lpSqlNodeValue->value.Date),
  1520. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ?
  1521. (SDWORD) SQL_NULL_DATA : sizeof(DATE_STRUCT);
  1522. break;
  1523. case TYPE_TIME:
  1524. fCType[cRestrict] = SQL_C_TIME;
  1525. rgbValue[cRestrict] = &(lpSqlNodeValue->value.Time);
  1526. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ?
  1527. (SDWORD) SQL_NULL_DATA : sizeof(TIME_STRUCT);
  1528. break;
  1529. case TYPE_TIMESTAMP:
  1530. fCType[cRestrict] = SQL_C_TIMESTAMP;
  1531. rgbValue[cRestrict] = &(lpSqlNodeValue->value.Timestamp);
  1532. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ?
  1533. (SDWORD) SQL_NULL_DATA : sizeof(TIMESTAMP_STRUCT);
  1534. break;
  1535. case TYPE_BINARY:
  1536. fCType[cRestrict] = SQL_C_BINARY;
  1537. rgbValue[cRestrict] = BINARY_DATA(lpSqlNodeValue->value.Binary);
  1538. cbValue[cRestrict] = lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  1539. BINARY_LENGTH(lpSqlNodeValue->value.Binary);
  1540. break;
  1541. default:
  1542. return ERR_NOTSUPPORTED;
  1543. }
  1544. /* Increase count */
  1545. cRestrict++;
  1546. /* Leave loop if maximum number of restrictions found */
  1547. if (cRestrict >= MAX_RESTRICTIONS)
  1548. break;
  1549. /* Point at next restriction */
  1550. idxRestrict = lpSqlNodeComparison->node.comparison.NextRestrict;
  1551. }
  1552. /* Apply the restriction */
  1553. err = ISAMRestrict(lpSqlNode->node.table.Handle, cRestrict,
  1554. icol, fOperator, fCType, rgbValue, cbValue);
  1555. if ((err != NO_ISAM_ERR) && (err != ISAM_NOTSUPPORTED)) {
  1556. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  1557. (LPUSTR)lpstmt->szISAMError);
  1558. return err;
  1559. }
  1560. else if (err == NO_ISAM_ERR)
  1561. lpstmt->fISAMTxnStarted = TRUE;
  1562. }
  1563. /* Rewind the table */
  1564. err = ISAMRewind(lpSqlNode->node.table.Handle);
  1565. if (err != NO_ISAM_ERR) {
  1566. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  1567. return err;
  1568. }
  1569. lpstmt->fISAMTxnStarted = TRUE;
  1570. lpSqlNode->node.table.Rewound = TRUE;
  1571. lpSqlNode->node.table.AllNull = FALSE;
  1572. break;
  1573. default:
  1574. return ERR_INTERNAL;
  1575. }
  1576. return ERR_SUCCESS;
  1577. }
  1578. /***************************************************************************/
  1579. RETCODE INTFUNC NextRawRecord (LPSTMT lpstmt,
  1580. LPSQLNODE lpSqlNode)
  1581. /* Finds the next record in in the table or table list. */
  1582. /* */
  1583. /* If a list of tables is given, the leftmost table spins the slowest */
  1584. /* and the rightmost table spins the fastest. In otherwords, for each */
  1585. /* row in a table, we iterate over the rows in the tables after that table */
  1586. {
  1587. LPSQLTREE lpSql;
  1588. SWORD err;
  1589. LPSQLNODE lpSqlNodeTable;
  1590. LPSQLNODE lpSqlNodeTables;
  1591. LPSQLNODE lpSqlNodeOuterJoinPredicate;
  1592. lpSql = lpstmt->lpSqlStmt;
  1593. switch (lpSqlNode->sqlNodeType) {
  1594. case NODE_TYPE_TABLES:
  1595. /* Are there any more tables on the list? */
  1596. lpSqlNodeTable = ToNode(lpSql, lpSqlNode->node.tables.Table);
  1597. if (lpSqlNode->node.tables.Next != NO_SQLNODE) {
  1598. /* Yes. Look for next record in the rest of the list */
  1599. while (TRUE) {
  1600. /* Move to the next record on rest of the table list */
  1601. lpSqlNodeTables = ToNode(lpSql, lpSqlNode->node.tables.Next);
  1602. err = NextRawRecord(lpstmt, lpSqlNodeTables);
  1603. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  1604. return err;
  1605. /* If a no more records, continue below */
  1606. if (err == ERR_NODATAFOUND)
  1607. break;
  1608. /* Is this table on right side of an outer join? */
  1609. if (lpSqlNodeTable->node.table.OuterJoinPredicate !=
  1610. NO_SQLNODE) {
  1611. /* Yes. Are we on the row of NULLs? */
  1612. if (!lpSqlNodeTable->node.table.AllNull) {
  1613. /* No. Test ON predicate */
  1614. lpSqlNodeOuterJoinPredicate = ToNode(lpSql,
  1615. lpSqlNodeTable->node.table.OuterJoinPredicate);
  1616. /* Test outer join criteria */
  1617. err = EvaluateExpression(lpstmt,
  1618. lpSqlNodeOuterJoinPredicate);
  1619. if (err != ERR_SUCCESS)
  1620. return err;
  1621. /* If record does not pass outer join criteria, */
  1622. /* try next one */
  1623. if ((lpSqlNodeOuterJoinPredicate->sqlIsNull) ||
  1624. (lpSqlNodeOuterJoinPredicate->value.Double !=
  1625. TRUE)) {
  1626. continue;
  1627. }
  1628. /* If record passes outer join criteria, use it */
  1629. else {
  1630. lpSqlNodeTable->node.table.Rewound = FALSE;
  1631. }
  1632. }
  1633. }
  1634. break;
  1635. }
  1636. /* If a record was found, return it */
  1637. if (err == ERR_SUCCESS)
  1638. break;
  1639. }
  1640. /* Loop until a record is found */
  1641. while (TRUE) {
  1642. /* Position to the next record in this table. */
  1643. err = NextRawRecord(lpstmt, lpSqlNodeTable);
  1644. if (err != ERR_SUCCESS)
  1645. return err;
  1646. /* More tables on the list? */
  1647. if (lpSqlNode->node.tables.Next != NO_SQLNODE) {
  1648. /* Yes. Rewind the other tables on the list */
  1649. lpSqlNodeTables = ToNode(lpSql, lpSqlNode->node.tables.Next);
  1650. err = Rewind(lpstmt, lpSqlNodeTables,
  1651. lpSqlNodeTable->node.table.AllNull);
  1652. if (err == ERR_NODATAFOUND)
  1653. continue;
  1654. if (err != ERR_SUCCESS)
  1655. return err;
  1656. /* Get the first record from the other tables on the list */
  1657. err = NextRawRecord(lpstmt, lpSqlNodeTables);
  1658. if (err == ERR_NODATAFOUND)
  1659. continue;
  1660. if (err != ERR_SUCCESS)
  1661. return err;
  1662. }
  1663. /* Is this table on right side of an outer join? */
  1664. if (lpSqlNodeTable->node.table.OuterJoinPredicate !=
  1665. NO_SQLNODE) {
  1666. /* Yes. Are we on the row of NULLs? */
  1667. if (!lpSqlNodeTable->node.table.AllNull) {
  1668. /* No. Test ON predicate */
  1669. lpSqlNodeOuterJoinPredicate = ToNode(lpSql,
  1670. lpSqlNodeTable->node.table.OuterJoinPredicate);
  1671. /* Test outer join criteria */
  1672. err = EvaluateExpression(lpstmt,
  1673. lpSqlNodeOuterJoinPredicate);
  1674. if (err != ERR_SUCCESS)
  1675. return err;
  1676. /* If record does not pass outer join criteria, */
  1677. /* try next one */
  1678. if ((lpSqlNodeOuterJoinPredicate->sqlIsNull) ||
  1679. (lpSqlNodeOuterJoinPredicate->value.Double != TRUE)) {
  1680. continue;
  1681. }
  1682. /* If record passes outer join criteria, use it */
  1683. else {
  1684. lpSqlNodeTable->node.table.Rewound = FALSE;
  1685. }
  1686. }
  1687. }
  1688. break;
  1689. }
  1690. break;
  1691. case NODE_TYPE_TABLE:
  1692. /* If currently on a record of all NULLs, error */
  1693. if ((lpSqlNode->node.table.OuterJoinPredicate != NO_SQLNODE) &&
  1694. lpSqlNode->node.table.AllNull)
  1695. return ERR_NODATAFOUND;
  1696. /* Are we already on a record of all nulls? */
  1697. if (lpSqlNode->node.table.AllNull)
  1698. /* Yes. Stay there */
  1699. err = ISAM_EOF;
  1700. else {
  1701. /* No. Get the next record from the ISAM */
  1702. err = ISAMNextRecord(lpSqlNode->node.table.Handle, lpstmt);
  1703. if ((err == NO_ISAM_ERR) || (err == ISAM_EOF))
  1704. lpstmt->fISAMTxnStarted = TRUE;
  1705. }
  1706. if (err == ISAM_EOF) {
  1707. /* End of table. If not an outer join, error */
  1708. if (lpSqlNode->node.table.OuterJoinPredicate == NO_SQLNODE)
  1709. return ERR_NODATAFOUND;
  1710. /* If this is not first read, error */
  1711. if (!(lpSqlNode->node.table.Rewound))
  1712. return ERR_NODATAFOUND;
  1713. /* Otherwise, use a record of all NULLs */
  1714. lpSqlNode->node.table.AllNull = TRUE;
  1715. }
  1716. else if (err != NO_ISAM_ERR) {
  1717. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  1718. return err;
  1719. }
  1720. break;
  1721. default:
  1722. return ERR_INTERNAL;
  1723. }
  1724. return ERR_SUCCESS;
  1725. }
  1726. /***************************************************************************/
  1727. RETCODE INTFUNC NextRecord (LPSTMT lpstmt,
  1728. LPSQLNODE lpSqlNode,
  1729. LPSQLNODE lpSqlNodePredicate)
  1730. /* Finds the next record in in the table or table list identified by */
  1731. /* lpSqlNode that satisfies the predicate lpSqlNodePredicte. */
  1732. /* */
  1733. /* If a list of tables is given, the leftmost table spins the slowest */
  1734. /* and the rightmost table spins the fastest. In otherwords, for each */
  1735. /* row in a table, we iterate over the rows in the tables after that table */
  1736. {
  1737. SWORD err;
  1738. /* Loop until a record is found */
  1739. while (TRUE) {
  1740. /* Go to next record */
  1741. err = NextRawRecord(lpstmt, lpSqlNode);
  1742. if (err != ERR_SUCCESS)
  1743. return err;
  1744. /* If no predicate, this record qualifies. */
  1745. if (lpSqlNodePredicate == NULL)
  1746. break;
  1747. /* If the predicate is TRUE, return this record */
  1748. err = EvaluateExpression(lpstmt, lpSqlNodePredicate);
  1749. if (err != ERR_SUCCESS)
  1750. return err;
  1751. if (!(lpSqlNodePredicate->sqlIsNull) &&
  1752. (lpSqlNodePredicate->value.Double == TRUE))
  1753. break;
  1754. }
  1755. return ERR_SUCCESS;
  1756. }
  1757. /***************************************************************************/
  1758. int INTFUNC lstrcmp_pad(LPUSTR lpszLeft, LPUSTR lpszRight)
  1759. /* Compares two string (blank padding the shorter one to the same length */
  1760. /* as the longer one). */
  1761. {
  1762. int cbLeft;
  1763. int cbRight;
  1764. UCHAR chr;
  1765. int result;
  1766. /* Get the length of the two strings */
  1767. cbLeft = s_lstrlen(lpszLeft);
  1768. cbRight = s_lstrlen(lpszRight);
  1769. /* If the strings are the same length, use plain old lstrcmp */
  1770. if (cbLeft == cbRight)
  1771. result = s_lstrcmp(lpszLeft, lpszRight);
  1772. /* If the left one is shorter, swap the strings and try again */
  1773. else if (cbLeft < cbRight)
  1774. result = -(lstrcmp_pad(lpszRight, lpszLeft));
  1775. /* Otherwise the right one is shorter... */
  1776. else {
  1777. /* Truncate the left one to the size of the right one */
  1778. chr = lpszLeft[cbRight];
  1779. lpszLeft[cbRight] = '\0';
  1780. /* Are the strings equal? */
  1781. result = s_lstrcmp(lpszLeft, lpszRight);
  1782. lpszLeft[cbRight] = chr; /* Untruncate the left one */
  1783. if (result == 0) {
  1784. /* Yes. Compare remaining characters on the left string to blanks */
  1785. while (cbRight < cbLeft) {
  1786. result = lpszLeft[cbRight] - ' ';
  1787. if (result != 0)
  1788. break;
  1789. cbRight++;
  1790. }
  1791. }
  1792. }
  1793. return result;
  1794. }
  1795. RETCODE INTFUNC ValueCompare(LPSQLNODE lpSqlNode, LPSQLNODE lpSqlNodeLeft,
  1796. UWORD Operator, LPSQLNODE lpSqlNodeRight)
  1797. /* Compares two values */
  1798. {
  1799. RETCODE err;
  1800. LONG idx;
  1801. /* Compare values */
  1802. err = ERR_SUCCESS;
  1803. lpSqlNode->sqlIsNull = FALSE;
  1804. switch (lpSqlNodeLeft->sqlDataType) {
  1805. case TYPE_DOUBLE:
  1806. case TYPE_INTEGER:
  1807. case TYPE_NUMERIC:
  1808. err = NumericCompare(lpSqlNode, lpSqlNodeLeft, Operator,
  1809. lpSqlNodeRight);
  1810. if (err != ERR_SUCCESS)
  1811. return err;
  1812. break;
  1813. case TYPE_CHAR:
  1814. switch (Operator) {
  1815. case OP_EQ:
  1816. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1817. lpSqlNodeRight->value.String) == 0)
  1818. lpSqlNode->value.Double = TRUE;
  1819. else
  1820. lpSqlNode->value.Double = FALSE;
  1821. break;
  1822. case OP_NE:
  1823. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1824. lpSqlNodeRight->value.String) != 0)
  1825. lpSqlNode->value.Double = TRUE;
  1826. else
  1827. lpSqlNode->value.Double = FALSE;
  1828. break;
  1829. case OP_LE:
  1830. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1831. lpSqlNodeRight->value.String) <= 0)
  1832. lpSqlNode->value.Double = TRUE;
  1833. else
  1834. lpSqlNode->value.Double = FALSE;
  1835. break;
  1836. case OP_LT:
  1837. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1838. lpSqlNodeRight->value.String) < 0)
  1839. lpSqlNode->value.Double = TRUE;
  1840. else
  1841. lpSqlNode->value.Double = FALSE;
  1842. break;
  1843. case OP_GE:
  1844. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1845. lpSqlNodeRight->value.String) >= 0)
  1846. lpSqlNode->value.Double = TRUE;
  1847. else
  1848. lpSqlNode->value.Double = FALSE;
  1849. break;
  1850. case OP_GT:
  1851. if (lstrcmp_pad(lpSqlNodeLeft->value.String,
  1852. lpSqlNodeRight->value.String) > 0)
  1853. lpSqlNode->value.Double = TRUE;
  1854. else
  1855. lpSqlNode->value.Double = FALSE;
  1856. break;
  1857. case OP_LIKE:
  1858. lpSqlNode->value.Double =
  1859. PatternMatch(FALSE, lpSqlNodeLeft->value.String,
  1860. s_lstrlen(lpSqlNodeLeft->value.String),
  1861. lpSqlNodeRight->value.String,
  1862. s_lstrlen(lpSqlNodeRight->value.String),
  1863. TRUE);
  1864. break;
  1865. case OP_NOTLIKE:
  1866. lpSqlNode->value.Double =
  1867. !(PatternMatch(FALSE, lpSqlNodeLeft->value.String,
  1868. s_lstrlen(lpSqlNodeLeft->value.String),
  1869. lpSqlNodeRight->value.String,
  1870. s_lstrlen(lpSqlNodeRight->value.String),
  1871. TRUE));
  1872. break;
  1873. default:
  1874. err = ERR_INTERNAL;
  1875. break;
  1876. }
  1877. break;
  1878. case TYPE_BINARY:
  1879. switch (Operator) {
  1880. case OP_EQ:
  1881. if (BINARY_LENGTH(lpSqlNodeLeft->value.Binary) ==
  1882. BINARY_LENGTH(lpSqlNodeRight->value.Binary)) {
  1883. lpSqlNode->value.Double = TRUE;
  1884. for (idx = 0;
  1885. idx < BINARY_LENGTH(lpSqlNodeRight->value.Binary);
  1886. idx++) {
  1887. if (BINARY_DATA(lpSqlNodeLeft->value.Binary)[idx] !=
  1888. BINARY_DATA(lpSqlNodeRight->value.Binary)[idx]) {
  1889. lpSqlNode->value.Double = FALSE;
  1890. break;
  1891. }
  1892. }
  1893. }
  1894. else
  1895. lpSqlNode->value.Double = FALSE;
  1896. break;
  1897. case OP_NE:
  1898. if (BINARY_LENGTH(lpSqlNodeLeft->value.Binary) ==
  1899. BINARY_LENGTH(lpSqlNodeRight->value.Binary)) {
  1900. lpSqlNode->value.Double = FALSE;
  1901. for (idx = 0;
  1902. idx < BINARY_LENGTH(lpSqlNodeRight->value.Binary);
  1903. idx++) {
  1904. if (BINARY_DATA(lpSqlNodeLeft->value.Binary)[idx] !=
  1905. BINARY_DATA(lpSqlNodeRight->value.Binary)[idx]) {
  1906. lpSqlNode->value.Double = TRUE;
  1907. break;
  1908. }
  1909. }
  1910. }
  1911. else
  1912. lpSqlNode->value.Double = TRUE;
  1913. break;
  1914. case OP_LE:
  1915. case OP_LT:
  1916. case OP_GE:
  1917. case OP_GT:
  1918. case OP_LIKE:
  1919. case OP_NOTLIKE:
  1920. default:
  1921. err = ERR_INTERNAL;
  1922. break;
  1923. }
  1924. break;
  1925. case TYPE_DATE:
  1926. switch (Operator) {
  1927. case OP_EQ:
  1928. if (DateCompare(lpSqlNodeLeft->value.Date,
  1929. lpSqlNodeRight->value.Date) == 0)
  1930. lpSqlNode->value.Double = TRUE;
  1931. else
  1932. lpSqlNode->value.Double = FALSE;
  1933. break;
  1934. case OP_NE:
  1935. if (DateCompare(lpSqlNodeLeft->value.Date,
  1936. lpSqlNodeRight->value.Date) != 0)
  1937. lpSqlNode->value.Double = TRUE;
  1938. else
  1939. lpSqlNode->value.Double = FALSE;
  1940. break;
  1941. case OP_LE:
  1942. if (DateCompare(lpSqlNodeLeft->value.Date,
  1943. lpSqlNodeRight->value.Date) <= 0)
  1944. lpSqlNode->value.Double = TRUE;
  1945. else
  1946. lpSqlNode->value.Double = FALSE;
  1947. break;
  1948. case OP_LT:
  1949. if (DateCompare(lpSqlNodeLeft->value.Date,
  1950. lpSqlNodeRight->value.Date) < 0)
  1951. lpSqlNode->value.Double = TRUE;
  1952. else
  1953. lpSqlNode->value.Double = FALSE;
  1954. break;
  1955. case OP_GE:
  1956. if (DateCompare(lpSqlNodeLeft->value.Date,
  1957. lpSqlNodeRight->value.Date) >= 0)
  1958. lpSqlNode->value.Double = TRUE;
  1959. else
  1960. lpSqlNode->value.Double = FALSE;
  1961. break;
  1962. case OP_GT:
  1963. if (DateCompare(lpSqlNodeLeft->value.Date,
  1964. lpSqlNodeRight->value.Date) > 0)
  1965. lpSqlNode->value.Double = TRUE;
  1966. else
  1967. lpSqlNode->value.Double = FALSE;
  1968. break;
  1969. case OP_LIKE:
  1970. case OP_NOTLIKE:
  1971. default:
  1972. err = ERR_INTERNAL;
  1973. break;
  1974. }
  1975. break;
  1976. case TYPE_TIME:
  1977. switch (Operator) {
  1978. case OP_EQ:
  1979. if (TimeCompare(lpSqlNodeLeft->value.Time,
  1980. lpSqlNodeRight->value.Time) == 0)
  1981. lpSqlNode->value.Double = TRUE;
  1982. else
  1983. lpSqlNode->value.Double = FALSE;
  1984. break;
  1985. case OP_NE:
  1986. if (TimeCompare(lpSqlNodeLeft->value.Time,
  1987. lpSqlNodeRight->value.Time) != 0)
  1988. lpSqlNode->value.Double = TRUE;
  1989. else
  1990. lpSqlNode->value.Double = FALSE;
  1991. break;
  1992. case OP_LE:
  1993. if (TimeCompare(lpSqlNodeLeft->value.Time,
  1994. lpSqlNodeRight->value.Time) <= 0)
  1995. lpSqlNode->value.Double = TRUE;
  1996. else
  1997. lpSqlNode->value.Double = FALSE;
  1998. break;
  1999. case OP_LT:
  2000. if (TimeCompare(lpSqlNodeLeft->value.Time,
  2001. lpSqlNodeRight->value.Time) < 0)
  2002. lpSqlNode->value.Double = TRUE;
  2003. else
  2004. lpSqlNode->value.Double = FALSE;
  2005. break;
  2006. case OP_GE:
  2007. if (TimeCompare(lpSqlNodeLeft->value.Time,
  2008. lpSqlNodeRight->value.Time) >= 0)
  2009. lpSqlNode->value.Double = TRUE;
  2010. else
  2011. lpSqlNode->value.Double = FALSE;
  2012. break;
  2013. case OP_GT:
  2014. if (TimeCompare(lpSqlNodeLeft->value.Time,
  2015. lpSqlNodeRight->value.Time) > 0)
  2016. lpSqlNode->value.Double = TRUE;
  2017. else
  2018. lpSqlNode->value.Double = FALSE;
  2019. break;
  2020. case OP_LIKE:
  2021. case OP_NOTLIKE:
  2022. default:
  2023. err = ERR_INTERNAL;
  2024. break;
  2025. }
  2026. break;
  2027. case TYPE_TIMESTAMP:
  2028. switch (Operator) {
  2029. case OP_EQ:
  2030. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2031. lpSqlNodeRight->value.Timestamp) == 0)
  2032. lpSqlNode->value.Double = TRUE;
  2033. else
  2034. lpSqlNode->value.Double = FALSE;
  2035. break;
  2036. case OP_NE:
  2037. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2038. lpSqlNodeRight->value.Timestamp) != 0)
  2039. lpSqlNode->value.Double = TRUE;
  2040. else
  2041. lpSqlNode->value.Double = FALSE;
  2042. break;
  2043. case OP_LE:
  2044. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2045. lpSqlNodeRight->value.Timestamp) <= 0)
  2046. lpSqlNode->value.Double = TRUE;
  2047. else
  2048. lpSqlNode->value.Double = FALSE;
  2049. break;
  2050. case OP_LT:
  2051. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2052. lpSqlNodeRight->value.Timestamp) < 0)
  2053. lpSqlNode->value.Double = TRUE;
  2054. else
  2055. lpSqlNode->value.Double = FALSE;
  2056. break;
  2057. case OP_GE:
  2058. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2059. lpSqlNodeRight->value.Timestamp) >= 0)
  2060. lpSqlNode->value.Double = TRUE;
  2061. else
  2062. lpSqlNode->value.Double = FALSE;
  2063. break;
  2064. case OP_GT:
  2065. if (TimestampCompare(lpSqlNodeLeft->value.Timestamp,
  2066. lpSqlNodeRight->value.Timestamp) > 0)
  2067. lpSqlNode->value.Double = TRUE;
  2068. else
  2069. lpSqlNode->value.Double = FALSE;
  2070. break;
  2071. case OP_LIKE:
  2072. case OP_NOTLIKE:
  2073. default:
  2074. err = ERR_INTERNAL;
  2075. break;
  2076. }
  2077. break;
  2078. default:
  2079. err = ERR_NOTSUPPORTED;
  2080. break;
  2081. }
  2082. return err;
  2083. }
  2084. /***************************************************************************/
  2085. RETCODE INTFUNC RetrieveSortRecordValue(LPSQLNODE lpSqlNodeStmt, LPSQLNODE lpSqlNode,
  2086. UDWORD Offset, UDWORD Length)
  2087. /* Retrieves a value from a sort record */
  2088. {
  2089. UCHAR cNullFlag;
  2090. UCHAR szBuffer[30];
  2091. UWORD len;
  2092. UDWORD SortRecordsize;
  2093. szBuffer[0] = 0;
  2094. /* Position to the value */
  2095. if (lpSqlNodeStmt->sqlNodeType != NODE_TYPE_SELECT)
  2096. return ERR_INTERNAL;
  2097. if (!(lpSqlNodeStmt->node.select.ReturningDistinct))
  2098. SortRecordsize = lpSqlNodeStmt->node.select.SortRecordsize;
  2099. else
  2100. SortRecordsize = lpSqlNodeStmt->node.select.DistinctRecordsize;
  2101. if (_llseek(lpSqlNodeStmt->node.select.Sortfile,
  2102. (lpSqlNodeStmt->node.select.CurrentRow * SortRecordsize)
  2103. + Offset - 1, 0) == HFILE_ERROR)
  2104. return ERR_SORT;
  2105. /* Read value */
  2106. switch (lpSqlNode->sqlDataType) {
  2107. case TYPE_DOUBLE:
  2108. case TYPE_INTEGER:
  2109. if (_lread(lpSqlNodeStmt->node.select.Sortfile,
  2110. &(lpSqlNode->value.Double),
  2111. sizeof(double)) != sizeof(double))
  2112. return ERR_SORT;
  2113. break;
  2114. case TYPE_NUMERIC:
  2115. if (_lread(lpSqlNodeStmt->node.select.Sortfile,
  2116. lpSqlNode->value.String,
  2117. (UINT) Length) != (UINT) Length)
  2118. return ERR_SORT;
  2119. lpSqlNode->value.String[Length]='\0';
  2120. /* Remove trailing blanks */
  2121. len = (UWORD) s_lstrlen(lpSqlNode->value.String);
  2122. while ((len > 0) && (lpSqlNode->value.String[len-1] == ' ')) {
  2123. lpSqlNode->value.String[len-1] = '\0';
  2124. len--;
  2125. }
  2126. break;
  2127. case TYPE_CHAR:
  2128. if (_lread(lpSqlNodeStmt->node.select.Sortfile,
  2129. lpSqlNode->value.String,
  2130. (UINT) Length) != (UINT) Length)
  2131. return ERR_SORT;
  2132. lpSqlNode->value.String[Length]='\0';
  2133. /* Remove trailing blanks if need be */
  2134. if ((lpSqlNode->sqlSqlType == SQL_VARCHAR) ||
  2135. (lpSqlNode->sqlSqlType == SQL_LONGVARCHAR)) {
  2136. len = (UWORD) s_lstrlen(lpSqlNode->value.String);
  2137. while ((len > 0) && (lpSqlNode->value.String[len-1] == ' ')) {
  2138. lpSqlNode->value.String[len-1] = '\0';
  2139. len--;
  2140. }
  2141. }
  2142. break;
  2143. case TYPE_DATE:
  2144. if (_lread(lpSqlNodeStmt->node.select.Sortfile, szBuffer,
  2145. (UINT) Length) != (UINT) Length)
  2146. return ERR_SORT;
  2147. CharToDate((LPUSTR)szBuffer, Length, &(lpSqlNode->value.Date));
  2148. break;
  2149. case TYPE_TIME:
  2150. if (_lread(lpSqlNodeStmt->node.select.Sortfile, szBuffer,
  2151. (UINT) Length) != (UINT) Length)
  2152. return ERR_SORT;
  2153. CharToTime((LPUSTR)szBuffer, Length, &(lpSqlNode->value.Time));
  2154. break;
  2155. case TYPE_TIMESTAMP:
  2156. if (_lread(lpSqlNodeStmt->node.select.Sortfile, szBuffer,
  2157. (UINT) Length) != (UINT) Length)
  2158. return ERR_SORT;
  2159. CharToTimestamp((LPUSTR)szBuffer, Length, &(lpSqlNode->value.Timestamp));
  2160. break;
  2161. case TYPE_BINARY:
  2162. return ERR_INTERNAL;
  2163. default:
  2164. return ERR_NOTSUPPORTED;
  2165. }
  2166. /* Read NULL flag */
  2167. if (_lread(lpSqlNodeStmt->node.select.Sortfile, &cNullFlag, 1) != 1)
  2168. return ERR_SORT;
  2169. switch (cNullFlag) {
  2170. case NULL_FLAG:
  2171. lpSqlNode->sqlIsNull = TRUE;
  2172. break;
  2173. case NOT_NULL_FLAG:
  2174. lpSqlNode->sqlIsNull = FALSE;
  2175. break;
  2176. default:
  2177. return ERR_SORT;
  2178. }
  2179. return ERR_SUCCESS;
  2180. }
  2181. /***************************************************************************/
  2182. RETCODE INTFUNC TxnCapableForDDL(LPSTMT lpstmt)
  2183. /* Makes sure the DDL statements can be executed if DML statements were */
  2184. /* encountered */
  2185. {
  2186. LPSTMT lpstmtOther;
  2187. RETCODE err;
  2188. /* What transaction capabilities are allowed? */
  2189. switch (lpstmt->lpdbc->lpISAM->fTxnCapable) {
  2190. case SQL_TC_NONE:
  2191. /* No transactions. Allow all DDL statements all the time */
  2192. break;
  2193. case SQL_TC_DML:
  2194. /* Transactions can never DDL statements */
  2195. for (lpstmtOther = lpstmt->lpdbc->lpstmts;
  2196. lpstmtOther != NULL;
  2197. lpstmtOther = lpstmtOther->lpNext) {
  2198. if (lpstmtOther->fDMLTxn)
  2199. return ERR_DDLENCOUNTERD;
  2200. }
  2201. break;
  2202. case SQL_TC_DDL_COMMIT:
  2203. /* Transactions that contain DDL statements cause a commit */
  2204. for (lpstmtOther = lpstmt->lpdbc->lpstmts;
  2205. lpstmtOther != NULL;
  2206. lpstmtOther = lpstmtOther->lpNext) {
  2207. if (lpstmtOther->fDMLTxn) {
  2208. err = SQLTransact(SQL_NULL_HENV, (HDBC)lpstmt->lpdbc,
  2209. SQL_COMMIT);
  2210. if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) {
  2211. lpstmt->errcode = lpstmt->lpdbc->errcode;
  2212. s_lstrcpy(lpstmt->szISAMError, lpstmt->lpdbc->szISAMError);
  2213. return err;
  2214. }
  2215. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  2216. return ERR_DDLSTATEMENTLOST;
  2217. else
  2218. return ERR_DDLCAUSEDACOMMIT;
  2219. }
  2220. }
  2221. break;
  2222. case SQL_TC_DDL_IGNORE:
  2223. /* DDL statements are ignored within a transaction */
  2224. for (lpstmtOther = lpstmt->lpdbc->lpstmts;
  2225. lpstmtOther != NULL;
  2226. lpstmtOther = lpstmtOther->lpNext) {
  2227. if (lpstmtOther->fDMLTxn)
  2228. return ERR_DDLIGNORED;
  2229. }
  2230. break;
  2231. case SQL_TC_ALL:
  2232. /* Allow all DDL statements all the time */
  2233. break;
  2234. }
  2235. return ERR_SUCCESS;
  2236. }
  2237. /***************************************************************************/
  2238. /***************************************************************************/
  2239. RETCODE INTFUNC FetchRow(LPSTMT lpstmt, LPSQLNODE lpSqlNode)
  2240. /* Fetch the next row from a SELECT */
  2241. {
  2242. LPSQLNODE lpSqlNodeTable;
  2243. LPSQLNODE lpSqlNodeTables;
  2244. LPSQLNODE lpSqlNodePredicate;
  2245. LPSQLNODE lpSqlNodeHaving;
  2246. SQLNODEIDX idxTables;
  2247. ISAMBOOKMARK bookmark;
  2248. RETCODE err;
  2249. // ODBCTRACE("\nWBEM ODBC Driver : FetchRow\n");
  2250. /* Error if after the last row */
  2251. if (lpSqlNode->node.select.CurrentRow == AFTER_LAST_ROW)
  2252. return ERR_NODATAFOUND;
  2253. /* Is there a sort file to read from */
  2254. if (lpSqlNode->node.select.Sortfile == HFILE_ERROR) {
  2255. /* No. Get the table list and predicate node. */
  2256. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.select.Tables);
  2257. if (lpSqlNode->node.select.Predicate == NO_SQLNODE)
  2258. lpSqlNodePredicate = NULL;
  2259. else
  2260. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.select.Predicate);
  2261. /* Get the next record */
  2262. err = NextRecord(lpstmt, lpSqlNodeTables, lpSqlNodePredicate);
  2263. if (err == ERR_NODATAFOUND) {
  2264. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  2265. return err;
  2266. }
  2267. else if (err != ERR_SUCCESS)
  2268. return err;
  2269. /* Set row flag */
  2270. if (lpSqlNode->node.select.CurrentRow == BEFORE_FIRST_ROW)
  2271. lpSqlNode->node.select.CurrentRow = 0;
  2272. else
  2273. lpSqlNode->node.select.CurrentRow++;
  2274. }
  2275. else if (!(lpSqlNode->node.select.ReturningDistinct)) {
  2276. /* Yes. Look for next record in sort file */
  2277. if (lpSqlNode->node.select.Having == NO_SQLNODE)
  2278. lpSqlNodeHaving = NULL;
  2279. else
  2280. lpSqlNodeHaving =
  2281. ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.select.Having);
  2282. while (TRUE) {
  2283. /* Set row flag */
  2284. if (lpSqlNode->node.select.CurrentRow == BEFORE_FIRST_ROW) {
  2285. if (lpSqlNode->node.select.RowCount != 0) {
  2286. lpSqlNode->node.select.CurrentRow = 0;
  2287. }
  2288. else {
  2289. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  2290. return ERR_NODATAFOUND;
  2291. }
  2292. }
  2293. else if (lpSqlNode->node.select.CurrentRow ==
  2294. lpSqlNode->node.select.RowCount-1) {
  2295. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  2296. return ERR_NODATAFOUND;
  2297. }
  2298. else
  2299. lpSqlNode->node.select.CurrentRow++;
  2300. /* If no HAVING clause, this record qualifies */
  2301. if (lpSqlNodeHaving == NULL)
  2302. break;
  2303. /* If HAVING condition is satisfied, this record qualifies */
  2304. err = EvaluateExpression(lpstmt, lpSqlNodeHaving);
  2305. if (err != ERR_SUCCESS)
  2306. return err;
  2307. if (!(lpSqlNodeHaving->sqlIsNull) &&
  2308. (lpSqlNodeHaving->value.Double == TRUE))
  2309. break;
  2310. }
  2311. /* Is there a group by? */
  2312. if ((lpSqlNode->node.select.Groupbycolumns == NO_SQLNODE) &&
  2313. (!lpSqlNode->node.select.ImplicitGroupby)) {
  2314. /* No. Position to bookmarks in that row */
  2315. if (_llseek(lpSqlNode->node.select.Sortfile,
  2316. (lpSqlNode->node.select.CurrentRow *
  2317. lpSqlNode->node.select.SortRecordsize) +
  2318. lpSqlNode->node.select.SortBookmarks - 1, 0) == HFILE_ERROR)
  2319. return ERR_SORT;
  2320. /* For each table... */
  2321. idxTables = lpSqlNode->node.select.Tables;
  2322. while (idxTables != NO_SQLNODE) {
  2323. /* Get the table node */
  2324. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt, idxTables);
  2325. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  2326. lpSqlNodeTables->node.tables.Table);
  2327. /* Read the bookmark for it */
  2328. if (_lread(lpSqlNode->node.select.Sortfile, &bookmark,
  2329. sizeof(ISAMBOOKMARK)) != sizeof(ISAMBOOKMARK))
  2330. return ERR_SORT;
  2331. /* Position to that record */
  2332. if (bookmark.currentRecord == NULL_BOOKMARK)
  2333. {
  2334. lpSqlNodeTable->node.table.AllNull = TRUE;
  2335. }
  2336. else
  2337. {
  2338. lpSqlNodeTable->node.table.AllNull = FALSE;
  2339. err = ISAMPosition(lpSqlNodeTable->node.table.Handle, &bookmark);
  2340. if (err != NO_ISAM_ERR) {
  2341. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  2342. (LPUSTR)lpstmt->szISAMError);
  2343. return err;
  2344. }
  2345. lpstmt->fISAMTxnStarted = TRUE;
  2346. }
  2347. /* Point at next table */
  2348. idxTables = lpSqlNodeTables->node.tables.Next;
  2349. }
  2350. }
  2351. }
  2352. else {
  2353. /* Yes. Look for next record in DISTINCT file. Set row flag */
  2354. if (lpSqlNode->node.select.CurrentRow == BEFORE_FIRST_ROW) {
  2355. if (lpSqlNode->node.select.RowCount != 0) {
  2356. lpSqlNode->node.select.CurrentRow = 0;
  2357. }
  2358. else {
  2359. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  2360. return ERR_NODATAFOUND;
  2361. }
  2362. }
  2363. else if (lpSqlNode->node.select.CurrentRow ==
  2364. lpSqlNode->node.select.RowCount-1) {
  2365. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  2366. return ERR_NODATAFOUND;
  2367. }
  2368. else
  2369. lpSqlNode->node.select.CurrentRow++;
  2370. }
  2371. return ERR_SUCCESS;
  2372. }
  2373. /***************************************************************************/
  2374. RETCODE INTFUNC EvaluateExpression(LPSTMT lpstmt, LPSQLNODE lpSqlNode)
  2375. /* Eavluates an SQL expression by walking the parse tree, computing */
  2376. /* the value of each node with respect to a database record, and */
  2377. /* storing the result in the string area. */
  2378. {
  2379. // ODBCTRACE ("\nWBEM ODBC Driver : EvaluateExpression\n");
  2380. LPSQLTREE lpSql;
  2381. LPSQLNODE lpSqlNodeLeft = 0;
  2382. LPSQLNODE lpSqlNodeRight = 0;
  2383. RETCODE err;
  2384. SQLNODEIDX idxValues;
  2385. LPSQLNODE lpSqlNodeValues;
  2386. LPUSTR lpWorkBuffer1;
  2387. LPUSTR lpWorkBuffer2;
  2388. LPUSTR lpWorkBuffer3;
  2389. BOOL fReturningDistinct;
  2390. LPSQLNODE lpSqlNodeSelect;
  2391. BOOL fTruncation;
  2392. BOOL fIsNull;
  2393. lpSql = lpstmt->lpSqlStmt;
  2394. if (lpSqlNode == NULL)
  2395. return ERR_INTERNAL;
  2396. err = ERR_SUCCESS;
  2397. switch (lpSqlNode->sqlNodeType) {
  2398. case NODE_TYPE_NONE:
  2399. case NODE_TYPE_ROOT:
  2400. case NODE_TYPE_CREATE:
  2401. case NODE_TYPE_DROP:
  2402. case NODE_TYPE_SELECT:
  2403. case NODE_TYPE_INSERT:
  2404. case NODE_TYPE_DELETE:
  2405. case NODE_TYPE_UPDATE:
  2406. case NODE_TYPE_CREATEINDEX:
  2407. case NODE_TYPE_DROPINDEX:
  2408. case NODE_TYPE_PASSTHROUGH:
  2409. case NODE_TYPE_TABLES:
  2410. case NODE_TYPE_VALUES:
  2411. case NODE_TYPE_COLUMNS:
  2412. case NODE_TYPE_SORTCOLUMNS:
  2413. case NODE_TYPE_GROUPBYCOLUMNS:
  2414. case NODE_TYPE_UPDATEVALUES:
  2415. case NODE_TYPE_CREATECOLS:
  2416. case NODE_TYPE_TABLE:
  2417. err = ERR_INTERNAL;
  2418. break;
  2419. case NODE_TYPE_BOOLEAN:
  2420. /* Evaluate the left child node */
  2421. lpSqlNodeLeft = ToNode(lpSql, lpSqlNode->node.boolean.Left);
  2422. err = EvaluateExpression(lpstmt, lpSqlNodeLeft);
  2423. if (err != ERR_SUCCESS)
  2424. return err;
  2425. /* Is this an AND? */
  2426. if (lpSqlNode->node.boolean.Operator == OP_AND) {
  2427. LPSQLNODE lpSqlNodeAnd;
  2428. BOOL sqlIsNull;
  2429. BOOL fResult;
  2430. /* Yes. Look at each sub-expression */
  2431. lpSqlNodeAnd = lpSqlNode;
  2432. sqlIsNull = FALSE;
  2433. fResult = TRUE;
  2434. while (TRUE) {
  2435. /* If the left child is FALSE, return FALSE */
  2436. if (!((BOOL) lpSqlNodeLeft->value.Double)) {
  2437. sqlIsNull = FALSE;
  2438. fResult = FALSE;
  2439. break;
  2440. }
  2441. /* If the left child is NULL, the result may be NULL */
  2442. else if (lpSqlNodeLeft->sqlIsNull) {
  2443. sqlIsNull = TRUE;
  2444. fResult = FALSE;
  2445. }
  2446. /* Get the right child */
  2447. lpSqlNodeRight = ToNode(lpSql, lpSqlNode->node.boolean.Right);
  2448. /* Is it an AND node? */
  2449. if ((lpSqlNodeRight->sqlNodeType != NODE_TYPE_BOOLEAN) ||
  2450. (lpSqlNodeRight->node.boolean.Operator != OP_AND)) {
  2451. /* No. Evaluate it */
  2452. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2453. if (err != ERR_SUCCESS)
  2454. return err;
  2455. /* If the right child is FALSE, return FALSE */
  2456. if (!((BOOL) lpSqlNodeRight->value.Double)) {
  2457. sqlIsNull = FALSE;
  2458. fResult = FALSE;
  2459. }
  2460. /* If the right child is NULL, the result is NULL */
  2461. else if (lpSqlNodeRight->sqlIsNull) {
  2462. sqlIsNull = TRUE;
  2463. fResult = FALSE;
  2464. }
  2465. /* Leave the loop */
  2466. break;
  2467. }
  2468. /* Point to right and continue to walk down the AND nodes */
  2469. lpSqlNode = lpSqlNodeRight;
  2470. lpSqlNodeLeft = ToNode(lpSql, lpSqlNode->node.boolean.Left);
  2471. err = EvaluateExpression(lpstmt, lpSqlNodeLeft);
  2472. if (err != ERR_SUCCESS)
  2473. return err;
  2474. }
  2475. /* Return result */
  2476. lpSqlNodeAnd->sqlIsNull = sqlIsNull;
  2477. lpSqlNodeAnd->value.Double = fResult;
  2478. break;
  2479. }
  2480. /* Is there a right child? */
  2481. if (lpSqlNode->node.boolean.Right != NO_SQLNODE) {
  2482. /* Yes. Evaluate it */
  2483. lpSqlNodeRight = ToNode(lpSql, lpSqlNode->node.boolean.Right);
  2484. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2485. if (err != ERR_SUCCESS)
  2486. return err;
  2487. }
  2488. if (lpSqlNode->node.boolean.Operator != OP_NOT && lpSqlNodeRight == 0)
  2489. return ERR_INTERNAL;
  2490. /* Perform the operation. */
  2491. switch (lpSqlNode->node.boolean.Operator) {
  2492. case OP_NOT:
  2493. /* If child is NULL, return NULL */
  2494. if (lpSqlNodeLeft->sqlIsNull) {
  2495. lpSqlNode->sqlIsNull = TRUE;
  2496. break;
  2497. }
  2498. /* Evaluate expression */
  2499. lpSqlNode->sqlIsNull = FALSE;
  2500. lpSqlNode->value.Double = !((BOOL) lpSqlNodeLeft->value.Double);
  2501. break;
  2502. case OP_AND:
  2503. /* Is left child NULL or TRUE? */
  2504. if ((lpSqlNodeLeft->sqlIsNull) ||
  2505. ((BOOL) lpSqlNodeLeft->value.Double)) {
  2506. /* Yes. If right child is NULL, return NULL */
  2507. if (lpSqlNodeRight->sqlIsNull)
  2508. lpSqlNode->sqlIsNull = TRUE;
  2509. /* If right child TRUE, return left child */
  2510. else if ((BOOL) lpSqlNodeRight->value.Double) {
  2511. lpSqlNode->sqlIsNull = lpSqlNodeLeft->sqlIsNull;
  2512. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double;
  2513. }
  2514. /* Otherwise right child must be FALSE, return FALSE */
  2515. else {
  2516. lpSqlNode->sqlIsNull = FALSE;
  2517. lpSqlNode->value.Double = FALSE;
  2518. }
  2519. }
  2520. /* Otherwise left child must be FALSE, return FALSE */
  2521. else {
  2522. lpSqlNode->sqlIsNull = FALSE;
  2523. lpSqlNode->value.Double = FALSE;
  2524. }
  2525. break;
  2526. case OP_OR:
  2527. /* Is left child NULL or FALSE? */
  2528. if ((lpSqlNodeLeft->sqlIsNull) ||
  2529. (!((BOOL) lpSqlNodeLeft->value.Double))) {
  2530. /* Yes. If right child is NULL, return NULL */
  2531. if (lpSqlNodeRight->sqlIsNull)
  2532. lpSqlNode->sqlIsNull = TRUE;
  2533. /* If right child FALSE, return left child */
  2534. else if (!((BOOL) lpSqlNodeRight->value.Double)) {
  2535. lpSqlNode->sqlIsNull = lpSqlNodeLeft->sqlIsNull;
  2536. lpSqlNode->value.Double = lpSqlNodeLeft->value.Double;
  2537. }
  2538. /* Otherwise right child must be TRUE, return TRUE */
  2539. else {
  2540. lpSqlNode->sqlIsNull = FALSE;
  2541. lpSqlNode->value.Double = TRUE;
  2542. }
  2543. }
  2544. /* Otherwise left child must be TRUE, return TRUE */
  2545. else {
  2546. lpSqlNode->sqlIsNull = FALSE;
  2547. lpSqlNode->value.Double = TRUE;
  2548. }
  2549. break;
  2550. default:
  2551. err = ERR_INTERNAL;
  2552. break;
  2553. }
  2554. break;
  2555. case NODE_TYPE_COMPARISON:
  2556. // ODBCTRACE ("\nWBEM ODBC Driver : NODE_TYPE_COMPARISON\n");
  2557. /* Evaluate the left child */
  2558. if (lpSqlNode->node.comparison.Operator != OP_EXISTS) {
  2559. lpSqlNodeLeft = ToNode(lpSql, lpSqlNode->node.comparison.Left);
  2560. err = EvaluateExpression(lpstmt, lpSqlNodeLeft);
  2561. if (err != ERR_SUCCESS)
  2562. return err;
  2563. }
  2564. /* EXISTS operator? */
  2565. if (lpSqlNode->node.comparison.Operator == OP_EXISTS) {
  2566. /* Do the sub-select */
  2567. lpSqlNodeSelect = ToNode(lpSql, lpSqlNode->node.comparison.Left);
  2568. err = ExecuteQuery(lpstmt, lpSqlNodeSelect);
  2569. if (err == ERR_DATATRUNCATED)
  2570. err = ERR_SUCCESS;
  2571. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  2572. return err;
  2573. /* Try to fetch a row */
  2574. if (err == ERR_SUCCESS) {
  2575. err = FetchRow(lpstmt, lpSqlNodeSelect);
  2576. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  2577. return err;
  2578. }
  2579. /* Return result */
  2580. lpSqlNode->sqlIsNull = FALSE;
  2581. if (err == ERR_NODATAFOUND)
  2582. lpSqlNode->value.Double = FALSE;
  2583. else
  2584. lpSqlNode->value.Double = TRUE;
  2585. }
  2586. /* Nested sub-select? */
  2587. else if (lpSqlNode->node.comparison.SelectModifier !=
  2588. SELECT_NOTSELECT) {
  2589. /* Yes. If left child is NULL, return NULL */
  2590. if (lpSqlNodeLeft->sqlIsNull) {
  2591. lpSqlNode->sqlIsNull = TRUE;
  2592. lpSqlNode->value.Double = 0;
  2593. break;
  2594. }
  2595. /* Do the sub-select */
  2596. fTruncation = FALSE;
  2597. lpSqlNodeSelect = ToNode(lpSql, lpSqlNode->node.comparison.Right);
  2598. lpSqlNodeRight = ToNode(lpSql, lpSqlNodeSelect->node.select.Values);
  2599. lpSqlNodeRight = ToNode(lpSql, lpSqlNodeRight->node.values.Value);
  2600. err = ExecuteQuery(lpstmt,
  2601. ToNode(lpSql, lpSqlNode->node.comparison.Right));
  2602. if (err == ERR_DATATRUNCATED) {
  2603. fTruncation = TRUE;
  2604. err = ERR_SUCCESS;
  2605. }
  2606. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  2607. return err;
  2608. /* Get the first value */
  2609. if (err == ERR_SUCCESS) {
  2610. // ODBCTRACE ("\nWBEM ODBC Driver : Get the first value\n");
  2611. err = FetchRow(lpstmt, lpSqlNodeSelect);
  2612. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  2613. return err;
  2614. }
  2615. /* Does the select return any rows? */
  2616. if (err == ERR_NODATAFOUND) {
  2617. /* No. Return result */
  2618. lpSqlNode->sqlIsNull = FALSE;
  2619. switch (lpSqlNode->node.comparison.SelectModifier) {
  2620. case SELECT_NOTSELECT:
  2621. return ERR_INTERNAL;
  2622. case SELECT_ALL:
  2623. lpSqlNode->value.Double = TRUE;
  2624. break;
  2625. case SELECT_ANY:
  2626. lpSqlNode->value.Double = FALSE;
  2627. break;
  2628. case SELECT_ONE:
  2629. return ERR_NOTSINGLESELECT;
  2630. break;
  2631. case SELECT_EXISTS:
  2632. default:
  2633. return ERR_INTERNAL;
  2634. }
  2635. }
  2636. else {
  2637. /* Yes. For each value returned */
  2638. fIsNull = FALSE;
  2639. while (TRUE) {
  2640. /* Get value */
  2641. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2642. if (err != ERR_SUCCESS)
  2643. return err;
  2644. /* Null value? */
  2645. if (!lpSqlNodeRight->sqlIsNull) {
  2646. /* No. Compare the values */
  2647. err = ValueCompare(lpSqlNode, lpSqlNodeLeft,
  2648. lpSqlNode->node.comparison.Operator,
  2649. lpSqlNodeRight);
  2650. if (err != ERR_SUCCESS)
  2651. return err;
  2652. /* Add it into the result */
  2653. switch (lpSqlNode->node.comparison.SelectModifier) {
  2654. case SELECT_NOTSELECT:
  2655. return ERR_INTERNAL;
  2656. case SELECT_ALL:
  2657. if (lpSqlNode->value.Double == FALSE) {
  2658. lpSqlNode->sqlIsNull = FALSE;
  2659. if (fTruncation)
  2660. return ERR_DATATRUNCATED;
  2661. return ERR_SUCCESS;
  2662. }
  2663. break;
  2664. case SELECT_ANY:
  2665. if (lpSqlNode->value.Double == TRUE) {
  2666. lpSqlNode->sqlIsNull = FALSE;
  2667. if (fTruncation)
  2668. return ERR_DATATRUNCATED;
  2669. return ERR_SUCCESS;
  2670. }
  2671. break;
  2672. case SELECT_ONE:
  2673. break;
  2674. case SELECT_EXISTS:
  2675. default:
  2676. return ERR_INTERNAL;
  2677. }
  2678. }
  2679. else
  2680. fIsNull = TRUE;
  2681. /* Get next value */
  2682. // ODBCTRACE ("\nWBEM ODBC Driver : Get next value\n");
  2683. err = FetchRow(lpstmt, lpSqlNodeSelect);
  2684. if (err == ERR_NODATAFOUND)
  2685. break;
  2686. if (err != ERR_SUCCESS)
  2687. return err;
  2688. /* Error if too mnay values */
  2689. if (lpSqlNode->node.comparison.SelectModifier==SELECT_ONE)
  2690. return ERR_NOTSINGLESELECT;
  2691. }
  2692. /* Figure out final answer */
  2693. err = ERR_SUCCESS;
  2694. if (fIsNull) {
  2695. lpSqlNode->sqlIsNull = TRUE;
  2696. lpSqlNode->value.Double = 0;
  2697. }
  2698. else {
  2699. lpSqlNode->sqlIsNull = FALSE;
  2700. switch (lpSqlNode->node.comparison.SelectModifier) {
  2701. case SELECT_NOTSELECT:
  2702. return ERR_INTERNAL;
  2703. case SELECT_ALL:
  2704. lpSqlNode->value.Double = TRUE;
  2705. break;
  2706. case SELECT_ANY:
  2707. lpSqlNode->value.Double = FALSE;
  2708. break;
  2709. case SELECT_ONE:
  2710. /* This was set by the call to ValueCompare above */
  2711. break;
  2712. case SELECT_EXISTS:
  2713. default:
  2714. return ERR_INTERNAL;
  2715. }
  2716. }
  2717. /* Return truncation error if need be */
  2718. if (fTruncation)
  2719. err = ERR_DATATRUNCATED;
  2720. }
  2721. }
  2722. /* IN or NOT IN operator? */
  2723. else if ((lpSqlNode->node.comparison.Operator != OP_IN) &&
  2724. (lpSqlNode->node.comparison.Operator != OP_NOTIN)) {
  2725. /* No. Evaluate the right child */
  2726. lpSqlNodeRight = ToNode(lpSql, lpSqlNode->node.comparison.Right);
  2727. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2728. if (err != ERR_SUCCESS)
  2729. return err;
  2730. /* Could this be an "IS NULL" or "IS NOT NULL" expression? */
  2731. if (lpSqlNodeRight->sqlIsNull &&
  2732. ((lpSqlNodeRight->sqlNodeType == NODE_TYPE_NULL) ||
  2733. (lpSqlNodeRight->sqlNodeType == NODE_TYPE_PARAMETER))) {
  2734. /* Possibly. Is this an "IS NULL" expression? */
  2735. if (lpSqlNode->node.comparison.Operator == OP_EQ) {
  2736. /* Yes. Return TRUE if the left child is NULL. */
  2737. lpSqlNode->sqlIsNull = FALSE;
  2738. if (lpSqlNodeLeft->sqlIsNull)
  2739. lpSqlNode->value.Double = TRUE;
  2740. else
  2741. lpSqlNode->value.Double = FALSE;
  2742. break;
  2743. }
  2744. /* Is this an "IS NOT NULL" expression? */
  2745. else if (lpSqlNode->node.comparison.Operator == OP_NE) {
  2746. /* Yes. Return FALSE if the left child is NULL. */
  2747. lpSqlNode->sqlIsNull = FALSE;
  2748. if (lpSqlNodeLeft->sqlIsNull)
  2749. lpSqlNode->value.Double = FALSE;
  2750. else
  2751. lpSqlNode->value.Double = TRUE;
  2752. break;
  2753. }
  2754. }
  2755. /* If either child is NULL, return NULL */
  2756. if (lpSqlNodeLeft->sqlIsNull || lpSqlNodeRight->sqlIsNull) {
  2757. lpSqlNode->sqlIsNull = TRUE;
  2758. lpSqlNode->value.Double = 0;
  2759. break;
  2760. }
  2761. /* Compare values */
  2762. err = ValueCompare(lpSqlNode, lpSqlNodeLeft,
  2763. lpSqlNode->node.comparison.Operator, lpSqlNodeRight);
  2764. if (err != ERR_SUCCESS)
  2765. return err;
  2766. }
  2767. else {
  2768. /* Yes. If test value is NULL, return NULL */
  2769. if (lpSqlNodeLeft->sqlIsNull) {
  2770. lpSqlNode->sqlIsNull = TRUE;
  2771. lpSqlNode->value.Double = 0;
  2772. break;
  2773. }
  2774. /* Set up the default answer */
  2775. lpSqlNode->sqlIsNull = FALSE;
  2776. lpSqlNode->value.Double = FALSE;
  2777. /* For each value on list... */
  2778. idxValues = lpSqlNode->node.comparison.Right;
  2779. while (idxValues != NO_SQLNODE) {
  2780. /* Get the value */
  2781. lpSqlNodeValues = ToNode(lpSql, idxValues);
  2782. lpSqlNodeRight = ToNode(lpSql, lpSqlNodeValues->node.values.Value);
  2783. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2784. if (err != ERR_SUCCESS)
  2785. return err;
  2786. /* Point at next value */
  2787. idxValues = lpSqlNodeValues->node.values.Next;
  2788. /* If this value is NULL, go on to the next one */
  2789. if (lpSqlNodeRight->sqlIsNull)
  2790. continue;
  2791. /* Compare this value to the test value */
  2792. err = ValueCompare(lpSqlNode, lpSqlNodeLeft, OP_EQ,
  2793. lpSqlNodeRight);
  2794. if (err != ERR_SUCCESS)
  2795. return err;
  2796. /* If value was found, leave */
  2797. if (lpSqlNode->value.Double == TRUE)
  2798. break;
  2799. }
  2800. /* If NOT IN operator, negate the answer */
  2801. if (lpSqlNode->node.comparison.Operator == OP_NOTIN) {
  2802. if (lpSqlNode->value.Double == TRUE)
  2803. lpSqlNode->value.Double = FALSE;
  2804. else
  2805. lpSqlNode->value.Double = TRUE;
  2806. }
  2807. }
  2808. break;
  2809. case NODE_TYPE_ALGEBRAIC:
  2810. /* Set up return buffer */
  2811. switch (lpSqlNode->sqlDataType) {
  2812. case TYPE_NUMERIC:
  2813. lpSqlNode->value.String =
  2814. ToString(lpSql,lpSqlNode->node.algebraic.Value);
  2815. break;
  2816. case TYPE_CHAR:
  2817. lpSqlNode->value.String =
  2818. ToString(lpSql,lpSqlNode->node.algebraic.Value);
  2819. break;
  2820. case TYPE_DOUBLE:
  2821. case TYPE_INTEGER:
  2822. case TYPE_DATE:
  2823. case TYPE_TIME:
  2824. case TYPE_TIMESTAMP:
  2825. break;
  2826. case TYPE_BINARY:
  2827. return ERR_INTERNAL;
  2828. default:
  2829. return ERR_NOTSUPPORTED;
  2830. }
  2831. /* Is this value in the sort DISTINCT record? */
  2832. lpSqlNodeSelect = ToNode(lpSql,
  2833. lpSqlNode->node.algebraic.EnclosingStatement);
  2834. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT)
  2835. fReturningDistinct = FALSE;
  2836. else
  2837. fReturningDistinct = lpSqlNodeSelect->node.select.ReturningDistinct;
  2838. if (!fReturningDistinct) {
  2839. /* No. Evaluate the left child */
  2840. lpSqlNodeLeft = ToNode(lpSql, lpSqlNode->node.algebraic.Left);
  2841. err = EvaluateExpression(lpstmt, lpSqlNodeLeft);
  2842. if (err != ERR_SUCCESS)
  2843. return err;
  2844. /* If left child is NULL, the expression is null */
  2845. if (lpSqlNodeLeft->sqlIsNull) {
  2846. lpSqlNode->sqlIsNull = TRUE;
  2847. break;
  2848. }
  2849. /* Evaluate the right child (if any) */
  2850. if (lpSqlNode->node.algebraic.Right != NO_SQLNODE) {
  2851. lpSqlNodeRight = ToNode(lpSql, lpSqlNode->node.algebraic.Right);
  2852. err = EvaluateExpression(lpstmt, lpSqlNodeRight);
  2853. if (err != ERR_SUCCESS)
  2854. return err;
  2855. /* If right child is NULL, the expression is null */
  2856. if (lpSqlNodeRight->sqlIsNull) {
  2857. lpSqlNode->sqlIsNull = TRUE;
  2858. break;
  2859. }
  2860. }
  2861. else
  2862. lpSqlNodeRight = NULL;
  2863. /* Result is not null */
  2864. lpSqlNode->sqlIsNull = FALSE;
  2865. /* Perform the operation */
  2866. lpWorkBuffer1 = NULL;
  2867. lpWorkBuffer2 = NULL;
  2868. lpWorkBuffer3 = NULL;
  2869. switch (lpSqlNode->sqlDataType) {
  2870. case TYPE_DOUBLE:
  2871. case TYPE_INTEGER:
  2872. case TYPE_DATE:
  2873. case TYPE_TIME:
  2874. case TYPE_TIMESTAMP:
  2875. break;
  2876. case TYPE_NUMERIC:
  2877. if ((lpSqlNode->node.algebraic.Operator == OP_TIMES) ||
  2878. (lpSqlNode->node.algebraic.Operator == OP_DIVIDEDBY)) {
  2879. lpWorkBuffer1 =
  2880. ToString(lpSql,lpSqlNode->node.algebraic.WorkBuffer1);
  2881. if (lpSqlNode->node.algebraic.Operator == OP_DIVIDEDBY) {
  2882. lpWorkBuffer2 =
  2883. ToString(lpSql,lpSqlNode->node.algebraic.WorkBuffer2);
  2884. lpWorkBuffer3 =
  2885. ToString(lpSql,lpSqlNode->node.algebraic.WorkBuffer3);
  2886. }
  2887. }
  2888. break;
  2889. case TYPE_CHAR:
  2890. break;
  2891. case TYPE_BINARY:
  2892. return ERR_INTERNAL;
  2893. default:
  2894. return ERR_NOTSUPPORTED;
  2895. }
  2896. err = NumericAlgebra(lpSqlNode, lpSqlNodeLeft,
  2897. lpSqlNode->node.algebraic.Operator, lpSqlNodeRight,
  2898. lpWorkBuffer1, lpWorkBuffer2, lpWorkBuffer3);
  2899. if (err != ERR_SUCCESS)
  2900. return err;
  2901. }
  2902. else {
  2903. /* Yes. Get the record */
  2904. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  2905. lpSqlNode->node.algebraic.DistinctOffset,
  2906. lpSqlNode->node.algebraic.DistinctLength);
  2907. if (err != ERR_SUCCESS)
  2908. return err;
  2909. }
  2910. break;
  2911. case NODE_TYPE_SCALAR:
  2912. /* Set up return buffer */
  2913. switch (lpSqlNode->sqlDataType) {
  2914. case TYPE_NUMERIC:
  2915. lpSqlNode->value.String =
  2916. ToString(lpSql,lpSqlNode->node.scalar.Value);
  2917. break;
  2918. case TYPE_CHAR:
  2919. lpSqlNode->value.String =
  2920. ToString(lpSql,lpSqlNode->node.scalar.Value);
  2921. break;
  2922. case TYPE_DOUBLE:
  2923. case TYPE_INTEGER:
  2924. case TYPE_DATE:
  2925. case TYPE_TIME:
  2926. case TYPE_TIMESTAMP:
  2927. break;
  2928. case TYPE_BINARY:
  2929. lpSqlNode->value.String =
  2930. ToString(lpSql,lpSqlNode->node.scalar.Value);
  2931. break;
  2932. default:
  2933. return ERR_NOTSUPPORTED;
  2934. }
  2935. /* Is this value in the sort DISTINCT record? */
  2936. lpSqlNodeSelect = ToNode(lpSql,
  2937. lpSqlNode->node.scalar.EnclosingStatement);
  2938. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT)
  2939. fReturningDistinct = FALSE;
  2940. else
  2941. fReturningDistinct = lpSqlNodeSelect->node.select.ReturningDistinct;
  2942. if (!fReturningDistinct) {
  2943. /* Perform the operation */
  2944. err = EvaluateScalar(lpstmt, lpSqlNode);
  2945. if (err != ERR_SUCCESS)
  2946. return err;
  2947. }
  2948. else {
  2949. /* Yes. Get the record */
  2950. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  2951. lpSqlNode->node.scalar.DistinctOffset,
  2952. lpSqlNode->node.scalar.DistinctLength);
  2953. if (err != ERR_SUCCESS)
  2954. return err;
  2955. }
  2956. break;
  2957. case NODE_TYPE_AGGREGATE:
  2958. /* Set up return buffer */
  2959. switch (lpSqlNode->sqlDataType) {
  2960. case TYPE_NUMERIC:
  2961. lpSqlNode->value.String =
  2962. ToString(lpSql,lpSqlNode->node.aggregate.Value);
  2963. break;
  2964. case TYPE_CHAR:
  2965. lpSqlNode->value.String =
  2966. ToString(lpSql,lpSqlNode->node.aggregate.Value);
  2967. break;
  2968. case TYPE_DOUBLE:
  2969. case TYPE_INTEGER:
  2970. case TYPE_DATE:
  2971. case TYPE_TIME:
  2972. case TYPE_TIMESTAMP:
  2973. break;
  2974. case TYPE_BINARY:
  2975. return ERR_INTERNAL;
  2976. default:
  2977. return ERR_NOTSUPPORTED;
  2978. }
  2979. /* Retrieve the value */
  2980. lpSqlNodeSelect = ToNode(lpSql,
  2981. lpSqlNode->node.aggregate.EnclosingStatement);
  2982. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT)
  2983. fReturningDistinct = FALSE;
  2984. else
  2985. fReturningDistinct = lpSqlNodeSelect->node.select.ReturningDistinct;
  2986. if (fReturningDistinct) {
  2987. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  2988. lpSqlNode->node.aggregate.DistinctOffset,
  2989. lpSqlNode->node.aggregate.DistinctLength);
  2990. }
  2991. else {
  2992. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  2993. lpSqlNode->node.aggregate.Offset,
  2994. lpSqlNode->node.aggregate.Length);
  2995. }
  2996. if (err != ERR_SUCCESS)
  2997. return err;
  2998. break;
  2999. case NODE_TYPE_COLUMN:
  3000. /* Set up return buffer */
  3001. switch (lpSqlNode->sqlDataType) {
  3002. case TYPE_NUMERIC:
  3003. lpSqlNode->value.String = ToString(lpSql,lpSqlNode->node.column.Value);
  3004. break;
  3005. case TYPE_CHAR:
  3006. lpSqlNode->value.String = ToString(lpSql,lpSqlNode->node.column.Value);
  3007. break;
  3008. case TYPE_DOUBLE:
  3009. case TYPE_INTEGER:
  3010. case TYPE_DATE:
  3011. case TYPE_TIME:
  3012. case TYPE_TIMESTAMP:
  3013. break;
  3014. case TYPE_BINARY:
  3015. lpSqlNode->value.Binary = ToString(lpSql,lpSqlNode->node.column.Value);
  3016. break;
  3017. default:
  3018. return ERR_NOTSUPPORTED;
  3019. }
  3020. /* Is this column in the sort DISTINCT record? */
  3021. lpSqlNodeSelect = ToNode(lpSql,
  3022. lpSqlNode->node.column.EnclosingStatement);
  3023. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT)
  3024. fReturningDistinct = FALSE;
  3025. else
  3026. fReturningDistinct = lpSqlNodeSelect->node.select.ReturningDistinct;
  3027. if (fReturningDistinct) {
  3028. /* Yes. Retrieve the value */
  3029. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  3030. lpSqlNode->node.column.DistinctOffset,
  3031. lpSqlNode->node.column.DistinctLength);
  3032. if (err != ERR_SUCCESS)
  3033. return err;
  3034. }
  3035. /* Is this column in the sort record? */
  3036. else if (!(lpSqlNode->node.column.InSortRecord)) {
  3037. SDWORD size;
  3038. LPSQLNODE lpSqlNodeTable;
  3039. /* No. Get the column value from the current record */
  3040. lpSqlNodeTable = ToNode(lpSql, lpSqlNode->node.column.Table);
  3041. if (!(lpSqlNodeTable->node.table.AllNull)) {
  3042. switch (lpSqlNode->sqlDataType) {
  3043. case TYPE_DOUBLE:
  3044. case TYPE_INTEGER:
  3045. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3046. lpSqlNode->node.column.Id, 0, SQL_C_DOUBLE,
  3047. &(lpSqlNode->value.Double), sizeof(double),
  3048. &size);
  3049. if (err != NO_ISAM_ERR) {
  3050. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3051. (LPUSTR)lpstmt->szISAMError);
  3052. return err;
  3053. }
  3054. lpstmt->fISAMTxnStarted = TRUE;
  3055. if (size == SQL_NULL_DATA)
  3056. lpSqlNode->sqlIsNull = TRUE;
  3057. else
  3058. lpSqlNode->sqlIsNull = FALSE;
  3059. break;
  3060. case TYPE_NUMERIC:
  3061. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3062. lpSqlNode->node.column.Id, 0, SQL_C_CHAR,
  3063. lpSqlNode->value.String,
  3064. (SDWORD) (1 + 2 + lpSqlNode->sqlPrecision),
  3065. &size);
  3066. if (err != NO_ISAM_ERR) {
  3067. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3068. (LPUSTR)lpstmt->szISAMError);
  3069. return err;
  3070. }
  3071. lpstmt->fISAMTxnStarted = TRUE;
  3072. if (size == SQL_NULL_DATA)
  3073. lpSqlNode->sqlIsNull = TRUE;
  3074. else {
  3075. lpSqlNode->sqlIsNull = FALSE;
  3076. BCDNormalize(lpSqlNode->value.String,
  3077. s_lstrlen(lpSqlNode->value.String),
  3078. lpSqlNode->value.String,
  3079. lpSqlNode->sqlPrecision + 2 + 1,
  3080. lpSqlNode->sqlPrecision,
  3081. lpSqlNode->sqlScale);
  3082. }
  3083. break;
  3084. case TYPE_CHAR:
  3085. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3086. lpSqlNode->node.column.Id, 0, SQL_C_CHAR,
  3087. lpSqlNode->value.String,
  3088. (SDWORD) (1 + lpSqlNode->sqlPrecision),
  3089. &size);
  3090. if (err != NO_ISAM_ERR) {
  3091. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3092. (LPUSTR)lpstmt->szISAMError);
  3093. return err;
  3094. }
  3095. lpstmt->fISAMTxnStarted = TRUE;
  3096. if (size == SQL_NULL_DATA)
  3097. lpSqlNode->sqlIsNull = TRUE;
  3098. else
  3099. lpSqlNode->sqlIsNull = FALSE;
  3100. break;
  3101. case TYPE_DATE:
  3102. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3103. lpSqlNode->node.column.Id, 0, SQL_C_DATE,
  3104. &(lpSqlNode->value.Date), sizeof(DATE_STRUCT),
  3105. &size);
  3106. if (err != NO_ISAM_ERR) {
  3107. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3108. (LPUSTR)lpstmt->szISAMError);
  3109. return err;
  3110. }
  3111. lpstmt->fISAMTxnStarted = TRUE;
  3112. if (size == SQL_NULL_DATA)
  3113. lpSqlNode->sqlIsNull = TRUE;
  3114. else
  3115. lpSqlNode->sqlIsNull = FALSE;
  3116. break;
  3117. case TYPE_TIME:
  3118. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3119. lpSqlNode->node.column.Id, 0, SQL_C_TIME,
  3120. &(lpSqlNode->value.Time), sizeof(TIME_STRUCT),
  3121. &size);
  3122. if (err != NO_ISAM_ERR) {
  3123. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3124. (LPUSTR)lpstmt->szISAMError);
  3125. return err;
  3126. }
  3127. lpstmt->fISAMTxnStarted = TRUE;
  3128. if (size == SQL_NULL_DATA)
  3129. lpSqlNode->sqlIsNull = TRUE;
  3130. else
  3131. lpSqlNode->sqlIsNull = FALSE;
  3132. break;
  3133. case TYPE_TIMESTAMP:
  3134. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3135. lpSqlNode->node.column.Id, 0, SQL_C_TIMESTAMP,
  3136. &(lpSqlNode->value.Timestamp), sizeof(TIMESTAMP_STRUCT),
  3137. &size);
  3138. if (err != NO_ISAM_ERR) {
  3139. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3140. (LPUSTR)lpstmt->szISAMError);
  3141. return err;
  3142. }
  3143. lpstmt->fISAMTxnStarted = TRUE;
  3144. if (size == SQL_NULL_DATA)
  3145. lpSqlNode->sqlIsNull = TRUE;
  3146. else
  3147. lpSqlNode->sqlIsNull = FALSE;
  3148. break;
  3149. case TYPE_BINARY:
  3150. err = ISAMGetData(lpSqlNodeTable->node.table.Handle,
  3151. lpSqlNode->node.column.Id, 0, SQL_C_BINARY,
  3152. BINARY_DATA(lpSqlNode->value.Binary),
  3153. (SDWORD) lpSqlNode->sqlPrecision,
  3154. &size);
  3155. if (err != NO_ISAM_ERR) {
  3156. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3157. (LPUSTR)lpstmt->szISAMError);
  3158. return err;
  3159. }
  3160. lpstmt->fISAMTxnStarted = TRUE;
  3161. if (size == SQL_NULL_DATA) {
  3162. lpSqlNode->sqlIsNull = TRUE;
  3163. BINARY_LENGTH(lpSqlNode->value.Binary) = 0;
  3164. }
  3165. else {
  3166. lpSqlNode->sqlIsNull = FALSE;
  3167. BINARY_LENGTH(lpSqlNode->value.Binary) = size;
  3168. }
  3169. break;
  3170. default:
  3171. err = ERR_NOTSUPPORTED;
  3172. break;
  3173. }
  3174. }
  3175. else {
  3176. err = NO_ISAM_ERR;
  3177. lpSqlNode->sqlIsNull = TRUE;
  3178. switch (lpSqlNode->sqlDataType) {
  3179. case TYPE_DOUBLE:
  3180. case TYPE_INTEGER:
  3181. lpSqlNode->value.Double = 0.0;
  3182. break;
  3183. case TYPE_NUMERIC:
  3184. s_lstrcpy(lpSqlNode->value.String, "");
  3185. break;
  3186. case TYPE_CHAR:
  3187. s_lstrcpy(lpSqlNode->value.String, "");
  3188. break;
  3189. case TYPE_DATE:
  3190. lpSqlNode->value.Date.year = 0;
  3191. lpSqlNode->value.Date.month = 0;
  3192. lpSqlNode->value.Date.day = 0;
  3193. break;
  3194. case TYPE_TIME:
  3195. lpSqlNode->value.Time.hour = 0;
  3196. lpSqlNode->value.Time.minute = 0;
  3197. lpSqlNode->value.Time.second = 0;
  3198. break;
  3199. case TYPE_TIMESTAMP:
  3200. lpSqlNode->value.Timestamp.year = 0;
  3201. lpSqlNode->value.Timestamp.month = 0;
  3202. lpSqlNode->value.Timestamp.day = 0;
  3203. lpSqlNode->value.Timestamp.hour = 0;
  3204. lpSqlNode->value.Timestamp.minute = 0;
  3205. lpSqlNode->value.Timestamp.second = 0;
  3206. lpSqlNode->value.Timestamp.fraction = 0;
  3207. break;
  3208. case TYPE_BINARY:
  3209. BINARY_LENGTH(lpSqlNode->value.Binary) = 0;
  3210. break;
  3211. default:
  3212. err = ERR_NOTSUPPORTED;
  3213. break;
  3214. }
  3215. }
  3216. }
  3217. else {
  3218. /* Yes. Retrieve the value */
  3219. err = RetrieveSortRecordValue(lpSqlNodeSelect, lpSqlNode,
  3220. lpSqlNode->node.column.Offset,
  3221. lpSqlNode->node.column.Length);
  3222. if (err != ERR_SUCCESS)
  3223. return err;
  3224. }
  3225. break;
  3226. case NODE_TYPE_STRING:
  3227. lpSqlNode->sqlIsNull = FALSE;
  3228. lpSqlNode->value.String = ToString(lpSql, lpSqlNode->node.string.Value);
  3229. break;
  3230. case NODE_TYPE_NUMERIC:
  3231. lpSqlNode->sqlIsNull = FALSE;
  3232. switch(lpSqlNode->sqlDataType) {
  3233. case TYPE_NUMERIC:
  3234. lpSqlNode->value.String =
  3235. ToString(lpSql, lpSqlNode->node.numeric.Numeric);
  3236. break;
  3237. case TYPE_DOUBLE:
  3238. case TYPE_INTEGER:
  3239. lpSqlNode->value.Double = lpSqlNode->node.numeric.Value;
  3240. break;
  3241. case TYPE_CHAR:
  3242. case TYPE_DATE:
  3243. case TYPE_TIME:
  3244. case TYPE_TIMESTAMP:
  3245. case TYPE_BINARY:
  3246. default:
  3247. return ERR_INTERNAL;
  3248. }
  3249. break;
  3250. case NODE_TYPE_PARAMETER:
  3251. break;
  3252. case NODE_TYPE_USER:
  3253. lpSqlNode->sqlIsNull = FALSE;
  3254. lpSqlNode->value.String =
  3255. (LPUSTR) ISAMUser(ToNode(lpSql, ROOT_SQLNODE)->node.root.lpISAM);
  3256. break;
  3257. case NODE_TYPE_NULL:
  3258. lpSqlNode->sqlIsNull = TRUE;
  3259. break;
  3260. case NODE_TYPE_DATE:
  3261. lpSqlNode->sqlIsNull = FALSE;
  3262. lpSqlNode->value.Date = lpSqlNode->node.date.Value;
  3263. break;
  3264. case NODE_TYPE_TIME:
  3265. lpSqlNode->sqlIsNull = FALSE;
  3266. lpSqlNode->value.Time = lpSqlNode->node.time.Value;
  3267. break;
  3268. case NODE_TYPE_TIMESTAMP:
  3269. lpSqlNode->sqlIsNull = FALSE;
  3270. lpSqlNode->value.Timestamp = lpSqlNode->node.timestamp.Value;
  3271. break;
  3272. default:
  3273. return ERR_INTERNAL;
  3274. }
  3275. return err;
  3276. }
  3277. /***************************************************************************/
  3278. RETCODE INTFUNC Sort(LPSTMT lpstmt, LPSQLNODE lpSqlNodeSelect)
  3279. /* Sorts results of a SELECT statement */
  3280. {
  3281. // ODBCTRACE("\nWBEM ODBC Driver : Sort\n");
  3282. #ifdef WIN32
  3283. UCHAR szTempDir[MAX_PATHNAME_SIZE+1];
  3284. szTempDir[0] = 0;
  3285. #endif
  3286. UCHAR szFilename[MAX_PATHNAME_SIZE+1];
  3287. szFilename[0] = 0;
  3288. HFILE_BUFFER hfSortfile;
  3289. HFILE hfSortfile2;
  3290. LPSQLNODE lpSqlNodeTables;
  3291. LPSQLNODE lpSqlNodePredicate;
  3292. RETCODE err;
  3293. SQLNODEIDX idxSortcolumns;
  3294. LPSQLNODE lpSqlNodeSortcolumns;
  3295. SQLNODEIDX idxGroupbycolumns;
  3296. LPSQLNODE lpSqlNodeGroupbycolumns;
  3297. LPSQLNODE lpSqlNodeColumn;
  3298. SDWORD len;
  3299. PTR ptr;
  3300. SQLNODEIDX idxTableList;
  3301. LPSQLNODE lpSqlNodeTableList;
  3302. LPSQLNODE lpSqlNodeTable;
  3303. ISAMBOOKMARK bookmark;
  3304. UCHAR szBuffer[20+TIMESTAMP_SCALE+1];
  3305. long recordCount;
  3306. int sortStatus;
  3307. UCHAR cNullFlag;
  3308. SQLNODEIDX idxAggregate;
  3309. LPSQLNODE lpSqlNodeAggregate;
  3310. LPSQLNODE lpSqlNodeExpression;
  3311. double dbl;
  3312. szBuffer[0] = 0;
  3313. /* Create temporary file */
  3314. #ifdef WIN32
  3315. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR)szTempDir))
  3316. return ERR_SORT;
  3317. if (!GetTempFileName((LPSTR)szTempDir, "LEM", 0, (LPSTR)szFilename))
  3318. return ERR_SORT;
  3319. #else
  3320. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename);
  3321. #endif
  3322. hfSortfile = _lcreat_buffer((LPCSTR) szFilename, 0);
  3323. if (hfSortfile == NULL)
  3324. return ERR_SORT;
  3325. /* Get the table list and predicate node. */
  3326. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt,
  3327. lpSqlNodeSelect->node.select.Tables);
  3328. if (lpSqlNodeSelect->node.select.Predicate == NO_SQLNODE)
  3329. lpSqlNodePredicate = NULL;
  3330. else
  3331. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt,
  3332. lpSqlNodeSelect->node.select.Predicate);
  3333. /* For each record of result set... */
  3334. lpSqlNodeSelect->node.select.RowCount = 0;
  3335. while (TRUE) {
  3336. /* Get the next record */
  3337. err = NextRecord(lpstmt, lpSqlNodeTables,
  3338. lpSqlNodePredicate);
  3339. if (err == ERR_NODATAFOUND) {
  3340. if (lpSqlNodeSelect->node.select.CurrentRow == BEFORE_FIRST_ROW) {
  3341. _lclose_buffer(hfSortfile);
  3342. DeleteFile((LPCSTR) szFilename);
  3343. lpSqlNodeSelect->node.select.CurrentRow = AFTER_LAST_ROW;
  3344. return ERR_SUCCESS;
  3345. }
  3346. break;
  3347. }
  3348. else if (err != ERR_SUCCESS) {
  3349. _lclose_buffer(hfSortfile);
  3350. DeleteFile((LPCSTR) szFilename);
  3351. return err;
  3352. }
  3353. /* Set row flag */
  3354. if (lpSqlNodeSelect->node.select.CurrentRow == BEFORE_FIRST_ROW)
  3355. lpSqlNodeSelect->node.select.CurrentRow = 0;
  3356. else
  3357. lpSqlNodeSelect->node.select.CurrentRow++;
  3358. /* Increase row count */
  3359. (lpSqlNodeSelect->node.select.RowCount)++;
  3360. /* If there is a GROUP BY, puts the columns in the sort file in */
  3361. /* the order specified by the GROUP BY list. Otherwise put the */
  3362. /* the column in the sort file in the order specified by the */
  3363. /* ORDER BY list. For each sort key value or group by value... */
  3364. if (lpSqlNodeSelect->node.select.ImplicitGroupby) {
  3365. idxGroupbycolumns = NO_SQLNODE;
  3366. idxSortcolumns = NO_SQLNODE;
  3367. }
  3368. else {
  3369. idxGroupbycolumns = lpSqlNodeSelect->node.select.Groupbycolumns;
  3370. if (idxGroupbycolumns == NO_SQLNODE)
  3371. idxSortcolumns = lpSqlNodeSelect->node.select.Sortcolumns;
  3372. else
  3373. idxSortcolumns = NO_SQLNODE;
  3374. }
  3375. while ((idxSortcolumns != NO_SQLNODE) ||
  3376. (idxGroupbycolumns != NO_SQLNODE)) {
  3377. /* Get next column */
  3378. if (idxGroupbycolumns != NO_SQLNODE) {
  3379. lpSqlNodeGroupbycolumns =
  3380. ToNode(lpstmt->lpSqlStmt, idxGroupbycolumns);
  3381. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt,
  3382. lpSqlNodeGroupbycolumns->node.groupbycolumns.Column);
  3383. }
  3384. else {
  3385. lpSqlNodeSortcolumns =
  3386. ToNode(lpstmt->lpSqlStmt, idxSortcolumns);
  3387. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt,
  3388. lpSqlNodeSortcolumns->node.sortcolumns.Column);
  3389. }
  3390. /* Get its value */
  3391. err = EvaluateExpression(lpstmt, lpSqlNodeColumn);
  3392. if (err != ERR_SUCCESS) {
  3393. _lclose_buffer(hfSortfile);
  3394. DeleteFile((LPCSTR) szFilename);
  3395. return err;
  3396. }
  3397. /* Get length and pointer to key value */
  3398. switch (lpSqlNodeColumn->sqlDataType) {
  3399. case TYPE_DOUBLE:
  3400. case TYPE_INTEGER:
  3401. if (lpSqlNodeColumn->sqlIsNull)
  3402. lpSqlNodeColumn->value.Double = -1.7E308; //RAID 27433
  3403. len = sizeof(double);
  3404. ptr = &(lpSqlNodeColumn->value.Double);
  3405. break;
  3406. case TYPE_NUMERIC:
  3407. if (lpSqlNodeColumn->sqlIsNull)
  3408. (lpSqlNodeColumn->value.String)[0] = 0;
  3409. len = lpSqlNodeColumn->sqlPrecision + 2;
  3410. ptr = lpSqlNodeColumn->value.String;
  3411. /* (blank pad string values) */
  3412. while (s_lstrlen(lpSqlNodeColumn->value.String) < len)
  3413. s_lstrcat(lpSqlNodeColumn->value.String, " ");
  3414. break;
  3415. case TYPE_CHAR:
  3416. if (lpSqlNodeColumn->sqlIsNull)
  3417. (lpSqlNodeColumn->value.String)[0] = 0;
  3418. len = lpSqlNodeColumn->sqlPrecision;
  3419. ptr = lpSqlNodeColumn->value.String;
  3420. /* (blank pad string values) */
  3421. while (s_lstrlen(lpSqlNodeColumn->value.String) < len)
  3422. s_lstrcat(lpSqlNodeColumn->value.String, " ");
  3423. break;
  3424. case TYPE_BINARY:
  3425. if (lpSqlNodeColumn->sqlIsNull)
  3426. BINARY_LENGTH(lpSqlNodeColumn->value.Binary) = 0;
  3427. len = lpSqlNodeColumn->sqlPrecision;
  3428. ptr = BINARY_DATA(lpSqlNodeColumn->value.Binary);
  3429. /* (zero pad binary values) */
  3430. while (BINARY_LENGTH(lpSqlNodeColumn->value.Binary) < len) {
  3431. BINARY_DATA(lpSqlNodeColumn->value.Binary)[
  3432. BINARY_LENGTH(lpSqlNodeColumn->value.Binary)] = 0;
  3433. BINARY_LENGTH(lpSqlNodeColumn->value.Binary) =
  3434. BINARY_LENGTH(lpSqlNodeColumn->value.Binary) + 1;
  3435. }
  3436. break;
  3437. case TYPE_DATE:
  3438. if (lpSqlNodeColumn->sqlIsNull) {
  3439. lpSqlNodeColumn->value.Date.year = 0;
  3440. lpSqlNodeColumn->value.Date.month = 0;
  3441. lpSqlNodeColumn->value.Date.day = 0;
  3442. }
  3443. DateToChar(&(lpSqlNodeColumn->value.Date), (LPUSTR)szBuffer);
  3444. len = s_lstrlen((char*)szBuffer);
  3445. ptr = szBuffer;
  3446. break;
  3447. case TYPE_TIME:
  3448. if (lpSqlNodeColumn->sqlIsNull) {
  3449. lpSqlNodeColumn->value.Time.hour = 0;
  3450. lpSqlNodeColumn->value.Time.minute = 0;
  3451. lpSqlNodeColumn->value.Time.second = 0;
  3452. }
  3453. TimeToChar(&(lpSqlNodeColumn->value.Time), (LPUSTR)szBuffer);
  3454. len = s_lstrlen((char*)szBuffer);
  3455. ptr = szBuffer;
  3456. break;
  3457. case TYPE_TIMESTAMP:
  3458. if (lpSqlNodeColumn->sqlIsNull) {
  3459. lpSqlNodeColumn->value.Timestamp.year = 0;
  3460. lpSqlNodeColumn->value.Timestamp.month = 0;
  3461. lpSqlNodeColumn->value.Timestamp.day = 0;
  3462. lpSqlNodeColumn->value.Timestamp.hour = 0;
  3463. lpSqlNodeColumn->value.Timestamp.minute = 0;
  3464. lpSqlNodeColumn->value.Timestamp.second = 0;
  3465. lpSqlNodeColumn->value.Timestamp.fraction = 0;
  3466. }
  3467. TimestampToChar(&(lpSqlNodeColumn->value.Timestamp), (LPUSTR)szBuffer);
  3468. len = s_lstrlen((char*)szBuffer);
  3469. ptr = szBuffer;
  3470. break;
  3471. default:
  3472. _lclose_buffer(hfSortfile);
  3473. DeleteFile((LPCSTR) szFilename);
  3474. return ERR_INTERNAL;
  3475. }
  3476. /* Put value into the file */
  3477. if (_lwrite_buffer(hfSortfile, (LPSTR) ptr, (UINT) len) != (UINT) len) {
  3478. _lclose_buffer(hfSortfile);
  3479. DeleteFile((LPCSTR) szFilename);
  3480. return ERR_SORT;
  3481. }
  3482. /* Put inthe null flag */
  3483. if (lpSqlNodeColumn->sqlIsNull)
  3484. cNullFlag = NULL_FLAG;
  3485. else
  3486. cNullFlag = NOT_NULL_FLAG;
  3487. if (_lwrite_buffer(hfSortfile, (LPSTR) &cNullFlag, 1) != 1) {
  3488. _lclose_buffer(hfSortfile);
  3489. DeleteFile((LPCSTR) szFilename);
  3490. return ERR_SORT;
  3491. }
  3492. /* Point at next key value */
  3493. if (idxGroupbycolumns != NO_SQLNODE)
  3494. idxGroupbycolumns =
  3495. lpSqlNodeGroupbycolumns->node.groupbycolumns.Next;
  3496. else
  3497. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  3498. }
  3499. /* Put the AGG function values into the record */
  3500. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3501. while (idxAggregate != NO_SQLNODE) {
  3502. /* Get next aggregate */
  3503. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  3504. /* Get its value */
  3505. if (lpSqlNodeAggregate->node.aggregate.Operator != AGG_COUNT) {
  3506. lpSqlNodeExpression = ToNode(lpstmt->lpSqlStmt,
  3507. lpSqlNodeAggregate->node.aggregate.Expression);
  3508. err = EvaluateExpression(lpstmt, lpSqlNodeExpression);
  3509. if (err != ERR_SUCCESS) {
  3510. _lclose_buffer(hfSortfile);
  3511. DeleteFile((LPCSTR) szFilename);
  3512. return err;
  3513. }
  3514. }
  3515. /* Get length and pointer to key value */
  3516. switch (lpSqlNodeAggregate->sqlDataType) {
  3517. case TYPE_DOUBLE:
  3518. case TYPE_INTEGER:
  3519. if (lpSqlNodeAggregate->node.aggregate.Operator != AGG_COUNT) {
  3520. if (lpSqlNodeExpression->sqlDataType != TYPE_NUMERIC) {
  3521. if (lpSqlNodeExpression->sqlIsNull)
  3522. lpSqlNodeExpression->value.Double = 0.0;
  3523. len = sizeof(double);
  3524. ptr = &(lpSqlNodeExpression->value.Double);
  3525. }
  3526. else {
  3527. CharToDouble(lpSqlNodeExpression->value.String,
  3528. s_lstrlen(lpSqlNodeExpression->value.String),
  3529. FALSE, -1.7E308, 1.7E308, &dbl);
  3530. len = sizeof(double);
  3531. ptr = &dbl;
  3532. }
  3533. }
  3534. else {
  3535. lpSqlNodeAggregate->value.Double = 1.0;
  3536. len = sizeof(double);
  3537. ptr = &(lpSqlNodeAggregate->value.Double);
  3538. }
  3539. break;
  3540. case TYPE_NUMERIC:
  3541. if (lpSqlNodeExpression->sqlIsNull)
  3542. (lpSqlNodeExpression->value.String)[0] = 0;
  3543. len = lpSqlNodeAggregate->node.aggregate.Length;
  3544. ptr = lpSqlNodeExpression->value.String;
  3545. /* (blank pad string values) */
  3546. while (s_lstrlen(lpSqlNodeExpression->value.String) < len)
  3547. s_lstrcat(lpSqlNodeExpression->value.String, " ");
  3548. break;
  3549. case TYPE_CHAR:
  3550. if (lpSqlNodeExpression->sqlIsNull)
  3551. (lpSqlNodeExpression->value.String)[0] = 0;
  3552. len = lpSqlNodeAggregate->node.aggregate.Length;
  3553. ptr = lpSqlNodeExpression->value.String;
  3554. /* (blank pad string values) */
  3555. while (s_lstrlen(lpSqlNodeExpression->value.String) < len)
  3556. s_lstrcat(lpSqlNodeExpression->value.String, " ");
  3557. break;
  3558. case TYPE_BINARY:
  3559. _lclose_buffer(hfSortfile);
  3560. DeleteFile((LPCSTR) szFilename);
  3561. return ERR_INTERNAL;
  3562. case TYPE_DATE:
  3563. if (lpSqlNodeExpression->sqlIsNull) {
  3564. lpSqlNodeExpression->value.Date.year = 0;
  3565. lpSqlNodeExpression->value.Date.month = 0;
  3566. lpSqlNodeExpression->value.Date.day = 0;
  3567. }
  3568. DateToChar(&(lpSqlNodeExpression->value.Date), (LPUSTR)szBuffer);
  3569. len = s_lstrlen((char*)szBuffer);
  3570. ptr = szBuffer;
  3571. break;
  3572. case TYPE_TIME:
  3573. if (lpSqlNodeExpression->sqlIsNull) {
  3574. lpSqlNodeExpression->value.Time.hour = 0;
  3575. lpSqlNodeExpression->value.Time.minute = 0;
  3576. lpSqlNodeExpression->value.Time.second = 0;
  3577. }
  3578. TimeToChar(&(lpSqlNodeExpression->value.Time), (LPUSTR)szBuffer);
  3579. len = s_lstrlen((char*)szBuffer);
  3580. ptr = szBuffer;
  3581. break;
  3582. case TYPE_TIMESTAMP:
  3583. if (lpSqlNodeExpression->sqlIsNull) {
  3584. lpSqlNodeExpression->value.Timestamp.year = 0;
  3585. lpSqlNodeExpression->value.Timestamp.month = 0;
  3586. lpSqlNodeExpression->value.Timestamp.day = 0;
  3587. lpSqlNodeExpression->value.Timestamp.hour = 0;
  3588. lpSqlNodeExpression->value.Timestamp.minute = 0;
  3589. lpSqlNodeExpression->value.Timestamp.second = 0;
  3590. lpSqlNodeExpression->value.Timestamp.fraction = 0;
  3591. }
  3592. TimestampToChar(&(lpSqlNodeExpression->value.Timestamp), (LPUSTR)szBuffer);
  3593. len = s_lstrlen((char*)szBuffer);
  3594. ptr = szBuffer;
  3595. break;
  3596. default:
  3597. _lclose_buffer(hfSortfile);
  3598. DeleteFile((LPCSTR) szFilename);
  3599. return ERR_INTERNAL;
  3600. }
  3601. /* Put value into the file */
  3602. if (_lwrite_buffer(hfSortfile, (LPSTR) ptr, (UINT) len) != (UINT) len) {
  3603. _lclose_buffer(hfSortfile);
  3604. DeleteFile((LPCSTR) szFilename);
  3605. return ERR_SORT;
  3606. }
  3607. /* Put inthe null flag */
  3608. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_COUNT)
  3609. cNullFlag = NOT_NULL_FLAG;
  3610. else if (lpSqlNodeExpression->sqlIsNull)
  3611. cNullFlag = NULL_FLAG;
  3612. else
  3613. cNullFlag = NOT_NULL_FLAG;
  3614. if (_lwrite_buffer(hfSortfile, (LPSTR) &cNullFlag, 1) != 1) {
  3615. _lclose_buffer(hfSortfile);
  3616. DeleteFile((LPCSTR) szFilename);
  3617. return ERR_SORT;
  3618. }
  3619. /* Point at next value */
  3620. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  3621. }
  3622. /* For each record in table list... */
  3623. if (lpSqlNodeSelect->node.select.ImplicitGroupby)
  3624. idxTableList = NO_SQLNODE;
  3625. else if (lpSqlNodeSelect->node.select.Groupbycolumns == NO_SQLNODE)
  3626. idxTableList = lpSqlNodeSelect->node.select.Tables;
  3627. else
  3628. idxTableList = NO_SQLNODE;
  3629. while (idxTableList != NO_SQLNODE) {
  3630. /* Get table */
  3631. lpSqlNodeTableList = ToNode(lpstmt->lpSqlStmt, idxTableList);
  3632. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  3633. lpSqlNodeTableList->node.tables.Table);
  3634. /* Get bookmark of current record */
  3635. if (lpSqlNodeTable->node.table.AllNull)
  3636. {
  3637. bookmark.currentRecord = NULL_BOOKMARK;
  3638. }
  3639. else
  3640. {
  3641. err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark);
  3642. if (err != ERR_SUCCESS) {
  3643. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  3644. (LPUSTR)lpstmt->szISAMError);
  3645. _lclose_buffer(hfSortfile);
  3646. DeleteFile((LPCSTR) szFilename);
  3647. return err;
  3648. }
  3649. lpstmt->fISAMTxnStarted = TRUE;
  3650. }
  3651. /* Put value into the file */
  3652. if (_lwrite_buffer(hfSortfile, (LPSTR) &bookmark, sizeof(ISAMBOOKMARK))
  3653. != sizeof(ISAMBOOKMARK)) {
  3654. _lclose_buffer(hfSortfile);
  3655. DeleteFile((LPCSTR) szFilename);
  3656. return ERR_SORT;
  3657. }
  3658. /* Point at next table */
  3659. idxTableList = lpSqlNodeTableList->node.tables.Next;
  3660. }
  3661. }
  3662. if (_lclose_buffer(hfSortfile) == HFILE_ERROR) {
  3663. DeleteFile((LPCSTR) szFilename);
  3664. return ERR_SORT;
  3665. }
  3666. /* Sort the file */
  3667. if (!(lpSqlNodeSelect->node.select.ImplicitGroupby)) {
  3668. /* Sort the file */
  3669. s_1mains((LPSTR) szFilename, (LPSTR) szFilename, (LPSTR)
  3670. ToString(lpstmt->lpSqlStmt,
  3671. lpSqlNodeSelect->node.select.SortDirective),
  3672. &recordCount, &sortStatus);
  3673. if (sortStatus != 0) {
  3674. DeleteFile((LPCSTR) szFilename);
  3675. return ERR_SORT;
  3676. }
  3677. lpSqlNodeSelect->node.select.RowCount = recordCount;
  3678. }
  3679. /* Open destination file */
  3680. hfSortfile2 = _lopen((LPCSTR) szFilename, OF_READ);
  3681. if (hfSortfile2 == HFILE_ERROR) {
  3682. DeleteFile((LPCSTR) szFilename);
  3683. return ERR_SORT;
  3684. }
  3685. /* Save name and handle to file of sorted records */
  3686. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  3687. lpSqlNodeSelect->node.select.SortfileName), szFilename);
  3688. lpSqlNodeSelect->node.select.Sortfile = hfSortfile2;
  3689. lpSqlNodeSelect->node.select.ReturningDistinct = FALSE;
  3690. /* Set up to read first row */
  3691. lpSqlNodeSelect->node.select.CurrentRow = BEFORE_FIRST_ROW;
  3692. return ERR_SUCCESS;
  3693. }
  3694. /***************************************************************************/
  3695. RETCODE INTFUNC GroupBy(LPSTMT lpstmt, LPSQLNODE lpSqlNodeSelect)
  3696. /* Does GROUP BY on results of a SELECT statement */
  3697. {
  3698. #ifdef WIN32
  3699. UCHAR szTempDir[MAX_PATHNAME_SIZE+1];
  3700. szTempDir[0] = 0;
  3701. #endif
  3702. UCHAR szFilename[MAX_PATHNAME_SIZE+1];
  3703. szFilename[0] = 0;
  3704. HFILE_BUFFER hfGroupbyfile;
  3705. HFILE hfGroupbyfile2;
  3706. HGLOBAL hGlobal;
  3707. LPUSTR lpResultRecord;
  3708. LPUSTR lpCurrentRecord;
  3709. SDWORD cRowCount;
  3710. SDWORD irow;
  3711. SQLNODEIDX idxAggregate;
  3712. LPSQLNODE lpSqlNodeAggregate;
  3713. LPUSTR lpValue;
  3714. LPUSTR lpValueNullFlag;
  3715. LPUSTR lpAggregateValue;
  3716. LPUSTR lpAggregateValueNullFlag;
  3717. /* If nothing to group, just return */
  3718. if (lpSqlNodeSelect->node.select.RowCount == 0)
  3719. return ERR_SUCCESS;
  3720. /* Create temporary file for the result of the group by */
  3721. #ifdef WIN32
  3722. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR)szTempDir))
  3723. return ERR_GROUPBY;
  3724. if (!GetTempFileName((LPSTR)szTempDir, "LEM", 0, (LPSTR)szFilename))
  3725. return ERR_GROUPBY;
  3726. #else
  3727. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename);
  3728. #endif
  3729. hfGroupbyfile = _lcreat_buffer((LPCSTR) szFilename, 0);
  3730. if (hfGroupbyfile == NULL)
  3731. return ERR_GROUPBY;
  3732. /* Allocate space for a result record buffer */
  3733. hGlobal = GlobalAlloc(GMEM_MOVEABLE,
  3734. (2 * lpSqlNodeSelect->node.select.SortRecordsize));
  3735. if (hGlobal == NULL ||
  3736. (lpResultRecord = (LPUSTR) GlobalLock(hGlobal)) == NULL) {
  3737. if (hGlobal)
  3738. GlobalFree(hGlobal);
  3739. _lclose_buffer(hfGroupbyfile);
  3740. DeleteFile((LPCSTR) szFilename);
  3741. return ERR_MEMALLOCFAIL;
  3742. }
  3743. /* Allocate space for current record key buffer */
  3744. lpCurrentRecord = lpResultRecord + lpSqlNodeSelect->node.select.SortRecordsize;
  3745. /* Position to the first record */
  3746. if (_llseek(lpSqlNodeSelect->node.select.Sortfile, 0, 0) == HFILE_ERROR) {
  3747. GlobalUnlock(hGlobal);
  3748. GlobalFree(hGlobal);
  3749. _lclose_buffer(hfGroupbyfile);
  3750. DeleteFile((LPCSTR) szFilename);
  3751. return ERR_GROUPBY;
  3752. }
  3753. /* Read the first record into the result record buffer */
  3754. if (_lread(lpSqlNodeSelect->node.select.Sortfile, lpResultRecord,
  3755. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) !=
  3756. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) {
  3757. GlobalUnlock(hGlobal);
  3758. GlobalFree(hGlobal);
  3759. _lclose_buffer(hfGroupbyfile);
  3760. DeleteFile((LPCSTR) szFilename);
  3761. return ERR_GROUPBY;
  3762. }
  3763. /* Initialize the count for averages */
  3764. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3765. while (idxAggregate != NO_SQLNODE) {
  3766. /* Get the function */
  3767. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  3768. /* Average operator? */
  3769. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG) {
  3770. /* Yes. Point to the value */
  3771. lpAggregateValue = lpResultRecord +
  3772. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  3773. lpAggregateValueNullFlag = lpAggregateValue +
  3774. lpSqlNodeAggregate->node.aggregate.Length;
  3775. /* If not null, set count to one. Otherwise zero */
  3776. switch (*lpAggregateValueNullFlag) {
  3777. case NULL_FLAG:
  3778. lpSqlNodeAggregate->node.aggregate.Count = 0.0;
  3779. break;
  3780. case NOT_NULL_FLAG:
  3781. lpSqlNodeAggregate->node.aggregate.Count = 1.0;
  3782. break;
  3783. default:
  3784. GlobalUnlock(hGlobal);
  3785. GlobalFree(hGlobal);
  3786. _lclose_buffer(hfGroupbyfile);
  3787. DeleteFile((LPCSTR) szFilename);
  3788. return ERR_GROUPBY;
  3789. }
  3790. }
  3791. /* Do next aggregate */
  3792. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  3793. }
  3794. /* For each record... */
  3795. cRowCount = 0;
  3796. for (irow = 1; irow < lpSqlNodeSelect->node.select.RowCount; irow++) {
  3797. /* Read current record */
  3798. if (_lread(lpSqlNodeSelect->node.select.Sortfile, lpCurrentRecord,
  3799. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) !=
  3800. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) {
  3801. GlobalUnlock(hGlobal);
  3802. GlobalFree(hGlobal);
  3803. _lclose_buffer(hfGroupbyfile);
  3804. DeleteFile((LPCSTR) szFilename);
  3805. return ERR_GROUPBY;
  3806. }
  3807. /* Does group by key match the key in the result record buffer? */
  3808. if (_fmemcmp(lpResultRecord, lpCurrentRecord,
  3809. (size_t) lpSqlNodeSelect->node.select.SortKeysize)) {
  3810. /* No. Calculate averages */
  3811. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3812. while (idxAggregate != NO_SQLNODE) {
  3813. /* Get the function */
  3814. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  3815. /* Average operator? */
  3816. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG) {
  3817. /* Yes. Point to the value */
  3818. lpAggregateValue = lpResultRecord +
  3819. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  3820. lpAggregateValueNullFlag = lpAggregateValue +
  3821. lpSqlNodeAggregate->node.aggregate.Length;
  3822. /* If not null, calculate average */
  3823. if (*lpAggregateValueNullFlag == NOT_NULL_FLAG)
  3824. *((double FAR *) lpAggregateValue) /=
  3825. (lpSqlNodeAggregate->node.aggregate.Count);
  3826. }
  3827. /* Do next aggregate */
  3828. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  3829. }
  3830. /* Write result record buffer to the file */
  3831. if (_lwrite_buffer(hfGroupbyfile, (LPSTR) lpResultRecord,
  3832. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) !=
  3833. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) {
  3834. GlobalUnlock(hGlobal);
  3835. GlobalFree(hGlobal);
  3836. _lclose_buffer(hfGroupbyfile);
  3837. DeleteFile((LPCSTR) szFilename);
  3838. return ERR_GROUPBY;
  3839. }
  3840. /* Increase count of number of records written */
  3841. cRowCount++;
  3842. /* Copy current record to the result record buffer */
  3843. _fmemcpy(lpResultRecord, lpCurrentRecord,
  3844. (size_t) lpSqlNodeSelect->node.select.SortRecordsize);
  3845. /* Initialize the count for averages */
  3846. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3847. while (idxAggregate != NO_SQLNODE) {
  3848. /* Get the function */
  3849. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  3850. /* Average operator? */
  3851. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG) {
  3852. /* Yes. Point to the value */
  3853. lpAggregateValue = lpResultRecord +
  3854. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  3855. lpAggregateValueNullFlag = lpAggregateValue +
  3856. lpSqlNodeAggregate->node.aggregate.Length;
  3857. /* If not null, set count to one. Otherwise zero */
  3858. switch (*lpAggregateValueNullFlag) {
  3859. case NULL_FLAG:
  3860. lpSqlNodeAggregate->node.aggregate.Count = 0.0;
  3861. break;
  3862. case NOT_NULL_FLAG:
  3863. lpSqlNodeAggregate->node.aggregate.Count = 1.0;
  3864. break;
  3865. default:
  3866. GlobalUnlock(hGlobal);
  3867. GlobalFree(hGlobal);
  3868. _lclose_buffer(hfGroupbyfile);
  3869. DeleteFile((LPCSTR) szFilename);
  3870. return ERR_GROUPBY;
  3871. }
  3872. }
  3873. /* Do next aggregate */
  3874. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  3875. }
  3876. }
  3877. else {
  3878. /* Yes. For each aggregate function... */
  3879. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3880. while (idxAggregate != NO_SQLNODE) {
  3881. /* Get the function */
  3882. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  3883. /* Point to the value */
  3884. lpValue = lpCurrentRecord +
  3885. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  3886. lpValueNullFlag = lpValue +
  3887. lpSqlNodeAggregate->node.aggregate.Length;
  3888. lpAggregateValue = lpResultRecord +
  3889. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  3890. lpAggregateValueNullFlag = lpAggregateValue +
  3891. lpSqlNodeAggregate->node.aggregate.Length;
  3892. /* Null value? */
  3893. if (*lpValueNullFlag == NOT_NULL_FLAG) {
  3894. /* No. Is aggregate value null? */
  3895. if (*lpAggregateValueNullFlag == NOT_NULL_FLAG) {
  3896. /* No. Is a TYPE_NUMERIC involved? */
  3897. if (lpSqlNodeAggregate->sqlDataType != TYPE_NUMERIC) {
  3898. /* No. Incorporate field value into aggregate */
  3899. switch (lpSqlNodeAggregate->node.aggregate.Operator) {
  3900. case AGG_AVG:
  3901. case AGG_SUM:
  3902. switch (lpSqlNodeAggregate->sqlDataType) {
  3903. case TYPE_DOUBLE:
  3904. case TYPE_INTEGER:
  3905. *((double FAR *) lpAggregateValue) +=
  3906. (*((double FAR *) lpValue));
  3907. break;
  3908. case TYPE_NUMERIC:
  3909. case TYPE_CHAR:
  3910. case TYPE_DATE:
  3911. case TYPE_TIME:
  3912. case TYPE_TIMESTAMP:
  3913. case TYPE_BINARY:
  3914. default:
  3915. GlobalUnlock(hGlobal);
  3916. GlobalFree(hGlobal);
  3917. _lclose_buffer(hfGroupbyfile);
  3918. DeleteFile((LPCSTR) szFilename);
  3919. return ERR_INTERNAL;
  3920. }
  3921. /* Increase count */
  3922. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG)
  3923. lpSqlNodeAggregate->node.aggregate.Count += (1.0);
  3924. break;
  3925. case AGG_COUNT:
  3926. *((double FAR *) lpAggregateValue) += (1.0);
  3927. break;
  3928. case AGG_MAX:
  3929. switch (lpSqlNodeAggregate->sqlDataType) {
  3930. case TYPE_DOUBLE:
  3931. case TYPE_INTEGER:
  3932. if (*((double FAR *) lpAggregateValue) <
  3933. *((double FAR *) lpValue))
  3934. *((double FAR *) lpAggregateValue) =
  3935. *((double FAR *) lpValue);
  3936. break;
  3937. case TYPE_CHAR:
  3938. case TYPE_DATE:
  3939. case TYPE_TIME:
  3940. case TYPE_TIMESTAMP:
  3941. if (_fmemcmp(lpValue,
  3942. lpAggregateValue, (size_t)
  3943. lpSqlNodeAggregate->node.aggregate.Length)
  3944. > 0)
  3945. _fmemcpy(lpAggregateValue,
  3946. lpValue, (size_t)
  3947. lpSqlNodeAggregate->node.aggregate.Length);
  3948. break;
  3949. case TYPE_NUMERIC:
  3950. case TYPE_BINARY:
  3951. default:
  3952. GlobalUnlock(hGlobal);
  3953. GlobalFree(hGlobal);
  3954. _lclose_buffer(hfGroupbyfile);
  3955. DeleteFile((LPCSTR) szFilename);
  3956. return ERR_INTERNAL;
  3957. }
  3958. break;
  3959. case AGG_MIN:
  3960. switch (lpSqlNodeAggregate->sqlDataType) {
  3961. case TYPE_DOUBLE:
  3962. case TYPE_INTEGER:
  3963. if (*((double FAR *) lpAggregateValue) >
  3964. *((double FAR *) lpValue))
  3965. *((double FAR *) lpAggregateValue) =
  3966. *((double FAR *) lpValue);
  3967. break;
  3968. case TYPE_CHAR:
  3969. case TYPE_DATE:
  3970. case TYPE_TIME:
  3971. case TYPE_TIMESTAMP:
  3972. if (_fmemcmp(lpValue,
  3973. lpAggregateValue, (size_t)
  3974. lpSqlNodeAggregate->node.aggregate.Length)
  3975. < 0)
  3976. _fmemcpy(lpAggregateValue,
  3977. lpValue, (size_t)
  3978. lpSqlNodeAggregate->node.aggregate.Length);
  3979. break;
  3980. case TYPE_NUMERIC:
  3981. case TYPE_BINARY:
  3982. default:
  3983. GlobalUnlock(hGlobal);
  3984. GlobalFree(hGlobal);
  3985. _lclose_buffer(hfGroupbyfile);
  3986. DeleteFile((LPCSTR) szFilename);
  3987. return ERR_INTERNAL;
  3988. }
  3989. break;
  3990. }
  3991. }
  3992. else {
  3993. SQLNODE left;
  3994. SQLNODE right;
  3995. SQLNODE result;
  3996. /* These buffers must be large enough to */
  3997. /* accomodate the largest SQL_NUMERIC or */
  3998. /* SQL_DECIMAL */
  3999. UCHAR szBufferLeft[64];
  4000. UCHAR szBufferRight[64];
  4001. UWORD len;
  4002. UCHAR szBufferResult[64];
  4003. RETCODE err;
  4004. /* Yes. Incorporate field value into aggregate */
  4005. switch (lpSqlNodeAggregate->node.aggregate.Operator) {
  4006. case AGG_AVG:
  4007. case AGG_COUNT:
  4008. GlobalUnlock(hGlobal);
  4009. GlobalFree(hGlobal);
  4010. _lclose_buffer(hfGroupbyfile);
  4011. DeleteFile((LPCSTR) szFilename);
  4012. return ERR_INTERNAL;
  4013. case AGG_MAX:
  4014. /* Create left value */
  4015. left = *lpSqlNodeAggregate;
  4016. _fmemcpy(szBufferLeft, lpAggregateValue,
  4017. (size_t)
  4018. lpSqlNodeAggregate->node.aggregate.Length);
  4019. szBufferLeft[lpSqlNodeAggregate->node.
  4020. aggregate.Length] = '\0';
  4021. len = (UWORD) s_lstrlen(szBufferLeft);
  4022. while ((len > 0) &&
  4023. (szBufferLeft[len-1] == ' ')) {
  4024. szBufferLeft[len-1] = '\0';
  4025. len--;
  4026. }
  4027. left.value.String = (LPUSTR)szBufferLeft;
  4028. /* Create right value */
  4029. right = *lpSqlNodeAggregate;
  4030. _fmemcpy(szBufferRight, lpValue, (size_t)
  4031. lpSqlNodeAggregate->node.aggregate.Length);
  4032. szBufferRight[lpSqlNodeAggregate->node.
  4033. aggregate.Length] = '\0';
  4034. len = (UWORD) s_lstrlen(szBufferRight);
  4035. while ((len > 0) &&
  4036. (szBufferRight[len-1] == ' ')) {
  4037. szBufferRight[len-1] = '\0';
  4038. len--;
  4039. }
  4040. right.value.String = (LPUSTR)szBufferRight;
  4041. /* Compare the values */
  4042. result.sqlNodeType = NODE_TYPE_COMPARISON;
  4043. result.node.comparison.Operator = OP_LT;
  4044. result.node.comparison.SelectModifier = SELECT_NOTSELECT;
  4045. result.node.comparison.Left = NO_SQLNODE;
  4046. result.node.comparison.Right = NO_SQLNODE;
  4047. result.node.comparison.fSelectivity = 0;
  4048. result.node.comparison.NextRestrict = NO_SQLNODE;
  4049. result.sqlDataType = TYPE_INTEGER;
  4050. result.sqlSqlType = SQL_BIT;
  4051. result.sqlPrecision = 1;
  4052. result.sqlScale = 0;
  4053. err = NumericCompare(&result, &left,
  4054. OP_LT, &right);
  4055. if (err != ERR_SUCCESS) {
  4056. GlobalUnlock(hGlobal);
  4057. GlobalFree(hGlobal);
  4058. _lclose_buffer(hfGroupbyfile);
  4059. DeleteFile((LPCSTR) szFilename);
  4060. return err;
  4061. }
  4062. /* If this value is bigger, save it */
  4063. if (result.value.Double == TRUE)
  4064. _fmemcpy(lpAggregateValue, lpValue,
  4065. (size_t)
  4066. lpSqlNodeAggregate->node.aggregate.Length);
  4067. break;
  4068. case AGG_MIN:
  4069. /* Create left value */
  4070. left = *lpSqlNodeAggregate;
  4071. _fmemcpy(szBufferLeft, lpAggregateValue,
  4072. (size_t)
  4073. lpSqlNodeAggregate->node.aggregate.Length);
  4074. szBufferLeft[lpSqlNodeAggregate->node.
  4075. aggregate.Length] = '\0';
  4076. len = (UWORD) s_lstrlen(szBufferLeft);
  4077. while ((len > 0) &&
  4078. (szBufferLeft[len-1] == ' ')) {
  4079. szBufferLeft[len-1] = '\0';
  4080. len--;
  4081. }
  4082. left.value.String = (LPUSTR)szBufferLeft;
  4083. /* Create right value */
  4084. right = *lpSqlNodeAggregate;
  4085. _fmemcpy(szBufferRight, lpValue, (size_t)
  4086. lpSqlNodeAggregate->node.aggregate.Length);
  4087. szBufferRight[lpSqlNodeAggregate->node.
  4088. aggregate.Length] = '\0';
  4089. len = (UWORD) s_lstrlen(szBufferRight);
  4090. while ((len > 0) &&
  4091. (szBufferRight[len-1] == ' ')) {
  4092. szBufferRight[len-1] = '\0';
  4093. len--;
  4094. }
  4095. right.value.String = (LPUSTR)szBufferRight;
  4096. /* Compare the values */
  4097. result.sqlNodeType = NODE_TYPE_COMPARISON;
  4098. result.node.comparison.Operator = OP_GT;
  4099. result.node.comparison.SelectModifier = SELECT_NOTSELECT;
  4100. result.node.comparison.Left = NO_SQLNODE;
  4101. result.node.comparison.Right = NO_SQLNODE;
  4102. result.node.comparison.fSelectivity = 0;
  4103. result.node.comparison.NextRestrict = NO_SQLNODE;
  4104. result.sqlDataType = TYPE_INTEGER;
  4105. result.sqlSqlType = SQL_BIT;
  4106. result.sqlPrecision = 1;
  4107. result.sqlScale = 0;
  4108. err = NumericCompare(&result, &left,
  4109. OP_GT, &right);
  4110. if (err != ERR_SUCCESS) {
  4111. GlobalUnlock(hGlobal);
  4112. GlobalFree(hGlobal);
  4113. _lclose_buffer(hfGroupbyfile);
  4114. DeleteFile((LPCSTR) szFilename);
  4115. return err;
  4116. }
  4117. /* If this value is smaller, save it */
  4118. if (result.value.Double == TRUE)
  4119. _fmemcpy(lpAggregateValue, lpValue,
  4120. (size_t)
  4121. lpSqlNodeAggregate->node.aggregate.Length);
  4122. break;
  4123. case AGG_SUM:
  4124. /* Create left value */
  4125. left = *lpSqlNodeAggregate;
  4126. _fmemcpy(szBufferLeft, lpAggregateValue,
  4127. (size_t)
  4128. lpSqlNodeAggregate->node.aggregate.Length);
  4129. szBufferLeft[lpSqlNodeAggregate->node.
  4130. aggregate.Length] = '\0';
  4131. len = (UWORD) s_lstrlen(szBufferLeft);
  4132. while ((len > 0) &&
  4133. (szBufferLeft[len-1] == ' ')) {
  4134. szBufferLeft[len-1] = '\0';
  4135. len--;
  4136. }
  4137. left.value.String = (LPUSTR)szBufferLeft;
  4138. /* Create right value */
  4139. right = *lpSqlNodeAggregate;
  4140. _fmemcpy(szBufferRight, lpValue, (size_t)
  4141. lpSqlNodeAggregate->node.aggregate.Length);
  4142. szBufferRight[lpSqlNodeAggregate->node.
  4143. aggregate.Length] = '\0';
  4144. len = (UWORD) s_lstrlen(szBufferRight);
  4145. while ((len > 0) &&
  4146. (szBufferRight[len-1] == ' ')) {
  4147. szBufferRight[len-1] = '\0';
  4148. len--;
  4149. }
  4150. right.value.String = (LPUSTR)szBufferRight;
  4151. /* Add the left value to the right */
  4152. result = *lpSqlNodeAggregate;
  4153. result.value.String = (LPUSTR)szBufferResult;
  4154. err = NumericAlgebra(&result, &left,
  4155. OP_PLUS, &right, NULL, NULL, NULL);
  4156. if (err != ERR_SUCCESS) {
  4157. GlobalUnlock(hGlobal);
  4158. GlobalFree(hGlobal);
  4159. _lclose_buffer(hfGroupbyfile);
  4160. DeleteFile((LPCSTR) szFilename);
  4161. return err;
  4162. }
  4163. /* Save the result */
  4164. while (s_lstrlen(szBufferResult) < (SDWORD)
  4165. lpSqlNodeAggregate->node.aggregate.Length)
  4166. s_lstrcat(szBufferResult, " ");
  4167. _fmemcpy(lpAggregateValue, szBufferResult,
  4168. (size_t)
  4169. lpSqlNodeAggregate->node.aggregate.Length);
  4170. break;
  4171. }
  4172. }
  4173. }
  4174. else {
  4175. /* Yes. Copy value from current record */
  4176. _fmemcpy(lpAggregateValue, lpValue, (size_t)
  4177. lpSqlNodeAggregate->node.aggregate.Length);
  4178. *lpAggregateValueNullFlag = NOT_NULL_FLAG;
  4179. /* Initilize average count */
  4180. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG)
  4181. lpSqlNodeAggregate->node.aggregate.Count = 1.0;
  4182. }
  4183. }
  4184. /* Do next aggregate */
  4185. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  4186. }
  4187. }
  4188. }
  4189. /* Calculate averages */
  4190. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  4191. while (idxAggregate != NO_SQLNODE) {
  4192. /* Get the function */
  4193. lpSqlNodeAggregate = ToNode(lpstmt->lpSqlStmt, idxAggregate);
  4194. /* Average operator? */
  4195. if (lpSqlNodeAggregate->node.aggregate.Operator == AGG_AVG) {
  4196. /* Yes. Point to the value */
  4197. lpAggregateValue = lpResultRecord +
  4198. lpSqlNodeAggregate->node.aggregate.Offset - 1;
  4199. lpAggregateValueNullFlag = lpAggregateValue +
  4200. lpSqlNodeAggregate->node.aggregate.Length;
  4201. /* If not null, calculate average */
  4202. if (*lpAggregateValueNullFlag == NOT_NULL_FLAG)
  4203. *((double FAR *) lpAggregateValue) /=
  4204. (lpSqlNodeAggregate->node.aggregate.Count);
  4205. }
  4206. /* Do next aggregate */
  4207. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  4208. }
  4209. /* Copy last record to the result record buffer */
  4210. if (_lwrite_buffer(hfGroupbyfile, (LPSTR) lpResultRecord,
  4211. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) !=
  4212. (UINT) lpSqlNodeSelect->node.select.SortRecordsize) {
  4213. GlobalUnlock(hGlobal);
  4214. GlobalFree(hGlobal);
  4215. _lclose_buffer(hfGroupbyfile);
  4216. DeleteFile((LPCSTR) szFilename);
  4217. return ERR_GROUPBY;
  4218. }
  4219. /* Increase count of number of records written */
  4220. cRowCount++;
  4221. /* Free buffers */
  4222. GlobalUnlock(hGlobal);
  4223. GlobalFree(hGlobal);
  4224. /* Close the file */
  4225. if (_lclose_buffer(hfGroupbyfile) == HFILE_ERROR) {
  4226. DeleteFile((LPCSTR) szFilename);
  4227. return ERR_GROUPBY;
  4228. }
  4229. /* Reopen the file for reading */
  4230. hfGroupbyfile2 = _lopen((LPCSTR) szFilename, OF_READ);
  4231. if (hfGroupbyfile2 == HFILE_ERROR) {
  4232. DeleteFile((LPCSTR) szFilename);
  4233. return ERR_GROUPBY;
  4234. }
  4235. /* Remove the sort file */
  4236. _lclose(lpSqlNodeSelect->node.select.Sortfile);
  4237. DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt,
  4238. lpSqlNodeSelect->node.select.SortfileName));
  4239. /* Save name and handle to file of group by records */
  4240. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  4241. lpSqlNodeSelect->node.select.SortfileName), szFilename);
  4242. lpSqlNodeSelect->node.select.Sortfile = hfGroupbyfile2;
  4243. lpSqlNodeSelect->node.select.ReturningDistinct = FALSE;
  4244. /* Save total number of records in the group by file */
  4245. lpSqlNodeSelect->node.select.RowCount = cRowCount;
  4246. /* Set up to read first row */
  4247. lpSqlNodeSelect->node.select.CurrentRow = BEFORE_FIRST_ROW;
  4248. return ERR_SUCCESS;
  4249. }
  4250. /***************************************************************************/
  4251. RETCODE INTFUNC Distinct(LPSTMT lpstmt, LPSQLNODE lpSqlNodeSelect)
  4252. /* Generates results for SELECT DISTINCT */
  4253. {
  4254. // ODBCTRACE("\nWBEM ODBC Driver : Distinct\n");
  4255. UCHAR szTempDir[MAX_PATHNAME_SIZE+1];
  4256. szTempDir[0] = 0;
  4257. UCHAR szFilename[MAX_PATHNAME_SIZE+1];
  4258. UCHAR szFilename2[MAX_PATHNAME_SIZE+1];
  4259. szFilename[0] = 0;
  4260. szFilename2[0] = 0;
  4261. HFILE_BUFFER hfSortfile;
  4262. HFILE hfSortfile2;
  4263. LPSQLNODE lpSqlNodeTables;
  4264. LPSQLNODE lpSqlNodePredicate;
  4265. LPSQLNODE lpSqlNodeHaving;
  4266. RETCODE err;
  4267. SQLNODEIDX idxTableList;
  4268. LPSQLNODE lpSqlNodeTableList;
  4269. LPSQLNODE lpSqlNodeTable;
  4270. ISAMBOOKMARK bookmark;
  4271. SQLNODEIDX idxValues;
  4272. LPSQLNODE lpSqlNodeValues;
  4273. LPSQLNODE lpSqlNodeValue;
  4274. SDWORD len;
  4275. PTR ptr;
  4276. #define NUM_LEN 5
  4277. UCHAR szFormat[16];
  4278. UCHAR szBuffer[20+TIMESTAMP_SCALE+1];
  4279. UCHAR szSortDirective[64 + 3 + MAX_PATHNAME_SIZE];
  4280. long recordCount;
  4281. int sortStatus;
  4282. UCHAR cNullFlag;
  4283. BOOL fGotOne;
  4284. szBuffer[0] = 0;
  4285. /* Create temporary file */
  4286. #ifdef WIN32
  4287. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR)szTempDir))
  4288. return ERR_SORT;
  4289. if (!GetTempFileName((LPSTR)szTempDir, "LEM", 0, (LPSTR)szFilename))
  4290. return ERR_SORT;
  4291. #else
  4292. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename);
  4293. #endif
  4294. hfSortfile = _lcreat_buffer((LPCSTR) szFilename, 0);
  4295. if (hfSortfile == NULL)
  4296. return ERR_SORT;
  4297. /* For each record of result set... */
  4298. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt,
  4299. lpSqlNodeSelect->node.select.Tables);
  4300. if (lpSqlNodeSelect->node.select.Predicate == NO_SQLNODE)
  4301. lpSqlNodePredicate = NULL;
  4302. else
  4303. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt,
  4304. lpSqlNodeSelect->node.select.Predicate);
  4305. if (lpSqlNodeSelect->node.select.Having == NO_SQLNODE)
  4306. lpSqlNodeHaving = NULL;
  4307. else
  4308. lpSqlNodeHaving = ToNode(lpstmt->lpSqlStmt,
  4309. lpSqlNodeSelect->node.select.Having);
  4310. wsprintf((LPSTR) szFormat, "%%0%dd", (UWORD) NUM_LEN);
  4311. while (TRUE) {
  4312. /* Is there a sort file to read from? */
  4313. if (lpSqlNodeSelect->node.select.Sortfile == HFILE_ERROR) {
  4314. /* No. Get the next record */
  4315. try
  4316. {
  4317. err = NextRecord(lpstmt, lpSqlNodeTables, lpSqlNodePredicate);
  4318. }
  4319. catch(...)
  4320. {
  4321. _lclose_buffer(hfSortfile);
  4322. DeleteFile((LPCSTR) szFilename);
  4323. return ERR_MEMALLOCFAIL;
  4324. }
  4325. if (err == ERR_NODATAFOUND) {
  4326. lpSqlNodeSelect->node.select.CurrentRow = AFTER_LAST_ROW;
  4327. break;
  4328. }
  4329. else if (err != ERR_SUCCESS) {
  4330. _lclose_buffer(hfSortfile);
  4331. DeleteFile((LPCSTR) szFilename);
  4332. return err;
  4333. }
  4334. /* Set row flag */
  4335. if (lpSqlNodeSelect->node.select.CurrentRow == BEFORE_FIRST_ROW)
  4336. lpSqlNodeSelect->node.select.CurrentRow = 0;
  4337. else
  4338. lpSqlNodeSelect->node.select.CurrentRow++;
  4339. }
  4340. else {
  4341. /* Yes. Look for next record in sort file */
  4342. while (TRUE) {
  4343. /* Set row flag */
  4344. if (lpSqlNodeSelect->node.select.CurrentRow == BEFORE_FIRST_ROW) {
  4345. if (lpSqlNodeSelect->node.select.RowCount != 0) {
  4346. lpSqlNodeSelect->node.select.CurrentRow = 0;
  4347. }
  4348. else {
  4349. lpSqlNodeSelect->node.select.CurrentRow = AFTER_LAST_ROW;
  4350. break;
  4351. }
  4352. }
  4353. else if (lpSqlNodeSelect->node.select.CurrentRow ==
  4354. lpSqlNodeSelect->node.select.RowCount-1) {
  4355. lpSqlNodeSelect->node.select.CurrentRow = AFTER_LAST_ROW;
  4356. break;
  4357. }
  4358. else
  4359. lpSqlNodeSelect->node.select.CurrentRow++;
  4360. /* If no HAVING clause, this record qualifies */
  4361. if (lpSqlNodeHaving == NULL)
  4362. break;
  4363. /* If HAVING condition is satisfied, this record qualifies */
  4364. err = EvaluateExpression(lpstmt, lpSqlNodeHaving);
  4365. if (err != ERR_SUCCESS) {
  4366. _lclose_buffer(hfSortfile);
  4367. DeleteFile((LPCSTR) szFilename);
  4368. return err;
  4369. }
  4370. if (!(lpSqlNodeHaving->sqlIsNull) &&
  4371. (lpSqlNodeHaving->value.Double == TRUE))
  4372. break;
  4373. }
  4374. if (lpSqlNodeSelect->node.select.CurrentRow == AFTER_LAST_ROW)
  4375. break;
  4376. /* Is there a group by? */
  4377. if ((lpSqlNodeSelect->node.select.Groupbycolumns == NO_SQLNODE) &&
  4378. (!lpSqlNodeSelect->node.select.ImplicitGroupby)) {
  4379. /* No. Position to bookmarks in that row */
  4380. if (_llseek(lpSqlNodeSelect->node.select.Sortfile,
  4381. (lpSqlNodeSelect->node.select.CurrentRow *
  4382. lpSqlNodeSelect->node.select.SortRecordsize) +
  4383. lpSqlNodeSelect->node.select.SortBookmarks - 1, 0)
  4384. == HFILE_ERROR) {
  4385. _lclose_buffer(hfSortfile);
  4386. DeleteFile((LPCSTR) szFilename);
  4387. return ERR_SORT;
  4388. }
  4389. /* For each table... */
  4390. idxTableList = lpSqlNodeSelect->node.select.Tables;
  4391. while (idxTableList != NO_SQLNODE) {
  4392. /* Get the table node */
  4393. lpSqlNodeTableList = ToNode(lpstmt->lpSqlStmt,
  4394. idxTableList);
  4395. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  4396. lpSqlNodeTableList->node.tables.Table);
  4397. /* Read the bookmark for it */
  4398. if (_lread(lpSqlNodeSelect->node.select.Sortfile,
  4399. &bookmark, sizeof(ISAMBOOKMARK)) !=
  4400. sizeof(ISAMBOOKMARK)) {
  4401. _lclose_buffer(hfSortfile);
  4402. DeleteFile((LPCSTR) szFilename);
  4403. return ERR_SORT;
  4404. }
  4405. /* Position to that record */
  4406. if (bookmark.currentRecord == NULL_BOOKMARK)
  4407. {
  4408. lpSqlNodeTable->node.table.AllNull = TRUE;
  4409. }
  4410. else
  4411. {
  4412. lpSqlNodeTable->node.table.AllNull = FALSE;
  4413. err = ISAMPosition(lpSqlNodeTable->node.table.Handle, &bookmark);
  4414. if (err != NO_ISAM_ERR) {
  4415. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  4416. (LPUSTR) lpstmt->szISAMError);
  4417. _lclose_buffer(hfSortfile);
  4418. DeleteFile((LPCSTR) szFilename);
  4419. return err;
  4420. }
  4421. lpstmt->fISAMTxnStarted = TRUE;
  4422. }
  4423. /* Point at next table */
  4424. idxTableList = lpSqlNodeTableList->node.tables.Next;
  4425. }
  4426. }
  4427. }
  4428. /* Leave if no more records */
  4429. if (lpSqlNodeSelect->node.select.CurrentRow == AFTER_LAST_ROW)
  4430. break;
  4431. /* Put in the record number */
  4432. wsprintf((LPSTR) szBuffer, (LPSTR) szFormat,
  4433. (UWORD) lpSqlNodeSelect->node.select.CurrentRow);
  4434. CString myBuffer;
  4435. myBuffer.Format("WBEM ODBC Driver : Distinct : Record Number = %s\n", szBuffer);
  4436. ODBCTRACE(myBuffer);
  4437. if (_lwrite_buffer(hfSortfile, (LPSTR) szBuffer, NUM_LEN) != NUM_LEN) {
  4438. _lclose_buffer(hfSortfile);
  4439. DeleteFile((LPCSTR) szFilename);
  4440. return ERR_SORT;
  4441. }
  4442. /* Put the columns in the sort file in the order specified by the */
  4443. /* select list. For each value... */
  4444. idxValues = lpSqlNodeSelect->node.select.Values;
  4445. fGotOne = FALSE;
  4446. while (idxValues != NO_SQLNODE) {
  4447. /* Get next column */
  4448. lpSqlNodeValues = ToNode(lpstmt->lpSqlStmt, idxValues);
  4449. lpSqlNodeValue = ToNode(lpstmt->lpSqlStmt,
  4450. lpSqlNodeValues->node.values.Value);
  4451. /* Does the value need to be put in the file? */
  4452. switch (lpSqlNodeValue->sqlNodeType) {
  4453. case NODE_TYPE_COLUMN:
  4454. case NODE_TYPE_AGGREGATE:
  4455. case NODE_TYPE_ALGEBRAIC:
  4456. case NODE_TYPE_SCALAR:
  4457. /* Yes. Continue below */
  4458. fGotOne = TRUE;
  4459. break;
  4460. case NODE_TYPE_STRING:
  4461. case NODE_TYPE_NUMERIC:
  4462. case NODE_TYPE_PARAMETER:
  4463. case NODE_TYPE_USER:
  4464. case NODE_TYPE_NULL:
  4465. case NODE_TYPE_DATE:
  4466. case NODE_TYPE_TIME:
  4467. case NODE_TYPE_TIMESTAMP:
  4468. /* No. Go to next value */
  4469. idxValues = lpSqlNodeValues->node.values.Next;
  4470. continue;
  4471. case NODE_TYPE_CREATE:
  4472. case NODE_TYPE_DROP:
  4473. case NODE_TYPE_SELECT:
  4474. case NODE_TYPE_INSERT:
  4475. case NODE_TYPE_DELETE:
  4476. case NODE_TYPE_UPDATE:
  4477. case NODE_TYPE_CREATEINDEX:
  4478. case NODE_TYPE_DROPINDEX:
  4479. case NODE_TYPE_PASSTHROUGH:
  4480. case NODE_TYPE_TABLES:
  4481. case NODE_TYPE_VALUES:
  4482. case NODE_TYPE_COLUMNS:
  4483. case NODE_TYPE_SORTCOLUMNS:
  4484. case NODE_TYPE_GROUPBYCOLUMNS:
  4485. case NODE_TYPE_UPDATEVALUES:
  4486. case NODE_TYPE_CREATECOLS:
  4487. case NODE_TYPE_BOOLEAN:
  4488. case NODE_TYPE_COMPARISON:
  4489. case NODE_TYPE_TABLE:
  4490. default:
  4491. return ERR_INTERNAL;
  4492. }
  4493. /* Get its value */
  4494. err = EvaluateExpression(lpstmt, lpSqlNodeValue);
  4495. if (err != ERR_SUCCESS) {
  4496. _lclose_buffer(hfSortfile);
  4497. DeleteFile((LPCSTR) szFilename);
  4498. return err;
  4499. }
  4500. /* Get length and pointer to key value */
  4501. switch (lpSqlNodeValue->sqlDataType) {
  4502. case TYPE_DOUBLE:
  4503. case TYPE_INTEGER:
  4504. if (lpSqlNodeValue->sqlIsNull)
  4505. lpSqlNodeValue->value.Double = 0.0;
  4506. len = sizeof(double);
  4507. ptr = &(lpSqlNodeValue->value.Double);
  4508. break;
  4509. case TYPE_NUMERIC:
  4510. if (lpSqlNodeValue->sqlIsNull)
  4511. (lpSqlNodeValue->value.String)[0] = 0;
  4512. len = lpSqlNodeValue->sqlPrecision + 2;
  4513. ptr = lpSqlNodeValue->value.String;
  4514. /* (blank pad string values) */
  4515. while (s_lstrlen(lpSqlNodeValue->value.String) < len)
  4516. s_lstrcat(lpSqlNodeValue->value.String, " ");
  4517. break;
  4518. case TYPE_CHAR:
  4519. if (lpSqlNodeValue->sqlIsNull)
  4520. (lpSqlNodeValue->value.String)[0] = 0;
  4521. len = lpSqlNodeValue->sqlPrecision;
  4522. ptr = lpSqlNodeValue->value.String;
  4523. ODBCTRACE(_T("\nWBEM ODBC Driver : Distinct : String = "));
  4524. if ((LPSTR)ptr)
  4525. {
  4526. ODBCTRACE((LPSTR)ptr);
  4527. CString myString;
  4528. myString.Format(" length = %ld\n", s_lstrlen((LPSTR)ptr));
  4529. ODBCTRACE(myString);
  4530. }
  4531. else
  4532. {
  4533. ODBCTRACE(_T("NULL\n"));
  4534. }
  4535. /* (blank pad string values) */
  4536. while (s_lstrlen(lpSqlNodeValue->value.String) < len)
  4537. s_lstrcat(lpSqlNodeValue->value.String, " ");
  4538. break;
  4539. case TYPE_BINARY:
  4540. if (lpSqlNodeValue->sqlIsNull)
  4541. BINARY_LENGTH(lpSqlNodeValue->value.Binary) = 0;
  4542. len = lpSqlNodeValue->sqlPrecision;
  4543. ptr = BINARY_DATA(lpSqlNodeValue->value.Binary);
  4544. /* (zero pad binary values) */
  4545. while (BINARY_LENGTH(lpSqlNodeValue->value.Binary) < len) {
  4546. BINARY_DATA(lpSqlNodeValue->value.Binary)[
  4547. BINARY_LENGTH(lpSqlNodeValue->value.Binary)] = 0;
  4548. BINARY_LENGTH(lpSqlNodeValue->value.Binary) =
  4549. BINARY_LENGTH(lpSqlNodeValue->value.Binary) + 1;
  4550. }
  4551. break;
  4552. case TYPE_DATE:
  4553. if (lpSqlNodeValue->sqlIsNull) {
  4554. lpSqlNodeValue->value.Date.year = 0;
  4555. lpSqlNodeValue->value.Date.month = 0;
  4556. lpSqlNodeValue->value.Date.day = 0;
  4557. }
  4558. DateToChar(&(lpSqlNodeValue->value.Date), (LPUSTR)szBuffer);
  4559. len = s_lstrlen((char*)szBuffer);
  4560. ptr = szBuffer;
  4561. break;
  4562. case TYPE_TIME:
  4563. if (lpSqlNodeValue->sqlIsNull) {
  4564. lpSqlNodeValue->value.Time.hour = 0;
  4565. lpSqlNodeValue->value.Time.minute = 0;
  4566. lpSqlNodeValue->value.Time.second = 0;
  4567. }
  4568. TimeToChar(&(lpSqlNodeValue->value.Time), (LPUSTR)szBuffer);
  4569. len = s_lstrlen((char*)szBuffer);
  4570. ptr = szBuffer;
  4571. break;
  4572. case TYPE_TIMESTAMP:
  4573. if (lpSqlNodeValue->sqlIsNull) {
  4574. lpSqlNodeValue->value.Timestamp.year = 0;
  4575. lpSqlNodeValue->value.Timestamp.month = 0;
  4576. lpSqlNodeValue->value.Timestamp.day = 0;
  4577. lpSqlNodeValue->value.Timestamp.hour = 0;
  4578. lpSqlNodeValue->value.Timestamp.minute = 0;
  4579. lpSqlNodeValue->value.Timestamp.second = 0;
  4580. lpSqlNodeValue->value.Timestamp.fraction = 0;
  4581. }
  4582. TimestampToChar(&(lpSqlNodeValue->value.Timestamp), (LPUSTR)szBuffer);
  4583. len = s_lstrlen((char*)szBuffer);
  4584. ptr = szBuffer;
  4585. break;
  4586. default:
  4587. _lclose_buffer(hfSortfile);
  4588. DeleteFile((LPCSTR) szFilename);
  4589. return ERR_INTERNAL;
  4590. }
  4591. /* Put value into the file */
  4592. if (_lwrite_buffer(hfSortfile, (LPSTR) ptr, (UINT) len) != (UINT) len) {
  4593. _lclose_buffer(hfSortfile);
  4594. DeleteFile((LPCSTR) szFilename);
  4595. return ERR_SORT;
  4596. }
  4597. /* Put in the null flag */
  4598. if (lpSqlNodeValue->sqlIsNull)
  4599. cNullFlag = NULL_FLAG;
  4600. else
  4601. cNullFlag = NOT_NULL_FLAG;
  4602. if (_lwrite_buffer(hfSortfile, (LPSTR) &cNullFlag, 1) != 1) {
  4603. _lclose_buffer(hfSortfile);
  4604. DeleteFile((LPCSTR) szFilename);
  4605. return ERR_SORT;
  4606. }
  4607. /* Point at next value */
  4608. idxValues = lpSqlNodeValues->node.values.Next;
  4609. }
  4610. /* If no fields in sort record, put a constant in */
  4611. if (!fGotOne) {
  4612. if (_lwrite_buffer(hfSortfile, "LEM", 3) != 3) {
  4613. _lclose_buffer(hfSortfile);
  4614. DeleteFile((LPCSTR) szFilename);
  4615. return ERR_SORT;
  4616. }
  4617. }
  4618. }
  4619. if (_lclose_buffer(hfSortfile) == HFILE_ERROR) {
  4620. DeleteFile((LPCSTR) szFilename);
  4621. return ERR_SORT;
  4622. }
  4623. /* Create a destination file */
  4624. #ifdef WIN32
  4625. if (!GetTempFileName((LPSTR) szTempDir, "LEM", 0, (LPSTR) szFilename2)) {
  4626. DeleteFile((LPCSTR) szFilename);
  4627. return ERR_SORT;
  4628. }
  4629. #else
  4630. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename2);
  4631. #endif
  4632. hfSortfile2 = _lcreat((LPCSTR) szFilename2, 0);
  4633. if (hfSortfile2 == HFILE_ERROR) {
  4634. DeleteFile((LPCSTR) szFilename);
  4635. return ERR_SORT;
  4636. }
  4637. _lclose(hfSortfile2);
  4638. /* Sort the file */
  4639. s_1mains((LPSTR) szFilename, (LPSTR) szFilename2, (LPSTR)
  4640. ToString(lpstmt->lpSqlStmt,
  4641. lpSqlNodeSelect->node.select.DistinctDirective),
  4642. &recordCount, &sortStatus);
  4643. if (sortStatus != 0) {
  4644. DeleteFile((LPCSTR) szFilename2);
  4645. DeleteFile((LPCSTR) szFilename);
  4646. return ERR_SORT;
  4647. }
  4648. DeleteFile((LPCSTR) szFilename);
  4649. /* Sort the file again (to put the values back into the original order) */
  4650. if (lpSqlNodeSelect->node.select.Sortcolumns != NO_SQLNODE) {
  4651. #ifdef WIN32
  4652. if (szTempDir[s_lstrlen(szTempDir)-1] != '\\')
  4653. s_lstrcat(szTempDir, "\\");
  4654. #else
  4655. GetTempFileName(NULL, "LEM", 0, (LPSTR) szTempDir);
  4656. while (szTempDir[s_lstrlen(szTempDir)-1] != '\\')
  4657. szTempDir[s_lstrlen(szTempDir)-1] = '\0';
  4658. #endif
  4659. wsprintf((LPSTR) szSortDirective, "S(1,%d,N,A)F(FIX,%d)W(%s)", (WORD) NUM_LEN,
  4660. (WORD) lpSqlNodeSelect->node.select.DistinctRecordsize,
  4661. (LPSTR) szTempDir);
  4662. s_1mains((LPSTR) szFilename2, (LPSTR) szFilename2,
  4663. (LPSTR) szSortDirective, &recordCount, &sortStatus);
  4664. if (sortStatus != 0) {
  4665. DeleteFile((LPCSTR) szFilename2);
  4666. return ERR_SORT;
  4667. }
  4668. }
  4669. lpSqlNodeSelect->node.select.RowCount = recordCount;
  4670. /* Open destination file */
  4671. hfSortfile2 = _lopen((LPCSTR) szFilename2, OF_READ);
  4672. if (hfSortfile2 == HFILE_ERROR) {
  4673. DeleteFile((LPCSTR) szFilename2);
  4674. return ERR_SORT;
  4675. }
  4676. /* Save name and handle to file of sorted records */
  4677. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  4678. lpSqlNodeSelect->node.select.SortfileName), szFilename2);
  4679. lpSqlNodeSelect->node.select.Sortfile = hfSortfile2;
  4680. lpSqlNodeSelect->node.select.ReturningDistinct = TRUE;
  4681. /* Set up to read first row */
  4682. lpSqlNodeSelect->node.select.CurrentRow = BEFORE_FIRST_ROW;
  4683. return ERR_SUCCESS;
  4684. }
  4685. /***************************************************************************/
  4686. RETCODE INTFUNC MSAccess(LPSTMT lpstmt, LPSQLNODE lpSqlNodeSelect,
  4687. SQLNODEIDX idxSelectStatement)
  4688. /* Evaluates optimized MSAccess statement */
  4689. {
  4690. // ODBCTRACE("\nWBEM ODBC Driver : MSAccess\n");
  4691. UCHAR szTempDir[MAX_PATHNAME_SIZE+1];
  4692. UCHAR szFilename[MAX_PATHNAME_SIZE+1];
  4693. UCHAR szFilename2[MAX_PATHNAME_SIZE+1];
  4694. HFILE hfSortfile;
  4695. LPSQLNODE lpSqlNodeTables;
  4696. LPSQLNODE lpSqlNodeTable;
  4697. LPSQLNODE lpSqlNodePredicate;
  4698. LPSQLNODE lpSqlNodeKeycondition;
  4699. SQLNODEIDX idxPredicate;
  4700. SQLNODEIDX idxKeycondition;
  4701. RETCODE err;
  4702. ISAMBOOKMARK bookmark;
  4703. long recordCount;
  4704. int sortStatus;
  4705. #define NUM_LEN 5
  4706. UCHAR szFormat[16];
  4707. UCHAR szBuffer[NUM_LEN+1];
  4708. UCHAR szSortDirective[64 + 3 + MAX_PATHNAME_SIZE];
  4709. /* Create temporary file */
  4710. #ifdef WIN32
  4711. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR) szTempDir))
  4712. return ERR_SORT;
  4713. if (!GetTempFileName((LPSTR) szTempDir, "LEM", 0, (LPSTR) szFilename))
  4714. return ERR_SORT;
  4715. #else
  4716. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename);
  4717. #endif
  4718. hfSortfile = _lcreat((LPCSTR) szFilename, 0);
  4719. if (hfSortfile == HFILE_ERROR)
  4720. return ERR_SORT;
  4721. /* Get the table and predicate node. */
  4722. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt,
  4723. lpSqlNodeSelect->node.select.Tables);
  4724. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt, lpSqlNodeTables->node.tables.Table);
  4725. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt,
  4726. lpSqlNodeSelect->node.select.Predicate);
  4727. /* For each of the key conditions...*/
  4728. wsprintf((LPSTR) szFormat, "%%0%dd", (UWORD) NUM_LEN);
  4729. lpSqlNodeSelect->node.select.RowCount = 0;
  4730. while (lpSqlNodePredicate != NULL) {
  4731. /* Get the next key condition */
  4732. if ((lpSqlNodePredicate->sqlNodeType == NODE_TYPE_BOOLEAN) &&
  4733. (lpSqlNodePredicate->node.boolean.Operator == OP_OR)) {
  4734. idxKeycondition = lpSqlNodePredicate->node.boolean.Left;
  4735. lpSqlNodeKeycondition = ToNode(lpstmt->lpSqlStmt,
  4736. idxKeycondition);
  4737. idxPredicate = lpSqlNodePredicate->node.boolean.Right;
  4738. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt, idxPredicate);
  4739. }
  4740. else {
  4741. idxKeycondition = idxPredicate;
  4742. lpSqlNodeKeycondition = lpSqlNodePredicate;
  4743. idxPredicate = NO_SQLNODE;
  4744. lpSqlNodePredicate = NULL;
  4745. }
  4746. /* Set the optimization predicate */
  4747. lpSqlNodeTable->node.table.cRestrict = 0;
  4748. lpSqlNodeTable->node.table.Restrict = NO_SQLNODE;
  4749. err = FindRestriction(lpstmt->lpSqlStmt,
  4750. ISAMCaseSensitive(lpstmt->lpdbc->lpISAM),
  4751. lpSqlNodeTable, idxKeycondition, idxSelectStatement,
  4752. &(lpSqlNodeTable->node.table.cRestrict),
  4753. &(lpSqlNodeTable->node.table.Restrict));
  4754. if (err != ERR_SUCCESS) {
  4755. lpSqlNodeTable->node.table.cRestrict = 0;
  4756. lpSqlNodeTable->node.table.Restrict = NO_SQLNODE;
  4757. return err;
  4758. }
  4759. /* Rewind the table */
  4760. err = Rewind(lpstmt, lpSqlNodeTable, FALSE);
  4761. if (err != ERR_SUCCESS) {
  4762. lpSqlNodeTable->node.table.cRestrict = 0;
  4763. lpSqlNodeTable->node.table.Restrict = NO_SQLNODE;
  4764. return err;
  4765. }
  4766. /* Clear the optimization predicate */
  4767. lpSqlNodeTable->node.table.cRestrict = 0;
  4768. lpSqlNodeTable->node.table.Restrict = NO_SQLNODE;
  4769. /* Set up to read first row */
  4770. lpSqlNodeSelect->node.select.CurrentRow = BEFORE_FIRST_ROW;
  4771. /* For each record of result set... */
  4772. while (TRUE) {
  4773. /* Get the next record */
  4774. err = NextRecord(lpstmt, lpSqlNodeTables,
  4775. lpSqlNodeKeycondition);
  4776. if (err == ERR_NODATAFOUND)
  4777. break;
  4778. else if (err != ERR_SUCCESS) {
  4779. _lclose(hfSortfile);
  4780. DeleteFile((LPCSTR) szFilename);
  4781. return err;
  4782. }
  4783. /* Set row flag */
  4784. if (lpSqlNodeSelect->node.select.CurrentRow == BEFORE_FIRST_ROW)
  4785. lpSqlNodeSelect->node.select.CurrentRow = 0;
  4786. else
  4787. lpSqlNodeSelect->node.select.CurrentRow++;
  4788. /* Increase row count */
  4789. (lpSqlNodeSelect->node.select.RowCount)++;
  4790. /* Get bookmark of current record */
  4791. if (lpSqlNodeTable->node.table.AllNull)
  4792. {
  4793. bookmark.currentRecord = NULL_BOOKMARK;
  4794. }
  4795. else
  4796. {
  4797. err = ISAMGetBookmark(lpSqlNodeTable->node.table.Handle, &bookmark);
  4798. if (err != ERR_SUCCESS) {
  4799. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  4800. (LPUSTR)lpstmt->szISAMError);
  4801. _lclose(hfSortfile);
  4802. DeleteFile((LPCSTR) szFilename);
  4803. return err;
  4804. }
  4805. lpstmt->fISAMTxnStarted = TRUE;
  4806. }
  4807. /* Put value into the file */
  4808. wsprintf((LPSTR) szBuffer, (LPSTR) szFormat,
  4809. (UWORD) lpSqlNodeSelect->node.select.RowCount);
  4810. if (_lwrite(hfSortfile, (LPSTR) szBuffer, NUM_LEN) != NUM_LEN) {
  4811. _lclose(hfSortfile);
  4812. DeleteFile((LPCSTR) szFilename);
  4813. return ERR_SORT;
  4814. }
  4815. if (_lwrite(hfSortfile, (LPSTR) &bookmark, sizeof(ISAMBOOKMARK))
  4816. != sizeof(ISAMBOOKMARK)) {
  4817. _lclose(hfSortfile);
  4818. DeleteFile((LPCSTR) szFilename);
  4819. return ERR_SORT;
  4820. }
  4821. }
  4822. }
  4823. if (lpSqlNodeSelect->node.select.RowCount == 0) {
  4824. _lclose(hfSortfile);
  4825. DeleteFile((LPCSTR) szFilename);
  4826. lpSqlNodeSelect->node.select.CurrentRow = AFTER_LAST_ROW;
  4827. return ERR_SUCCESS;
  4828. }
  4829. _lclose(hfSortfile);
  4830. /* Create a destination file */
  4831. #ifdef WIN32
  4832. if (!GetTempFileName((LPSTR) szTempDir, "LEM", 0, (LPSTR) szFilename2)) {
  4833. DeleteFile((LPCSTR) szFilename);
  4834. return ERR_SORT;
  4835. }
  4836. #else
  4837. GetTempFileName(NULL, "LEM", 0, (LPSTR) szFilename2);
  4838. #endif
  4839. hfSortfile = _lcreat((LPCSTR) szFilename2, 0);
  4840. if (hfSortfile == HFILE_ERROR) {
  4841. DeleteFile((LPCSTR) szFilename);
  4842. return ERR_SORT;
  4843. }
  4844. _lclose(hfSortfile);
  4845. /* Get name of workspace directory */
  4846. #ifdef WIN32
  4847. if (szTempDir[s_lstrlen(szTempDir)-1] != '\\')
  4848. s_lstrcat(szTempDir, "\\");
  4849. #else
  4850. GetTempFileName(NULL, "LEM", 0, (LPSTR) szTempDir);
  4851. while (szTempDir[s_lstrlen(szTempDir)-1] != '\\')
  4852. szTempDir[s_lstrlen(szTempDir)-1] = '\0';
  4853. #endif
  4854. /* Sort the file and remove duplicate bookmarks */
  4855. wsprintf((LPSTR) szSortDirective, "S(%d,%d,W,A)DUPO(B%d,%d,%d)F(FIX,%d)W(%s)",
  4856. (WORD) NUM_LEN+1, (WORD) sizeof(ISAMBOOKMARK),
  4857. (WORD) (sizeof(ISAMBOOKMARK) + NUM_LEN), (WORD) NUM_LEN+1,
  4858. (WORD) sizeof(ISAMBOOKMARK),
  4859. (WORD) (sizeof(ISAMBOOKMARK) + NUM_LEN),
  4860. (LPSTR) szTempDir);
  4861. s_1mains((LPSTR) szFilename, (LPSTR) szFilename2,
  4862. (LPSTR) szSortDirective, &recordCount, &sortStatus);
  4863. if (sortStatus != 0) {
  4864. DeleteFile((LPCSTR) szFilename2);
  4865. DeleteFile((LPCSTR) szFilename);
  4866. return ERR_SORT;
  4867. }
  4868. DeleteFile((LPCSTR) szFilename);
  4869. /* Sort the file again (to put the values back into the original order) */
  4870. wsprintf((LPSTR) szSortDirective, "S(1,%d,N,A)F(FIX,%d)W(%s)", (WORD) NUM_LEN,
  4871. (WORD) (sizeof(ISAMBOOKMARK) + NUM_LEN),
  4872. (LPSTR) szTempDir);
  4873. s_1mains((LPSTR) szFilename2, (LPSTR) szFilename2,
  4874. (LPSTR) szSortDirective, &recordCount, &sortStatus);
  4875. if (sortStatus != 0) {
  4876. DeleteFile((LPCSTR) szFilename2);
  4877. return ERR_SORT;
  4878. }
  4879. lpSqlNodeSelect->node.select.RowCount = recordCount;
  4880. /* Open destination file */
  4881. hfSortfile = _lopen((LPCSTR) szFilename2, OF_READ);
  4882. if (hfSortfile == HFILE_ERROR) {
  4883. DeleteFile((LPCSTR) szFilename2);
  4884. return ERR_SORT;
  4885. }
  4886. /* Save name and handle to file of records found */
  4887. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  4888. lpSqlNodeSelect->node.select.SortfileName), szFilename2);
  4889. lpSqlNodeSelect->node.select.Sortfile = hfSortfile;
  4890. /* Set up to read first row */
  4891. lpSqlNodeSelect->node.select.CurrentRow = BEFORE_FIRST_ROW;
  4892. return ERR_SUCCESS;
  4893. }
  4894. /***************************************************************************/
  4895. RETCODE INTFUNC ExecuteQuery(LPSTMT lpstmt, LPSQLNODE lpSqlNode)
  4896. /* Executes the current query */
  4897. {
  4898. LPUSTR lpstrTablename;
  4899. LPUSTR lpstrColumnname;
  4900. LPISAMTABLEDEF lpISAMTableDef;
  4901. SWORD err;
  4902. SWORD finalErr;
  4903. SQLNODEIDX idxTables;
  4904. SQLNODEIDX idxSqlNodeColumns;
  4905. SQLNODEIDX idxSqlNodeValues;
  4906. SQLNODEIDX idxSqlNodeSets;
  4907. SQLNODEIDX idxSortcolumns;
  4908. SQLNODEIDX idxParameter;
  4909. LPSQLNODE lpSqlNodeTables;
  4910. LPSQLNODE lpSqlNodeTable;
  4911. LPSQLNODE lpSqlNodeColumns;
  4912. LPSQLNODE lpSqlNodeColumn;
  4913. LPSQLNODE lpSqlNodeValues;
  4914. LPSQLNODE lpSqlNodeValue;
  4915. LPSQLNODE lpSqlNodePredicate;
  4916. LPSQLNODE lpSqlNodeSets;
  4917. LPSQLNODE lpSqlNodeSortcolumns;
  4918. LPSQLNODE lpSqlNodeParameter;
  4919. LPSQLNODE lpSqlNodeSelect;
  4920. UWORD idx;
  4921. BOOL fSelect;
  4922. BOOL fSubSelect;
  4923. // ODBCTRACE ("\nWBEM ODBC Driver : ExecuteQuery\n");
  4924. /* Nested sub-select? */
  4925. if (lpSqlNode == NULL) {
  4926. /* No. Count of rows is not available */
  4927. fSubSelect = FALSE;
  4928. lpstmt->cRowCount = -1;
  4929. /* If there are passthrough parameters, send them now */
  4930. lpSqlNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE);
  4931. if (lpSqlNode->node.root.passthroughParams) {
  4932. idxParameter = lpSqlNode->node.root.parameters;
  4933. while (idxParameter != NO_SQLNODE) {
  4934. lpSqlNodeParameter = ToNode(lpstmt->lpSqlStmt, idxParameter);
  4935. switch (lpSqlNodeParameter->sqlDataType) {
  4936. case TYPE_DOUBLE:
  4937. case TYPE_INTEGER:
  4938. err = ISAMParameter(lpstmt->lpISAMStatement,
  4939. lpSqlNodeParameter->node.parameter.Id,
  4940. SQL_C_DOUBLE,
  4941. &(lpSqlNodeParameter->value.Double),
  4942. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4943. sizeof(double));
  4944. break;
  4945. case TYPE_NUMERIC:
  4946. case TYPE_CHAR:
  4947. err = ISAMParameter(lpstmt->lpISAMStatement,
  4948. lpSqlNodeParameter->node.parameter.Id,
  4949. SQL_C_CHAR, lpSqlNodeParameter->value.String,
  4950. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4951. s_lstrlen(lpSqlNodeParameter->value.String));
  4952. break;
  4953. case TYPE_BINARY:
  4954. err = ISAMParameter(lpstmt->lpISAMStatement,
  4955. lpSqlNodeParameter->node.parameter.Id,
  4956. SQL_C_BINARY,
  4957. BINARY_DATA(lpSqlNodeParameter->value.Binary),
  4958. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4959. BINARY_LENGTH(lpSqlNodeParameter->value.Binary));
  4960. break;
  4961. case TYPE_DATE:
  4962. err = ISAMParameter(lpstmt->lpISAMStatement,
  4963. lpSqlNodeParameter->node.parameter.Id,
  4964. SQL_C_DATE, &(lpSqlNodeParameter->value.Date),
  4965. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4966. sizeof(DATE_STRUCT));
  4967. break;
  4968. case TYPE_TIME:
  4969. err = ISAMParameter(lpstmt->lpISAMStatement,
  4970. lpSqlNodeParameter->node.parameter.Id,
  4971. SQL_C_TIME, &(lpSqlNodeParameter->value.Time),
  4972. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4973. sizeof(TIME_STRUCT));
  4974. break;
  4975. case TYPE_TIMESTAMP:
  4976. err = ISAMParameter(lpstmt->lpISAMStatement,
  4977. lpSqlNodeParameter->node.parameter.Id,
  4978. SQL_C_TIMESTAMP,
  4979. &(lpSqlNodeParameter->value.Timestamp),
  4980. lpSqlNodeParameter->sqlIsNull ? SQL_NULL_DATA :
  4981. sizeof(TIMESTAMP_STRUCT));
  4982. break;
  4983. default:
  4984. return ERR_NOTSUPPORTED;
  4985. }
  4986. if (err != NO_ISAM_ERR) {
  4987. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  4988. (LPUSTR)lpstmt->szISAMError);
  4989. return err;
  4990. }
  4991. lpstmt->fISAMTxnStarted = TRUE;
  4992. idxParameter = lpSqlNodeParameter->node.parameter.Next;
  4993. }
  4994. }
  4995. /* Get the root node of the operation */
  4996. lpSqlNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE);
  4997. lpSqlNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.root.sql);
  4998. }
  4999. else {
  5000. /* Yes. It is a sub-select */
  5001. fSubSelect = TRUE;
  5002. }
  5003. finalErr = ERR_SUCCESS;
  5004. fSelect = FALSE;
  5005. switch (lpSqlNode->sqlNodeType) {
  5006. /* Create a table */
  5007. case NODE_TYPE_CREATE:
  5008. /* Make sure this DDL statement is allowed now */
  5009. err = TxnCapableForDDL(lpstmt);
  5010. if (err == ERR_DDLIGNORED)
  5011. return ERR_DDLIGNORED;
  5012. else if (err == ERR_DDLCAUSEDACOMMIT)
  5013. finalErr = ERR_DDLCAUSEDACOMMIT;
  5014. else if (err != ERR_SUCCESS)
  5015. return err;
  5016. /* Find the table to create */
  5017. lpstrTablename = ToString(lpstmt->lpSqlStmt, lpSqlNode->node.create.Table);
  5018. /* Create the table */
  5019. err = ISAMCreateTable(lpstmt->lpdbc->lpISAM,
  5020. (LPUSTR) lpstrTablename, &lpISAMTableDef);
  5021. if (err != NO_ISAM_ERR) {
  5022. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5023. return err;
  5024. }
  5025. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5026. lpstmt->fISAMTxnStarted = TRUE;
  5027. /* Add the columns to the table */
  5028. lpSqlNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.create.Columns);
  5029. while (TRUE) {
  5030. /* Error if wrong node type */
  5031. if (lpSqlNode->sqlNodeType != NODE_TYPE_CREATECOLS) {
  5032. ISAMCloseTable(lpISAMTableDef);
  5033. if (NO_ISAM_ERR ==
  5034. ISAMDeleteTable(lpstmt->lpdbc->lpISAM, (LPUSTR) lpstrTablename)) {
  5035. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5036. lpstmt->fISAMTxnStarted = TRUE;
  5037. }
  5038. return ERR_INTERNAL;
  5039. }
  5040. /* Get column name */
  5041. lpstrColumnname = ToString(lpstmt->lpSqlStmt,
  5042. lpSqlNode->node.createcols.Name);
  5043. /* Add the column to the table */
  5044. err = ISAMAddColumn(lpISAMTableDef, (LPUSTR) lpstrColumnname,
  5045. lpSqlNode->node.createcols.iSqlType,
  5046. lpSqlNode->node.createcols.Param1, lpSqlNode->node.createcols.Param2);
  5047. if (err != NO_ISAM_ERR) {
  5048. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5049. (LPUSTR)lpstmt->szISAMError);
  5050. ISAMCloseTable(lpISAMTableDef);
  5051. if (NO_ISAM_ERR ==
  5052. ISAMDeleteTable(lpstmt->lpdbc->lpISAM, (LPUSTR) lpstrTablename)) {
  5053. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5054. lpstmt->fISAMTxnStarted = TRUE;
  5055. }
  5056. return err;
  5057. }
  5058. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5059. lpstmt->fISAMTxnStarted = TRUE;
  5060. /* Find next column */
  5061. if (lpSqlNode->node.createcols.Next == NO_SQLNODE)
  5062. break;
  5063. lpSqlNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.createcols.Next);
  5064. }
  5065. /* Close the table */
  5066. err = ISAMCloseTable(lpISAMTableDef);
  5067. if (err != NO_ISAM_ERR) {
  5068. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5069. if (NO_ISAM_ERR ==
  5070. ISAMDeleteTable(lpstmt->lpdbc->lpISAM, (LPUSTR) lpstrTablename)) {
  5071. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5072. lpstmt->fISAMTxnStarted = TRUE;
  5073. }
  5074. return err;
  5075. }
  5076. break;
  5077. /* Drop a table */
  5078. case NODE_TYPE_DROP:
  5079. /* Make sure this DDL statement is allowed now */
  5080. err = TxnCapableForDDL(lpstmt);
  5081. if (err == ERR_DDLIGNORED)
  5082. return ERR_DDLIGNORED;
  5083. else if (err == ERR_DDLCAUSEDACOMMIT)
  5084. finalErr = ERR_DDLCAUSEDACOMMIT;
  5085. else if (err != ERR_SUCCESS)
  5086. return err;
  5087. /* Find the table to drop */
  5088. lpstrTablename = ToString(lpstmt->lpSqlStmt, lpSqlNode->node.drop.Table);
  5089. /* Drop the table */
  5090. err = ISAMDeleteTable(lpstmt->lpdbc->lpISAM, (LPUSTR) lpstrTablename);
  5091. if (err != NO_ISAM_ERR) {
  5092. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5093. return err;
  5094. }
  5095. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5096. lpstmt->fISAMTxnStarted = TRUE;
  5097. break;
  5098. /* SELECT statement */
  5099. case NODE_TYPE_SELECT:
  5100. /* Is there a passthrough SQL statement? */
  5101. lpstmt->fDMLTxn = TRUE;
  5102. fSelect = TRUE;
  5103. if (!fSubSelect) {
  5104. if (lpstmt->lpISAMStatement != NULL) {
  5105. /* Yes. Execute it now */
  5106. err = ISAMExecute(lpstmt->lpISAMStatement,
  5107. &(lpSqlNode->node.select.RowCount));
  5108. if (err != NO_ISAM_ERR) {
  5109. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5110. (LPUSTR)lpstmt->szISAMError);
  5111. return err;
  5112. }
  5113. lpstmt->fISAMTxnStarted = TRUE;
  5114. }
  5115. else {
  5116. lpSqlNode->node.select.RowCount = -1;
  5117. }
  5118. }
  5119. /* Is there a pushdown sort? */
  5120. if ((lpSqlNode->node.select.Sortcolumns != NO_SQLNODE) &&
  5121. lpSqlNode->node.select.fPushdownSort) {
  5122. UWORD icol[MAX_COLUMNS_IN_ORDER_BY];
  5123. BOOL fDescending[MAX_COLUMNS_IN_ORDER_BY];
  5124. /* Yes. For each table... */
  5125. idxTables = lpSqlNode->node.select.Tables;
  5126. while (idxTables != NO_SQLNODE) {
  5127. /* If no pushdown sort for this table, leave the loop */
  5128. /* (since there will be no pushdowns for any of the */
  5129. /* subsequent tables either) */
  5130. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt, idxTables);
  5131. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  5132. lpSqlNodeTables->node.tables.Table);
  5133. if (lpSqlNodeTable->node.table.Sortcount == 0)
  5134. break;
  5135. /* Create sort info arrays. For each column in sequence... */
  5136. idxSortcolumns = lpSqlNodeTable->node.table.Sortcolumns;
  5137. for (idx = 0; idx < lpSqlNodeTable->node.table.Sortcount; idx++) {
  5138. /* Get the column description */
  5139. lpSqlNodeSortcolumns = ToNode(lpstmt->lpSqlStmt,
  5140. idxSortcolumns);
  5141. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt,
  5142. lpSqlNodeSortcolumns->node.sortcolumns.Column);
  5143. /* Put information into the array */
  5144. icol[idx] = lpSqlNodeColumn->node.column.Id;
  5145. fDescending[idx] =
  5146. lpSqlNodeSortcolumns->node.sortcolumns.Descending;
  5147. /* Look at next column */
  5148. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  5149. }
  5150. /* Get the records in sorted order */
  5151. err = ISAMSort(lpSqlNodeTable->node.table.Handle,
  5152. lpSqlNodeTable->node.table.Sortcount,
  5153. icol, fDescending);
  5154. /* Can this sort be pushed down? */
  5155. if (err == ISAM_NOTSUPPORTED) {
  5156. /* No. Turn off all the sorts */
  5157. idxTables = lpSqlNode->node.select.Tables;
  5158. while (idxTables != NO_SQLNODE) {
  5159. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt, idxTables);
  5160. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  5161. lpSqlNodeTables->node.tables.Table);
  5162. if (lpSqlNodeTable->node.table.Sortcount == 0)
  5163. break;
  5164. err = ISAMSort(lpSqlNodeTable->node.table.Handle, 0,
  5165. icol, fDescending);
  5166. if ((err != NO_ISAM_ERR) &&
  5167. (err != ISAM_NOTSUPPORTED)) {
  5168. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5169. (LPUSTR)lpstmt->szISAMError);
  5170. return err;
  5171. }
  5172. if (err == NO_ISAM_ERR)
  5173. lpstmt->fISAMTxnStarted = TRUE;
  5174. idxTables = lpSqlNodeTables->node.tables.Next;
  5175. }
  5176. /* Don't try to do pushdown sort again */
  5177. lpSqlNode->node.select.fPushdownSort = FALSE;
  5178. /* Leave this loop */
  5179. break;
  5180. }
  5181. else if (err != NO_ISAM_ERR) {
  5182. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5183. (LPUSTR)lpstmt->szISAMError);
  5184. return err;
  5185. }
  5186. else
  5187. lpstmt->fISAMTxnStarted = TRUE;
  5188. /* Look at next table */
  5189. idxTables = lpSqlNodeTables->node.tables.Next;
  5190. }
  5191. }
  5192. /* Rewind the tables */
  5193. lpSqlNodeTables = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.select.Tables);
  5194. err = Rewind(lpstmt, lpSqlNodeTables, FALSE);
  5195. if (err == ERR_NODATAFOUND) {
  5196. if (!fSubSelect) {
  5197. lpstmt->fStmtType = STMT_TYPE_SELECT;
  5198. lpstmt->fStmtSubtype = STMT_SUBTYPE_NONE;
  5199. lpstmt->cRowCount = 0;
  5200. }
  5201. lpSqlNode->node.select.RowCount = 0;
  5202. lpSqlNode->node.select.CurrentRow = AFTER_LAST_ROW;
  5203. if (!fSubSelect) {
  5204. lpstmt->icol = NO_COLUMN;
  5205. lpstmt->cbOffset = 0;
  5206. }
  5207. break;
  5208. }
  5209. else if (err != ERR_SUCCESS)
  5210. return err;
  5211. /* Show a SELECT statement as the active statement */
  5212. if (!fSubSelect) {
  5213. lpstmt->fStmtType = STMT_TYPE_SELECT;
  5214. lpstmt->fStmtSubtype = STMT_SUBTYPE_NONE;
  5215. }
  5216. /* So far no data read */
  5217. lpSqlNode->node.select.CurrentRow = BEFORE_FIRST_ROW;
  5218. /* So far no column read */
  5219. if (!fSubSelect) {
  5220. lpstmt->icol = NO_COLUMN;
  5221. lpstmt->cbOffset = 0;
  5222. }
  5223. /* Is a sort needed? */
  5224. if (((lpSqlNode->node.select.Sortcolumns != NO_SQLNODE) ||
  5225. (lpSqlNode->node.select.ImplicitGroupby)) &&
  5226. (!lpSqlNode->node.select.fPushdownSort)) {
  5227. /* Yes. Do it */
  5228. err = Sort(lpstmt, lpSqlNode);
  5229. if (err != ERR_SUCCESS)
  5230. return err;
  5231. }
  5232. /* Is group by needed? */
  5233. if ((lpSqlNode->node.select.Groupbycolumns != NO_SQLNODE) ||
  5234. (lpSqlNode->node.select.ImplicitGroupby)) {
  5235. /* Yes. Do it */
  5236. err = GroupBy(lpstmt, lpSqlNode);
  5237. if (err != ERR_SUCCESS) {
  5238. if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) {
  5239. _lclose(lpSqlNode->node.select.Sortfile);
  5240. lpSqlNode->node.select.Sortfile = HFILE_ERROR;
  5241. lpSqlNode->node.select.ReturningDistinct = FALSE;
  5242. DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt,
  5243. lpSqlNode->node.select.SortfileName));
  5244. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  5245. lpSqlNode->node.select.SortfileName), "");
  5246. }
  5247. return err;
  5248. }
  5249. }
  5250. /* Is DISTINCT specified? */
  5251. if (lpSqlNode->node.select.Distinct) {
  5252. /* Yes. Do it */
  5253. err = Distinct(lpstmt, lpSqlNode);
  5254. if (err != ERR_SUCCESS) {
  5255. if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) {
  5256. _lclose(lpSqlNode->node.select.Sortfile);
  5257. lpSqlNode->node.select.Sortfile = HFILE_ERROR;
  5258. lpSqlNode->node.select.ReturningDistinct = FALSE;
  5259. DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt,
  5260. lpSqlNode->node.select.SortfileName));
  5261. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  5262. lpSqlNode->node.select.SortfileName), "");
  5263. }
  5264. return err;
  5265. }
  5266. }
  5267. /* MSAccess optimization needed? */
  5268. if (lpSqlNode->node.select.fMSAccess) {
  5269. /* Yes. Do it */
  5270. err = MSAccess(lpstmt, lpSqlNode,
  5271. ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE)->node.root.sql);
  5272. if (err != ERR_SUCCESS) {
  5273. if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) {
  5274. _lclose(lpSqlNode->node.select.Sortfile);
  5275. lpSqlNode->node.select.Sortfile = HFILE_ERROR;
  5276. lpSqlNode->node.select.ReturningDistinct = FALSE;
  5277. DeleteFile((LPCSTR) ToString(lpstmt->lpSqlStmt,
  5278. lpSqlNode->node.select.SortfileName));
  5279. s_lstrcpy(ToString(lpstmt->lpSqlStmt,
  5280. lpSqlNode->node.select.SortfileName), "");
  5281. }
  5282. return err;
  5283. }
  5284. }
  5285. /* Return the row count */
  5286. if (!fSubSelect) {
  5287. lpstmt->cRowCount = lpSqlNode->node.select.RowCount;
  5288. }
  5289. break;
  5290. /* INSERT statement */
  5291. case NODE_TYPE_INSERT:
  5292. {
  5293. /* Sub-select? */
  5294. lpSqlNodeSelect = ToNode(lpstmt->lpSqlStmt,
  5295. lpSqlNode->node.insert.Values);
  5296. if (lpSqlNodeSelect->sqlNodeType == NODE_TYPE_SELECT) {
  5297. err = ExecuteQuery(lpstmt, lpSqlNodeSelect);
  5298. if (err == ERR_DATATRUNCATED) {
  5299. finalErr = ERR_DATATRUNCATED;
  5300. err = ERR_SUCCESS;
  5301. }
  5302. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  5303. return err;
  5304. }
  5305. else
  5306. lpSqlNodeSelect = NULL;
  5307. /* Insert rows into the table */
  5308. lpstmt->cRowCount = 0;
  5309. while (TRUE) {
  5310. /* Get next row to insert */
  5311. if (lpSqlNodeSelect != NULL) {
  5312. if (err == ERR_SUCCESS) {
  5313. // ODBCTRACE("\nWBEM ODBC Driver : Get next row to insert\n");
  5314. err = FetchRow(lpstmt, lpSqlNodeSelect);
  5315. if ((err != ERR_SUCCESS) && (err != ERR_NODATAFOUND))
  5316. return err;
  5317. }
  5318. /* Leave if no more rows */
  5319. if (err == ERR_NODATAFOUND)
  5320. break;
  5321. /* Get list of values */
  5322. idxSqlNodeValues = lpSqlNodeSelect->node.select.Values;
  5323. }
  5324. else {
  5325. idxSqlNodeValues = lpSqlNode->node.insert.Values;
  5326. }
  5327. /* Add a row to the table. */
  5328. lpstmt->fDMLTxn = TRUE;
  5329. lpSqlNodeTable =
  5330. ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.insert.Table);
  5331. lpISAMTableDef = lpSqlNodeTable->node.table.Handle;
  5332. err = ISAMInsertRecord(lpISAMTableDef);
  5333. if (err != NO_ISAM_ERR) {
  5334. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5335. return err;
  5336. }
  5337. lpstmt->fISAMTxnStarted = TRUE;
  5338. /* Evaluate each column value and copy it into the new record. */
  5339. idxSqlNodeColumns = lpSqlNode->node.insert.Columns;
  5340. while (idxSqlNodeColumns != NO_SQLNODE) {
  5341. lpSqlNodeColumns = ToNode(lpstmt->lpSqlStmt, idxSqlNodeColumns);
  5342. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt, lpSqlNodeColumns->node.columns.Column);
  5343. lpSqlNodeValues = ToNode(lpstmt->lpSqlStmt, idxSqlNodeValues);
  5344. lpSqlNodeValue = ToNode(lpstmt->lpSqlStmt, lpSqlNodeValues->node.values.Value);
  5345. err = EvaluateExpression(lpstmt, lpSqlNodeValue);
  5346. if (err != ERR_SUCCESS) {
  5347. if (ERR_SUCCESS == ISAMDeleteRecord(lpISAMTableDef))
  5348. lpstmt->fISAMTxnStarted = TRUE;
  5349. return err;
  5350. }
  5351. switch (lpSqlNodeColumn->sqlDataType) {
  5352. case TYPE_DOUBLE:
  5353. case TYPE_INTEGER:
  5354. {
  5355. switch (lpSqlNodeValue->sqlDataType) {
  5356. case TYPE_DOUBLE:
  5357. case TYPE_INTEGER:
  5358. lpSqlNodeColumn->value.Double =
  5359. lpSqlNodeValue->value.Double;
  5360. break;
  5361. case TYPE_NUMERIC:
  5362. if (!(lpSqlNodeValue->sqlIsNull))
  5363. CharToDouble(lpSqlNodeValue->value.String,
  5364. s_lstrlen(lpSqlNodeValue->value.String), FALSE,
  5365. -1.7E308, 1.7E308,
  5366. &(lpSqlNodeColumn->value.Double));
  5367. else
  5368. lpSqlNodeColumn->value.Double = 0.0;
  5369. break;
  5370. case TYPE_CHAR:
  5371. case TYPE_BINARY:
  5372. case TYPE_DATE:
  5373. case TYPE_TIME:
  5374. case TYPE_TIMESTAMP:
  5375. default:
  5376. return ERR_INTERNAL;
  5377. }
  5378. err = ISAMPutData(lpISAMTableDef,
  5379. lpSqlNodeColumn->node.column.Id, SQL_C_DOUBLE,
  5380. &(lpSqlNodeColumn->value.Double),
  5381. lpSqlNodeValue->sqlIsNull ?
  5382. (SDWORD) SQL_NULL_DATA : sizeof(double));
  5383. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5384. lpstmt->fISAMTxnStarted = TRUE;
  5385. }
  5386. break;
  5387. case TYPE_NUMERIC:
  5388. {
  5389. lpSqlNodeColumn->value.String = ToString(lpstmt->lpSqlStmt,
  5390. lpSqlNodeColumn->node.column.Value);
  5391. switch (lpSqlNodeValue->sqlDataType) {
  5392. case TYPE_DOUBLE:
  5393. case TYPE_INTEGER:
  5394. if (!(lpSqlNodeValue->sqlIsNull)) {
  5395. if (DoubleToChar(lpSqlNodeValue->value.Double,
  5396. FALSE, lpSqlNodeColumn->value.String,
  5397. 1 + 2 + lpSqlNodeColumn->sqlPrecision)) {
  5398. lpSqlNodeColumn->value.String[1 + 2 +
  5399. lpSqlNodeColumn->sqlPrecision - 1] = '\0';
  5400. finalErr = ERR_DATATRUNCATED;
  5401. }
  5402. }
  5403. else
  5404. s_lstrcpy(lpSqlNodeColumn->value.String, "0");
  5405. break;
  5406. case TYPE_NUMERIC:
  5407. s_lstrcpy(lpSqlNodeColumn->value.String,
  5408. lpSqlNodeValue->value.String);
  5409. break;
  5410. case TYPE_CHAR:
  5411. case TYPE_BINARY:
  5412. case TYPE_DATE:
  5413. case TYPE_TIME:
  5414. case TYPE_TIMESTAMP:
  5415. default:
  5416. return ERR_INTERNAL;
  5417. }
  5418. err = BCDNormalize(lpSqlNodeColumn->value.String,
  5419. s_lstrlen(lpSqlNodeColumn->value.String),
  5420. lpSqlNodeColumn->value.String,
  5421. 1 + 2 + lpSqlNodeColumn->sqlPrecision,
  5422. lpSqlNodeColumn->sqlPrecision,
  5423. lpSqlNodeColumn->sqlScale);
  5424. if (err == ERR_DATATRUNCATED) {
  5425. finalErr = ERR_DATATRUNCATED;
  5426. err = ERR_SUCCESS;
  5427. }
  5428. if (err == ERR_SUCCESS) {
  5429. err = ISAMPutData(lpISAMTableDef,
  5430. lpSqlNodeColumn->node.column.Id, SQL_C_CHAR,
  5431. lpSqlNodeColumn->value.String,
  5432. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5433. s_lstrlen(lpSqlNodeColumn->value.String));
  5434. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5435. lpstmt->fISAMTxnStarted = TRUE;
  5436. }
  5437. }
  5438. break;
  5439. case TYPE_CHAR:
  5440. err = ISAMPutData(lpISAMTableDef,
  5441. lpSqlNodeColumn->node.column.Id,
  5442. SQL_C_CHAR, lpSqlNodeValue->value.String,
  5443. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5444. s_lstrlen(lpSqlNodeValue->value.String));
  5445. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5446. lpstmt->fISAMTxnStarted = TRUE;
  5447. break;
  5448. case TYPE_BINARY:
  5449. err = ISAMPutData(lpISAMTableDef, lpSqlNodeColumn->node.column.Id,
  5450. SQL_C_BINARY, BINARY_DATA(lpSqlNodeValue->value.Binary),
  5451. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5452. BINARY_LENGTH(lpSqlNodeValue->value.Binary));
  5453. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5454. lpstmt->fISAMTxnStarted = TRUE;
  5455. break;
  5456. case TYPE_DATE:
  5457. err = ISAMPutData(lpISAMTableDef, lpSqlNodeColumn->node.column.Id,
  5458. SQL_C_DATE, &(lpSqlNodeValue->value.Date),
  5459. lpSqlNodeValue->sqlIsNull ?
  5460. (SDWORD) SQL_NULL_DATA : sizeof(DATE_STRUCT));
  5461. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5462. lpstmt->fISAMTxnStarted = TRUE;
  5463. break;
  5464. case TYPE_TIME:
  5465. err = ISAMPutData(lpISAMTableDef, lpSqlNodeColumn->node.column.Id,
  5466. SQL_C_TIME, &(lpSqlNodeValue->value.Time),
  5467. lpSqlNodeValue->sqlIsNull ?
  5468. (SDWORD) SQL_NULL_DATA : sizeof(TIME_STRUCT));
  5469. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5470. lpstmt->fISAMTxnStarted = TRUE;
  5471. break;
  5472. case TYPE_TIMESTAMP:
  5473. err = ISAMPutData(lpISAMTableDef, lpSqlNodeColumn->node.column.Id,
  5474. SQL_C_TIMESTAMP, &(lpSqlNodeValue->value.Timestamp),
  5475. lpSqlNodeValue->sqlIsNull ?
  5476. (SDWORD) SQL_NULL_DATA : sizeof(TIMESTAMP_STRUCT));
  5477. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5478. lpstmt->fISAMTxnStarted = TRUE;
  5479. break;
  5480. default:
  5481. err = ERR_INTERNAL;
  5482. }
  5483. if (err == ISAM_TRUNCATION) {
  5484. finalErr = ERR_DATATRUNCATED;
  5485. err = NO_ISAM_ERR;
  5486. }
  5487. if (err != NO_ISAM_ERR) {
  5488. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5489. (LPUSTR)lpstmt->szISAMError);
  5490. if (ERR_SUCCESS == ISAMDeleteRecord(lpISAMTableDef))
  5491. lpstmt->fISAMTxnStarted = TRUE;
  5492. return err;
  5493. }
  5494. idxSqlNodeColumns = lpSqlNodeColumns->node.columns.Next;
  5495. idxSqlNodeValues = lpSqlNodeValues->node.values.Next;
  5496. }
  5497. /* Write the updated row to the table. */
  5498. err = ISAMUpdateRecord(lpISAMTableDef);
  5499. if (err != NO_ISAM_ERR) {
  5500. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5501. if (ERR_SUCCESS == ISAMDeleteRecord(lpISAMTableDef))
  5502. lpstmt->fISAMTxnStarted = TRUE;
  5503. return err;
  5504. }
  5505. lpstmt->fISAMTxnStarted = TRUE;
  5506. /* Increment row count */
  5507. lpstmt->cRowCount++;
  5508. /* Leave if just inserting a single row */
  5509. if (lpSqlNodeSelect == NULL)
  5510. break;
  5511. }
  5512. }
  5513. break;
  5514. /* DELETE statement */
  5515. case NODE_TYPE_DELETE:
  5516. {
  5517. /* Get the table handle and predicate node. */
  5518. lpstmt->fDMLTxn = TRUE;
  5519. lpSqlNodeTable = ToNode (lpstmt->lpSqlStmt, lpSqlNode->node.delet.Table);
  5520. lpISAMTableDef = lpSqlNodeTable->node.table.Handle;
  5521. if (lpSqlNode->node.delet.Predicate == NO_SQLNODE)
  5522. lpSqlNodePredicate = NULL;
  5523. else
  5524. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt,
  5525. lpSqlNode->node.delet.Predicate);
  5526. /* Rewind the table */
  5527. err = Rewind(lpstmt, lpSqlNodeTable, FALSE);
  5528. if (err != ERR_SUCCESS)
  5529. return err;
  5530. /* Delete each record that satisfies the WHERE clause. */
  5531. lpstmt->cRowCount = 0;
  5532. while (TRUE) {
  5533. /* Get next record */
  5534. err = NextRecord(lpstmt, lpSqlNodeTable,
  5535. lpSqlNodePredicate);
  5536. if (err == ERR_NODATAFOUND)
  5537. break;
  5538. else if (err != ERR_SUCCESS)
  5539. return err;
  5540. /* Delete record */
  5541. err = ISAMDeleteRecord(lpISAMTableDef);
  5542. if (err != NO_ISAM_ERR) {
  5543. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5544. (LPUSTR)lpstmt->szISAMError);
  5545. return err;
  5546. }
  5547. lpstmt->fISAMTxnStarted = TRUE;
  5548. /* Increase count */
  5549. (lpstmt->cRowCount)++;
  5550. }
  5551. }
  5552. break;
  5553. /* UPDATE statement */
  5554. case NODE_TYPE_UPDATE:
  5555. {
  5556. /* Get the table handle, predicate node. */
  5557. lpstmt->fDMLTxn = TRUE;
  5558. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt, lpSqlNode->node.update.Table);
  5559. lpISAMTableDef = lpSqlNodeTable->node.table.Handle;
  5560. if (lpSqlNode->node.update.Predicate == NO_SQLNODE)
  5561. lpSqlNodePredicate = NULL;
  5562. else
  5563. lpSqlNodePredicate = ToNode(lpstmt->lpSqlStmt,
  5564. lpSqlNode->node.update.Predicate);
  5565. /* Rewind the table */
  5566. err = Rewind(lpstmt, lpSqlNodeTable, FALSE);
  5567. if (err != ERR_SUCCESS)
  5568. return err;
  5569. /* Update each record that satisfies the WHERE clause. */
  5570. lpstmt->cRowCount = 0;
  5571. while (TRUE) {
  5572. /* Get next record */
  5573. err = NextRecord(lpstmt, lpSqlNodeTable,
  5574. lpSqlNodePredicate);
  5575. if (err == ERR_NODATAFOUND)
  5576. break;
  5577. else if (err != ERR_SUCCESS)
  5578. return err;
  5579. /* For each set column... */
  5580. idxSqlNodeSets = lpSqlNode->node.update.Updatevalues;
  5581. while (idxSqlNodeSets != NO_SQLNODE) {
  5582. /* Get the column */
  5583. lpSqlNodeSets = ToNode(lpstmt->lpSqlStmt, idxSqlNodeSets);
  5584. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt, lpSqlNodeSets->node.updatevalues.Column);
  5585. /* Get the value to set the column to */
  5586. lpSqlNodeValue = ToNode(lpstmt->lpSqlStmt, lpSqlNodeSets->node.updatevalues.Value);
  5587. err = EvaluateExpression(lpstmt, lpSqlNodeValue);
  5588. if (err != ERR_SUCCESS)
  5589. return err;
  5590. /* Put the data into the record */
  5591. switch (lpSqlNodeColumn->sqlDataType) {
  5592. case TYPE_DOUBLE:
  5593. case TYPE_INTEGER:
  5594. switch (lpSqlNodeValue->sqlDataType) {
  5595. case TYPE_DOUBLE:
  5596. case TYPE_INTEGER:
  5597. lpSqlNodeColumn->value.Double =
  5598. lpSqlNodeValue->value.Double;
  5599. break;
  5600. case TYPE_NUMERIC:
  5601. if (!(lpSqlNodeValue->sqlIsNull))
  5602. CharToDouble(lpSqlNodeValue->value.String,
  5603. s_lstrlen(lpSqlNodeValue->value.String), FALSE,
  5604. -1.7E308, 1.7E308,
  5605. &(lpSqlNodeColumn->value.Double));
  5606. else
  5607. lpSqlNodeColumn->value.Double = 0.0;
  5608. break;
  5609. case TYPE_CHAR:
  5610. case TYPE_BINARY:
  5611. case TYPE_DATE:
  5612. case TYPE_TIME:
  5613. case TYPE_TIMESTAMP:
  5614. default:
  5615. return ERR_INTERNAL;
  5616. }
  5617. err = ISAMPutData(lpISAMTableDef,
  5618. lpSqlNodeColumn->node.column.Id, SQL_C_DOUBLE,
  5619. &(lpSqlNodeColumn->value.Double),
  5620. lpSqlNodeValue->sqlIsNull ?
  5621. (SDWORD) SQL_NULL_DATA : sizeof(double));
  5622. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5623. lpstmt->fISAMTxnStarted = TRUE;
  5624. break;
  5625. case TYPE_NUMERIC:
  5626. lpSqlNodeColumn->value.String =ToString(lpstmt->lpSqlStmt,
  5627. lpSqlNodeColumn->node.column.Value);
  5628. switch (lpSqlNodeValue->sqlDataType) {
  5629. case TYPE_DOUBLE:
  5630. case TYPE_INTEGER:
  5631. if (!(lpSqlNodeValue->sqlIsNull)) {
  5632. if (DoubleToChar(lpSqlNodeValue->value.Double,
  5633. FALSE, lpSqlNodeColumn->value.String,
  5634. 1 + 2 + lpSqlNodeColumn->sqlPrecision)) {
  5635. lpSqlNodeColumn->value.String[
  5636. 1+2+lpSqlNodeColumn->sqlPrecision-1]='\0';
  5637. finalErr = ERR_DATATRUNCATED;
  5638. }
  5639. }
  5640. else
  5641. s_lstrcpy(lpSqlNodeColumn->value.String, "0");
  5642. break;
  5643. case TYPE_NUMERIC:
  5644. s_lstrcpy(lpSqlNodeColumn->value.String,
  5645. lpSqlNodeValue->value.String);
  5646. break;
  5647. case TYPE_CHAR:
  5648. case TYPE_BINARY:
  5649. case TYPE_DATE:
  5650. case TYPE_TIME:
  5651. case TYPE_TIMESTAMP:
  5652. default:
  5653. return ERR_INTERNAL;
  5654. }
  5655. err = BCDNormalize(lpSqlNodeColumn->value.String,
  5656. s_lstrlen(lpSqlNodeColumn->value.String),
  5657. lpSqlNodeColumn->value.String,
  5658. 1 + 2 + lpSqlNodeColumn->sqlPrecision,
  5659. lpSqlNodeColumn->sqlPrecision,
  5660. lpSqlNodeColumn->sqlScale);
  5661. if (err == ERR_DATATRUNCATED) {
  5662. finalErr = ERR_DATATRUNCATED;
  5663. err = ERR_SUCCESS;
  5664. }
  5665. if (err == ERR_SUCCESS) {
  5666. err = ISAMPutData(lpISAMTableDef,
  5667. lpSqlNodeColumn->node.column.Id, SQL_C_CHAR,
  5668. lpSqlNodeColumn->value.String,
  5669. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5670. s_lstrlen(lpSqlNodeColumn->value.String));
  5671. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5672. lpstmt->fISAMTxnStarted = TRUE;
  5673. }
  5674. break;
  5675. case TYPE_CHAR:
  5676. err = ISAMPutData(lpISAMTableDef,
  5677. lpSqlNodeColumn->node.column.Id, SQL_C_CHAR,
  5678. lpSqlNodeValue->value.String,
  5679. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5680. s_lstrlen(lpSqlNodeValue->value.String));
  5681. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5682. lpstmt->fISAMTxnStarted = TRUE;
  5683. break;
  5684. case TYPE_BINARY:
  5685. err = ISAMPutData(lpISAMTableDef,
  5686. lpSqlNodeColumn->node.column.Id, SQL_C_BINARY,
  5687. BINARY_DATA(lpSqlNodeValue->value.Binary),
  5688. lpSqlNodeValue->sqlIsNull ? SQL_NULL_DATA :
  5689. BINARY_LENGTH(lpSqlNodeValue->value.Binary));
  5690. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5691. lpstmt->fISAMTxnStarted = TRUE;
  5692. break;
  5693. case TYPE_DATE:
  5694. err = ISAMPutData(lpISAMTableDef,
  5695. lpSqlNodeColumn->node.column.Id, SQL_C_DATE,
  5696. &(lpSqlNodeValue->value.Date),
  5697. lpSqlNodeValue->sqlIsNull ?
  5698. (SDWORD) SQL_NULL_DATA : sizeof(DATE_STRUCT));
  5699. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5700. lpstmt->fISAMTxnStarted = TRUE;
  5701. break;
  5702. case TYPE_TIME:
  5703. err = ISAMPutData(lpISAMTableDef,
  5704. lpSqlNodeColumn->node.column.Id, SQL_C_TIME,
  5705. &(lpSqlNodeValue->value.Time),
  5706. lpSqlNodeValue->sqlIsNull ?
  5707. (SDWORD) SQL_NULL_DATA : sizeof(TIME_STRUCT));
  5708. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5709. lpstmt->fISAMTxnStarted = TRUE;
  5710. break;
  5711. case TYPE_TIMESTAMP:
  5712. err = ISAMPutData(lpISAMTableDef,
  5713. lpSqlNodeColumn->node.column.Id, SQL_C_TIMESTAMP,
  5714. &(lpSqlNodeValue->value.Timestamp),
  5715. lpSqlNodeValue->sqlIsNull ?
  5716. (SDWORD) SQL_NULL_DATA : sizeof(TIMESTAMP_STRUCT));
  5717. if ((err == NO_ISAM_ERR) || (err == ISAM_TRUNCATION))
  5718. lpstmt->fISAMTxnStarted = TRUE;
  5719. break;
  5720. default:
  5721. return ERR_INTERNAL;
  5722. }
  5723. if (err == ISAM_TRUNCATION) {
  5724. finalErr = ERR_DATATRUNCATED;
  5725. err = NO_ISAM_ERR;
  5726. }
  5727. if (err != NO_ISAM_ERR) {
  5728. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5729. (LPUSTR)lpstmt->szISAMError);
  5730. return err;
  5731. }
  5732. idxSqlNodeSets = lpSqlNodeSets->node.updatevalues.Next;
  5733. }
  5734. /* Write the updated row to the table. */
  5735. err = ISAMUpdateRecord (lpISAMTableDef);
  5736. if (err != NO_ISAM_ERR) {
  5737. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5738. (LPUSTR)lpstmt->szISAMError);
  5739. return err;
  5740. }
  5741. lpstmt->fISAMTxnStarted = TRUE;
  5742. /* Increase count */
  5743. (lpstmt->cRowCount)++;
  5744. }
  5745. }
  5746. break;
  5747. case NODE_TYPE_CREATEINDEX:
  5748. {
  5749. UWORD icol[MAX_COLUMNS_IN_INDEX];
  5750. BOOL fDescending[MAX_COLUMNS_IN_INDEX];
  5751. UWORD count;
  5752. /* Make sure this DDL statement is allowed now */
  5753. err = TxnCapableForDDL(lpstmt);
  5754. if (err == ERR_DDLIGNORED)
  5755. return ERR_DDLIGNORED;
  5756. else if (err == ERR_DDLCAUSEDACOMMIT)
  5757. finalErr = ERR_DDLCAUSEDACOMMIT;
  5758. else if (err != ERR_SUCCESS)
  5759. return err;
  5760. /* Get handle to table */
  5761. lpSqlNodeTable = ToNode(lpstmt->lpSqlStmt,
  5762. lpSqlNode->node.createindex.Table);
  5763. lpISAMTableDef = lpSqlNodeTable->node.table.Handle;
  5764. /* Get definition of the index */
  5765. idxSortcolumns = lpSqlNode->node.createindex.Columns;
  5766. count = 0;
  5767. while (idxSortcolumns != NO_SQLNODE) {
  5768. lpSqlNodeSortcolumns =
  5769. ToNode(lpstmt->lpSqlStmt, idxSortcolumns);
  5770. lpSqlNodeColumn = ToNode(lpstmt->lpSqlStmt,
  5771. lpSqlNodeSortcolumns->node.sortcolumns.Column);
  5772. icol[count] = lpSqlNodeColumn->node.column.Id;
  5773. fDescending[count] =
  5774. lpSqlNodeSortcolumns->node.sortcolumns.Descending;
  5775. count++;
  5776. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  5777. }
  5778. /* Create the index */
  5779. err = ISAMCreateIndex(lpISAMTableDef,
  5780. ToString(lpstmt->lpSqlStmt,
  5781. lpSqlNode->node.createindex.Index),
  5782. lpSqlNode->node.createindex.Unique,
  5783. count, icol, fDescending);
  5784. if (err != NO_ISAM_ERR) {
  5785. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM,
  5786. (LPUSTR) lpstmt->szISAMError);
  5787. return err;
  5788. }
  5789. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5790. lpstmt->fISAMTxnStarted = TRUE;
  5791. }
  5792. break;
  5793. case NODE_TYPE_DROPINDEX:
  5794. /* Make sure this DDL statement is allowed now */
  5795. err = TxnCapableForDDL(lpstmt);
  5796. if (err == ERR_DDLIGNORED)
  5797. return ERR_DDLIGNORED;
  5798. else if (err == ERR_DDLCAUSEDACOMMIT)
  5799. finalErr = ERR_DDLCAUSEDACOMMIT;
  5800. else if (err != ERR_SUCCESS)
  5801. return err;
  5802. /* Delete the index */
  5803. err = ISAMDeleteIndex(lpstmt->lpdbc->lpISAM,
  5804. ToString(lpstmt->lpSqlStmt,
  5805. lpSqlNode->node.dropindex.Index));
  5806. if (err != NO_ISAM_ERR) {
  5807. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR) lpstmt->szISAMError);
  5808. return err;
  5809. }
  5810. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  5811. lpstmt->fISAMTxnStarted = TRUE;
  5812. break;
  5813. case NODE_TYPE_PASSTHROUGH:
  5814. err = ISAMExecute(lpstmt->lpISAMStatement, &(lpstmt->cRowCount));
  5815. if (err != NO_ISAM_ERR) {
  5816. ISAMGetErrorMessage(lpstmt->lpdbc->lpISAM, (LPUSTR)lpstmt->szISAMError);
  5817. return err;
  5818. }
  5819. lpstmt->fISAMTxnStarted = TRUE;
  5820. break;
  5821. /* Internal error if these nodes are hanging off the root */
  5822. case NODE_TYPE_TABLES:
  5823. case NODE_TYPE_VALUES:
  5824. case NODE_TYPE_COLUMNS:
  5825. case NODE_TYPE_SORTCOLUMNS:
  5826. case NODE_TYPE_GROUPBYCOLUMNS:
  5827. case NODE_TYPE_UPDATEVALUES:
  5828. case NODE_TYPE_CREATECOLS:
  5829. case NODE_TYPE_BOOLEAN:
  5830. case NODE_TYPE_COMPARISON:
  5831. case NODE_TYPE_ALGEBRAIC:
  5832. case NODE_TYPE_SCALAR:
  5833. case NODE_TYPE_AGGREGATE:
  5834. case NODE_TYPE_TABLE:
  5835. case NODE_TYPE_COLUMN:
  5836. case NODE_TYPE_STRING:
  5837. case NODE_TYPE_NUMERIC:
  5838. case NODE_TYPE_PARAMETER:
  5839. case NODE_TYPE_USER:
  5840. case NODE_TYPE_NULL:
  5841. case NODE_TYPE_DATE:
  5842. case NODE_TYPE_TIME:
  5843. case NODE_TYPE_TIMESTAMP:
  5844. default:
  5845. return ERR_INTERNAL;
  5846. }
  5847. if (!fSelect && (lpstmt->lpdbc->lpISAM->fTxnCapable != SQL_TC_NONE) &&
  5848. lpstmt->lpdbc->fAutoCommitTxn) {
  5849. err = SQLTransact(SQL_NULL_HENV, (HDBC)lpstmt->lpdbc, SQL_COMMIT);
  5850. if ((err != SQL_SUCCESS) && (err != SQL_SUCCESS_WITH_INFO)) {
  5851. lpstmt->errcode = lpstmt->lpdbc->errcode;
  5852. s_lstrcpy(lpstmt->szISAMError, lpstmt->lpdbc->szISAMError);
  5853. return lpstmt->errcode;
  5854. }
  5855. }
  5856. return finalErr;
  5857. }
  5858. /***************************************************************************/