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.

5136 lines
180 KiB

  1. /***************************************************************************/
  2. /* SEMANTIC.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. /***************************************************************************/
  18. RETCODE INTFUNC FindColumn(LPSTMT lpstmt,
  19. LPSQLTREE lpSql,
  20. BOOL fCaseSensitive,
  21. LPSQLNODE lpSqlNodeColumn,
  22. SQLNODEIDX idxTable,
  23. STRINGIDX idxQualifier)
  24. /* Sees if the table identified by idxTable contains the column identifeid */
  25. /* lpSqNodeColumn. If it does, the semantic information for the column */
  26. /* is filled in. Otherwise an error is returned. */
  27. {
  28. LPSQLNODE lpSqlNodeTable;
  29. LPISAMTABLEDEF lpISAMTableDef;
  30. LPSTR lpName;
  31. UWORD index;
  32. LPUSTR lpTableAlias;
  33. LPUSTR lpColumnAlias;
  34. LPUSTR lpTableName;
  35. BOOL matchedAlias = FALSE;
  36. BOOL fIsPassthroughTable = FALSE;
  37. /* Table/Column name given? */
  38. lpName = (LPSTR) ToString(lpSql, lpSqlNodeColumn->node.column.Column);
  39. lpSqlNodeTable = ToNode(lpSql, idxTable);
  40. if (lpSqlNodeColumn->node.column.Tablealias != NO_STRING) {
  41. // this can be either a tablename or an tablename alias
  42. /* Yes. Make sure it matches */
  43. int found = FALSE;
  44. if (lpSqlNodeTable->node.table.Alias != NO_STRING &&
  45. lpSqlNodeColumn->node.column.Qualifier == NO_STRING)
  46. {
  47. //
  48. //Comparing Aliases
  49. //
  50. lpTableAlias = ToString(lpSql, lpSqlNodeTable->node.table.Alias);
  51. lpColumnAlias = ToString(lpSql, lpSqlNodeColumn->node.column.Tablealias);
  52. if (fCaseSensitive) {
  53. if (!s_lstrcmp(lpTableAlias, lpColumnAlias)) {
  54. found = TRUE;
  55. }
  56. }
  57. else {
  58. if (!s_lstrcmpi(lpTableAlias, lpColumnAlias)) {
  59. found = TRUE;
  60. }
  61. }
  62. if (!found)
  63. return ERR_COLUMNNOTFOUND;
  64. }
  65. //
  66. //Not comparing Aliases
  67. //
  68. if (!found) // try matching the column qualifier + alias to the table qualifier + table name
  69. {
  70. lpTableAlias = ToString(lpSql, lpSqlNodeTable->node.table.Qualifier);
  71. lpColumnAlias = ToString(lpSql, lpSqlNodeColumn->node.column.Tablealias);
  72. char *pszNewQualifier = NULL;
  73. if (lpSqlNodeColumn->node.column.Qualifier != NO_STRING)
  74. {
  75. LPSTR lpColumnQualifier = (LPSTR) ToString (lpSql, lpSqlNodeColumn->node.column.Qualifier);
  76. if ( (strlen(lpColumnQualifier) >= 4) &&
  77. (_strnicmp("root", lpColumnQualifier, 4) == 0))
  78. {
  79. // absolute qualifier (no need to change)
  80. pszNewQualifier = new char [s_lstrlen (lpColumnAlias)+
  81. s_lstrlen (lpColumnQualifier) + 3];
  82. s_lstrcpy (pszNewQualifier, lpColumnQualifier);
  83. s_lstrcat (pszNewQualifier, ".");
  84. s_lstrcat (pszNewQualifier, lpColumnAlias);
  85. }
  86. else
  87. {
  88. // concatenate the current namespace with the qualifier
  89. LPUSTR currQual = ISAMDatabase (lpSql->node.root.lpISAM);
  90. pszNewQualifier = new char [s_lstrlen (lpColumnAlias)+
  91. s_lstrlen (currQual) +
  92. s_lstrlen (lpColumnQualifier) + 3 + 2];
  93. s_lstrcpy (pszNewQualifier, currQual);
  94. s_lstrcat (pszNewQualifier, "\\");
  95. s_lstrcat (pszNewQualifier, lpColumnQualifier);
  96. s_lstrcat (pszNewQualifier, ".");
  97. s_lstrcat (pszNewQualifier, lpColumnAlias);
  98. }
  99. }
  100. else
  101. {
  102. LPUSTR currQual = ISAMDatabase (lpSql->node.root.lpISAM);
  103. pszNewQualifier = new char [s_lstrlen (lpColumnAlias)+
  104. s_lstrlen (currQual)+ 2 + 1];
  105. s_lstrcpy (pszNewQualifier, currQual);
  106. s_lstrcat (pszNewQualifier, ".");
  107. s_lstrcat (pszNewQualifier, lpColumnAlias);
  108. }
  109. // get the table name and concatenate with the table qualifier
  110. // before the check
  111. lpTableName = ToString(lpSql, lpSqlNodeTable->node.table.Name);
  112. char *lpszFQTN = new char [s_lstrlen (lpTableName) +
  113. s_lstrlen (lpTableAlias) + 2 + 1];
  114. s_lstrcpy (lpszFQTN, lpTableAlias);
  115. s_lstrcat (lpszFQTN, ".");
  116. s_lstrcat (lpszFQTN, lpTableName);
  117. if (fCaseSensitive) {
  118. if (!lstrcmp(lpszFQTN, pszNewQualifier)) {
  119. found = TRUE;
  120. }
  121. }
  122. else {
  123. if (!lstrcmpi(lpszFQTN, pszNewQualifier)) {
  124. found = TRUE;
  125. }
  126. }
  127. delete [] pszNewQualifier;
  128. delete lpszFQTN;
  129. }
  130. else
  131. {
  132. matchedAlias = TRUE;
  133. }
  134. //Check if this is the passthrough SQL table
  135. if (lpSqlNodeTable->node.table.Handle->fIsPassthroughSQL)
  136. found = TRUE;
  137. if (!found)
  138. return ERR_COLUMNNOTFOUND;
  139. }
  140. /* Search the table definition for a column with a matching name. */
  141. lpISAMTableDef = lpSqlNodeTable->node.table.Handle;
  142. BOOL fPassthroughSQLWithAlias = FALSE;
  143. LPSTR lpAlias = NULL;
  144. if ( (lpSqlNodeColumn->node.column.Tablealias != NO_STRING) && lpSqlNodeTable->node.table.Handle->fIsPassthroughSQL )
  145. {
  146. lpAlias = (LPSTR) ToString(lpSql, lpSqlNodeColumn->node.column.Tablealias);
  147. if ( lpAlias && lstrlen(lpAlias) )
  148. fPassthroughSQLWithAlias = TRUE;
  149. }
  150. ClassColumnInfoBase* cInfoBase = lpISAMTableDef->pColumnInfo;
  151. if ( !cInfoBase->IsValid() )
  152. {
  153. return ERR_COLUMNNOTFOUND;
  154. }
  155. //Sai
  156. //The current column is lpName, if this is a system property
  157. //and SYSPROPS=FALSE then return an error
  158. if (lpISAMTableDef && lpISAMTableDef->lpISAM)
  159. {
  160. if ( ! lpISAMTableDef->lpISAM->fSysProps)
  161. {
  162. //we are not asking for system properties
  163. //so a system property should not be in the SELECT list
  164. if (_strnicmp("__", lpName, 2) == 0)
  165. {
  166. return ERR_COLUMNNOTFOUND;
  167. }
  168. }
  169. }
  170. UWORD cNumberOfCols = cInfoBase->GetNumberOfColumns();
  171. char pColumnName [MAX_COLUMN_NAME_LENGTH+1];
  172. char pColumnAlias [MAX_COLUMN_NAME_LENGTH+1];
  173. pColumnAlias[0] = 0;
  174. BOOL fMatch = FALSE;
  175. for (index = 0; index < cNumberOfCols; index++)
  176. {
  177. fMatch = FALSE;
  178. if ( FAILED(cInfoBase->GetColumnName(index, pColumnName, pColumnAlias)) )
  179. {
  180. return ERR_COLUMNNOTFOUND;
  181. }
  182. if (fCaseSensitive)
  183. {
  184. if (!s_lstrcmp(lpName, pColumnName))
  185. {
  186. fMatch = TRUE;
  187. // break;
  188. }
  189. }
  190. else
  191. {
  192. if (!s_lstrcmpi(lpName, pColumnName))
  193. {
  194. fMatch = TRUE;
  195. // break;
  196. }
  197. }
  198. //Extra check for passthrough SQL
  199. if (fPassthroughSQLWithAlias && fMatch)
  200. {
  201. fMatch = FALSE;
  202. if (fCaseSensitive)
  203. {
  204. if (!s_lstrcmp(lpAlias, pColumnAlias))
  205. break;
  206. }
  207. else
  208. {
  209. if (!s_lstrcmpi(lpAlias, pColumnAlias))
  210. break;
  211. }
  212. }
  213. if (fMatch)
  214. break;
  215. }
  216. #ifdef TESTING
  217. if (idxQualifier != NO_STRING)
  218. {
  219. char* lpTestQual = ToString(lpSql, lpSqlNodeTable->table.Qualifier);
  220. char* lpOrgQual = ToString(lpSql, idxQualifier);
  221. if (lpTestQual && lpOrgQual && strcmp(lpTestQual, lpOrgQual))
  222. return ERR_COLUMNNOTFOUND;
  223. }
  224. #endif
  225. /* Error if not found */
  226. if (index == cNumberOfCols)
  227. {
  228. s_lstrcpy(lpstmt->szError, lpName);
  229. return ERR_COLUMNNOTFOUND;
  230. }
  231. /* Set the table and column information in the column node. */
  232. lpSqlNodeColumn->node.column.Table = idxTable;
  233. lpSqlNodeColumn->node.column.Id = (UWORD) index;
  234. if (lpSqlNodeColumn->node.column.Tablealias == NO_STRING)
  235. {
  236. lpSqlNodeColumn->node.column.Tablealias = lpSqlNodeTable->node.table.Name;
  237. }
  238. // to keep this consistent I'm going to put a flag in to say if it matched
  239. // a table name or an alias and put the qualifier in too
  240. lpSqlNodeColumn->node.column.MatchedAlias = matchedAlias;
  241. lpSqlNodeColumn->node.column.Qualifier = lpSqlNodeTable->node.table.Qualifier;
  242. // go further and set the column table reference to the table index. In fact,
  243. // this is the best way of doing this. Not sure why SYWARE didn't go this way
  244. // originally. Probably as it ensured every table had an alias. It really
  245. // encapsualtes all the above info.
  246. lpSqlNodeColumn->node.column.TableIndex = idxTable;
  247. /* Figure out type of data */
  248. cInfoBase->GetSQLType(index, lpSqlNodeColumn->sqlSqlType);
  249. switch (lpSqlNodeColumn->sqlSqlType) {
  250. case SQL_DECIMAL:
  251. case SQL_NUMERIC:
  252. {
  253. lpSqlNodeColumn->sqlDataType = TYPE_NUMERIC;
  254. UDWORD uwPrec = 0;
  255. cInfoBase->GetPrecision(index, uwPrec);
  256. lpSqlNodeColumn->sqlPrecision = (SWORD)uwPrec;
  257. cInfoBase->GetScale(index, lpSqlNodeColumn->sqlScale);
  258. }
  259. break;
  260. case SQL_BIGINT:
  261. {
  262. lpSqlNodeColumn->sqlDataType = TYPE_NUMERIC;
  263. UDWORD uwPrec = 0;
  264. cInfoBase->GetPrecision(index, uwPrec);
  265. lpSqlNodeColumn->sqlPrecision = (SWORD)uwPrec;
  266. lpSqlNodeColumn->sqlScale = 0;
  267. }
  268. break;
  269. case SQL_TINYINT:
  270. lpSqlNodeColumn->sqlDataType = TYPE_INTEGER;
  271. lpSqlNodeColumn->sqlPrecision = 3;
  272. lpSqlNodeColumn->sqlScale = 0;
  273. break;
  274. case SQL_SMALLINT:
  275. lpSqlNodeColumn->sqlDataType = TYPE_INTEGER;
  276. lpSqlNodeColumn->sqlPrecision = 5;
  277. lpSqlNodeColumn->sqlScale = 0;
  278. break;
  279. case SQL_INTEGER:
  280. lpSqlNodeColumn->sqlDataType = TYPE_INTEGER;
  281. lpSqlNodeColumn->sqlPrecision = 10;
  282. lpSqlNodeColumn->sqlScale = 0;
  283. break;
  284. case SQL_BIT:
  285. lpSqlNodeColumn->sqlDataType = TYPE_INTEGER;
  286. lpSqlNodeColumn->sqlPrecision = 1;
  287. lpSqlNodeColumn->sqlScale = 0;
  288. break;
  289. case SQL_REAL:
  290. lpSqlNodeColumn->sqlDataType = TYPE_DOUBLE;
  291. lpSqlNodeColumn->sqlPrecision = 7;
  292. lpSqlNodeColumn->sqlScale = NO_SCALE;
  293. break;
  294. case SQL_FLOAT:
  295. case SQL_DOUBLE:
  296. lpSqlNodeColumn->sqlDataType = TYPE_DOUBLE;
  297. lpSqlNodeColumn->sqlPrecision = 15;
  298. lpSqlNodeColumn->sqlScale = NO_SCALE;
  299. break;
  300. case SQL_CHAR:
  301. case SQL_VARCHAR:
  302. case SQL_LONGVARCHAR:
  303. {
  304. lpSqlNodeColumn->sqlDataType = TYPE_CHAR;
  305. UDWORD uwPrec = 0;
  306. cInfoBase->GetPrecision(index, uwPrec);
  307. lpSqlNodeColumn->sqlPrecision = (SWORD)uwPrec;
  308. if (lpSqlNodeColumn->sqlPrecision > MAX_CHAR_LITERAL_LENGTH)
  309. lpSqlNodeColumn->sqlPrecision = MAX_CHAR_LITERAL_LENGTH;
  310. lpSqlNodeColumn->sqlScale = NO_SCALE;
  311. }
  312. break;
  313. case SQL_BINARY:
  314. case SQL_VARBINARY:
  315. case SQL_LONGVARBINARY:
  316. {
  317. lpSqlNodeColumn->sqlDataType = TYPE_BINARY;
  318. UDWORD uwPrec = 0;
  319. cInfoBase->GetPrecision(index, uwPrec);
  320. lpSqlNodeColumn->sqlPrecision = (SWORD)uwPrec;
  321. lpSqlNodeColumn->sqlScale = NO_SCALE;
  322. }
  323. break;
  324. case SQL_DATE:
  325. lpSqlNodeColumn->sqlDataType = TYPE_DATE;
  326. lpSqlNodeColumn->sqlPrecision = 10;
  327. lpSqlNodeColumn->sqlScale = NO_SCALE;
  328. break;
  329. case SQL_TIME:
  330. lpSqlNodeColumn->sqlDataType = TYPE_TIME;
  331. lpSqlNodeColumn->sqlPrecision = 8;
  332. lpSqlNodeColumn->sqlScale = NO_SCALE;
  333. break;
  334. case SQL_TIMESTAMP:
  335. lpSqlNodeColumn->sqlDataType = TYPE_TIMESTAMP;
  336. if (TIMESTAMP_SCALE > 0)
  337. lpSqlNodeColumn->sqlPrecision = 20 + TIMESTAMP_SCALE;
  338. else
  339. lpSqlNodeColumn->sqlPrecision = 19;
  340. lpSqlNodeColumn->sqlScale = TIMESTAMP_SCALE;
  341. break;
  342. default:
  343. return ERR_NOTSUPPORTED;
  344. }
  345. return ERR_SUCCESS;
  346. }
  347. /***************************************************************************/
  348. void INTFUNC ErrorOpCode(LPSTMT lpstmt,
  349. UWORD opCode)
  350. /* Puts opcode in szError (as a string) */
  351. {
  352. switch (opCode) {
  353. case OP_NONE:
  354. s_lstrcpy(lpstmt->szError, "<assignment>");
  355. break;
  356. case OP_EQ:
  357. s_lstrcpy(lpstmt->szError, "=");
  358. break;
  359. case OP_NE:
  360. s_lstrcpy(lpstmt->szError, "<>");
  361. break;
  362. case OP_LE:
  363. s_lstrcpy(lpstmt->szError, "<=");
  364. break;
  365. case OP_LT:
  366. s_lstrcpy(lpstmt->szError, "<");
  367. break;
  368. case OP_GE:
  369. s_lstrcpy(lpstmt->szError, ">=");
  370. break;
  371. case OP_GT:
  372. s_lstrcpy(lpstmt->szError, ">");
  373. break;
  374. case OP_IN:
  375. s_lstrcpy(lpstmt->szError, "IN");
  376. break;
  377. case OP_NOTIN:
  378. s_lstrcpy(lpstmt->szError, "NOT IN");
  379. break;
  380. case OP_LIKE:
  381. s_lstrcpy(lpstmt->szError, "LIKE");
  382. break;
  383. case OP_NOTLIKE:
  384. s_lstrcpy(lpstmt->szError, "NOT LIKE");
  385. break;
  386. case OP_NEG:
  387. s_lstrcpy(lpstmt->szError, "-");
  388. break;
  389. case OP_PLUS:
  390. s_lstrcpy(lpstmt->szError, "+");
  391. break;
  392. case OP_MINUS:
  393. s_lstrcpy(lpstmt->szError, "-");
  394. break;
  395. case OP_TIMES:
  396. s_lstrcpy(lpstmt->szError, "*");
  397. break;
  398. case OP_DIVIDEDBY:
  399. s_lstrcpy(lpstmt->szError, "/");
  400. break;
  401. case OP_NOT:
  402. s_lstrcpy(lpstmt->szError, "NOT");
  403. break;
  404. case OP_AND:
  405. s_lstrcpy(lpstmt->szError, "AND");
  406. break;
  407. case OP_OR:
  408. s_lstrcpy(lpstmt->szError, "OR");
  409. break;
  410. case OP_EXISTS:
  411. s_lstrcpy(lpstmt->szError, "EXISTS");
  412. break;
  413. default:
  414. s_lstrcpy(lpstmt->szError, "");
  415. break;
  416. }
  417. }
  418. /***************************************************************************/
  419. void INTFUNC ErrorAggCode(LPSTMT lpstmt,
  420. UWORD aggCode)
  421. /* Puts aggreagate operator code in szError (as a string) */
  422. {
  423. switch(aggCode) {
  424. case AGG_AVG:
  425. s_lstrcpy(lpstmt->szError, "AVG");
  426. break;
  427. case AGG_COUNT:
  428. s_lstrcpy(lpstmt->szError, "COUNT");
  429. break;
  430. case AGG_MAX:
  431. s_lstrcpy(lpstmt->szError, "MAX");
  432. break;
  433. case AGG_MIN:
  434. s_lstrcpy(lpstmt->szError, "MIN");
  435. break;
  436. case AGG_SUM:
  437. s_lstrcpy(lpstmt->szError, "SUM");
  438. break;
  439. default:
  440. s_lstrcpy(lpstmt->szError, "");
  441. break;
  442. }
  443. }
  444. /***************************************************************************/
  445. RETCODE INTFUNC TypeCheck(LPSTMT lpstmt,
  446. LPSQLTREE lpSql,
  447. SQLNODEIDX idxLeft,
  448. SQLNODEIDX idxRight,
  449. UWORD opCode,
  450. SWORD FAR *pfDataType,
  451. SWORD FAR *pfSqlType,
  452. SDWORD FAR *pPrecision,
  453. SWORD FAR *pScale)
  454. /* Checks to see if the types of the two children nodes are compatible. */
  455. /* If the type of one of the children is unknown (because it was a */
  456. /* parameter or the value NULL), it set to the type of the other child. */
  457. {
  458. LPSQLNODE lpSqlNodeLeft;
  459. LPSQLNODE lpSqlNodeRight;
  460. SWORD fDataTypeLeft;
  461. SWORD fSqlTypeLeft;
  462. SDWORD precisionLeft;
  463. SWORD scaleLeft;
  464. SWORD fDataTypeRight;
  465. SWORD fSqlTypeRight;
  466. SDWORD precisionRight;
  467. SWORD scaleRight;
  468. SWORD fDataType;
  469. SWORD fSqlType;
  470. SDWORD precision;
  471. SWORD scale;
  472. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  473. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  474. /* Get left type */
  475. if (idxLeft == NO_SQLNODE)
  476. return ERR_INTERNAL;
  477. lpSqlNodeLeft = ToNode(lpSql, idxLeft);
  478. fDataTypeLeft = lpSqlNodeLeft->sqlDataType;
  479. fSqlTypeLeft = lpSqlNodeLeft->sqlSqlType;
  480. precisionLeft = lpSqlNodeLeft->sqlPrecision;
  481. scaleLeft = lpSqlNodeLeft->sqlScale;
  482. /* Is there a right epxression? */
  483. if (idxRight != NO_SQLNODE) {
  484. /* Yes. Get right type. */
  485. lpSqlNodeRight = ToNode(lpSql, idxRight);
  486. fDataTypeRight = lpSqlNodeRight->sqlDataType;
  487. fSqlTypeRight = lpSqlNodeRight->sqlSqlType;
  488. precisionRight = lpSqlNodeRight->sqlPrecision;
  489. scaleRight = lpSqlNodeRight->sqlScale;
  490. }
  491. else {
  492. /* No. This must be an arithmetic negation operator. Use left */
  493. /* type as the right type */
  494. if (opCode != OP_NEG)
  495. return ERR_INTERNAL;
  496. if (fDataTypeLeft == TYPE_UNKNOWN)
  497. return ERR_UNKNOWNTYPE;
  498. fDataTypeRight = fDataTypeLeft;
  499. fSqlTypeRight = fSqlTypeLeft;
  500. precisionRight = precisionLeft;
  501. scaleRight = scaleLeft;
  502. }
  503. /* Is left side unknown? */
  504. if (fDataTypeLeft == TYPE_UNKNOWN) {
  505. /* Yes. Error if right side is unknown also */
  506. if (fDataTypeRight == TYPE_UNKNOWN)
  507. return ERR_UNKNOWNTYPE;
  508. /* If right side is string value, make sure opcode is legal */
  509. if (fDataTypeRight == TYPE_CHAR) {
  510. switch (opCode) {
  511. case OP_NONE:
  512. case OP_EQ:
  513. case OP_NE:
  514. case OP_LE:
  515. case OP_LT:
  516. case OP_GE:
  517. case OP_GT:
  518. case OP_IN:
  519. case OP_NOTIN:
  520. case OP_LIKE:
  521. case OP_NOTLIKE:
  522. break;
  523. case OP_NEG:
  524. ErrorOpCode(lpstmt, opCode);
  525. return ERR_INVALIDOPERAND;
  526. case OP_PLUS:
  527. if (fSqlTypeRight == SQL_LONGVARCHAR) {
  528. ErrorOpCode(lpstmt, opCode);
  529. return ERR_INVALIDOPERAND;
  530. }
  531. break;
  532. case OP_MINUS:
  533. case OP_TIMES:
  534. case OP_DIVIDEDBY:
  535. case OP_NOT:
  536. case OP_AND:
  537. case OP_OR:
  538. case OP_EXISTS:
  539. ErrorOpCode(lpstmt, opCode);
  540. return ERR_INVALIDOPERAND;
  541. }
  542. }
  543. /* If right side is date value, make sure opcode is legal */
  544. else if (fDataTypeRight == TYPE_DATE) {
  545. switch (opCode) {
  546. case OP_NONE:
  547. case OP_EQ:
  548. case OP_NE:
  549. case OP_LE:
  550. case OP_LT:
  551. case OP_GE:
  552. case OP_GT:
  553. case OP_IN:
  554. case OP_NOTIN:
  555. break;
  556. case OP_LIKE:
  557. case OP_NOTLIKE:
  558. case OP_NEG:
  559. ErrorOpCode(lpstmt, opCode);
  560. return ERR_INVALIDOPERAND;
  561. case OP_PLUS:
  562. case OP_MINUS:
  563. break;
  564. case OP_TIMES:
  565. case OP_DIVIDEDBY:
  566. case OP_NOT:
  567. case OP_AND:
  568. case OP_OR:
  569. case OP_EXISTS:
  570. ErrorOpCode(lpstmt, opCode);
  571. return ERR_INVALIDOPERAND;
  572. }
  573. }
  574. /* Adding to a date? */
  575. if ((fDataTypeRight == TYPE_DATE) && (opCode == OP_PLUS)) {
  576. /* Yes. The left side must be integer */
  577. lpSqlNodeLeft->sqlDataType = TYPE_INTEGER;
  578. lpSqlNodeLeft->sqlSqlType = SQL_INTEGER;
  579. lpSqlNodeLeft->sqlPrecision = 10;
  580. lpSqlNodeLeft->sqlScale = 0;
  581. }
  582. else {
  583. /* No. Use type from right as type for left */
  584. /* Note: This disallows ? from being a date in (? - 3) */
  585. /* Note: This disallows ? from being a date in (? + 3) */
  586. lpSqlNodeLeft->sqlDataType = fDataTypeRight;
  587. lpSqlNodeLeft->sqlSqlType = fSqlTypeRight;
  588. lpSqlNodeLeft->sqlPrecision = precisionRight;
  589. lpSqlNodeLeft->sqlScale = scaleRight;
  590. /* If string concatenation, adjust type and precision */
  591. if ((fDataTypeRight == TYPE_CHAR) && (opCode == OP_PLUS)) {
  592. lpSqlNodeLeft->sqlSqlType = SQL_VARCHAR;
  593. lpSqlNodeLeft->sqlPrecision = MAX_CHAR_LITERAL_LENGTH;
  594. }
  595. }
  596. /* Adding to a date? */
  597. if ((fDataTypeRight == TYPE_DATE) && (opCode == OP_PLUS)) {
  598. /* Yes. The result type is a date */
  599. if (pfDataType != NULL)
  600. *pfDataType = lpSqlNodeRight->sqlDataType;
  601. if (pfSqlType != NULL)
  602. *pfSqlType = lpSqlNodeRight->sqlSqlType;
  603. if (pPrecision != NULL)
  604. *pPrecision = lpSqlNodeRight->sqlPrecision;
  605. if (pScale != NULL)
  606. *pScale = lpSqlNodeRight->sqlScale;
  607. }
  608. /* Calculating the differnce of two dates? */
  609. else if ((lpSqlNodeLeft->sqlDataType == TYPE_DATE) &&
  610. (opCode == OP_MINUS)) {
  611. /* Yes. The result type is integer */
  612. if (pfDataType != NULL)
  613. *pfDataType = TYPE_INTEGER;
  614. if (pfSqlType != NULL)
  615. *pfSqlType = SQL_INTEGER;
  616. if (pPrecision != NULL)
  617. *pPrecision = 10;
  618. if (pScale != NULL)
  619. *pScale = 0;
  620. }
  621. else {
  622. /* No. The result type is the same as the left side */
  623. if (pfDataType != NULL)
  624. *pfDataType = lpSqlNodeLeft->sqlDataType;
  625. if (pfSqlType != NULL)
  626. *pfSqlType = lpSqlNodeLeft->sqlSqlType;
  627. if (pPrecision != NULL)
  628. *pPrecision = lpSqlNodeLeft->sqlPrecision;
  629. if (pScale != NULL)
  630. *pScale = lpSqlNodeLeft->sqlScale;
  631. }
  632. }
  633. /* Is right side unknown? */
  634. else if (fDataTypeRight == TYPE_UNKNOWN) {
  635. /* Yes. If left side is string value, make sure opcode is legal */
  636. if (fDataTypeLeft == TYPE_CHAR) {
  637. switch (opCode) {
  638. case OP_NONE:
  639. case OP_EQ:
  640. case OP_NE:
  641. case OP_LE:
  642. case OP_LT:
  643. case OP_GE:
  644. case OP_GT:
  645. case OP_IN:
  646. case OP_NOTIN:
  647. case OP_LIKE:
  648. case OP_NOTLIKE:
  649. break;
  650. case OP_NEG:
  651. ErrorOpCode(lpstmt, opCode);
  652. return ERR_INVALIDOPERAND;
  653. case OP_PLUS:
  654. if (fSqlTypeLeft == SQL_LONGVARCHAR) {
  655. ErrorOpCode(lpstmt, opCode);
  656. return ERR_INVALIDOPERAND;
  657. }
  658. break;
  659. case OP_MINUS:
  660. case OP_TIMES:
  661. case OP_DIVIDEDBY:
  662. case OP_NOT:
  663. case OP_AND:
  664. case OP_OR:
  665. case OP_EXISTS:
  666. ErrorOpCode(lpstmt, opCode);
  667. return ERR_INVALIDOPERAND;
  668. }
  669. }
  670. /* If left side is date value, make sure opcode is legal */
  671. else if (fDataTypeLeft == TYPE_DATE) {
  672. switch (opCode) {
  673. case OP_NONE:
  674. case OP_EQ:
  675. case OP_NE:
  676. case OP_LE:
  677. case OP_LT:
  678. case OP_GE:
  679. case OP_GT:
  680. case OP_IN:
  681. case OP_NOTIN:
  682. break;
  683. case OP_LIKE:
  684. case OP_NOTLIKE:
  685. case OP_NEG:
  686. ErrorOpCode(lpstmt, opCode);
  687. return ERR_INVALIDOPERAND;
  688. case OP_PLUS:
  689. case OP_MINUS:
  690. break;
  691. case OP_TIMES:
  692. case OP_DIVIDEDBY:
  693. case OP_NOT:
  694. case OP_AND:
  695. case OP_OR:
  696. case OP_EXISTS:
  697. ErrorOpCode(lpstmt, opCode);
  698. return ERR_INVALIDOPERAND;
  699. }
  700. }
  701. /* Adding to a date? */
  702. if ((fDataTypeLeft == TYPE_DATE) && (opCode == OP_PLUS)) {
  703. /* Yes. The right side must be integer */
  704. lpSqlNodeRight->sqlDataType = TYPE_INTEGER;
  705. lpSqlNodeRight->sqlSqlType = SQL_INTEGER;
  706. lpSqlNodeRight->sqlPrecision = 10;
  707. lpSqlNodeRight->sqlScale = 0;
  708. }
  709. else {
  710. /* No. Use type from left as type for right */
  711. /* Note: This disallows ? from being a number in (<date> - ? ) */
  712. /* Note: This disallows ? from being a date in (<number> + ? ) */
  713. lpSqlNodeRight->sqlDataType = fDataTypeLeft;
  714. lpSqlNodeRight->sqlSqlType = fSqlTypeLeft;
  715. lpSqlNodeRight->sqlPrecision = precisionLeft;
  716. lpSqlNodeRight->sqlScale = scaleLeft;
  717. /* If string concatenation, adjust type and precision */
  718. if ((fDataTypeLeft == TYPE_CHAR) && (opCode == OP_PLUS)) {
  719. lpSqlNodeRight->sqlSqlType = SQL_VARCHAR;
  720. lpSqlNodeRight->sqlPrecision = MAX_CHAR_LITERAL_LENGTH;
  721. }
  722. }
  723. /* Adding to a date? */
  724. if ((fDataTypeLeft == TYPE_DATE) && (opCode == OP_PLUS)) {
  725. /* Yes. The result type is a date */
  726. if (pfDataType != NULL)
  727. *pfDataType = TYPE_DATE;
  728. if (pfSqlType != NULL)
  729. *pfSqlType = SQL_DATE;
  730. if (pPrecision != NULL)
  731. *pPrecision = 10;
  732. if (pScale != NULL)
  733. *pScale = 0;
  734. }
  735. /* Calculating the difference of two dates? */
  736. else if ((fDataTypeLeft == TYPE_DATE) && (opCode == OP_MINUS)) {
  737. /* Yes. The result type is integer */
  738. if (pfDataType != NULL)
  739. *pfDataType = TYPE_INTEGER;
  740. if (pfSqlType != NULL)
  741. *pfSqlType = SQL_INTEGER;
  742. if (pPrecision != NULL)
  743. *pPrecision = 10;
  744. if (pScale != NULL)
  745. *pScale = 0;
  746. }
  747. else {
  748. /* No. The result type is the same as the right side */
  749. if (pfDataType != NULL)
  750. *pfDataType = lpSqlNodeRight->sqlDataType;
  751. if (pfSqlType != NULL)
  752. *pfSqlType = lpSqlNodeRight->sqlSqlType;
  753. if (pPrecision != NULL)
  754. *pPrecision = lpSqlNodeRight->sqlPrecision;
  755. if (pScale != NULL)
  756. *pScale = lpSqlNodeRight->sqlScale;
  757. }
  758. }
  759. /* Do types match? */
  760. else if ((fDataTypeLeft == fDataTypeRight) ||
  761. ((fDataTypeLeft == TYPE_DOUBLE) &&
  762. (fDataTypeRight == TYPE_NUMERIC)) ||
  763. ((fDataTypeLeft == TYPE_DOUBLE) &&
  764. (fDataTypeRight == TYPE_INTEGER)) ||
  765. ((fDataTypeLeft == TYPE_NUMERIC) &&
  766. (fDataTypeRight == TYPE_DOUBLE)) ||
  767. ((fDataTypeLeft == TYPE_NUMERIC) &&
  768. (fDataTypeRight == TYPE_INTEGER)) ||
  769. ((fDataTypeLeft == TYPE_INTEGER) &&
  770. (fDataTypeRight == TYPE_DOUBLE)) ||
  771. ((fDataTypeLeft == TYPE_INTEGER) &&
  772. (fDataTypeRight == TYPE_NUMERIC))) {
  773. /* Yes. If left side is string value, make sure opcode is legal */
  774. if (fDataTypeLeft == TYPE_CHAR) {
  775. switch (opCode) {
  776. case OP_NONE:
  777. case OP_EQ:
  778. case OP_NE:
  779. case OP_LE:
  780. case OP_LT:
  781. case OP_GE:
  782. case OP_GT:
  783. case OP_IN:
  784. case OP_NOTIN:
  785. case OP_LIKE:
  786. case OP_NOTLIKE:
  787. break;
  788. case OP_NEG:
  789. ErrorOpCode(lpstmt, opCode);
  790. return ERR_INVALIDOPERAND;
  791. case OP_PLUS:
  792. if ((fSqlTypeRight == SQL_LONGVARCHAR) ||
  793. (fSqlTypeLeft == SQL_LONGVARCHAR)) {
  794. ErrorOpCode(lpstmt, opCode);
  795. return ERR_INVALIDOPERAND;
  796. }
  797. break;
  798. case OP_MINUS:
  799. case OP_TIMES:
  800. case OP_DIVIDEDBY:
  801. case OP_NOT:
  802. case OP_AND:
  803. case OP_OR:
  804. case OP_EXISTS:
  805. ErrorOpCode(lpstmt, opCode);
  806. return ERR_INVALIDOPERAND;
  807. }
  808. }
  809. /* If left side is date value, make sure opcode is legal */
  810. else if (fDataTypeLeft == TYPE_DATE) {
  811. switch (opCode) {
  812. case OP_NONE:
  813. case OP_EQ:
  814. case OP_NE:
  815. case OP_LE:
  816. case OP_LT:
  817. case OP_GE:
  818. case OP_GT:
  819. case OP_IN:
  820. case OP_NOTIN:
  821. break;
  822. case OP_LIKE:
  823. case OP_NOTLIKE:
  824. case OP_NEG:
  825. case OP_PLUS:
  826. ErrorOpCode(lpstmt, opCode);
  827. return ERR_INVALIDOPERAND;
  828. case OP_MINUS:
  829. break;
  830. case OP_TIMES:
  831. case OP_DIVIDEDBY:
  832. case OP_NOT:
  833. case OP_AND:
  834. case OP_OR:
  835. case OP_EXISTS:
  836. ErrorOpCode(lpstmt, opCode);
  837. return ERR_INVALIDOPERAND;
  838. }
  839. }
  840. /* Figure out resultant type */
  841. if ((fDataTypeLeft == TYPE_NUMERIC) && (fDataTypeRight == TYPE_DOUBLE))
  842. fDataType = TYPE_DOUBLE;
  843. else if ((fDataTypeLeft == TYPE_INTEGER) && (fDataTypeRight == TYPE_DOUBLE))
  844. fDataType = TYPE_DOUBLE;
  845. else if ((fDataTypeLeft == TYPE_INTEGER) && (fDataTypeRight == TYPE_NUMERIC))
  846. fDataType = TYPE_NUMERIC;
  847. else
  848. fDataType = fDataTypeLeft;
  849. if (pfDataType != NULL)
  850. *pfDataType = fDataType;
  851. /* Figure out resultant SQL type, precision, and scale */
  852. switch (fSqlTypeLeft) {
  853. case SQL_DOUBLE:
  854. switch (fSqlTypeRight) {
  855. case SQL_DOUBLE:
  856. if (pfSqlType != NULL)
  857. *pfSqlType = fSqlTypeRight;
  858. if (pPrecision != NULL)
  859. *pPrecision = precisionRight;
  860. if (pScale != NULL)
  861. *pScale = NO_SCALE;
  862. break;
  863. case SQL_FLOAT:
  864. case SQL_REAL:
  865. case SQL_DECIMAL:
  866. case SQL_NUMERIC:
  867. case SQL_BIGINT:
  868. case SQL_INTEGER:
  869. case SQL_SMALLINT:
  870. case SQL_TINYINT:
  871. case SQL_BIT:
  872. if (pfSqlType != NULL)
  873. *pfSqlType = fSqlTypeLeft;
  874. if (pPrecision != NULL)
  875. *pPrecision = precisionLeft;
  876. if (pScale != NULL)
  877. *pScale = NO_SCALE;
  878. break;
  879. case SQL_LONGVARCHAR:
  880. case SQL_VARCHAR:
  881. case SQL_CHAR:
  882. case SQL_LONGVARBINARY:
  883. case SQL_VARBINARY:
  884. case SQL_BINARY:
  885. case SQL_DATE:
  886. case SQL_TIME:
  887. case SQL_TIMESTAMP:
  888. return ERR_INTERNAL;
  889. default:
  890. return ERR_NOTSUPPORTED;
  891. }
  892. break;
  893. case SQL_FLOAT:
  894. switch (fSqlTypeRight) {
  895. case SQL_DOUBLE:
  896. case SQL_FLOAT:
  897. if (pfSqlType != NULL)
  898. *pfSqlType = fSqlTypeRight;
  899. if (pPrecision != NULL)
  900. *pPrecision = precisionRight;
  901. if (pScale != NULL)
  902. *pScale = NO_SCALE;
  903. break;
  904. case SQL_REAL:
  905. case SQL_DECIMAL:
  906. case SQL_NUMERIC:
  907. case SQL_BIGINT:
  908. case SQL_INTEGER:
  909. case SQL_SMALLINT:
  910. case SQL_TINYINT:
  911. case SQL_BIT:
  912. if (pfSqlType != NULL)
  913. *pfSqlType = fSqlTypeLeft;
  914. if (pPrecision != NULL)
  915. *pPrecision = precisionLeft;
  916. if (pScale != NULL)
  917. *pScale = NO_SCALE;
  918. break;
  919. case SQL_LONGVARCHAR:
  920. case SQL_VARCHAR:
  921. case SQL_CHAR:
  922. case SQL_LONGVARBINARY:
  923. case SQL_VARBINARY:
  924. case SQL_BINARY:
  925. case SQL_DATE:
  926. case SQL_TIME:
  927. case SQL_TIMESTAMP:
  928. return ERR_INTERNAL;
  929. default:
  930. return ERR_NOTSUPPORTED;
  931. }
  932. break;
  933. case SQL_REAL:
  934. switch (fSqlTypeRight) {
  935. case SQL_DOUBLE:
  936. case SQL_FLOAT:
  937. case SQL_REAL:
  938. if (pfSqlType != NULL)
  939. *pfSqlType = fSqlTypeRight;
  940. if (pPrecision != NULL)
  941. *pPrecision = precisionRight;
  942. if (pScale != NULL)
  943. *pScale = NO_SCALE;
  944. break;
  945. case SQL_DECIMAL:
  946. case SQL_NUMERIC:
  947. case SQL_BIGINT:
  948. case SQL_INTEGER:
  949. case SQL_SMALLINT:
  950. case SQL_TINYINT:
  951. case SQL_BIT:
  952. if (pfSqlType != NULL)
  953. *pfSqlType = fSqlTypeLeft;
  954. if (pPrecision != NULL)
  955. *pPrecision = precisionLeft;
  956. if (pScale != NULL)
  957. *pScale = NO_SCALE;
  958. break;
  959. case SQL_LONGVARCHAR:
  960. case SQL_VARCHAR:
  961. case SQL_CHAR:
  962. case SQL_LONGVARBINARY:
  963. case SQL_VARBINARY:
  964. case SQL_BINARY:
  965. case SQL_DATE:
  966. case SQL_TIME:
  967. case SQL_TIMESTAMP:
  968. return ERR_INTERNAL;
  969. default:
  970. return ERR_NOTSUPPORTED;
  971. }
  972. break;
  973. case SQL_DECIMAL:
  974. case SQL_NUMERIC:
  975. case SQL_BIGINT:
  976. case SQL_INTEGER:
  977. case SQL_SMALLINT:
  978. case SQL_TINYINT:
  979. case SQL_BIT:
  980. switch (fSqlTypeRight) {
  981. case SQL_DOUBLE:
  982. case SQL_FLOAT:
  983. case SQL_REAL:
  984. if (pfSqlType != NULL)
  985. *pfSqlType = fSqlTypeRight;
  986. if (pPrecision != NULL)
  987. *pPrecision = precisionRight;
  988. if (pScale != NULL)
  989. *pScale = NO_SCALE;
  990. break;
  991. case SQL_DECIMAL:
  992. case SQL_NUMERIC:
  993. case SQL_BIGINT:
  994. case SQL_INTEGER:
  995. case SQL_SMALLINT:
  996. case SQL_TINYINT:
  997. case SQL_BIT:
  998. if ((fSqlTypeRight == SQL_DECIMAL) ||
  999. (fSqlTypeLeft == SQL_DECIMAL))
  1000. fSqlType = SQL_DECIMAL;
  1001. else if ((fSqlTypeRight == SQL_NUMERIC) ||
  1002. (fSqlTypeLeft == SQL_NUMERIC))
  1003. fSqlType = SQL_NUMERIC;
  1004. else if ((fSqlTypeRight == SQL_BIGINT) ||
  1005. (fSqlTypeLeft == SQL_BIGINT))
  1006. fSqlType = SQL_BIGINT;
  1007. else if ((fSqlTypeRight == SQL_INTEGER) ||
  1008. (fSqlTypeLeft == SQL_INTEGER))
  1009. fSqlType = SQL_INTEGER;
  1010. else if ((fSqlTypeRight == SQL_SMALLINT) ||
  1011. (fSqlTypeLeft == SQL_SMALLINT))
  1012. fSqlType = SQL_SMALLINT;
  1013. else if ((fSqlTypeRight == SQL_TINYINT) ||
  1014. (fSqlTypeLeft == SQL_TINYINT))
  1015. fSqlType = SQL_TINYINT;
  1016. else
  1017. fSqlType = SQL_BIT;
  1018. if (pfSqlType != NULL)
  1019. *pfSqlType = fSqlType;
  1020. switch (opCode) {
  1021. case OP_NONE:
  1022. case OP_EQ:
  1023. case OP_NE:
  1024. case OP_LE:
  1025. case OP_LT:
  1026. case OP_GE:
  1027. case OP_GT:
  1028. case OP_IN:
  1029. case OP_NOTIN:
  1030. if (pPrecision != NULL)
  1031. *pPrecision = precisionLeft;
  1032. if (pScale != NULL)
  1033. *pScale = scaleLeft;
  1034. break;
  1035. case OP_LIKE:
  1036. case OP_NOTLIKE:
  1037. ErrorOpCode(lpstmt, opCode);
  1038. return ERR_INVALIDOPERAND;
  1039. case OP_NEG:
  1040. if (pPrecision != NULL)
  1041. *pPrecision = precisionLeft;
  1042. if (pScale != NULL)
  1043. *pScale = scaleLeft;
  1044. break;
  1045. case OP_PLUS:
  1046. case OP_MINUS:
  1047. scale = MAX(scaleRight, scaleLeft);
  1048. switch (fSqlType) {
  1049. case SQL_DOUBLE:
  1050. case SQL_FLOAT:
  1051. case SQL_REAL:
  1052. return ERR_INTERNAL;
  1053. case SQL_DECIMAL:
  1054. case SQL_NUMERIC:
  1055. case SQL_BIGINT:
  1056. precision = scale + MAX(precisionRight - scaleRight,
  1057. precisionLeft - scaleLeft) + 1;
  1058. break;
  1059. case SQL_INTEGER:
  1060. precision = 10;
  1061. break;
  1062. case SQL_SMALLINT:
  1063. precision = 5;
  1064. break;
  1065. case SQL_TINYINT:
  1066. precision = 3;
  1067. break;
  1068. case SQL_BIT:
  1069. precision = 1;
  1070. break;
  1071. case SQL_LONGVARCHAR:
  1072. case SQL_VARCHAR:
  1073. case SQL_CHAR:
  1074. case SQL_LONGVARBINARY:
  1075. case SQL_VARBINARY:
  1076. case SQL_BINARY:
  1077. case SQL_DATE:
  1078. case SQL_TIME:
  1079. case SQL_TIMESTAMP:
  1080. return ERR_INTERNAL;
  1081. default:
  1082. return ERR_NOTSUPPORTED;
  1083. }
  1084. if (pPrecision != NULL)
  1085. *pPrecision = precision;
  1086. if (pScale != NULL)
  1087. *pScale = scale;
  1088. break;
  1089. case OP_TIMES:
  1090. case OP_DIVIDEDBY:
  1091. scale = scaleRight + scaleLeft;
  1092. switch (fSqlType) {
  1093. case SQL_DOUBLE:
  1094. case SQL_FLOAT:
  1095. case SQL_REAL:
  1096. return ERR_INTERNAL;
  1097. case SQL_DECIMAL:
  1098. case SQL_NUMERIC:
  1099. case SQL_BIGINT:
  1100. precision = scale + (precisionRight - scaleRight) +
  1101. (precisionLeft - scaleLeft);
  1102. break;
  1103. case SQL_INTEGER:
  1104. precision = 10;
  1105. break;
  1106. case SQL_SMALLINT:
  1107. precision = 5;
  1108. break;
  1109. case SQL_TINYINT:
  1110. precision = 3;
  1111. break;
  1112. case SQL_BIT:
  1113. precision = 1;
  1114. break;
  1115. case SQL_LONGVARCHAR:
  1116. case SQL_VARCHAR:
  1117. case SQL_CHAR:
  1118. case SQL_LONGVARBINARY:
  1119. case SQL_VARBINARY:
  1120. case SQL_BINARY:
  1121. case SQL_DATE:
  1122. case SQL_TIME:
  1123. case SQL_TIMESTAMP:
  1124. return ERR_INTERNAL;
  1125. default:
  1126. return ERR_NOTSUPPORTED;
  1127. }
  1128. if (pPrecision != NULL)
  1129. *pPrecision = precision;
  1130. if (pScale != NULL)
  1131. *pScale = scale;
  1132. break;
  1133. case OP_NOT:
  1134. case OP_AND:
  1135. case OP_OR:
  1136. case OP_EXISTS:
  1137. ErrorOpCode(lpstmt, opCode);
  1138. return ERR_INVALIDOPERAND;
  1139. }
  1140. break;
  1141. case SQL_LONGVARCHAR:
  1142. case SQL_VARCHAR:
  1143. case SQL_CHAR:
  1144. case SQL_LONGVARBINARY:
  1145. case SQL_VARBINARY:
  1146. case SQL_BINARY:
  1147. case SQL_DATE:
  1148. case SQL_TIME:
  1149. case SQL_TIMESTAMP:
  1150. return ERR_INTERNAL;
  1151. default:
  1152. return ERR_NOTSUPPORTED;
  1153. }
  1154. break;
  1155. case SQL_LONGVARCHAR:
  1156. switch (fSqlTypeRight) {
  1157. case SQL_DOUBLE:
  1158. case SQL_FLOAT:
  1159. case SQL_REAL:
  1160. case SQL_DECIMAL:
  1161. case SQL_NUMERIC:
  1162. case SQL_BIGINT:
  1163. case SQL_INTEGER:
  1164. case SQL_SMALLINT:
  1165. case SQL_TINYINT:
  1166. case SQL_BIT:
  1167. return ERR_INTERNAL;
  1168. case SQL_LONGVARCHAR:
  1169. if (pfSqlType != NULL)
  1170. *pfSqlType = fSqlTypeRight;
  1171. if (pPrecision != NULL)
  1172. *pPrecision = precisionRight;
  1173. if (pScale != NULL)
  1174. *pScale = NO_SCALE;
  1175. break;
  1176. case SQL_VARCHAR:
  1177. case SQL_CHAR:
  1178. if (pfSqlType != NULL)
  1179. *pfSqlType = fSqlTypeLeft;
  1180. if (pPrecision != NULL) {
  1181. if (precisionLeft > precisionRight)
  1182. *pPrecision = precisionLeft;
  1183. else
  1184. *pPrecision = precisionRight;
  1185. }
  1186. if (pScale != NULL)
  1187. *pScale = NO_SCALE;
  1188. break;
  1189. case SQL_LONGVARBINARY:
  1190. case SQL_VARBINARY:
  1191. case SQL_BINARY:
  1192. case SQL_DATE:
  1193. case SQL_TIME:
  1194. case SQL_TIMESTAMP:
  1195. return ERR_INTERNAL;
  1196. default:
  1197. return ERR_NOTSUPPORTED;
  1198. }
  1199. break;
  1200. case SQL_VARCHAR:
  1201. switch (fSqlTypeRight) {
  1202. case SQL_DOUBLE:
  1203. case SQL_FLOAT:
  1204. case SQL_REAL:
  1205. case SQL_DECIMAL:
  1206. case SQL_NUMERIC:
  1207. case SQL_BIGINT:
  1208. case SQL_INTEGER:
  1209. case SQL_SMALLINT:
  1210. case SQL_TINYINT:
  1211. case SQL_BIT:
  1212. return ERR_INTERNAL;
  1213. case SQL_LONGVARCHAR:
  1214. case SQL_VARCHAR:
  1215. if (pfSqlType != NULL)
  1216. *pfSqlType = fSqlTypeRight;
  1217. if (pPrecision != NULL)
  1218. *pPrecision = precisionRight;
  1219. if (pScale != NULL)
  1220. *pScale = NO_SCALE;
  1221. break;
  1222. case SQL_CHAR:
  1223. if (pfSqlType != NULL)
  1224. *pfSqlType = fSqlTypeLeft;
  1225. if (pPrecision != NULL)
  1226. *pPrecision = precisionLeft;
  1227. if (pScale != NULL)
  1228. *pScale = NO_SCALE;
  1229. break;
  1230. case SQL_LONGVARBINARY:
  1231. case SQL_VARBINARY:
  1232. case SQL_BINARY:
  1233. case SQL_DATE:
  1234. case SQL_TIME:
  1235. case SQL_TIMESTAMP:
  1236. return ERR_INTERNAL;
  1237. default:
  1238. return ERR_NOTSUPPORTED;
  1239. }
  1240. /* Adjust precision for string concatenation operator */
  1241. if ((opCode == OP_PLUS) && (pPrecision != NULL))
  1242. *pPrecision = MIN(precisionRight + precisionLeft,
  1243. MAX_CHAR_LITERAL_LENGTH);
  1244. break;
  1245. case SQL_CHAR:
  1246. switch (fSqlTypeRight) {
  1247. case SQL_DOUBLE:
  1248. case SQL_FLOAT:
  1249. case SQL_REAL:
  1250. case SQL_DECIMAL:
  1251. case SQL_NUMERIC:
  1252. case SQL_BIGINT:
  1253. case SQL_INTEGER:
  1254. case SQL_SMALLINT:
  1255. case SQL_TINYINT:
  1256. case SQL_BIT:
  1257. return ERR_INTERNAL;
  1258. case SQL_LONGVARCHAR:
  1259. case SQL_VARCHAR:
  1260. case SQL_CHAR:
  1261. if (pfSqlType != NULL)
  1262. *pfSqlType = fSqlTypeRight;
  1263. if (pPrecision != NULL)
  1264. *pPrecision = precisionRight;
  1265. if (pScale != NULL)
  1266. *pScale = NO_SCALE;
  1267. break;
  1268. case SQL_LONGVARBINARY:
  1269. case SQL_VARBINARY:
  1270. case SQL_BINARY:
  1271. case SQL_DATE:
  1272. case SQL_TIME:
  1273. case SQL_TIMESTAMP:
  1274. return ERR_INTERNAL;
  1275. default:
  1276. return ERR_NOTSUPPORTED;
  1277. }
  1278. /* Adjust precision for string concatenation operator */
  1279. if ((opCode == OP_PLUS) && (pPrecision != NULL))
  1280. *pPrecision = MIN(precisionRight + precisionLeft,
  1281. MAX_CHAR_LITERAL_LENGTH);
  1282. break;
  1283. case SQL_LONGVARBINARY:
  1284. switch (fSqlTypeRight) {
  1285. case SQL_DOUBLE:
  1286. case SQL_FLOAT:
  1287. case SQL_REAL:
  1288. case SQL_DECIMAL:
  1289. case SQL_NUMERIC:
  1290. case SQL_BIGINT:
  1291. case SQL_INTEGER:
  1292. case SQL_SMALLINT:
  1293. case SQL_TINYINT:
  1294. case SQL_BIT:
  1295. case SQL_LONGVARCHAR:
  1296. case SQL_VARCHAR:
  1297. case SQL_CHAR:
  1298. return ERR_INTERNAL;
  1299. case SQL_LONGVARBINARY:
  1300. if (pfSqlType != NULL)
  1301. *pfSqlType = fSqlTypeRight;
  1302. if (pPrecision != NULL)
  1303. *pPrecision = precisionRight;
  1304. if (pScale != NULL)
  1305. *pScale = NO_SCALE;
  1306. break;
  1307. case SQL_VARBINARY:
  1308. case SQL_BINARY:
  1309. if (pfSqlType != NULL)
  1310. *pfSqlType = fSqlTypeLeft;
  1311. if (pPrecision != NULL)
  1312. *pPrecision = precisionLeft;
  1313. if (pScale != NULL)
  1314. *pScale = NO_SCALE;
  1315. break;
  1316. case SQL_DATE:
  1317. case SQL_TIME:
  1318. case SQL_TIMESTAMP:
  1319. return ERR_INTERNAL;
  1320. default:
  1321. return ERR_NOTSUPPORTED;
  1322. }
  1323. break;
  1324. case SQL_VARBINARY:
  1325. switch (fSqlTypeRight) {
  1326. case SQL_DOUBLE:
  1327. case SQL_FLOAT:
  1328. case SQL_REAL:
  1329. case SQL_DECIMAL:
  1330. case SQL_NUMERIC:
  1331. case SQL_BIGINT:
  1332. case SQL_INTEGER:
  1333. case SQL_SMALLINT:
  1334. case SQL_TINYINT:
  1335. case SQL_BIT:
  1336. case SQL_LONGVARCHAR:
  1337. case SQL_VARCHAR:
  1338. case SQL_CHAR:
  1339. return ERR_INTERNAL;
  1340. case SQL_LONGVARBINARY:
  1341. case SQL_VARBINARY:
  1342. if (pfSqlType != NULL)
  1343. *pfSqlType = fSqlTypeRight;
  1344. if (pPrecision != NULL)
  1345. *pPrecision = precisionRight;
  1346. if (pScale != NULL)
  1347. *pScale = NO_SCALE;
  1348. break;
  1349. case SQL_BINARY:
  1350. if (pfSqlType != NULL)
  1351. *pfSqlType = fSqlTypeLeft;
  1352. if (pPrecision != NULL)
  1353. *pPrecision = precisionLeft;
  1354. if (pScale != NULL)
  1355. *pScale = NO_SCALE;
  1356. break;
  1357. case SQL_DATE:
  1358. case SQL_TIME:
  1359. case SQL_TIMESTAMP:
  1360. return ERR_INTERNAL;
  1361. default:
  1362. return ERR_NOTSUPPORTED;
  1363. }
  1364. break;
  1365. case SQL_BINARY:
  1366. switch (fSqlTypeRight) {
  1367. case SQL_DOUBLE:
  1368. case SQL_FLOAT:
  1369. case SQL_REAL:
  1370. case SQL_DECIMAL:
  1371. case SQL_NUMERIC:
  1372. case SQL_BIGINT:
  1373. case SQL_INTEGER:
  1374. case SQL_SMALLINT:
  1375. case SQL_TINYINT:
  1376. case SQL_BIT:
  1377. case SQL_LONGVARCHAR:
  1378. case SQL_VARCHAR:
  1379. case SQL_CHAR:
  1380. return ERR_INTERNAL;
  1381. case SQL_LONGVARBINARY:
  1382. case SQL_VARBINARY:
  1383. case SQL_BINARY:
  1384. if (pfSqlType != NULL)
  1385. *pfSqlType = fSqlTypeRight;
  1386. if (pPrecision != NULL)
  1387. *pPrecision = precisionRight;
  1388. if (pScale != NULL)
  1389. *pScale = NO_SCALE;
  1390. break;
  1391. case SQL_DATE:
  1392. case SQL_TIME:
  1393. case SQL_TIMESTAMP:
  1394. return ERR_INTERNAL;
  1395. default:
  1396. return ERR_NOTSUPPORTED;
  1397. }
  1398. break;
  1399. case SQL_DATE:
  1400. switch (fSqlTypeRight) {
  1401. case SQL_DOUBLE:
  1402. case SQL_FLOAT:
  1403. case SQL_REAL:
  1404. case SQL_DECIMAL:
  1405. case SQL_NUMERIC:
  1406. case SQL_BIGINT:
  1407. case SQL_INTEGER:
  1408. case SQL_SMALLINT:
  1409. case SQL_TINYINT:
  1410. case SQL_BIT:
  1411. case SQL_LONGVARCHAR:
  1412. case SQL_VARCHAR:
  1413. case SQL_CHAR:
  1414. case SQL_LONGVARBINARY:
  1415. case SQL_VARBINARY:
  1416. case SQL_BINARY:
  1417. return ERR_INTERNAL;
  1418. case SQL_DATE:
  1419. switch (opCode) {
  1420. case OP_NONE:
  1421. case OP_EQ:
  1422. case OP_NE:
  1423. case OP_LE:
  1424. case OP_LT:
  1425. case OP_GE:
  1426. case OP_GT:
  1427. case OP_IN:
  1428. case OP_NOTIN:
  1429. if (pfSqlType != NULL)
  1430. *pfSqlType = fSqlTypeLeft;
  1431. if (pPrecision != NULL)
  1432. *pPrecision = precisionLeft;
  1433. if (pScale != NULL)
  1434. *pScale = scaleLeft;
  1435. break;
  1436. case OP_LIKE:
  1437. case OP_NOTLIKE:
  1438. case OP_NEG:
  1439. case OP_PLUS:
  1440. ErrorOpCode(lpstmt, opCode);
  1441. return ERR_INVALIDOPERAND;
  1442. case OP_MINUS:
  1443. if (pfDataType != NULL)
  1444. *pfDataType = TYPE_INTEGER;
  1445. if (pPrecision != NULL)
  1446. *pPrecision = 10;
  1447. if (pfSqlType != NULL)
  1448. *pfSqlType = SQL_INTEGER;
  1449. if (pScale != NULL)
  1450. *pScale = 0;
  1451. break;
  1452. case OP_TIMES:
  1453. case OP_DIVIDEDBY:
  1454. case OP_NOT:
  1455. case OP_AND:
  1456. case OP_OR:
  1457. case OP_EXISTS:
  1458. ErrorOpCode(lpstmt, opCode);
  1459. return ERR_INVALIDOPERAND;
  1460. }
  1461. break;
  1462. case SQL_TIME:
  1463. case SQL_TIMESTAMP:
  1464. return ERR_INTERNAL;
  1465. default:
  1466. return ERR_NOTSUPPORTED;
  1467. }
  1468. break;
  1469. case SQL_TIME:
  1470. switch (fSqlTypeRight) {
  1471. case SQL_DOUBLE:
  1472. case SQL_FLOAT:
  1473. case SQL_REAL:
  1474. case SQL_DECIMAL:
  1475. case SQL_NUMERIC:
  1476. case SQL_BIGINT:
  1477. case SQL_INTEGER:
  1478. case SQL_SMALLINT:
  1479. case SQL_TINYINT:
  1480. case SQL_BIT:
  1481. case SQL_LONGVARCHAR:
  1482. case SQL_VARCHAR:
  1483. case SQL_CHAR:
  1484. case SQL_LONGVARBINARY:
  1485. case SQL_VARBINARY:
  1486. case SQL_BINARY:
  1487. case SQL_DATE:
  1488. return ERR_INTERNAL;
  1489. case SQL_TIME:
  1490. if (pfSqlType != NULL)
  1491. *pfSqlType = fSqlTypeRight;
  1492. if (pPrecision != NULL)
  1493. *pPrecision = precisionRight;
  1494. if (pScale != NULL)
  1495. *pScale = NO_SCALE;
  1496. break;
  1497. case SQL_TIMESTAMP:
  1498. return ERR_INTERNAL;
  1499. default:
  1500. return ERR_NOTSUPPORTED;
  1501. }
  1502. break;
  1503. case SQL_TIMESTAMP:
  1504. switch (fSqlTypeRight) {
  1505. case SQL_DOUBLE:
  1506. case SQL_FLOAT:
  1507. case SQL_REAL:
  1508. case SQL_DECIMAL:
  1509. case SQL_NUMERIC:
  1510. case SQL_BIGINT:
  1511. case SQL_INTEGER:
  1512. case SQL_SMALLINT:
  1513. case SQL_TINYINT:
  1514. case SQL_BIT:
  1515. case SQL_LONGVARCHAR:
  1516. case SQL_VARCHAR:
  1517. case SQL_CHAR:
  1518. case SQL_LONGVARBINARY:
  1519. case SQL_VARBINARY:
  1520. case SQL_BINARY:
  1521. case SQL_DATE:
  1522. case SQL_TIME:
  1523. return ERR_INTERNAL;
  1524. case SQL_TIMESTAMP:
  1525. if (pfSqlType != NULL)
  1526. *pfSqlType = fSqlTypeRight;
  1527. if (pPrecision != NULL)
  1528. *pPrecision = precisionRight;
  1529. if (pScale != NULL)
  1530. *pScale = TIMESTAMP_SCALE;
  1531. break;
  1532. default:
  1533. return ERR_NOTSUPPORTED;
  1534. }
  1535. break;
  1536. default:
  1537. return ERR_NOTSUPPORTED;
  1538. }
  1539. }
  1540. else if ((fDataTypeLeft == TYPE_DATE) &&
  1541. ((fDataTypeRight == TYPE_DOUBLE) ||
  1542. (fDataTypeRight == TYPE_NUMERIC) ||
  1543. (fDataTypeRight == TYPE_INTEGER))) {
  1544. switch (opCode) {
  1545. case OP_NONE:
  1546. case OP_EQ:
  1547. case OP_NE:
  1548. case OP_LE:
  1549. case OP_LT:
  1550. case OP_GE:
  1551. case OP_GT:
  1552. case OP_IN:
  1553. case OP_NOTIN:
  1554. case OP_LIKE:
  1555. case OP_NOTLIKE:
  1556. case OP_NEG:
  1557. ErrorOpCode(lpstmt, opCode);
  1558. return ERR_INVALIDOPERAND;
  1559. case OP_PLUS:
  1560. case OP_MINUS:
  1561. if (pfDataType != NULL)
  1562. *pfDataType = fDataTypeLeft;
  1563. if (pfSqlType != NULL)
  1564. *pfSqlType = fSqlTypeLeft;
  1565. if (pPrecision != NULL)
  1566. *pPrecision = precisionLeft;
  1567. if (pScale != NULL)
  1568. *pScale = scaleLeft;
  1569. break;
  1570. case OP_TIMES:
  1571. case OP_DIVIDEDBY:
  1572. case OP_NOT:
  1573. case OP_AND:
  1574. case OP_OR:
  1575. case OP_EXISTS:
  1576. ErrorOpCode(lpstmt, opCode);
  1577. return ERR_INVALIDOPERAND;
  1578. }
  1579. }
  1580. else if ((fDataTypeRight == TYPE_DATE) &&
  1581. ((fDataTypeLeft == TYPE_DOUBLE) ||
  1582. (fDataTypeLeft == TYPE_NUMERIC) ||
  1583. (fDataTypeLeft == TYPE_INTEGER))) {
  1584. switch (opCode) {
  1585. case OP_NONE:
  1586. case OP_EQ:
  1587. case OP_NE:
  1588. case OP_LE:
  1589. case OP_LT:
  1590. case OP_GE:
  1591. case OP_GT:
  1592. case OP_IN:
  1593. case OP_NOTIN:
  1594. case OP_LIKE:
  1595. case OP_NOTLIKE:
  1596. case OP_NEG:
  1597. ErrorOpCode(lpstmt, opCode);
  1598. return ERR_INVALIDOPERAND;
  1599. case OP_PLUS:
  1600. if (pfDataType != NULL)
  1601. *pfDataType = fDataTypeRight;
  1602. if (pfSqlType != NULL)
  1603. *pfSqlType = fSqlTypeRight;
  1604. if (pPrecision != NULL)
  1605. *pPrecision = precisionRight;
  1606. if (pScale != NULL)
  1607. *pScale = scaleRight;
  1608. break;
  1609. case OP_MINUS:
  1610. case OP_TIMES:
  1611. case OP_DIVIDEDBY:
  1612. case OP_NOT:
  1613. case OP_AND:
  1614. case OP_OR:
  1615. case OP_EXISTS:
  1616. ErrorOpCode(lpstmt, opCode);
  1617. return ERR_INVALIDOPERAND;
  1618. }
  1619. }
  1620. else {
  1621. ErrorOpCode(lpstmt, opCode);
  1622. return ERR_INVALIDOPERAND;
  1623. }
  1624. return ERR_SUCCESS;
  1625. }
  1626. /***************************************************************************/
  1627. BOOL INTFUNC FindAggregate(LPSQLTREE lpSql, SQLNODEIDX idxNode)
  1628. /* Looks for the next aggregate function on a select list */
  1629. {
  1630. LPSQLNODE lpSqlNode;
  1631. if (idxNode == NO_SQLNODE)
  1632. return FALSE;
  1633. lpSqlNode = ToNode(lpSql, idxNode);
  1634. switch (lpSqlNode->sqlNodeType) {
  1635. case NODE_TYPE_NONE:
  1636. case NODE_TYPE_ROOT:
  1637. case NODE_TYPE_CREATE:
  1638. case NODE_TYPE_DROP:
  1639. return FALSE; /* Internal error */
  1640. case NODE_TYPE_SELECT:
  1641. return FALSE;
  1642. case NODE_TYPE_INSERT:
  1643. case NODE_TYPE_DELETE:
  1644. case NODE_TYPE_UPDATE:
  1645. case NODE_TYPE_CREATEINDEX:
  1646. case NODE_TYPE_DROPINDEX:
  1647. case NODE_TYPE_PASSTHROUGH:
  1648. case NODE_TYPE_TABLES:
  1649. return FALSE; /* Internal error */
  1650. case NODE_TYPE_VALUES:
  1651. while (TRUE) {
  1652. if (FindAggregate(lpSql, lpSqlNode->node.values.Value))
  1653. return TRUE;
  1654. if (lpSqlNode->node.values.Next == NO_SQLNODE)
  1655. return FALSE;
  1656. lpSqlNode = ToNode(lpSql, lpSqlNode->node.values.Next);
  1657. }
  1658. case NODE_TYPE_COLUMNS:
  1659. case NODE_TYPE_SORTCOLUMNS:
  1660. case NODE_TYPE_GROUPBYCOLUMNS:
  1661. case NODE_TYPE_UPDATEVALUES:
  1662. case NODE_TYPE_CREATECOLS:
  1663. case NODE_TYPE_BOOLEAN:
  1664. case NODE_TYPE_COMPARISON:
  1665. return FALSE; /* Internal error */
  1666. case NODE_TYPE_ALGEBRAIC:
  1667. if (FindAggregate(lpSql, lpSqlNode->node.algebraic.Left))
  1668. return TRUE;
  1669. return (FindAggregate(lpSql, lpSqlNode->node.algebraic.Right));
  1670. case NODE_TYPE_SCALAR:
  1671. return (FindAggregate(lpSql, lpSqlNode->node.scalar.Arguments));
  1672. case NODE_TYPE_AGGREGATE:
  1673. return TRUE;
  1674. case NODE_TYPE_TABLE:
  1675. return FALSE; /* Internal error */
  1676. case NODE_TYPE_COLUMN:
  1677. case NODE_TYPE_STRING:
  1678. case NODE_TYPE_NUMERIC:
  1679. case NODE_TYPE_PARAMETER:
  1680. case NODE_TYPE_USER:
  1681. case NODE_TYPE_NULL:
  1682. case NODE_TYPE_DATE:
  1683. case NODE_TYPE_TIME:
  1684. case NODE_TYPE_TIMESTAMP:
  1685. return FALSE;
  1686. default:
  1687. return FALSE; /* Internal error */
  1688. }
  1689. }
  1690. /***************************************************************************/
  1691. RETCODE INTFUNC SelectCheck(LPSTMT lpstmt, LPSQLTREE FAR *lplpSql,
  1692. SQLNODEIDX idxNode, BOOL fCaseSensitive,
  1693. SQLNODEIDX idxEnclosingStatement)
  1694. /* Walks a SELECT parse tree, checks it for semantic correctness, and */
  1695. /* fills in the semantic information. */
  1696. {
  1697. LPSQLNODE lpSqlNode;
  1698. RETCODE err;
  1699. UWORD count;
  1700. UDWORD offset;
  1701. BOOL fIsGroupby;
  1702. if (idxNode == NO_SQLNODE)
  1703. return ERR_SUCCESS;
  1704. lpSqlNode = ToNode(*lplpSql, idxNode);
  1705. /* Save pointer to enclosing statement */
  1706. lpSqlNode->node.select.EnclosingStatement = idxEnclosingStatement;
  1707. /* Check the list of tables */
  1708. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Tables,
  1709. FALSE, fCaseSensitive, NO_SQLNODE, idxNode);
  1710. if (err != ERR_SUCCESS)
  1711. return err;
  1712. /* Check the GROUP BY columns */
  1713. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Groupbycolumns,
  1714. FALSE, fCaseSensitive, NO_SQLNODE, idxNode);
  1715. if (err != ERR_SUCCESS)
  1716. return err;
  1717. /* Is there a GROUP BY clause? */
  1718. count = 0;
  1719. offset = 1;
  1720. if (lpSqlNode->node.select.Groupbycolumns != NO_SQLNODE) {
  1721. UDWORD length;
  1722. SQLNODEIDX idxGroupbycolumns;
  1723. LPSQLNODE lpSqlNodeGroupbycolumns;
  1724. LPSQLNODE lpSqlNodeColumn;
  1725. /* Yes. Error if SELECT * */
  1726. if (lpSqlNode->node.select.Values == NO_SQLNODE)
  1727. return ERR_NOSELECTSTAR;
  1728. /* Figure out offset and length of each column when it */
  1729. /* is in the sort file */
  1730. idxGroupbycolumns = lpSqlNode->node.select.Groupbycolumns;
  1731. while (idxGroupbycolumns != NO_SQLNODE) {
  1732. /* Add this column to the count */
  1733. count++;
  1734. /* Error if too many columns */
  1735. if (count > MAX_COLUMNS_IN_GROUP_BY)
  1736. return ERR_GROUPBYTOOLARGE;
  1737. /* Save column offset */
  1738. lpSqlNodeGroupbycolumns = ToNode(*lplpSql, idxGroupbycolumns);
  1739. lpSqlNodeColumn = ToNode(*lplpSql,
  1740. lpSqlNodeGroupbycolumns->node.groupbycolumns.Column);
  1741. lpSqlNodeColumn->node.column.Offset = offset;
  1742. /* Get length of the column */
  1743. switch (lpSqlNodeColumn->sqlDataType) {
  1744. case TYPE_DOUBLE:
  1745. length = sizeof(double);
  1746. break;
  1747. case TYPE_NUMERIC:
  1748. length = 2 + lpSqlNodeColumn->sqlPrecision;
  1749. break;
  1750. case TYPE_INTEGER:
  1751. length = sizeof(double);
  1752. break;
  1753. case TYPE_CHAR:
  1754. length = lpSqlNodeColumn->sqlPrecision;
  1755. if (length > MAX_CHAR_LITERAL_LENGTH) {
  1756. s_lstrcpy((char*)lpstmt->szError,
  1757. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  1758. return ERR_CANTGROUPBYONTHIS;
  1759. }
  1760. break;
  1761. case TYPE_BINARY:
  1762. s_lstrcpy((char*)lpstmt->szError,
  1763. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  1764. return ERR_CANTGROUPBYONTHIS;
  1765. case TYPE_DATE:
  1766. length = 10;
  1767. break;
  1768. case TYPE_TIME:
  1769. length = 8;
  1770. break;
  1771. case TYPE_TIMESTAMP:
  1772. if (TIMESTAMP_SCALE > 0)
  1773. length = 20 + TIMESTAMP_SCALE;
  1774. else
  1775. length = 19;
  1776. break;
  1777. default:
  1778. s_lstrcpy((char*)lpstmt->szError,
  1779. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  1780. return ERR_CANTGROUPBYONTHIS;
  1781. }
  1782. /* Put length of the column column description */
  1783. lpSqlNodeColumn->node.column.Length = length;
  1784. /* Go to next column */
  1785. offset += (length);
  1786. offset++; /* for the IS NULL flag */
  1787. idxGroupbycolumns = lpSqlNodeGroupbycolumns->node.groupbycolumns.Next;
  1788. }
  1789. /* Set flag */
  1790. fIsGroupby = TRUE;
  1791. }
  1792. else {
  1793. /* No. Are there any aggregates in the select list? */
  1794. if (!FindAggregate(*lplpSql, lpSqlNode->node.select.Values)) {
  1795. /* No. Error if there is a HAVING clause */
  1796. if (lpSqlNode->node.select.Having != NO_SQLNODE)
  1797. return ERR_NOGROUPBY;
  1798. /* Set flag */
  1799. fIsGroupby = FALSE;
  1800. }
  1801. else {
  1802. /* Yes. Set flags */
  1803. lpSqlNode->node.select.ImplicitGroupby = TRUE;
  1804. fIsGroupby = TRUE;
  1805. }
  1806. }
  1807. /* SELECT * ? */
  1808. if (lpSqlNode->node.select.Values == NO_SQLNODE) {
  1809. SQLNODEIDX idxTables;
  1810. LPSQLNODE lpSqlNodeTables;
  1811. SQLNODEIDX idxTable;
  1812. LPSQLNODE lpSqlNodeTable;
  1813. // STRINGIDX idxAlias;
  1814. LPISAMTABLEDEF lpTableHandle;
  1815. SQLNODEIDX idxValues;
  1816. LPSQLNODE lpSqlNodeValues;
  1817. SQLNODEIDX idxValuesPrev;
  1818. LPSQLNODE lpSqlNodeValuesPrev;
  1819. SQLNODEIDX idxColumn;
  1820. LPSQLNODE lpSqlNodeColumn;
  1821. SWORD idx;
  1822. /* Yes. Loop though all the tables in the table list */
  1823. idxValuesPrev = NO_SQLNODE;
  1824. idxTables = lpSqlNode->node.select.Tables;
  1825. while (idxTables != NO_SQLNODE) {
  1826. /* Get pointer to the next table */
  1827. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  1828. idxTables = lpSqlNodeTables->node.tables.Next;
  1829. /* Get pointer to this table */
  1830. idxTable = lpSqlNodeTables->node.tables.Table;
  1831. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  1832. /* Loop through all the columns of this table */
  1833. lpTableHandle = lpSqlNodeTable->node.table.Handle;
  1834. ClassColumnInfoBase* cInfoBase = lpTableHandle->pColumnInfo;
  1835. LPISAM myISAM = lpTableHandle->lpISAM;
  1836. if ( !cInfoBase->IsValid() )
  1837. {
  1838. return ERR_COLUMNNOTFOUND;
  1839. }
  1840. //Store able alias before allocating memory
  1841. //in order to avoid bug
  1842. STRINGIDX idxTheAlias = lpSqlNodeTable->node.table.Alias;
  1843. STRINGIDX idxTheQual = lpSqlNodeTable->node.table.Qualifier;
  1844. UWORD cNumberOfCols = cInfoBase->GetNumberOfColumns();
  1845. char pColumnName [MAX_COLUMN_NAME_LENGTH+1];
  1846. //Sai added - fetch the column alias
  1847. //only filled in if using passthrough SQL, ignored otherwise
  1848. char pAliasName [MAX_COLUMN_NAME_LENGTH+1];
  1849. pAliasName[0] = 0;
  1850. for (idx = 0; idx < (SWORD) cNumberOfCols; idx++)
  1851. {
  1852. if ( FAILED(cInfoBase->GetColumnName(idx, pColumnName, pAliasName)) )
  1853. {
  1854. return ERR_COLUMNNOTFOUND;
  1855. }
  1856. //Ignore any OLEMS specific columns which we want to hide
  1857. if (myISAM && !(myISAM->fSysProps))
  1858. {
  1859. if (_strnicmp("__", pColumnName, 2) == 0)
  1860. {
  1861. continue;
  1862. }
  1863. }
  1864. //Ignore any 'lazy' columns
  1865. BOOL fIsLazy = FALSE;
  1866. if ( cInfoBase->IsLazy(idx, fIsLazy) )
  1867. {
  1868. if (fIsLazy)
  1869. {
  1870. continue;
  1871. }
  1872. }
  1873. //Check if this column type is support
  1874. //if not we skip this column
  1875. if (! ISAMGetColumnType(lpTableHandle, (UWORD) idx) )
  1876. {
  1877. continue;
  1878. }
  1879. /* Create a node for this column */
  1880. idxColumn = AllocateNode(lplpSql, NODE_TYPE_COLUMN);
  1881. if (idxColumn == NO_SQLNODE)
  1882. return ERR_MEMALLOCFAIL;
  1883. //Get new pointers
  1884. lpSqlNodeColumn = ToNode(*lplpSql, idxColumn);
  1885. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  1886. lpSqlNodeColumn->node.column.Tablealias = idxTheAlias;
  1887. if (lpSqlNodeTable->node.table.Alias != NO_STRING)
  1888. {
  1889. lpSqlNodeColumn->node.column.MatchedAlias = TRUE;
  1890. }
  1891. else
  1892. {
  1893. lpSqlNodeColumn->node.column.MatchedAlias = FALSE;
  1894. }
  1895. lpSqlNodeColumn->node.column.TableIndex = idxTable;
  1896. lpSqlNodeColumn->node.column.Qualifier = idxTheQual;
  1897. lpSqlNodeColumn->node.column.Column = AllocateString(lplpSql,
  1898. (LPUSTR)pColumnName);
  1899. //New - for identical column names when using passthrough SQL
  1900. if ( pAliasName && lstrlen(pAliasName) )
  1901. {
  1902. lpSqlNodeColumn->node.column.Tablealias = AllocateString(lplpSql,
  1903. (LPUSTR)pAliasName);
  1904. }
  1905. //To avoid bug recalc lpSqlNodeColumn
  1906. lpSqlNodeColumn = ToNode(*lplpSql, idxColumn);
  1907. if (lpSqlNodeColumn->node.column.Column == NO_STRING)
  1908. return ERR_MEMALLOCFAIL;
  1909. lpSqlNodeColumn->node.table.Handle = NULL;
  1910. lpSqlNodeColumn->node.column.Id = -1;
  1911. lpSqlNodeColumn->node.column.Value = NO_STRING;
  1912. lpSqlNodeColumn->node.column.InSortRecord = FALSE;
  1913. lpSqlNodeColumn->node.column.Offset = 0;
  1914. lpSqlNodeColumn->node.column.Length = 0;
  1915. lpSqlNodeColumn->node.column.DistinctOffset = 0;
  1916. lpSqlNodeColumn->node.column.DistinctLength = 0;
  1917. lpSqlNodeColumn->node.column.EnclosingStatement = NO_SQLNODE;
  1918. /* Put it on the list */
  1919. idxValues = AllocateNode(lplpSql, NODE_TYPE_VALUES);
  1920. if (idxValues == NO_SQLNODE)
  1921. return ERR_MEMALLOCFAIL;
  1922. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  1923. lpSqlNodeValues->node.values.Value = idxColumn;
  1924. lpSqlNodeValues->node.values.Alias = NO_STRING;
  1925. lpSqlNodeValues->node.values.Next = NO_SQLNODE;
  1926. if (idxValuesPrev == NO_SQLNODE) {
  1927. lpSqlNode = ToNode(*lplpSql, idxNode);
  1928. lpSqlNode->node.select.Values = idxValues;
  1929. }
  1930. else {
  1931. lpSqlNodeValuesPrev = ToNode(*lplpSql, idxValuesPrev);
  1932. lpSqlNodeValuesPrev->node.values.Next = idxValues;
  1933. }
  1934. idxValuesPrev = idxValues;
  1935. }
  1936. }
  1937. lpSqlNode = ToNode(*lplpSql, idxNode);
  1938. }
  1939. /* SELECT aliasname.* ? */
  1940. {
  1941. SQLNODEIDX idxValuesPrev;
  1942. SQLNODEIDX idxValues;
  1943. LPSQLNODE lpSqlNodeValues;
  1944. SQLNODEIDX idxTables;
  1945. LPSQLNODE lpSqlNodeTables;
  1946. SQLNODEIDX idxTable;
  1947. LPSQLNODE lpSqlNodeTable;
  1948. LPUSTR lpTableAlias;
  1949. LPUSTR lpValuesAlias;
  1950. LPSQLNODE lpSqlNodeValuesPrev;
  1951. LPISAMTABLEDEF lpTableHandle;
  1952. SQLNODEIDX idxColumn;
  1953. LPSQLNODE lpSqlNodeColumn;
  1954. SWORD idx;
  1955. STRINGIDX idxAlias;
  1956. SQLNODEIDX idxValuesNew;
  1957. /* Yes. Loop though all the nodes in the select list */
  1958. idxValuesPrev = NO_SQLNODE;
  1959. idxValues = lpSqlNode->node.select.Values;
  1960. while (idxValues != NO_SQLNODE) {
  1961. /* Get pointer to the values node */
  1962. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  1963. /* Is this a <table>.* node? */
  1964. if (lpSqlNodeValues->node.values.Value != NO_SQLNODE) {
  1965. /* No. Go to next entry */
  1966. idxValuesPrev = idxValues;
  1967. idxValues = lpSqlNodeValues->node.values.Next;
  1968. continue;
  1969. }
  1970. idxValues = lpSqlNodeValues->node.values.Next;
  1971. /* Find the table */
  1972. lpValuesAlias = ToString(*lplpSql,
  1973. lpSqlNodeValues->node.values.Alias);
  1974. idxTables = lpSqlNode->node.select.Tables;
  1975. //First pass : check alias's
  1976. while (idxTables != NO_SQLNODE) {
  1977. /* Get pointer to the table */
  1978. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  1979. /* Get pointer to this table */
  1980. idxTable = lpSqlNodeTables->node.tables.Table;
  1981. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  1982. /* Get Alias of this table */
  1983. idxAlias = lpSqlNodeTable->node.table.Alias;
  1984. /* Leave loop if it matches */
  1985. lpTableAlias = ToString(*lplpSql, idxAlias);
  1986. if (fCaseSensitive) {
  1987. if (!s_lstrcmp(lpTableAlias, lpValuesAlias))
  1988. break;
  1989. }
  1990. else {
  1991. if (!s_lstrcmpi(lpTableAlias, lpValuesAlias))
  1992. break;
  1993. }
  1994. /* It does not match. Try next table */
  1995. idxTables = lpSqlNodeTables->node.tables.Next;
  1996. }
  1997. //second pass : table name
  1998. if (idxTables == NO_SQLNODE) {
  1999. idxTables = lpSqlNode->node.select.Tables;
  2000. while (idxTables != NO_SQLNODE) {
  2001. /* Get pointer to the table */
  2002. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  2003. /* Get pointer to this table */
  2004. idxTable = lpSqlNodeTables->node.tables.Table;
  2005. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  2006. /* Get Alias of this table */
  2007. idxAlias = lpSqlNodeTable->node.table.Name;
  2008. /* Leave loop if it matches */
  2009. lpTableAlias = ToString(*lplpSql, idxAlias);
  2010. if (fCaseSensitive) {
  2011. if (!s_lstrcmp(lpTableAlias, lpValuesAlias))
  2012. {
  2013. lpSqlNodeTable->node.table.Alias = idxAlias;
  2014. break;
  2015. }
  2016. }
  2017. else {
  2018. if (!s_lstrcmpi(lpTableAlias, lpValuesAlias))
  2019. {
  2020. lpSqlNodeTable->node.table.Alias = idxAlias;
  2021. break;
  2022. }
  2023. }
  2024. /* It does not match. Try next table */
  2025. idxTables = lpSqlNodeTables->node.tables.Next;
  2026. }
  2027. }
  2028. /* Error if not tables match */
  2029. if (idxTables == NO_SQLNODE) {
  2030. s_lstrcpy(lpstmt->szError, lpValuesAlias);
  2031. return ERR_TABLENOTFOUND;
  2032. }
  2033. /* Remove the <table>.* node */
  2034. if (idxValuesPrev == NO_SQLNODE)
  2035. lpSqlNode->node.select.Values = idxValues;
  2036. else {
  2037. lpSqlNodeValuesPrev = ToNode(*lplpSql, idxValuesPrev);
  2038. lpSqlNodeValuesPrev->node.values.Next = idxValues;
  2039. }
  2040. /* Loop through all the columns of the table */
  2041. lpTableHandle = lpSqlNodeTable->node.table.Handle;
  2042. ClassColumnInfoBase* cInfoBase = lpTableHandle->pColumnInfo;
  2043. LPISAM myISAM = lpTableHandle->lpISAM;
  2044. if ( !cInfoBase->IsValid() )
  2045. {
  2046. return ERR_COLUMNNOTFOUND;
  2047. }
  2048. //Store able alias before allocating memory
  2049. //in order to avoid bug
  2050. STRINGIDX idxTheAlias = lpSqlNodeTable->node.table.Alias;
  2051. STRINGIDX idxTheQual = lpSqlNodeTable->node.table.Qualifier;
  2052. UWORD cNumberOfCols = cInfoBase->GetNumberOfColumns();
  2053. char pColumnName [MAX_COLUMN_NAME_LENGTH+1];
  2054. //Sai added - fetch the column alias
  2055. //only filled in if using passthrough SQL, ignored otherwise
  2056. char pAliasName [MAX_COLUMN_NAME_LENGTH+1];
  2057. pAliasName[0] = 0;
  2058. for (idx = 0; idx < (SWORD) cNumberOfCols; idx++) {
  2059. if ( FAILED(cInfoBase->GetColumnName(idx, pColumnName, pAliasName)) )
  2060. {
  2061. return ERR_COLUMNNOTFOUND;
  2062. }
  2063. //Ignore any OLEMS specific columns which we want to hide
  2064. if (myISAM && !(myISAM->fSysProps))
  2065. {
  2066. if (_strnicmp("__", pColumnName, 2) == 0)
  2067. {
  2068. continue;
  2069. }
  2070. }
  2071. //Ignore any 'lazy' columns
  2072. BOOL fIsLazy = FALSE;
  2073. if ( cInfoBase->IsLazy(idx, fIsLazy) )
  2074. {
  2075. if (fIsLazy)
  2076. {
  2077. continue;
  2078. }
  2079. }
  2080. //Check if this column type is support
  2081. //if not we skip this column
  2082. if (! ISAMGetColumnType(lpTableHandle, (UWORD) idx) )
  2083. {
  2084. continue;
  2085. }
  2086. /* Create a node for this column */
  2087. idxColumn = AllocateNode(lplpSql, NODE_TYPE_COLUMN);
  2088. if (idxColumn == NO_SQLNODE)
  2089. return ERR_MEMALLOCFAIL;
  2090. //Get new pointers
  2091. lpSqlNodeColumn = ToNode(*lplpSql, idxColumn);
  2092. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  2093. lpSqlNodeColumn->node.column.Tablealias = idxAlias;
  2094. lpSqlNodeColumn->node.column.Column = AllocateString(lplpSql,
  2095. (LPUSTR)pColumnName);
  2096. if (lpSqlNodeColumn->node.column.Column == NO_STRING)
  2097. return ERR_MEMALLOCFAIL;
  2098. if (lpSqlNodeTable->node.table.Alias != NO_STRING)
  2099. {
  2100. lpSqlNodeColumn->node.column.MatchedAlias = TRUE;
  2101. }
  2102. else
  2103. {
  2104. lpSqlNodeColumn->node.column.MatchedAlias = FALSE;
  2105. }
  2106. //New - for identical column names when using passthrough SQL
  2107. if ( pAliasName && lstrlen(pAliasName) )
  2108. {
  2109. lpSqlNodeColumn->node.column.Tablealias = AllocateString(lplpSql,
  2110. (LPUSTR)pAliasName);
  2111. }
  2112. //To avoid bug recalc lpSqlNodeColumn
  2113. lpSqlNodeColumn = ToNode(*lplpSql, idxColumn);
  2114. lpSqlNodeColumn->node.column.TableIndex = idxTable;
  2115. lpSqlNodeColumn->node.column.Qualifier = NO_STRING; //idxTheQual;
  2116. lpSqlNodeColumn->node.table.Handle = NULL;
  2117. lpSqlNodeColumn->node.column.Table = NO_SQLNODE;
  2118. lpSqlNodeColumn->node.column.Id = -1;
  2119. lpSqlNodeColumn->node.column.Value = NO_STRING;
  2120. lpSqlNodeColumn->node.column.InSortRecord = FALSE;
  2121. lpSqlNodeColumn->node.column.Offset = 0;
  2122. lpSqlNodeColumn->node.column.Length = 0;
  2123. lpSqlNodeColumn->node.column.DistinctOffset = 0;
  2124. lpSqlNodeColumn->node.column.DistinctLength = 0;
  2125. lpSqlNodeColumn->node.column.EnclosingStatement = NO_SQLNODE;
  2126. /* Put it on the list */
  2127. idxValuesNew = AllocateNode(lplpSql, NODE_TYPE_VALUES);
  2128. if (idxValuesNew == NO_SQLNODE)
  2129. return ERR_MEMALLOCFAIL;
  2130. lpSqlNodeValues = ToNode(*lplpSql, idxValuesNew);
  2131. lpSqlNodeValues->node.values.Value = idxColumn;
  2132. lpSqlNodeValues->node.values.Alias = NO_STRING;
  2133. lpSqlNodeValues->node.values.Next = idxValues;
  2134. if (idxValuesPrev == NO_SQLNODE) {
  2135. lpSqlNode = ToNode(*lplpSql, idxNode);
  2136. lpSqlNode->node.select.Values = idxValuesNew;
  2137. }
  2138. else {
  2139. lpSqlNodeValuesPrev = ToNode(*lplpSql, idxValuesPrev);
  2140. lpSqlNodeValuesPrev->node.values.Next = idxValuesNew;
  2141. }
  2142. idxValuesPrev = idxValuesNew;
  2143. }
  2144. }
  2145. lpSqlNode = ToNode(*lplpSql, idxNode);
  2146. }
  2147. /* Check the ORDER BY columns */
  2148. err = SemanticCheck(lpstmt, lplpSql,lpSqlNode->node.select.Sortcolumns,
  2149. fIsGroupby, fCaseSensitive, NO_SQLNODE, idxNode);
  2150. if (err != ERR_SUCCESS)
  2151. return err;
  2152. /* Check that each group by column is on sort list (and put it */
  2153. /* there if it is not already there so the sort directive will */
  2154. /* be constructed correctly)... */
  2155. {
  2156. SQLNODEIDX idxGroupbycolumns;
  2157. LPSQLNODE lpSqlNodeGroupbycolumns;
  2158. LPSQLNODE lpSqlNodeColumnGroupby;
  2159. SQLNODEIDX idxSortcolumns;
  2160. SQLNODEIDX idxSortcolumnsPrev;
  2161. LPSQLNODE lpSqlNodeSortcolumns;
  2162. LPSQLNODE lpSqlNodeColumnSort;
  2163. SQLNODEIDX idxColumn;
  2164. SQLNODEIDX idxTableGroupby;
  2165. // LPUSTR lpszTableGroupby;
  2166. LPUSTR lpszColumnGroupby;
  2167. SQLNODEIDX idxTableSort;
  2168. // LPUSTR lpszTableSort;
  2169. LPUSTR lpszColumnSort;
  2170. idxGroupbycolumns = lpSqlNode->node.select.Groupbycolumns;
  2171. while (idxGroupbycolumns != NO_SQLNODE) {
  2172. /* Get this group by column */
  2173. lpSqlNodeGroupbycolumns = ToNode(*lplpSql, idxGroupbycolumns);
  2174. lpSqlNodeColumnGroupby = ToNode(*lplpSql,
  2175. lpSqlNodeGroupbycolumns->node.groupbycolumns.Column);
  2176. /* Get column name and table name of the group by column */
  2177. idxTableGroupby = lpSqlNodeColumnGroupby->node.column.TableIndex;
  2178. lpszColumnGroupby = ToString(*lplpSql,
  2179. lpSqlNodeColumnGroupby->node.column.Column);
  2180. /* Look for this column on the sort list. For each */
  2181. /* column in the sort list... */
  2182. idxSortcolumns = lpSqlNode->node.select.Sortcolumns;
  2183. idxSortcolumnsPrev = NO_SQLNODE;
  2184. while (idxSortcolumns != NO_SQLNODE) {
  2185. /* Get next element on the sort list */
  2186. lpSqlNodeSortcolumns = ToNode(*lplpSql, idxSortcolumns);
  2187. lpSqlNodeColumnSort = ToNode(*lplpSql,
  2188. lpSqlNodeSortcolumns->node.sortcolumns.Column);
  2189. /* Is it a column reference? */
  2190. if (lpSqlNodeColumnSort->sqlNodeType == NODE_TYPE_COLUMN) {
  2191. /* Yes. Get column name and table name of sort column */
  2192. idxTableSort = lpSqlNodeColumnSort->node.column.TableIndex;
  2193. lpszColumnSort = ToString(*lplpSql,
  2194. lpSqlNodeColumnSort->node.column.Column);
  2195. /* Leave if this sort column is the group by column */
  2196. if (idxTableSort == idxTableGroupby)
  2197. {
  2198. if (fCaseSensitive) {
  2199. // if (!s_lstrcmp(lpszTableSort, lpszTableGroupby) &&
  2200. // !s_lstrcmp(lpszColumnSort, lpszColumnGroupby))
  2201. if ( !s_lstrcmp(lpszColumnSort, lpszColumnGroupby) )
  2202. break;
  2203. }
  2204. else {
  2205. // if (!s_lstrcmpi(lpszTableSort, lpszTableGroupby) &&
  2206. // !s_lstrcmpi(lpszColumnSort, lpszColumnGroupby))
  2207. if ( !s_lstrcmpi(lpszColumnSort, lpszColumnGroupby) )
  2208. break;
  2209. }
  2210. }
  2211. }
  2212. /* Get next sort column */
  2213. idxSortcolumnsPrev = idxSortcolumns;
  2214. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  2215. }
  2216. /* Was group by columnn found in the sort list? */
  2217. if (idxSortcolumns == NO_SQLNODE) {
  2218. /* No. A new entry will be needed. Create a node for */
  2219. /* the column */
  2220. idxColumn = AllocateNode(lplpSql, NODE_TYPE_COLUMN);
  2221. if (idxColumn == NO_SQLNODE)
  2222. return ERR_MEMALLOCFAIL;
  2223. lpSqlNodeColumnSort = ToNode(*lplpSql, idxColumn);
  2224. /* Recalculate these pointers since the Alloc above */
  2225. /* may have moved them */
  2226. /* addeed th enext line */
  2227. lpSqlNodeGroupbycolumns = ToNode (*lplpSql, idxGroupbycolumns);
  2228. lpSqlNodeColumnGroupby = ToNode(*lplpSql,
  2229. lpSqlNodeGroupbycolumns->node.groupbycolumns.Column);
  2230. /* Fill in the node */
  2231. lpSqlNodeColumnSort->node.column.Tablealias =
  2232. lpSqlNodeColumnGroupby->node.column.Tablealias;
  2233. lpSqlNodeColumnSort->node.column.Column =
  2234. lpSqlNodeColumnGroupby->node.column.Column;
  2235. lpSqlNodeColumnSort->node.column.Qualifier =
  2236. lpSqlNodeColumnGroupby->node.column.Qualifier;
  2237. lpSqlNodeColumnSort->node.column.TableIndex =
  2238. lpSqlNodeColumnGroupby->node.column.TableIndex;
  2239. lpSqlNodeColumnSort->node.column.MatchedAlias =
  2240. lpSqlNodeColumnGroupby->node.column.MatchedAlias;
  2241. lpSqlNodeColumnSort->node.column.Table = NO_SQLNODE;
  2242. lpSqlNodeColumnSort->node.column.Id = -1;
  2243. lpSqlNodeColumnSort->node.column.Value = NO_STRING;
  2244. lpSqlNodeColumnSort->node.column.InSortRecord = FALSE;
  2245. lpSqlNodeColumnSort->node.column.Offset = 0;
  2246. lpSqlNodeColumnSort->node.column.Length = 0;
  2247. lpSqlNodeColumnSort->node.column.DistinctOffset = 0;
  2248. lpSqlNodeColumnSort->node.column.DistinctLength = 0;
  2249. lpSqlNodeColumnSort->node.column.EnclosingStatement = NO_SQLNODE;
  2250. /* Create sort list element */
  2251. idxSortcolumns = AllocateNode(lplpSql,
  2252. NODE_TYPE_SORTCOLUMNS);
  2253. if (idxSortcolumns == NO_SQLNODE)
  2254. return ERR_MEMALLOCFAIL;
  2255. lpSqlNodeSortcolumns = ToNode(*lplpSql, idxSortcolumns);
  2256. lpSqlNodeSortcolumns->node.sortcolumns.Column = idxColumn;
  2257. lpSqlNodeSortcolumns->node.sortcolumns.Descending = FALSE;
  2258. lpSqlNodeSortcolumns->node.sortcolumns.Next = NO_SQLNODE;
  2259. /* Recalculate these pointers since the Alloc above */
  2260. /* may have moved them */
  2261. lpSqlNodeGroupbycolumns =
  2262. ToNode(*lplpSql, idxGroupbycolumns);
  2263. lpSqlNode = ToNode(*lplpSql, idxNode);
  2264. /* Put it on the sort list */
  2265. if (idxSortcolumnsPrev == NO_SQLNODE)
  2266. lpSqlNode->node.select.Sortcolumns = idxSortcolumns;
  2267. else {
  2268. lpSqlNodeSortcolumns =
  2269. ToNode(*lplpSql, idxSortcolumnsPrev);
  2270. lpSqlNodeSortcolumns->node.sortcolumns.Next =
  2271. idxSortcolumns;
  2272. }
  2273. /* Semantic check the newly created nodes */
  2274. err = SemanticCheck(lpstmt, lplpSql, idxSortcolumns,
  2275. fIsGroupby, fCaseSensitive, NO_SQLNODE, idxNode);
  2276. }
  2277. /* Look at next group by column */
  2278. idxGroupbycolumns =
  2279. lpSqlNodeGroupbycolumns->node.groupbycolumns.Next;
  2280. }
  2281. }
  2282. /* Check the select list */
  2283. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Values,
  2284. fIsGroupby, fCaseSensitive, NO_SQLNODE, idxNode);
  2285. if (err != ERR_SUCCESS)
  2286. return err;
  2287. /* Check the WHERE clause */
  2288. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Predicate,
  2289. FALSE, fCaseSensitive, NO_SQLNODE, idxNode);
  2290. if (err != ERR_SUCCESS)
  2291. return err;
  2292. /* Check the HAVING clause */
  2293. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.select.Having,
  2294. fIsGroupby, fCaseSensitive, NO_SQLNODE, idxNode);
  2295. if (err != ERR_SUCCESS)
  2296. return err;
  2297. /* Build the sorting directive and determine the overall key size. */
  2298. /* At the same time check to make sure that there are not too many */
  2299. /* columns in ORDER BY and that character or binary keys are not */
  2300. /* too big. */
  2301. if (lpSqlNode->node.select.Sortcolumns != NO_SQLNODE) {
  2302. SQLNODEIDX idxSortcolumns;
  2303. LPSQLNODE lpSqlNodeSortcolumns;
  2304. LPSQLNODE lpSqlNodeColumn;
  2305. UDWORD length;
  2306. SQLNODEIDX idxTables;
  2307. LPSQLNODE lpSqlNodeTables;
  2308. #define NUM_LEN 5
  2309. UCHAR szSortDirective[10 + NUM_LEN +
  2310. (MAX_COLUMNS_IN_ORDER_BY * (6 + (2 * NUM_LEN)))
  2311. + 3 + MAX_PATHNAME_SIZE];
  2312. szSortDirective[0] = 0;
  2313. SQLNODEIDX idxAggregate;
  2314. LPSQLNODE lpSqlNodeAggregate;
  2315. /* For each sort column... */
  2316. s_lstrcpy(szSortDirective, "S(");
  2317. idxSortcolumns = lpSqlNode->node.select.Sortcolumns;
  2318. while (idxSortcolumns != NO_SQLNODE) {
  2319. /* Is this node on the group by list ? */
  2320. lpSqlNodeSortcolumns = ToNode(*lplpSql, idxSortcolumns);
  2321. lpSqlNodeColumn = ToNode(*lplpSql,
  2322. lpSqlNodeSortcolumns->node.sortcolumns.Column);
  2323. if ((lpSqlNode->node.select.Groupbycolumns == NO_SQLNODE) ||
  2324. (lpSqlNodeColumn->sqlNodeType != NODE_TYPE_COLUMN)) {
  2325. /* No. Add this sort column to the count */
  2326. count++;
  2327. /* Error if too many sort columns */
  2328. if (count > MAX_COLUMNS_IN_ORDER_BY)
  2329. return ERR_ORDERBYTOOLARGE;
  2330. /* Get length of the column. */
  2331. switch (lpSqlNodeColumn->sqlDataType) {
  2332. case TYPE_DOUBLE:
  2333. length = sizeof(double);
  2334. break;
  2335. case TYPE_NUMERIC:
  2336. length = 2 + lpSqlNodeColumn->sqlPrecision;
  2337. break;
  2338. case TYPE_INTEGER:
  2339. length = sizeof(double);
  2340. break;
  2341. case TYPE_CHAR:
  2342. length = lpSqlNodeColumn->sqlPrecision;
  2343. if (length > MAX_CHAR_LITERAL_LENGTH) {
  2344. if (lpSqlNodeColumn->sqlNodeType == NODE_TYPE_COLUMN)
  2345. s_lstrcpy(lpstmt->szError,
  2346. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  2347. else
  2348. s_lstrcpy(lpstmt->szError, "<expression>");
  2349. return ERR_CANTORDERBYONTHIS;
  2350. }
  2351. break;
  2352. case TYPE_BINARY:
  2353. length = lpSqlNodeColumn->sqlPrecision;
  2354. if (length > MAX_BINARY_LITERAL_LENGTH) {
  2355. if (lpSqlNodeColumn->sqlNodeType == NODE_TYPE_COLUMN)
  2356. s_lstrcpy((char*)lpstmt->szError,
  2357. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  2358. else
  2359. s_lstrcpy(lpstmt->szError, "<expression>");
  2360. return ERR_CANTORDERBYONTHIS;
  2361. }
  2362. break;
  2363. case TYPE_DATE:
  2364. length = 10;
  2365. break;
  2366. case TYPE_TIME:
  2367. length = 8;
  2368. break;
  2369. case TYPE_TIMESTAMP:
  2370. if (TIMESTAMP_SCALE > 0)
  2371. length = 20 + TIMESTAMP_SCALE;
  2372. else
  2373. length = 19;
  2374. break;
  2375. default:
  2376. if (lpSqlNodeColumn->sqlNodeType == NODE_TYPE_COLUMN)
  2377. s_lstrcpy(lpstmt->szError,
  2378. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column));
  2379. else
  2380. s_lstrcpy((char*)lpstmt->szError, "<expression>");
  2381. return ERR_CANTORDERBYONTHIS;
  2382. }
  2383. /* Put offset of the key column in the sort directive */
  2384. wsprintf((LPSTR) (szSortDirective + s_lstrlen((LPSTR)szSortDirective)),
  2385. "%lu,", offset);
  2386. /* Adjust offset */
  2387. offset += (length);
  2388. offset++; /* for the IS NULL flag */
  2389. }
  2390. else {
  2391. /* Yes. Get length */
  2392. length = lpSqlNodeColumn->node.column.Length;
  2393. /* Put offset of the key column in the sort directive */
  2394. wsprintf((LPSTR)(szSortDirective + s_lstrlen((LPSTR)szSortDirective)),
  2395. "%lu,", lpSqlNodeColumn->node.column.Offset);
  2396. }
  2397. /* Put length of the key column in the sort directive */
  2398. wsprintf((LPSTR)(szSortDirective + s_lstrlen((LPSTR)szSortDirective)),
  2399. "%lu,", length);
  2400. /* Put type of the key column in the sort directive */
  2401. switch (lpSqlNodeColumn->sqlDataType) {
  2402. case TYPE_DOUBLE:
  2403. s_lstrcat((LPSTR)szSortDirective, "E,");
  2404. break;
  2405. case TYPE_NUMERIC:
  2406. s_lstrcat((LPSTR)szSortDirective, "N,");
  2407. break;
  2408. case TYPE_INTEGER:
  2409. s_lstrcat((LPSTR)szSortDirective, "E,");
  2410. break;
  2411. case TYPE_CHAR:
  2412. case TYPE_BINARY:
  2413. case TYPE_DATE:
  2414. case TYPE_TIME:
  2415. case TYPE_TIMESTAMP:
  2416. s_lstrcat((LPSTR)szSortDirective, "C,");
  2417. break;
  2418. default:
  2419. return ERR_INTERNAL;
  2420. }
  2421. /* Put direction of the key column in the sort directive */
  2422. if (lpSqlNodeSortcolumns->node.sortcolumns.Descending)
  2423. s_lstrcat((char*)szSortDirective, "D");
  2424. else
  2425. s_lstrcat((char*)szSortDirective, "A");
  2426. /* Go to next sort column */
  2427. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  2428. if (idxSortcolumns != NO_SQLNODE)
  2429. s_lstrcat((char*)szSortDirective, ",");
  2430. }
  2431. /* Save the sort key size */
  2432. lpSqlNode->node.select.SortKeysize = offset-1;
  2433. /* Is there a GROUP BY statement? */
  2434. if ((lpSqlNode->node.select.Groupbycolumns == NO_SQLNODE) &&
  2435. (!lpSqlNode->node.select.ImplicitGroupby)) {
  2436. /* No. Save offset of the bookmark */
  2437. lpSqlNode->node.select.SortBookmarks = offset;
  2438. /* For each table in table list, add bookmark size to offset */
  2439. idxTables = lpSqlNode->node.select.Tables;
  2440. while (idxTables != NO_SQLNODE) {
  2441. /* Update offset */
  2442. offset += (sizeof(ISAMBOOKMARK));
  2443. /* Get pointer to the next table */
  2444. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  2445. idxTables = lpSqlNodeTables->node.tables.Next;
  2446. }
  2447. }
  2448. else {
  2449. /* Yes. Calculate the offset of each aggregate field */
  2450. idxAggregate = lpSqlNode->node.select.Aggregates;
  2451. while (idxAggregate != NO_SQLNODE) {
  2452. /* Save offset of the aggregate */
  2453. lpSqlNodeAggregate = ToNode(*lplpSql, idxAggregate);
  2454. lpSqlNodeAggregate->node.aggregate.Offset = offset;
  2455. /* Update offset */
  2456. offset += (lpSqlNodeAggregate->node.aggregate.Length + 1);
  2457. /* Get pointer to the next aggregate */
  2458. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  2459. }
  2460. }
  2461. offset--;
  2462. s_lstrcat((char*)szSortDirective, ")");
  2463. /* Put record size into sort directive */
  2464. s_lstrcat((char*)szSortDirective, "F(FIX,");
  2465. wsprintf((LPSTR)(szSortDirective + s_lstrlen((char*)szSortDirective)),
  2466. "%lu", offset);
  2467. lstrcat((char*)szSortDirective, ")");
  2468. /* Put in work drive */
  2469. s_lstrcat(szSortDirective, "W(");
  2470. #ifdef WIN32
  2471. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR)
  2472. szSortDirective + s_lstrlen(szSortDirective)))
  2473. return ERR_SORT;
  2474. if (szSortDirective[s_lstrlen(szSortDirective)-1] != '\\')
  2475. s_lstrcat(szSortDirective, "\\");
  2476. #else
  2477. GetTempFileName(NULL, "LEM", 0, (LPSTR) szSortDirective +
  2478. s_lstrlen(szSortDirective));
  2479. while (szSortDirective[s_lstrlen(szSortDirective)-1] != '\\')
  2480. szSortDirective[s_lstrlen(szSortDirective)-1] = '\0';
  2481. #endif
  2482. s_lstrcat(szSortDirective, ")");
  2483. /* Save the directive */
  2484. lpSqlNode->node.select.SortDirective = AllocateString(lplpSql,
  2485. (LPUSTR)szSortDirective);
  2486. if (lpSqlNode->node.select.SortDirective == NO_STRING)
  2487. return ERR_MEMALLOCFAIL;
  2488. /* Save the sort record size */
  2489. lpSqlNode->node.select.SortRecordsize = offset;
  2490. }
  2491. /* If there is no group by list originally but there is a group by */
  2492. /* list now, there was an aggregate in the select list. Calculate */
  2493. /* the offset of each aggregate field */
  2494. if (lpSqlNode->node.select.ImplicitGroupby) {
  2495. SQLNODEIDX idxAggregate;
  2496. LPSQLNODE lpSqlNodeAggregate;
  2497. idxAggregate = lpSqlNode->node.select.Aggregates;
  2498. while (idxAggregate != NO_SQLNODE) {
  2499. /* Save offset of the aggregate */
  2500. lpSqlNodeAggregate = ToNode(*lplpSql, idxAggregate);
  2501. lpSqlNodeAggregate->node.aggregate.Offset = offset;
  2502. /* Update offset */
  2503. offset += (lpSqlNodeAggregate->node.aggregate.Length + 1);
  2504. /* Get pointer to the next aggregate */
  2505. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  2506. }
  2507. /* Adjust the offset */
  2508. offset--;
  2509. /* Save the sort record size */
  2510. lpSqlNode->node.select.SortRecordsize = offset;
  2511. }
  2512. /* Build the sorting directive for SELECT DISTINCT and determine the */
  2513. /* overall key size. At the same time check to make sure that there */
  2514. /* are not too many columns in ORDER BY and that character or binary */
  2515. /* keys are not too big. */
  2516. if (lpSqlNode->node.select.Distinct) {
  2517. SQLNODEIDX idxValues;
  2518. LPSQLNODE lpSqlNodeValues;
  2519. LPSQLNODE lpSqlNodeExpression;
  2520. UDWORD length;
  2521. #define NUM_LEN 5
  2522. UCHAR szSortDirective[19 + (4 * NUM_LEN) +
  2523. (MAX_COLUMNS_IN_ORDER_BY * (6 + (2 * NUM_LEN)))
  2524. + 3 + MAX_PATHNAME_SIZE];
  2525. /* For each sort column... */
  2526. count = 0;
  2527. offset = NUM_LEN + 1;
  2528. s_lstrcpy(szSortDirective, "S(");
  2529. idxValues = lpSqlNode->node.select.Values;
  2530. while (idxValues != NO_SQLNODE) {
  2531. /* Is this node of interest? */
  2532. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  2533. lpSqlNodeExpression = ToNode(*lplpSql,
  2534. lpSqlNodeValues->node.values.Value);
  2535. switch (lpSqlNodeExpression->sqlNodeType) {
  2536. case NODE_TYPE_COLUMN:
  2537. case NODE_TYPE_AGGREGATE:
  2538. case NODE_TYPE_ALGEBRAIC:
  2539. case NODE_TYPE_SCALAR:
  2540. /* Yes. Add this sort column to the count */
  2541. count++;
  2542. /* Error if too many sort columns */
  2543. if (count > MAX_COLUMNS_IN_ORDER_BY)
  2544. return ERR_ORDERBYTOOLARGE;
  2545. /* Get length of the column. */
  2546. switch (lpSqlNodeExpression->sqlDataType) {
  2547. case TYPE_DOUBLE:
  2548. length = sizeof(double);
  2549. break;
  2550. case TYPE_NUMERIC:
  2551. length = 2 + lpSqlNodeExpression->sqlPrecision;
  2552. break;
  2553. case TYPE_INTEGER:
  2554. length = sizeof(double);
  2555. break;
  2556. case TYPE_CHAR:
  2557. length = lpSqlNodeExpression->sqlPrecision;
  2558. if (length > MAX_CHAR_LITERAL_LENGTH) {
  2559. if (lpSqlNodeExpression->sqlNodeType == NODE_TYPE_COLUMN)
  2560. s_lstrcpy((char*)lpstmt->szError,
  2561. ToString(*lplpSql, lpSqlNodeExpression->node.column.Column));
  2562. else
  2563. s_lstrcpy((char*)lpstmt->szError, "<expression>");
  2564. return ERR_CANTORDERBYONTHIS;
  2565. }
  2566. break;
  2567. case TYPE_BINARY:
  2568. length = lpSqlNodeExpression->sqlPrecision;
  2569. if (length > MAX_BINARY_LITERAL_LENGTH) {
  2570. if (lpSqlNodeExpression->sqlNodeType == NODE_TYPE_COLUMN)
  2571. s_lstrcpy((char*)lpstmt->szError,
  2572. ToString(*lplpSql, lpSqlNodeExpression->node.column.Column));
  2573. else
  2574. s_lstrcpy((char*)lpstmt->szError, "<expression>");
  2575. return ERR_CANTORDERBYONTHIS;
  2576. }
  2577. break;
  2578. case TYPE_DATE:
  2579. length = 10;
  2580. break;
  2581. case TYPE_TIME:
  2582. length = 8;
  2583. break;
  2584. case TYPE_TIMESTAMP:
  2585. if (TIMESTAMP_SCALE > 0)
  2586. length = 20 + TIMESTAMP_SCALE;
  2587. else
  2588. length = 19;
  2589. break;
  2590. default:
  2591. if (lpSqlNodeExpression->sqlNodeType == NODE_TYPE_COLUMN)
  2592. s_lstrcpy((char*)lpstmt->szError,
  2593. ToString(*lplpSql, lpSqlNodeExpression->node.column.Column));
  2594. else
  2595. s_lstrcpy((char*)lpstmt->szError, "<expression>");
  2596. return ERR_CANTORDERBYONTHIS;
  2597. }
  2598. /* Put offset of the key column in the sort directive */
  2599. wsprintf((LPSTR)(szSortDirective + s_lstrlen((char*)szSortDirective)),
  2600. "%lu,", offset);
  2601. /* Save offset and length */
  2602. switch (lpSqlNodeExpression->sqlNodeType) {
  2603. case NODE_TYPE_COLUMN:
  2604. lpSqlNodeExpression->node.column.DistinctOffset = offset;
  2605. lpSqlNodeExpression->node.column.DistinctLength = length;
  2606. break;
  2607. case NODE_TYPE_AGGREGATE:
  2608. lpSqlNodeExpression->node.aggregate.DistinctOffset = offset;
  2609. lpSqlNodeExpression->node.aggregate.DistinctLength = length;
  2610. break;
  2611. case NODE_TYPE_ALGEBRAIC:
  2612. lpSqlNodeExpression->node.algebraic.DistinctOffset = offset;
  2613. lpSqlNodeExpression->node.algebraic.DistinctLength = length;
  2614. break;
  2615. case NODE_TYPE_SCALAR:
  2616. lpSqlNodeExpression->node.scalar.DistinctOffset = offset;
  2617. lpSqlNodeExpression->node.scalar.DistinctLength = length;
  2618. break;
  2619. default:
  2620. return ERR_INTERNAL;
  2621. }
  2622. /* Adjust offset */
  2623. offset += (length);
  2624. offset++; /* for the IS NULL flag */
  2625. /* Put length of the key column in the sort directive */
  2626. wsprintf((LPSTR)(szSortDirective + s_lstrlen((char*)szSortDirective)),
  2627. "%lu,", length);
  2628. /* Put type of the key column in the sort directive */
  2629. switch (lpSqlNodeExpression->sqlDataType) {
  2630. case TYPE_DOUBLE:
  2631. s_lstrcat(szSortDirective, "E,");
  2632. break;
  2633. case TYPE_NUMERIC:
  2634. s_lstrcat(szSortDirective, "N,");
  2635. break;
  2636. case TYPE_INTEGER:
  2637. s_lstrcat(szSortDirective, "E,");
  2638. break;
  2639. case TYPE_CHAR:
  2640. case TYPE_BINARY:
  2641. case TYPE_DATE:
  2642. case TYPE_TIME:
  2643. case TYPE_TIMESTAMP:
  2644. s_lstrcat(szSortDirective, "C,");
  2645. break;
  2646. default:
  2647. return ERR_INTERNAL;
  2648. }
  2649. /* Put direction of the key column in the sort directive */
  2650. s_lstrcat(szSortDirective, "A");
  2651. break;
  2652. case NODE_TYPE_STRING:
  2653. case NODE_TYPE_NUMERIC:
  2654. case NODE_TYPE_PARAMETER:
  2655. case NODE_TYPE_USER:
  2656. case NODE_TYPE_NULL:
  2657. case NODE_TYPE_DATE:
  2658. case NODE_TYPE_TIME:
  2659. case NODE_TYPE_TIMESTAMP:
  2660. break;
  2661. case NODE_TYPE_CREATE:
  2662. case NODE_TYPE_DROP:
  2663. case NODE_TYPE_SELECT:
  2664. case NODE_TYPE_INSERT:
  2665. case NODE_TYPE_DELETE:
  2666. case NODE_TYPE_UPDATE:
  2667. case NODE_TYPE_CREATEINDEX:
  2668. case NODE_TYPE_DROPINDEX:
  2669. case NODE_TYPE_PASSTHROUGH:
  2670. case NODE_TYPE_TABLES:
  2671. case NODE_TYPE_VALUES:
  2672. case NODE_TYPE_COLUMNS:
  2673. case NODE_TYPE_SORTCOLUMNS:
  2674. case NODE_TYPE_GROUPBYCOLUMNS:
  2675. case NODE_TYPE_UPDATEVALUES:
  2676. case NODE_TYPE_CREATECOLS:
  2677. case NODE_TYPE_BOOLEAN:
  2678. case NODE_TYPE_COMPARISON:
  2679. case NODE_TYPE_TABLE:
  2680. default:
  2681. return ERR_INTERNAL;
  2682. }
  2683. /* Go to next sort column */
  2684. idxValues = lpSqlNodeValues->node.values.Next;
  2685. if (idxValues != NO_SQLNODE)
  2686. s_lstrcat(szSortDirective, ",");
  2687. }
  2688. offset--;
  2689. /* If no fields in sort record, put a constant in */
  2690. if (offset == NUM_LEN) {
  2691. offset = 3;
  2692. s_lstrcat(szSortDirective, "1,3,C,A");
  2693. }
  2694. s_lstrcat(szSortDirective, ")");
  2695. /* Put duplicate removal into sort directive */
  2696. s_lstrcat(szSortDirective, "DUPO(B");
  2697. wsprintf((LPSTR) szSortDirective + s_lstrlen(szSortDirective),
  2698. "%lu", offset);
  2699. s_lstrcat(szSortDirective, ",");
  2700. wsprintf((LPSTR) szSortDirective + s_lstrlen(szSortDirective),
  2701. "%u", (WORD) NUM_LEN+1);
  2702. s_lstrcat(szSortDirective, ",");
  2703. wsprintf((LPSTR) szSortDirective + s_lstrlen(szSortDirective),
  2704. "%lu", offset - NUM_LEN);
  2705. s_lstrcat(szSortDirective, ")");
  2706. /* Put record size into sort directive */
  2707. s_lstrcat(szSortDirective, "F(FIX,");
  2708. wsprintf((LPSTR) szSortDirective + s_lstrlen(szSortDirective),
  2709. "%lu", offset);
  2710. s_lstrcat(szSortDirective, ")");
  2711. /* Put in work drive */
  2712. s_lstrcat(szSortDirective, "W(");
  2713. #ifdef WIN32
  2714. if (!GetTempPath(MAX_PATHNAME_SIZE+1, (LPSTR)
  2715. szSortDirective + s_lstrlen(szSortDirective)))
  2716. return ERR_SORT;
  2717. if (szSortDirective[s_lstrlen(szSortDirective)-1] != '\\')
  2718. s_lstrcat(szSortDirective, "\\");
  2719. #else
  2720. GetTempFileName(NULL, "LEM", 0, (LPSTR) szSortDirective +
  2721. + s_lstrlen(szSortDirective));
  2722. while (szSortDirective[s_lstrlen(szSortDirective)-1] != '\\')
  2723. szSortDirective[s_lstrlen(szSortDirective)-1] = '\0';
  2724. #endif
  2725. s_lstrcat(szSortDirective, ")");
  2726. /* Save the directive */
  2727. lpSqlNode->node.select.DistinctDirective = AllocateString(lplpSql,
  2728. szSortDirective);
  2729. if (lpSqlNode->node.select.DistinctDirective == NO_STRING)
  2730. return ERR_MEMALLOCFAIL;
  2731. /* Save the sort record size */
  2732. lpSqlNode->node.select.DistinctRecordsize = offset;
  2733. }
  2734. /* Allocate space for the sortfile name if need be */
  2735. if ((lpSqlNode->node.select.Distinct) ||
  2736. (lpSqlNode->node.select.ImplicitGroupby) ||
  2737. (lpSqlNode->node.select.Groupbycolumns != NO_SQLNODE) ||
  2738. (lpSqlNode->node.select.Sortcolumns != NO_SQLNODE)) {
  2739. lpSqlNode->node.select.SortfileName = AllocateSpace(lplpSql,
  2740. MAX_PATHNAME_SIZE+1);
  2741. if (lpSqlNode->node.select.SortfileName == NO_STRING)
  2742. return ERR_MEMALLOCFAIL;
  2743. }
  2744. return ERR_SUCCESS;
  2745. }
  2746. /***************************************************************************/
  2747. RETCODE INTFUNC SemanticCheck(LPSTMT lpstmt, LPSQLTREE FAR *lplpSql,
  2748. SQLNODEIDX idxNode, BOOL fIsGroupby, BOOL fCaseSensitive,
  2749. SQLNODEIDX idxNodeTableOuterJoinFromTables,
  2750. SQLNODEIDX idxEnclosingStatement)
  2751. /* Walks a parse tree, checks it for semantic correctness, and fills in */
  2752. /* the semantic information. */
  2753. {
  2754. LPSQLNODE lpSqlNode;
  2755. RETCODE err;
  2756. LPUSTR ptr;
  2757. if (idxNode == NO_SQLNODE)
  2758. return ERR_SUCCESS;
  2759. lpSqlNode = ToNode(*lplpSql, idxNode);
  2760. err = ERR_SUCCESS;
  2761. switch (lpSqlNode->sqlNodeType) {
  2762. case NODE_TYPE_NONE:
  2763. break;
  2764. case NODE_TYPE_ROOT:
  2765. /* Check the statement */
  2766. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.root.sql,
  2767. fIsGroupby, fCaseSensitive,
  2768. idxNodeTableOuterJoinFromTables,
  2769. idxEnclosingStatement);
  2770. if (err != ERR_SUCCESS)
  2771. return err;
  2772. break;
  2773. case NODE_TYPE_CREATE:
  2774. /* Make sure table name is not too long */
  2775. ptr = ToString(*lplpSql, lpSqlNode->node.create.Table);
  2776. if (s_lstrlen(ptr) > ISAMMaxTableNameLength(lpstmt->lpdbc->lpISAM)) {
  2777. s_lstrcpy(lpstmt->szError, ptr);
  2778. return ERR_INVALIDTABLENAME;
  2779. }
  2780. /* Check the new column definitions */
  2781. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.create.Columns,
  2782. fIsGroupby, fCaseSensitive,
  2783. idxNodeTableOuterJoinFromTables, idxNode);
  2784. if (err != ERR_SUCCESS)
  2785. return err;
  2786. break;
  2787. case NODE_TYPE_DROP:
  2788. /* Make sure table name is not too long */
  2789. ptr = ToString(*lplpSql, lpSqlNode->node.drop.Table);
  2790. if (s_lstrlen(ptr) > ISAMMaxTableNameLength(lpstmt->lpdbc->lpISAM)) {
  2791. s_lstrcpy(lpstmt->szError, ptr);
  2792. return ERR_INVALIDTABLENAME;
  2793. }
  2794. break;
  2795. case NODE_TYPE_SELECT:
  2796. err = SelectCheck(lpstmt, lplpSql, idxNode, fCaseSensitive,
  2797. idxEnclosingStatement);
  2798. break;
  2799. case NODE_TYPE_INSERT:
  2800. {
  2801. /* Check the table */
  2802. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.insert.Table,
  2803. fIsGroupby, fCaseSensitive,
  2804. idxNodeTableOuterJoinFromTables, idxNode);
  2805. if (err != ERR_SUCCESS)
  2806. return err;
  2807. /* Is there a column list? */
  2808. if (lpSqlNode->node.insert.Columns == NO_SQLNODE) {
  2809. LPSQLNODE lpSqlNodeTable;
  2810. STRINGIDX idxAlias;
  2811. LPISAMTABLEDEF lpTableHandle;
  2812. SQLNODEIDX idxColumns;
  2813. LPSQLNODE lpSqlNodeColumns;
  2814. SQLNODEIDX idxColumnsPrev;
  2815. LPSQLNODE lpSqlNodeColumnsPrev;
  2816. SQLNODEIDX idxColumn;
  2817. LPSQLNODE lpSqlNodeColumn;
  2818. SWORD idx;
  2819. /* No. Get node Alias of this table */
  2820. lpSqlNodeTable = ToNode(*lplpSql, lpSqlNode->node.insert.Table);
  2821. idxAlias = lpSqlNodeTable->node.table.Alias;
  2822. /* Loop through all the columns of this table */
  2823. lpTableHandle = lpSqlNodeTable->node.table.Handle;
  2824. idxColumnsPrev = NO_SQLNODE;
  2825. ClassColumnInfoBase* cInfoBase = lpTableHandle->pColumnInfo;
  2826. if ( !cInfoBase->IsValid() )
  2827. {
  2828. return ERR_COLUMNNOTFOUND;
  2829. }
  2830. UWORD cNumberOfCols = cInfoBase->GetNumberOfColumns();
  2831. char pColumnName [MAX_COLUMN_NAME_LENGTH+1];
  2832. for (idx = 0; idx < (SWORD) cNumberOfCols; idx++)
  2833. {
  2834. if ( FAILED(cInfoBase->GetColumnName(idx, pColumnName)) )
  2835. {
  2836. return ERR_COLUMNNOTFOUND;
  2837. }
  2838. /* Create a node for this column */
  2839. idxColumn = AllocateNode(lplpSql, NODE_TYPE_COLUMN);
  2840. if (idxColumn == NO_SQLNODE)
  2841. return ERR_MEMALLOCFAIL;
  2842. lpSqlNodeColumn = ToNode(*lplpSql, idxColumn);
  2843. lpSqlNodeColumn->node.column.Tablealias = idxAlias;
  2844. lpSqlNodeColumn->node.column.Column = AllocateString(lplpSql,
  2845. (LPUSTR)pColumnName);
  2846. if (lpSqlNodeColumn->node.column.Column == NO_STRING)
  2847. return ERR_MEMALLOCFAIL;
  2848. lpSqlNodeColumn->node.column.Table =
  2849. lpSqlNode->node.insert.Table;
  2850. lpSqlNodeColumn->node.column.Id = idx;
  2851. lpSqlNodeColumn->node.column.Value = NO_STRING;
  2852. lpSqlNodeColumn->node.column.InSortRecord = FALSE;
  2853. lpSqlNodeColumn->node.column.Offset = 0;
  2854. lpSqlNodeColumn->node.column.Length = 0;
  2855. lpSqlNodeColumn->node.column.DistinctOffset = 0;
  2856. lpSqlNodeColumn->node.column.DistinctLength = 0;
  2857. lpSqlNodeColumn->node.column.EnclosingStatement = NO_SQLNODE;
  2858. /* Put it on the list */
  2859. idxColumns = AllocateNode(lplpSql, NODE_TYPE_COLUMNS);
  2860. if (idxColumns == NO_SQLNODE)
  2861. return ERR_MEMALLOCFAIL;
  2862. lpSqlNodeColumns = ToNode(*lplpSql, idxColumns);
  2863. lpSqlNodeColumns->node.columns.Column = idxColumn;
  2864. lpSqlNodeColumns->node.columns.Next = NO_SQLNODE;
  2865. if (idxColumnsPrev == NO_SQLNODE) {
  2866. lpSqlNode = ToNode(*lplpSql, idxNode);
  2867. lpSqlNode->node.insert.Columns = idxColumns;
  2868. }
  2869. else {
  2870. lpSqlNodeColumnsPrev = ToNode(*lplpSql, idxColumnsPrev);
  2871. lpSqlNodeColumnsPrev->node.columns.Next = idxColumns;
  2872. }
  2873. idxColumnsPrev = idxColumns;
  2874. lpSqlNode = ToNode(*lplpSql, idxNode);
  2875. }
  2876. lpSqlNode = ToNode(*lplpSql, idxNode);
  2877. }
  2878. /* Check the column list */
  2879. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.insert.Columns,
  2880. fIsGroupby, fCaseSensitive,
  2881. idxNodeTableOuterJoinFromTables, idxNode);
  2882. if (err != ERR_SUCCESS)
  2883. return err;
  2884. /* Check the value list */
  2885. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.insert.Values,
  2886. fIsGroupby, fCaseSensitive,
  2887. idxNodeTableOuterJoinFromTables, idxNode);
  2888. if (err != ERR_SUCCESS)
  2889. return err;
  2890. /* Look at each value */
  2891. {
  2892. SQLNODEIDX idxValues;
  2893. LPSQLNODE lpSqlNodeValues;
  2894. LPSQLNODE lpSqlNodeValue;
  2895. SQLNODEIDX idxColumns;
  2896. LPSQLNODE lpSqlNodeColumns;
  2897. LPSQLNODE lpSqlNodeSelect;
  2898. /* Get list of insert values */
  2899. lpSqlNodeSelect = ToNode(*lplpSql, lpSqlNode->node.insert.Values);
  2900. if (lpSqlNodeSelect->sqlNodeType == NODE_TYPE_SELECT)
  2901. idxValues = lpSqlNodeSelect->node.select.Values;
  2902. else
  2903. idxValues = lpSqlNode->node.insert.Values;
  2904. /* For each value... */
  2905. idxColumns = lpSqlNode->node.insert.Columns;
  2906. while (idxValues != NO_SQLNODE) {
  2907. /* Error if no more columns */
  2908. if (idxColumns == NO_SQLNODE)
  2909. return ERR_UNEQUALINSCOLS;
  2910. /* Get the value */
  2911. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  2912. lpSqlNodeValue = ToNode(*lplpSql, lpSqlNodeValues->node.values.Value);
  2913. /* Get the column the value is for */
  2914. lpSqlNodeColumns = ToNode(*lplpSql, idxColumns);
  2915. /* Sub-select? */
  2916. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT) {
  2917. /* No. Make sure the value is NUMERIC, STRING, */
  2918. /* PARAMETER, USER, NULL, DATE, TIME, or TIMESTAMP */
  2919. switch (lpSqlNodeValue->sqlNodeType) {
  2920. case NODE_TYPE_ALGEBRAIC:
  2921. case NODE_TYPE_SCALAR:
  2922. case NODE_TYPE_AGGREGATE:
  2923. case NODE_TYPE_COLUMN:
  2924. return ERR_INVALIDINSVAL;
  2925. case NODE_TYPE_PARAMETER:
  2926. case NODE_TYPE_NULL:
  2927. case NODE_TYPE_NUMERIC:
  2928. case NODE_TYPE_STRING:
  2929. case NODE_TYPE_USER:
  2930. case NODE_TYPE_DATE:
  2931. case NODE_TYPE_TIME:
  2932. case NODE_TYPE_TIMESTAMP:
  2933. break;
  2934. default:
  2935. return ERR_INTERNAL;
  2936. }
  2937. }
  2938. /* Make sure value is of the proper type */
  2939. err = TypeCheck(lpstmt, *lplpSql,
  2940. lpSqlNodeColumns->node.columns.Column,
  2941. lpSqlNodeValues->node.values.Value, OP_NONE,
  2942. NULL, NULL, NULL, NULL);
  2943. if (err != ERR_SUCCESS)
  2944. return err;
  2945. /* Look at next element */
  2946. idxValues = lpSqlNodeValues->node.values.Next;
  2947. idxColumns = lpSqlNodeColumns->node.columns.Next;
  2948. }
  2949. /* Error if extra columns */
  2950. if (idxColumns != NO_SQLNODE)
  2951. return ERR_UNEQUALINSCOLS;
  2952. }
  2953. }
  2954. break;
  2955. case NODE_TYPE_DELETE:
  2956. /* Check the table */
  2957. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.delet.Table,
  2958. fIsGroupby, fCaseSensitive,
  2959. idxNodeTableOuterJoinFromTables, idxNode);
  2960. if (err != ERR_SUCCESS)
  2961. return err;
  2962. /* Check the predicate */
  2963. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.delet.Predicate,
  2964. fIsGroupby, fCaseSensitive,
  2965. idxNodeTableOuterJoinFromTables, idxNode);
  2966. if (err != ERR_SUCCESS)
  2967. return err;
  2968. break;
  2969. case NODE_TYPE_UPDATE:
  2970. /* Check the table */
  2971. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.update.Table,
  2972. fIsGroupby, fCaseSensitive,
  2973. idxNodeTableOuterJoinFromTables, idxNode);
  2974. if (err != ERR_SUCCESS)
  2975. return err;
  2976. /* Check the update values */
  2977. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.update.Updatevalues,
  2978. fIsGroupby, fCaseSensitive,
  2979. idxNodeTableOuterJoinFromTables, idxNode);
  2980. if (err != ERR_SUCCESS)
  2981. return err;
  2982. /* Check the predicate */
  2983. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.update.Predicate,
  2984. fIsGroupby, fCaseSensitive,
  2985. idxNodeTableOuterJoinFromTables, idxNode);
  2986. if (err != ERR_SUCCESS)
  2987. return err;
  2988. break;
  2989. case NODE_TYPE_CREATEINDEX:
  2990. {
  2991. SQLNODEIDX idxSortcolumns;
  2992. LPSQLNODE lpSqlNodeSortcolumns;
  2993. UWORD count;
  2994. /* Make sure index name is not too long */
  2995. ptr = ToString(*lplpSql, lpSqlNode->node.createindex.Index);
  2996. if (s_lstrlen(ptr) > MAX_INDEX_NAME_LENGTH) {
  2997. s_lstrcpy(lpstmt->szError, ptr);
  2998. return ERR_INVALIDINDEXNAME;
  2999. }
  3000. /* Check the table */
  3001. err = SemanticCheck(lpstmt, lplpSql,
  3002. lpSqlNode->node.createindex.Table,
  3003. fIsGroupby, fCaseSensitive,
  3004. idxNodeTableOuterJoinFromTables, idxNode);
  3005. if (err != ERR_SUCCESS)
  3006. return err;
  3007. /* Check the list of columns */
  3008. err = SemanticCheck(lpstmt, lplpSql,
  3009. lpSqlNode->node.createindex.Columns,
  3010. fIsGroupby, fCaseSensitive,
  3011. idxNodeTableOuterJoinFromTables, idxNode);
  3012. if (err != ERR_SUCCESS)
  3013. return err;
  3014. /* Make sure there aren't too many columns */
  3015. idxSortcolumns = lpSqlNode->node.createindex.Columns;
  3016. count = 0;
  3017. while (idxSortcolumns != NO_SQLNODE) {
  3018. lpSqlNodeSortcolumns =
  3019. ToNode(lpstmt->lpSqlStmt, idxSortcolumns);
  3020. count++;
  3021. idxSortcolumns = lpSqlNodeSortcolumns->node.sortcolumns.Next;
  3022. }
  3023. if (count > MAX_COLUMNS_IN_INDEX) {
  3024. return ERR_TOOMANYINDEXCOLS;
  3025. }
  3026. }
  3027. break;
  3028. case NODE_TYPE_DROPINDEX:
  3029. /* Make sure index name is not too long */
  3030. ptr = ToString(*lplpSql, lpSqlNode->node.dropindex.Index);
  3031. if (s_lstrlen(ptr) > MAX_INDEX_NAME_LENGTH) {
  3032. s_lstrcpy(lpstmt->szError, ptr);
  3033. return ERR_INVALIDINDEXNAME;
  3034. }
  3035. break;
  3036. case NODE_TYPE_PASSTHROUGH:
  3037. s_lstrcpy((LPSTR)lpstmt->szError, "CREATE, DROP, SELECT, INSERT, UPDATE, or DELETE");
  3038. return ERR_EXPECTEDOTHER;
  3039. case NODE_TYPE_TABLES:
  3040. /* Check the table */
  3041. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Table,
  3042. fIsGroupby, fCaseSensitive,
  3043. idxNodeTableOuterJoinFromTables,
  3044. idxEnclosingStatement);
  3045. if (err != ERR_SUCCESS)
  3046. return err;
  3047. /* Check the rest of the list */
  3048. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.tables.Next,
  3049. fIsGroupby, fCaseSensitive,
  3050. idxNodeTableOuterJoinFromTables,
  3051. idxEnclosingStatement);
  3052. if (err != ERR_SUCCESS)
  3053. return err;
  3054. /* Error if any correlation name reused */
  3055. {
  3056. LPUSTR lpstrAlias;
  3057. SQLNODEIDX idxTables;
  3058. LPSQLNODE lpSqlNodeTables;
  3059. LPSQLNODE lpSqlNodeTable;
  3060. /* Get the alias for this table */
  3061. lpSqlNodeTable = ToNode(*lplpSql, lpSqlNode->node.tables.Table);
  3062. if (lpSqlNodeTable->node.table.Alias != NO_STRING)
  3063. {
  3064. lpstrAlias = ToString(*lplpSql, lpSqlNodeTable->node.table.Alias);
  3065. /* For each table on the rest of the list */
  3066. idxTables = lpSqlNode->node.tables.Next;
  3067. while (idxTables != NO_SQLNODE) {
  3068. /* Get pointer to table node */
  3069. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  3070. lpSqlNodeTable = ToNode(*lplpSql, lpSqlNodeTables->node.tables.Table);
  3071. /* Error if its name is the same */
  3072. if (lpSqlNodeTable->node.table.Alias != NO_STRING)
  3073. {
  3074. if (fCaseSensitive) {
  3075. if (!s_lstrcmp(lpstrAlias,
  3076. ToString(*lplpSql, lpSqlNodeTable->node.table.Alias))) {
  3077. s_lstrcpy((char*)lpstmt->szError, lpstrAlias);
  3078. return ERR_ALIASINUSE;
  3079. }
  3080. }
  3081. else {
  3082. if (!s_lstrcmpi(lpstrAlias,
  3083. ToString(*lplpSql, lpSqlNodeTable->node.table.Alias))) {
  3084. s_lstrcpy((char*)lpstmt->szError, lpstrAlias);
  3085. return ERR_ALIASINUSE;
  3086. }
  3087. }
  3088. }
  3089. /* Go to next element */
  3090. idxTables = lpSqlNodeTables->node.tables.Next;
  3091. }
  3092. }
  3093. {
  3094. LPSQLNODE lpSqlNodeTable;
  3095. /* Check the outer join predicate (if any) */
  3096. lpSqlNodeTable = ToNode(*lplpSql, lpSqlNode->node.tables.Table);
  3097. err = SemanticCheck(lpstmt, lplpSql,
  3098. lpSqlNodeTable->node.table.OuterJoinPredicate,
  3099. FALSE, fCaseSensitive,
  3100. lpSqlNodeTable->node.table.OuterJoinFromTables,
  3101. idxEnclosingStatement);
  3102. if (err != ERR_SUCCESS)
  3103. return err;
  3104. }
  3105. }
  3106. break;
  3107. case NODE_TYPE_VALUES:
  3108. while (TRUE) {
  3109. /* Check this value */
  3110. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.values.Value,
  3111. fIsGroupby, fCaseSensitive,
  3112. idxNodeTableOuterJoinFromTables,
  3113. idxEnclosingStatement);
  3114. if (err != ERR_SUCCESS)
  3115. return err;
  3116. /* Check the rest of the list */
  3117. if (lpSqlNode->node.values.Next == NO_SQLNODE)
  3118. break;
  3119. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.values.Next);
  3120. }
  3121. break;
  3122. case NODE_TYPE_COLUMNS:
  3123. while (TRUE) {
  3124. /* Check this column */
  3125. err = SemanticCheck(lpstmt, lplpSql,
  3126. lpSqlNode->node.columns.Column,
  3127. fIsGroupby, fCaseSensitive,
  3128. idxNodeTableOuterJoinFromTables,
  3129. idxEnclosingStatement);
  3130. if (err != ERR_SUCCESS)
  3131. return err;
  3132. /* Check the rest of the list */
  3133. if (lpSqlNode->node.columns.Next == NO_SQLNODE)
  3134. break;
  3135. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.columns.Next);
  3136. }
  3137. lpSqlNode = ToNode(*lplpSql, idxNode);
  3138. /* Error if any column on list more than once */
  3139. {
  3140. LPUSTR lpstrName;
  3141. SQLNODEIDX idxColumns;
  3142. LPSQLNODE lpSqlNodeColumns;
  3143. LPSQLNODE lpSqlNodeColumn;
  3144. /* Get the name for this column */
  3145. lpSqlNodeColumn = ToNode(*lplpSql, lpSqlNode->node.columns.Column);
  3146. lpstrName = ToString(*lplpSql, lpSqlNodeColumn->node.column.Column);
  3147. /* For each column on the rest of the list */
  3148. idxColumns = lpSqlNode->node.columns.Next;
  3149. while (idxColumns != NO_SQLNODE) {
  3150. /* Get pointer to table node */
  3151. lpSqlNodeColumns = ToNode(*lplpSql, idxColumns);
  3152. lpSqlNodeColumn = ToNode(*lplpSql, lpSqlNodeColumns->node.columns.Column);
  3153. /* Error if its name is the same */
  3154. if (fCaseSensitive) {
  3155. if (!s_lstrcmp(lpstrName,
  3156. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column))) {
  3157. s_lstrcpy(lpstmt->szError, lpstrName);
  3158. return ERR_COLUMNONLIST;
  3159. }
  3160. }
  3161. else {
  3162. if (!s_lstrcmpi(lpstrName,
  3163. ToString(*lplpSql, lpSqlNodeColumn->node.column.Column))) {
  3164. s_lstrcpy(lpstmt->szError, lpstrName);
  3165. return ERR_COLUMNONLIST;
  3166. }
  3167. }
  3168. /* Go to next element */
  3169. idxColumns = lpSqlNodeColumns->node.columns.Next;
  3170. }
  3171. }
  3172. break;
  3173. case NODE_TYPE_SORTCOLUMNS:
  3174. while (TRUE) {
  3175. LPSQLNODE lpSqlNodeSort;
  3176. LPSQLNODE lpSqlNodeStmt;
  3177. SQLNODEIDX idxValues;
  3178. SWORD count;
  3179. LPSQLNODE lpSqlNodeValues;
  3180. LPSQLNODE lpSqlNodeColumn;
  3181. /* Check this column */
  3182. err = SemanticCheck(lpstmt,
  3183. lplpSql,lpSqlNode->node.sortcolumns.Column,
  3184. fIsGroupby, fCaseSensitive,
  3185. idxNodeTableOuterJoinFromTables,
  3186. idxEnclosingStatement);
  3187. if (err != ERR_SUCCESS)
  3188. return err;
  3189. /* Was an ordinal position in the select list given as sort? */
  3190. lpSqlNodeSort = ToNode(*lplpSql, lpSqlNode->node.sortcolumns.Column);
  3191. if (lpSqlNodeSort->sqlNodeType == NODE_TYPE_NUMERIC) {
  3192. /* No. Get the select list */
  3193. lpSqlNodeStmt = ToNode(*lplpSql, idxEnclosingStatement);
  3194. if (lpSqlNodeStmt->sqlNodeType != NODE_TYPE_SELECT)
  3195. return ERR_INTERNAL;
  3196. /* Find the element in the select list */
  3197. idxValues = lpSqlNodeStmt->node.select.Values;
  3198. count = 1;
  3199. while (TRUE) {
  3200. if (idxValues == NO_SQLNODE)
  3201. return ERR_ORDINALTOOLARGE;
  3202. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  3203. if (count == (SWORD) lpSqlNodeSort->node.numeric.Value)
  3204. break;
  3205. idxValues = lpSqlNodeValues->node.values.Next;
  3206. count++;
  3207. }
  3208. lpSqlNodeColumn = ToNode(*lplpSql,
  3209. lpSqlNodeValues->node.values.Value);
  3210. /* Error if a column reference was not given */
  3211. if (lpSqlNodeColumn->sqlNodeType != NODE_TYPE_COLUMN)
  3212. return ERR_ORDERBYCOLUMNONLY;
  3213. /* Convert the sort node to a column reference */
  3214. lpSqlNodeSort->sqlNodeType = NODE_TYPE_COLUMN;
  3215. lpSqlNodeSort->sqlDataType = TYPE_UNKNOWN;
  3216. lpSqlNodeSort->sqlSqlType = SQL_TYPE_NULL;
  3217. lpSqlNodeSort->sqlPrecision = 0;
  3218. lpSqlNodeSort->sqlScale = NO_SCALE;
  3219. lpSqlNodeSort->value.String = NULL;
  3220. lpSqlNodeSort->value.Double = 0.0;
  3221. lpSqlNodeSort->value.Date.year = 0;
  3222. lpSqlNodeSort->value.Date.month = 0;
  3223. lpSqlNodeSort->value.Date.day = 0;
  3224. lpSqlNodeSort->value.Time.hour = 0;
  3225. lpSqlNodeSort->value.Time.minute = 0;
  3226. lpSqlNodeSort->value.Time.second = 0;
  3227. lpSqlNodeSort->value.Timestamp.year = 0;
  3228. lpSqlNodeSort->value.Timestamp.month = 0;
  3229. lpSqlNodeSort->value.Timestamp.day = 0;
  3230. lpSqlNodeSort->value.Timestamp.hour = 0;
  3231. lpSqlNodeSort->value.Timestamp.minute = 0;
  3232. lpSqlNodeSort->value.Timestamp.second = 0;
  3233. lpSqlNodeSort->value.Timestamp.fraction = 0;
  3234. lpSqlNodeSort->value.Binary = NULL;
  3235. lpSqlNodeSort->sqlIsNull = TRUE;
  3236. lpSqlNodeSort->node.column.Tablealias = lpSqlNodeColumn->node.column.Tablealias;
  3237. lpSqlNodeSort->node.column.Qualifier = lpSqlNodeColumn->node.column.Qualifier;
  3238. lpSqlNodeSort->node.column.MatchedAlias = lpSqlNodeColumn->node.column.MatchedAlias;
  3239. lpSqlNodeSort->node.column.Column = lpSqlNodeColumn->node.column.Column;
  3240. lpSqlNodeSort->node.column.TableIndex = lpSqlNodeColumn->node.column.TableIndex;
  3241. // lpSqlNodeSort->node.table.Handle = NULL;
  3242. lpSqlNodeSort->node.column.Id = -1;
  3243. lpSqlNodeSort->node.column.Value = NO_STRING;
  3244. lpSqlNodeSort->node.column.InSortRecord = FALSE;
  3245. lpSqlNodeSort->node.column.Offset = 0;
  3246. lpSqlNodeSort->node.column.Length = 0;
  3247. lpSqlNodeSort->node.column.DistinctOffset = 0;
  3248. lpSqlNodeSort->node.column.DistinctLength = 0;
  3249. lpSqlNodeSort->node.column.EnclosingStatement = NO_SQLNODE;
  3250. /* Semantic check the newly created node */
  3251. err = SemanticCheck(lpstmt, lplpSql,
  3252. lpSqlNode->node.sortcolumns.Column,
  3253. fIsGroupby, fCaseSensitive,
  3254. idxNodeTableOuterJoinFromTables,
  3255. idxEnclosingStatement);
  3256. if (err != ERR_SUCCESS)
  3257. return err;
  3258. }
  3259. /* Check the rest of the list */
  3260. if (lpSqlNode->node.sortcolumns.Next == NO_SQLNODE)
  3261. break;
  3262. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.sortcolumns.Next);
  3263. }
  3264. break;
  3265. case NODE_TYPE_GROUPBYCOLUMNS:
  3266. while (TRUE) {
  3267. /* Check this column */
  3268. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.groupbycolumns.Column,
  3269. fIsGroupby, fCaseSensitive,
  3270. idxNodeTableOuterJoinFromTables,
  3271. idxEnclosingStatement);
  3272. if (err != ERR_SUCCESS)
  3273. return err;
  3274. /* Check the rest of the list */
  3275. if (lpSqlNode->node.groupbycolumns.Next == NO_SQLNODE)
  3276. break;
  3277. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.groupbycolumns.Next);
  3278. }
  3279. break;
  3280. case NODE_TYPE_UPDATEVALUES:
  3281. while (TRUE) {
  3282. /* Check this column */
  3283. err = SemanticCheck(lpstmt, lplpSql,
  3284. lpSqlNode->node.updatevalues.Column, fIsGroupby,
  3285. fCaseSensitive,
  3286. idxNodeTableOuterJoinFromTables,
  3287. idxEnclosingStatement);
  3288. if (err != ERR_SUCCESS)
  3289. return err;
  3290. /* Check the value being assigned to the column */
  3291. err = SemanticCheck(lpstmt, lplpSql,
  3292. lpSqlNode->node.updatevalues.Value, fIsGroupby,
  3293. fCaseSensitive,
  3294. idxNodeTableOuterJoinFromTables,
  3295. idxEnclosingStatement);
  3296. if (err != ERR_SUCCESS)
  3297. return err;
  3298. /* Error if value has incompatible type */
  3299. err = TypeCheck(lpstmt, *lplpSql, lpSqlNode->node.updatevalues.Column,
  3300. lpSqlNode->node.updatevalues.Value, OP_NONE, NULL, NULL,
  3301. NULL, NULL);
  3302. if (err != ERR_SUCCESS)
  3303. return err;
  3304. /* Check the rest of the list */
  3305. if (lpSqlNode->node.updatevalues.Next == NO_SQLNODE)
  3306. break;
  3307. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.updatevalues.Next);
  3308. }
  3309. break;
  3310. case NODE_TYPE_CREATECOLS:
  3311. while (TRUE) {
  3312. UWORD count;
  3313. UWORD idx;
  3314. /* Make sure column name is not too long */
  3315. ptr = ToString(*lplpSql, lpSqlNode->node.createcols.Name);
  3316. if (s_lstrlen(ptr)>ISAMMaxColumnNameLength(lpstmt->lpdbc->lpISAM)) {
  3317. s_lstrcpy(lpstmt->szError, ptr);
  3318. return ERR_INVALIDCOLNAME;
  3319. }
  3320. /* Find data type */
  3321. ptr = ToString(*lplpSql, lpSqlNode->node.createcols.Type);
  3322. for (idx = 0; idx < lpstmt->lpdbc->lpISAM->cSQLTypes; idx++) {
  3323. if (lpstmt->lpdbc->lpISAM->SQLTypes[idx].supported &&
  3324. !s_lstrcmpi(lpstmt->lpdbc->lpISAM->SQLTypes[idx].name, ptr))
  3325. break;
  3326. }
  3327. if (idx >= lpstmt->lpdbc->lpISAM->cSQLTypes) {
  3328. s_lstrcpy(lpstmt->szError, ptr);
  3329. return ERR_NOSUCHTYPE;
  3330. }
  3331. lpSqlNode->node.createcols.iSqlType = idx;
  3332. /* Count the number of create parameters */
  3333. count = 0;
  3334. ptr = lpstmt->lpdbc->lpISAM->SQLTypes[idx].params;
  3335. if (ptr != NULL) {
  3336. count = 1;
  3337. for (; *ptr; ptr++) {
  3338. if (*ptr == ',')
  3339. count++;
  3340. }
  3341. }
  3342. /* Error if wrong number of parameters */
  3343. if (count != lpSqlNode->node.createcols.Params) {
  3344. s_lstrcpy((char*)lpstmt->szError,
  3345. ToString(*lplpSql, lpSqlNode->node.createcols.Type));
  3346. return ERR_BADPARAMCOUNT;
  3347. }
  3348. /* Check next one on list */
  3349. if (lpSqlNode->node.createcols.Next == NO_SQLNODE)
  3350. break;
  3351. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.createcols.Next);
  3352. }
  3353. break;
  3354. case NODE_TYPE_BOOLEAN:
  3355. while (TRUE) {
  3356. /* Check left child */
  3357. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.boolean.Left,
  3358. fIsGroupby, fCaseSensitive,
  3359. idxNodeTableOuterJoinFromTables,
  3360. idxEnclosingStatement);
  3361. if (err != ERR_SUCCESS)
  3362. return err;
  3363. /* The result is always a boolean */
  3364. lpSqlNode->sqlDataType = TYPE_INTEGER;
  3365. lpSqlNode->sqlSqlType = SQL_BIT;
  3366. lpSqlNode->sqlPrecision = 1;
  3367. lpSqlNode->sqlScale = 0;
  3368. /* Leave loop if no right child */
  3369. if (lpSqlNode->node.boolean.Right == NO_SQLNODE)
  3370. break;
  3371. /* Is right child a NODE_TYPE_BOOLEAN node? */
  3372. if (ToNode(*lplpSql, lpSqlNode->node.boolean.Right)->sqlNodeType !=
  3373. NODE_TYPE_BOOLEAN) {
  3374. /* No. Semantic check that and leave the loop */
  3375. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.boolean.Right,
  3376. fIsGroupby, fCaseSensitive,
  3377. idxNodeTableOuterJoinFromTables,
  3378. idxEnclosingStatement);
  3379. if (err != ERR_SUCCESS)
  3380. return err;
  3381. break;
  3382. }
  3383. /* Semantic check the right node on next iteration of the loop */
  3384. lpSqlNode = ToNode(*lplpSql, lpSqlNode->node.boolean.Right);
  3385. }
  3386. break;
  3387. case NODE_TYPE_COMPARISON:
  3388. /* Check left child */
  3389. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Left,
  3390. fIsGroupby, fCaseSensitive,
  3391. idxNodeTableOuterJoinFromTables,
  3392. idxEnclosingStatement);
  3393. if (err != ERR_SUCCESS)
  3394. return err;
  3395. /* Check right child */
  3396. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.comparison.Right,
  3397. fIsGroupby, fCaseSensitive,
  3398. idxNodeTableOuterJoinFromTables,
  3399. idxEnclosingStatement);
  3400. if (err != ERR_SUCCESS)
  3401. return err;
  3402. /* Is this an IN or NOT IN comparison against a sub-select? */
  3403. if (((lpSqlNode->node.comparison.Operator == OP_IN) ||
  3404. (lpSqlNode->node.comparison.Operator == OP_NOTIN)) &&
  3405. (ToNode(*lplpSql, lpSqlNode->node.comparison.Right)->sqlNodeType
  3406. == NODE_TYPE_SELECT)) {
  3407. /* Yes. Convert it to a regular comparison */
  3408. if (lpSqlNode->node.comparison.Operator == OP_IN) {
  3409. lpSqlNode->node.comparison.Operator = OP_EQ;
  3410. lpSqlNode->node.comparison.SelectModifier = SELECT_ANY;
  3411. }
  3412. else if (lpSqlNode->node.comparison.Operator == OP_NOTIN) {
  3413. lpSqlNode->node.comparison.Operator = OP_NE;
  3414. lpSqlNode->node.comparison.SelectModifier = SELECT_ALL;
  3415. }
  3416. }
  3417. /* Is this an EXISTS operation ? */
  3418. if (lpSqlNode->node.comparison.Operator == OP_EXISTS) {
  3419. /* Yes. Nothing else to do */
  3420. ;
  3421. }
  3422. /* Is this an IN or NOT IN comparison? */
  3423. else if ((lpSqlNode->node.comparison.Operator != OP_IN) &&
  3424. (lpSqlNode->node.comparison.Operator != OP_NOTIN)) {
  3425. /* No. Is the right child NODE_TYPE_SELECT? */
  3426. switch (lpSqlNode->node.comparison.SelectModifier) {
  3427. case SELECT_NOTSELECT:
  3428. break;
  3429. case SELECT_ALL:
  3430. case SELECT_ANY:
  3431. case SELECT_ONE:
  3432. {
  3433. LPSQLNODE lpSqlNodeSelect;
  3434. LPSQLNODE lpSqlNodeValues;
  3435. LPSQLNODE lpSqlNodeValue;
  3436. /* Yes. Get the select list */
  3437. lpSqlNodeSelect = ToNode(*lplpSql,
  3438. lpSqlNode->node.comparison.Right);
  3439. lpSqlNodeValues = ToNode(*lplpSql,
  3440. lpSqlNodeSelect->node.select.Values);
  3441. /* If more than one value on the list, error */
  3442. if (lpSqlNodeValues->node.values.Next != NO_SQLNODE)
  3443. return ERR_MULTICOLUMNSELECT;
  3444. /* If long value, error */
  3445. lpSqlNodeValue = ToNode(*lplpSql,
  3446. lpSqlNodeValues->node.values.Value);
  3447. if ((lpSqlNodeValue->sqlSqlType == SQL_LONGVARCHAR) ||
  3448. (lpSqlNodeValue->sqlSqlType == SQL_LONGVARBINARY)) {
  3449. ErrorOpCode(lpstmt,
  3450. lpSqlNode->node.comparison.Operator);
  3451. return ERR_INVALIDOPERAND;
  3452. }
  3453. /* Set the type of the value returned by the sub-query */
  3454. lpSqlNodeSelect->sqlDataType = lpSqlNodeValue->sqlDataType;
  3455. lpSqlNodeSelect->sqlSqlType = lpSqlNodeValue->sqlSqlType;
  3456. lpSqlNodeSelect->sqlPrecision = lpSqlNodeValue->sqlPrecision;
  3457. lpSqlNodeSelect->sqlScale = lpSqlNodeValue->sqlScale;
  3458. }
  3459. break;
  3460. case SELECT_EXISTS:
  3461. default:
  3462. return ERR_INTERNAL;
  3463. }
  3464. /* Error if incompatible types */
  3465. err = TypeCheck(lpstmt, *lplpSql, lpSqlNode->node.comparison.Left,
  3466. lpSqlNode->node.comparison.Right,
  3467. lpSqlNode->node.comparison.Operator,
  3468. &(lpSqlNode->sqlDataType), &(lpSqlNode->sqlSqlType),
  3469. &(lpSqlNode->sqlPrecision), &(lpSqlNode->sqlScale));
  3470. if (err != ERR_SUCCESS)
  3471. return err;
  3472. /* Error if "LIKE" or "NOT LIKE" used for non-char data */
  3473. if ((lpSqlNode->sqlDataType != TYPE_CHAR) &&
  3474. ((lpSqlNode->node.comparison.Operator == OP_LIKE) ||
  3475. (lpSqlNode->node.comparison.Operator == OP_NOTLIKE))) {
  3476. ErrorOpCode(lpstmt, lpSqlNode->node.comparison.Operator);
  3477. return ERR_INVALIDOPERAND;
  3478. }
  3479. /* Error if binary data */
  3480. if (lpSqlNode->sqlDataType == TYPE_BINARY) {
  3481. if (((lpSqlNode->node.comparison.Operator != OP_EQ) &&
  3482. (lpSqlNode->node.comparison.Operator != OP_NE)) ||
  3483. (lpSqlNode->sqlPrecision > MAX_BINARY_LITERAL_LENGTH)) {
  3484. ErrorOpCode(lpstmt, lpSqlNode->node.comparison.Operator);
  3485. return ERR_INVALIDOPERAND;
  3486. }
  3487. }
  3488. }
  3489. else {
  3490. /* Yes. Look at each value */
  3491. SQLNODEIDX idxValues;
  3492. LPSQLNODE lpSqlNodeValues;
  3493. LPSQLNODE lpSqlNodeValue;
  3494. /* For each value... */
  3495. idxValues = lpSqlNode->node.comparison.Right;
  3496. while (idxValues != NO_SQLNODE) {
  3497. /* Get the value */
  3498. lpSqlNodeValues = ToNode(*lplpSql, idxValues);
  3499. lpSqlNodeValue = ToNode(*lplpSql, lpSqlNodeValues->node.values.Value);
  3500. /* Make sure the value is NUMERIC, STRING, */
  3501. /* PARAMETER, USER, DATE, TIME, or TIMESTAMP */
  3502. switch (lpSqlNodeValue->sqlNodeType) {
  3503. case NODE_TYPE_ALGEBRAIC:
  3504. case NODE_TYPE_SCALAR:
  3505. case NODE_TYPE_AGGREGATE:
  3506. case NODE_TYPE_COLUMN:
  3507. return ERR_INVALIDINVAL;
  3508. case NODE_TYPE_PARAMETER:
  3509. case NODE_TYPE_NUMERIC:
  3510. case NODE_TYPE_STRING:
  3511. case NODE_TYPE_USER:
  3512. case NODE_TYPE_DATE:
  3513. case NODE_TYPE_TIME:
  3514. case NODE_TYPE_TIMESTAMP:
  3515. /* Make sure value is of the proper type */
  3516. err = TypeCheck(lpstmt, *lplpSql,
  3517. lpSqlNode->node.comparison.Left,
  3518. lpSqlNodeValues->node.values.Value,
  3519. lpSqlNode->node.comparison.Operator,
  3520. &(lpSqlNode->sqlDataType),
  3521. &(lpSqlNode->sqlSqlType),
  3522. &(lpSqlNode->sqlPrecision),
  3523. &(lpSqlNode->sqlScale));
  3524. if (err != ERR_SUCCESS)
  3525. return err;
  3526. break;
  3527. case NODE_TYPE_NULL:
  3528. return ERR_INVALIDINVAL;
  3529. default:
  3530. return ERR_INTERNAL;
  3531. }
  3532. /* Look at next element */
  3533. idxValues = lpSqlNodeValues->node.values.Next;
  3534. }
  3535. }
  3536. /* The result is always a boolean */
  3537. lpSqlNode->sqlDataType = TYPE_INTEGER;
  3538. lpSqlNode->sqlSqlType = SQL_BIT;
  3539. lpSqlNode->sqlPrecision = 1;
  3540. lpSqlNode->sqlScale = 0;
  3541. break;
  3542. case NODE_TYPE_ALGEBRAIC:
  3543. /* Save pointer to enclosing statement */
  3544. lpSqlNode->node.algebraic.EnclosingStatement = idxEnclosingStatement;
  3545. {
  3546. LPSQLNODE lpSqlNodeLeft;
  3547. LPUSTR lpszToken;
  3548. UCHAR szTempToken[MAX_TOKEN_SIZE + 1];
  3549. /* Check left child */
  3550. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.algebraic.Left,
  3551. fIsGroupby, fCaseSensitive,
  3552. idxNodeTableOuterJoinFromTables,
  3553. idxEnclosingStatement);
  3554. if (err != ERR_SUCCESS)
  3555. return err;
  3556. /* Check right child */
  3557. err = SemanticCheck(lpstmt, lplpSql, lpSqlNode->node.algebraic.Right,
  3558. fIsGroupby, fCaseSensitive,
  3559. idxNodeTableOuterJoinFromTables,
  3560. idxEnclosingStatement);
  3561. if (err != ERR_SUCCESS)
  3562. return err;
  3563. /* Check data type compatibility */
  3564. err = TypeCheck(lpstmt, *lplpSql, lpSqlNode->node.algebraic.Left,
  3565. lpSqlNode->node.algebraic.Right,
  3566. lpSqlNode->node.algebraic.Operator,
  3567. &(lpSqlNode->sqlDataType), &(lpSqlNode->sqlSqlType),
  3568. &(lpSqlNode->sqlPrecision), &(lpSqlNode->sqlScale));
  3569. if (err != ERR_SUCCESS)
  3570. return err;
  3571. /* Allocate space for the column value and make sure the */
  3572. /* result is numeric, date, or string */
  3573. switch (lpSqlNode->sqlDataType) {
  3574. case TYPE_DOUBLE:
  3575. case TYPE_INTEGER:
  3576. break;
  3577. case TYPE_NUMERIC:
  3578. lpSqlNode->node.algebraic.Value = AllocateSpace(lplpSql,
  3579. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3580. if (lpSqlNode->node.algebraic.Value == NO_STRING)
  3581. return ERR_MEMALLOCFAIL;
  3582. if (lpSqlNode->node.algebraic.Operator == OP_TIMES) {
  3583. lpSqlNode->node.algebraic.WorkBuffer1 = AllocateSpace(lplpSql,
  3584. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3585. if (lpSqlNode->node.algebraic.WorkBuffer1 == NO_STRING)
  3586. return ERR_MEMALLOCFAIL;
  3587. }
  3588. else if (lpSqlNode->node.algebraic.Operator == OP_DIVIDEDBY) {
  3589. lpSqlNode->node.algebraic.WorkBuffer1 = AllocateSpace(lplpSql,
  3590. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3591. if (lpSqlNode->node.algebraic.WorkBuffer1 == NO_STRING)
  3592. return ERR_MEMALLOCFAIL;
  3593. lpSqlNode->node.algebraic.WorkBuffer2 = AllocateSpace(lplpSql,
  3594. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3595. if (lpSqlNode->node.algebraic.WorkBuffer2 == NO_STRING)
  3596. return ERR_MEMALLOCFAIL;
  3597. lpSqlNode->node.algebraic.WorkBuffer3 = AllocateSpace(lplpSql,
  3598. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3599. if (lpSqlNode->node.algebraic.WorkBuffer3 == NO_STRING)
  3600. return ERR_MEMALLOCFAIL;
  3601. }
  3602. break;
  3603. case TYPE_CHAR:
  3604. lpSqlNode->node.algebraic.Value = AllocateSpace(lplpSql,
  3605. (SWORD) (1 + lpSqlNode->sqlPrecision));
  3606. if (lpSqlNode->node.algebraic.Value == NO_STRING)
  3607. return ERR_MEMALLOCFAIL;
  3608. break;
  3609. case TYPE_BINARY:
  3610. ErrorOpCode(lpstmt, lpSqlNode->node.algebraic.Operator);
  3611. return ERR_INVALIDOPERAND;
  3612. case TYPE_DATE:
  3613. break;
  3614. case TYPE_TIME:
  3615. case TYPE_TIMESTAMP:
  3616. ErrorOpCode(lpstmt, lpSqlNode->node.algebraic.Operator);
  3617. return ERR_INVALIDOPERAND;
  3618. default:
  3619. return ERR_NOTSUPPORTED;
  3620. }
  3621. /* If this is just negation of a numeric value, collapse the */
  3622. /* two nodes into one */
  3623. lpSqlNodeLeft = ToNode(*lplpSql, lpSqlNode->node.algebraic.Left);
  3624. if ((lpSqlNode->node.algebraic.Operator == OP_NEG) &&
  3625. (lpSqlNodeLeft->sqlNodeType == NODE_TYPE_NUMERIC)) {
  3626. *lpSqlNode = *lpSqlNodeLeft;
  3627. lpSqlNode->node.numeric.Value = -(lpSqlNode->node.numeric.Value);
  3628. lpszToken = ToString(*lplpSql, lpSqlNode->node.numeric.Numeric);
  3629. if (*lpszToken != '-') {
  3630. s_lstrcpy((char*)szTempToken, lpszToken);
  3631. s_lstrcpy(lpszToken, "-");
  3632. s_lstrcat(lpszToken, (char*)szTempToken);
  3633. BCDNormalize(lpszToken, s_lstrlen(lpszToken),
  3634. lpszToken, s_lstrlen(lpszToken) + 1,
  3635. lpSqlNode->sqlPrecision,
  3636. lpSqlNode->sqlScale);
  3637. }
  3638. else {
  3639. s_lstrcpy((char*)szTempToken, lpszToken);
  3640. s_lstrcpy(lpszToken, (char*) (szTempToken+1));
  3641. }
  3642. }
  3643. }
  3644. break;
  3645. case NODE_TYPE_SCALAR:
  3646. /* Save pointer to enclosing statement */
  3647. lpSqlNode->node.scalar.EnclosingStatement = idxEnclosingStatement;
  3648. /* Check the node */
  3649. err = ScalarCheck(lpstmt, lplpSql, idxNode, fIsGroupby,
  3650. fCaseSensitive, idxNodeTableOuterJoinFromTables,
  3651. idxEnclosingStatement);
  3652. if (err != ERR_SUCCESS)
  3653. return err;
  3654. /* Allocate space as need be */
  3655. switch (lpSqlNode->sqlDataType) {
  3656. case TYPE_DOUBLE:
  3657. break;
  3658. case TYPE_NUMERIC:
  3659. lpSqlNode->node.scalar.Value = AllocateSpace(lplpSql,
  3660. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  3661. if (lpSqlNode->node.scalar.Value == NO_STRING)
  3662. return ERR_MEMALLOCFAIL;
  3663. break;
  3664. case TYPE_INTEGER:
  3665. break;
  3666. case TYPE_CHAR:
  3667. lpSqlNode->node.scalar.Value = AllocateSpace(lplpSql,
  3668. (SWORD) (1 + lpSqlNode->sqlPrecision));
  3669. if (lpSqlNode->node.scalar.Value == NO_STRING)
  3670. return ERR_MEMALLOCFAIL;
  3671. break;
  3672. case TYPE_BINARY:
  3673. lpSqlNode->node.scalar.Value = AllocateSpace(lplpSql,
  3674. (SWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision));
  3675. if (lpSqlNode->node.scalar.Value == NO_STRING)
  3676. return ERR_MEMALLOCFAIL;
  3677. break;
  3678. case TYPE_DATE:
  3679. break;
  3680. case TYPE_TIME:
  3681. break;
  3682. case TYPE_TIMESTAMP:
  3683. break;
  3684. default:
  3685. return ERR_NOTSUPPORTED;
  3686. }
  3687. break;
  3688. case NODE_TYPE_AGGREGATE:
  3689. /* Save pointer to enclosing statement */
  3690. lpSqlNode->node.aggregate.EnclosingStatement = idxEnclosingStatement;
  3691. {
  3692. LPSQLNODE lpSqlNodeExpression;
  3693. LPSQLNODE lpSqlNodeSelect;
  3694. LPSQLNODE lpSqlNodeAggregate;
  3695. SQLNODEIDX idxAggregate;
  3696. /* Error if no group by */
  3697. if (!fIsGroupby) {
  3698. ErrorAggCode(lpstmt, lpSqlNode->node.aggregate.Operator);
  3699. return ERR_AGGNOTALLOWED;
  3700. }
  3701. /* Check expression */
  3702. err = SemanticCheck(lpstmt, lplpSql,
  3703. lpSqlNode->node.aggregate.Expression,
  3704. FALSE, fCaseSensitive,
  3705. idxNodeTableOuterJoinFromTables,
  3706. idxEnclosingStatement);
  3707. if (err != ERR_SUCCESS)
  3708. return err;
  3709. /* Figure out type of result */
  3710. if (lpSqlNode->node.aggregate.Operator != AGG_COUNT)
  3711. lpSqlNodeExpression =
  3712. ToNode(*lplpSql, lpSqlNode->node.aggregate.Expression);
  3713. switch(lpSqlNode->node.aggregate.Operator) {
  3714. case AGG_AVG:
  3715. switch (lpSqlNodeExpression->sqlDataType) {
  3716. case TYPE_DOUBLE:
  3717. case TYPE_NUMERIC:
  3718. case TYPE_INTEGER:
  3719. lpSqlNode->sqlDataType = TYPE_DOUBLE;
  3720. lpSqlNode->sqlSqlType = SQL_DOUBLE;
  3721. lpSqlNode->sqlPrecision = 15;
  3722. lpSqlNode->sqlScale = NO_SCALE;
  3723. break;
  3724. case TYPE_CHAR:
  3725. case TYPE_DATE:
  3726. case TYPE_TIME:
  3727. case TYPE_TIMESTAMP:
  3728. case TYPE_BINARY:
  3729. ErrorAggCode(lpstmt, lpSqlNode->node.aggregate.Operator);
  3730. return ERR_INVALIDOPERAND;
  3731. default:
  3732. return ERR_NOTSUPPORTED;
  3733. }
  3734. break;
  3735. case AGG_COUNT:
  3736. lpSqlNode->sqlDataType = TYPE_INTEGER;
  3737. lpSqlNode->sqlSqlType = SQL_INTEGER;
  3738. lpSqlNode->sqlPrecision = 10;
  3739. lpSqlNode->sqlScale = 0;
  3740. break;
  3741. case AGG_MAX:
  3742. case AGG_MIN:
  3743. switch (lpSqlNodeExpression->sqlDataType) {
  3744. case TYPE_DOUBLE:
  3745. case TYPE_NUMERIC:
  3746. case TYPE_INTEGER:
  3747. case TYPE_CHAR:
  3748. case TYPE_DATE:
  3749. case TYPE_TIME:
  3750. case TYPE_TIMESTAMP:
  3751. lpSqlNode->sqlDataType = lpSqlNodeExpression->sqlDataType;
  3752. lpSqlNode->sqlSqlType = lpSqlNodeExpression->sqlSqlType;
  3753. lpSqlNode->sqlPrecision = lpSqlNodeExpression->sqlPrecision;
  3754. lpSqlNode->sqlScale = lpSqlNodeExpression->sqlScale;
  3755. break;
  3756. case TYPE_BINARY:
  3757. ErrorAggCode(lpstmt, lpSqlNode->node.aggregate.Operator);
  3758. return ERR_INVALIDOPERAND;
  3759. default:
  3760. return ERR_NOTSUPPORTED;
  3761. }
  3762. break;
  3763. case AGG_SUM:
  3764. switch (lpSqlNodeExpression->sqlDataType) {
  3765. case TYPE_DOUBLE:
  3766. case TYPE_NUMERIC:
  3767. case TYPE_INTEGER:
  3768. lpSqlNode->sqlDataType = lpSqlNodeExpression->sqlDataType;
  3769. lpSqlNode->sqlSqlType = lpSqlNodeExpression->sqlSqlType;
  3770. lpSqlNode->sqlPrecision = lpSqlNodeExpression->sqlPrecision;
  3771. lpSqlNode->sqlScale = lpSqlNodeExpression->sqlScale;
  3772. break;
  3773. case TYPE_CHAR:
  3774. case TYPE_DATE:
  3775. case TYPE_TIME:
  3776. case TYPE_TIMESTAMP:
  3777. case TYPE_BINARY:
  3778. ErrorAggCode(lpstmt, lpSqlNode->node.aggregate.Operator);
  3779. return ERR_INVALIDOPERAND;
  3780. default:
  3781. return ERR_NOTSUPPORTED;
  3782. }
  3783. break;
  3784. default:
  3785. return ERR_INTERNAL;
  3786. }
  3787. /* Allocate space for the aggregate value */
  3788. switch (lpSqlNode->sqlDataType) {
  3789. case TYPE_DOUBLE:
  3790. lpSqlNode->node.aggregate.Length = sizeof(double);
  3791. break;
  3792. case TYPE_NUMERIC:
  3793. switch (lpSqlNode->sqlSqlType) {
  3794. case SQL_NUMERIC:
  3795. case SQL_DECIMAL:
  3796. lpSqlNode->node.aggregate.Length =
  3797. lpSqlNodeExpression->sqlPrecision + 2;
  3798. break;
  3799. case SQL_BIGINT:
  3800. lpSqlNode->node.aggregate.Length =
  3801. lpSqlNodeExpression->sqlPrecision + 1;
  3802. break;
  3803. case SQL_TINYINT:
  3804. case SQL_SMALLINT:
  3805. case SQL_INTEGER:
  3806. case SQL_BIT:
  3807. case SQL_REAL:
  3808. case SQL_FLOAT:
  3809. case SQL_DOUBLE:
  3810. case SQL_CHAR:
  3811. case SQL_VARCHAR:
  3812. case SQL_LONGVARCHAR:
  3813. case SQL_BINARY:
  3814. case SQL_VARBINARY:
  3815. case SQL_LONGVARBINARY:
  3816. case SQL_DATE:
  3817. case SQL_TIME:
  3818. case SQL_TIMESTAMP:
  3819. default:
  3820. return ERR_INTERNAL;
  3821. }
  3822. lpSqlNode->node.aggregate.Value =
  3823. AllocateSpace(lplpSql, (SWORD)
  3824. (lpSqlNode->node.aggregate.Length + 1));
  3825. if (lpSqlNode->node.aggregate.Value == NO_STRING)
  3826. return ERR_MEMALLOCFAIL;
  3827. break;
  3828. case TYPE_INTEGER:
  3829. lpSqlNode->node.aggregate.Length = sizeof(double);
  3830. break;
  3831. case TYPE_CHAR:
  3832. lpSqlNode->node.aggregate.Length =
  3833. lpSqlNodeExpression->sqlPrecision;
  3834. lpSqlNode->node.aggregate.Value =
  3835. AllocateSpace(lplpSql, (SWORD)
  3836. (lpSqlNode->node.aggregate.Length + 1));
  3837. if (lpSqlNode->node.aggregate.Value == NO_STRING)
  3838. return ERR_MEMALLOCFAIL;
  3839. break;
  3840. case TYPE_DATE:
  3841. lpSqlNode->node.aggregate.Length = 10;
  3842. break;
  3843. case TYPE_TIME:
  3844. lpSqlNode->node.aggregate.Length = 8;
  3845. break;
  3846. case TYPE_TIMESTAMP:
  3847. if (TIMESTAMP_SCALE > 0)
  3848. lpSqlNode->node.aggregate.Length = 20 + TIMESTAMP_SCALE;
  3849. else
  3850. lpSqlNode->node.aggregate.Length = 19;
  3851. break;
  3852. case TYPE_BINARY:
  3853. return ERR_INTERNAL;
  3854. default:
  3855. return ERR_NOTSUPPORTED;
  3856. }
  3857. /* Get SELECT statement node */
  3858. lpSqlNodeSelect = ToNode(*lplpSql, idxEnclosingStatement);
  3859. if (lpSqlNodeSelect->sqlNodeType != NODE_TYPE_SELECT)
  3860. return ERR_INTERNAL;
  3861. /* Add to list of AGG functions in the select node */
  3862. lpSqlNodeAggregate = NULL;
  3863. idxAggregate = lpSqlNodeSelect->node.select.Aggregates;
  3864. while (idxAggregate != NO_SQLNODE) {
  3865. lpSqlNodeAggregate = ToNode(*lplpSql, idxAggregate);
  3866. idxAggregate = lpSqlNodeAggregate->node.aggregate.Next;
  3867. }
  3868. if (lpSqlNodeAggregate != NULL)
  3869. lpSqlNodeAggregate->node.aggregate.Next = idxNode;
  3870. else
  3871. lpSqlNodeSelect->node.select.Aggregates = idxNode;
  3872. }
  3873. break;
  3874. case NODE_TYPE_TABLE:
  3875. {
  3876. LPSQLNODE lpSqlNodeRoot;
  3877. LPSQLNODE lpSqlNodeStmt;
  3878. BOOL fReadOnly;
  3879. char tableNameBuff [MAX_TABLE_NAME_LENGTH + 1];
  3880. /* Make sure table name is not too long */
  3881. ptr = ToString(*lplpSql, lpSqlNode->node.table.Name);
  3882. if (s_lstrlen(ptr) > ISAMMaxTableNameLength(lpstmt->lpdbc->lpISAM)){
  3883. s_lstrcpy(lpstmt->szError, ptr);
  3884. return ERR_INVALIDTABLENAME;
  3885. }
  3886. else
  3887. {
  3888. //Copy table name
  3889. tableNameBuff[0] = 0;
  3890. s_lstrcpy (tableNameBuff, ptr);
  3891. }
  3892. /* Figure out if write access is needed */
  3893. lpSqlNodeStmt = ToNode(*lplpSql, idxEnclosingStatement);
  3894. switch (lpSqlNodeStmt->sqlNodeType) {
  3895. case NODE_TYPE_SELECT:
  3896. fReadOnly = TRUE;
  3897. break;
  3898. case NODE_TYPE_INSERT:
  3899. fReadOnly = FALSE;
  3900. break;
  3901. case NODE_TYPE_UPDATE:
  3902. fReadOnly = FALSE;
  3903. break;
  3904. case NODE_TYPE_DELETE:
  3905. fReadOnly = FALSE;
  3906. break;
  3907. case NODE_TYPE_CREATEINDEX:
  3908. fReadOnly = FALSE;
  3909. break;
  3910. case NODE_TYPE_DROPINDEX:
  3911. fReadOnly = FALSE;
  3912. break;
  3913. default:
  3914. return ERR_INTERNAL;
  3915. }
  3916. /* resolve qualifier */
  3917. if (lpSqlNode->node.table.Qualifier != NO_STRING)
  3918. {
  3919. LPSTR pQual = (LPSTR) ToString(*lplpSql, lpSqlNode->node.table.Qualifier);
  3920. if (lstrlen(pQual) > ISAMMaxTableNameLength(lpstmt->lpdbc->lpISAM)) {
  3921. s_lstrcpy((char*)lpstmt->szError, ptr);
  3922. return ERR_INVALIDTABLENAME;
  3923. }
  3924. if ( (lstrlen(pQual) >= 4) && (_strnicmp("root", pQual, 4) == 0) )
  3925. {
  3926. // absolute qualifier [starts with 'root'] (no need to change)
  3927. }
  3928. else
  3929. {
  3930. // concatenate the current namespace with the qualifier
  3931. LPUSTR currQual = ISAMDatabase (lpstmt->lpdbc->lpISAM);
  3932. char * pszNewQualifier = new char [strlen (pQual)+
  3933. s_lstrlen (currQual)+2+1];
  3934. s_lstrcpy (pszNewQualifier, currQual);
  3935. s_lstrcat (pszNewQualifier, "\\");
  3936. s_lstrcat (pszNewQualifier, pQual);
  3937. lpSqlNode->node.table.Qualifier = AllocateString (lplpSql, (LPUSTR)pszNewQualifier);
  3938. delete [] pszNewQualifier;
  3939. }
  3940. }
  3941. else
  3942. {
  3943. // the current namespace is the qualifier
  3944. LPUSTR currQual = ISAMDatabase (lpstmt->lpdbc->lpISAM);
  3945. lpSqlNode->node.table.Qualifier = AllocateString (lplpSql, (LPUSTR)currQual);
  3946. }
  3947. #ifdef TESTING
  3948. //Create extra test class with dummy values for testing
  3949. // IMosProvider* pDummyProv = ISAMGetGatewayServer(lpstmt->lpdbc->lpISAM);
  3950. // CreateClassAndInstance(pDummyProv);
  3951. #endif
  3952. /* Open the table */
  3953. LPUSTR pQual = ToString(*lplpSql, lpSqlNode->node.table.Qualifier);
  3954. lpSqlNodeRoot = ToNode(*lplpSql, ROOT_SQLNODE);
  3955. //If this the special Passthrough SQL table ?
  3956. char* virTbl = WBEMDR32_VIRTUAL_TABLE2;
  3957. if (s_lstrcmp(tableNameBuff, virTbl) == 0)
  3958. {
  3959. //Yes this is the Passthrough SQL table
  3960. err = ISAMOpenTable(lpSqlNodeRoot->node.root.lpISAM,
  3961. (LPUSTR) pQual, (SWORD) s_lstrlen (pQual),
  3962. (LPUSTR) tableNameBuff, fReadOnly,
  3963. &(lpSqlNode->node.table.Handle),
  3964. lpstmt);
  3965. }
  3966. else
  3967. {
  3968. //No normal table
  3969. err = ISAMOpenTable(lpSqlNodeRoot->node.root.lpISAM,
  3970. (LPUSTR) pQual, (SWORD) s_lstrlen (pQual),
  3971. (LPUSTR) tableNameBuff, fReadOnly,
  3972. &(lpSqlNode->node.table.Handle));
  3973. }
  3974. if (err != NO_ISAM_ERR) {
  3975. lpSqlNode->node.table.Handle = NULL;
  3976. ISAMGetErrorMessage(lpSqlNodeRoot->node.root.lpISAM,
  3977. (LPUSTR)lpstmt->szISAMError);
  3978. return err;
  3979. }
  3980. if (lpstmt->lpdbc->lpISAM->fSchemaInfoTransactioned)
  3981. lpstmt->fISAMTxnStarted = TRUE;
  3982. err = ERR_SUCCESS;
  3983. }
  3984. break;
  3985. case NODE_TYPE_COLUMN:
  3986. /* Save pointer to enclosing statement */
  3987. lpSqlNode->node.column.EnclosingStatement = idxEnclosingStatement;
  3988. //Sai Wong table column info
  3989. /* Is this column node in an outer join predicate? */
  3990. if (idxNodeTableOuterJoinFromTables == NO_SQLNODE) {
  3991. /* No. Resolve it against the table lists */
  3992. LPSQLNODE lpSqlNodeStmt;
  3993. LPSQLNODE lpSqlNodeTables;
  3994. SQLNODEIDX idxTables;
  3995. SQLNODEIDX idxStatement;
  3996. STRINGIDX idxOriginalAlias;
  3997. STRINGIDX idxAlias;
  3998. BOOL fFoundMatch;
  3999. STRINGIDX idxQualifier, idxOriginalQualifier;
  4000. /* No. Search up all the enclosing statements for the column */
  4001. idxStatement = idxEnclosingStatement;
  4002. while (idxStatement != NO_SQLNODE) {
  4003. /* Get node of the statement */
  4004. lpSqlNodeStmt = ToNode(*lplpSql, idxStatement);
  4005. /* Resolve column */
  4006. switch (lpSqlNodeStmt->sqlNodeType) {
  4007. case NODE_TYPE_SELECT:
  4008. /* Save the table alias and qualifier specified */
  4009. idxAlias = lpSqlNode->node.column.Tablealias;
  4010. idxOriginalAlias = lpSqlNode->node.column.Tablealias;
  4011. idxQualifier = idxOriginalQualifier = lpSqlNode->node.column.Qualifier;
  4012. /* Look through the list of tables */
  4013. fFoundMatch = FALSE;
  4014. err = ERR_COLUMNNOTFOUND;
  4015. for (idxTables = lpSqlNodeStmt->node.select.Tables;
  4016. idxTables != NO_SQLNODE;
  4017. idxTables = lpSqlNodeTables->node.tables.Next) {
  4018. /* Is the column in this table? */
  4019. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  4020. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive,
  4021. lpSqlNode, lpSqlNodeTables->node.tables.Table, idxQualifier);
  4022. if (err == ERR_SUCCESS)
  4023. {
  4024. /* Yes. Error if column also in another table */
  4025. if (fFoundMatch) {
  4026. s_lstrcpy((char*)lpstmt->szError,
  4027. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4028. return ERR_COLUMNFOUND;
  4029. }
  4030. fFoundMatch = TRUE;
  4031. /* If a table alias was specified for column, */
  4032. /* there is no need to check the other tables */
  4033. /* I'm going to remove this check as there is the */
  4034. /* possibility of a clash between an alias-qualified*/
  4035. /* name and a namespace qualified name. This clash */
  4036. /* is not picked up during the semantic check of the*/
  4037. /* table list */
  4038. //if (idxOriginalAlias != NO_STRING)
  4039. // break;
  4040. /* Save the alias of the table found */
  4041. idxAlias = lpSqlNode->node.column.Tablealias;
  4042. idxQualifier = lpSqlNode->node.column.Qualifier;
  4043. /* Restore the original alias and keep looking */
  4044. //Added by Sai Wong
  4045. lpSqlNode->node.column.Tablealias = idxOriginalAlias; //NO_STRING;
  4046. lpSqlNode->node.column.Qualifier = idxOriginalQualifier;
  4047. }
  4048. else if (err != ERR_COLUMNNOTFOUND)
  4049. return err;
  4050. }
  4051. /* Restore the alias found */
  4052. lpSqlNode->node.column.Tablealias = idxAlias;
  4053. lpSqlNode->node.column.Qualifier = idxQualifier;
  4054. /* Was the column found in this statement? */
  4055. if (fFoundMatch)
  4056. err = ERR_SUCCESS;
  4057. else
  4058. err = ERR_COLUMNNOTFOUND;
  4059. break;
  4060. case NODE_TYPE_INSERT:
  4061. if (idxStatement == idxEnclosingStatement)
  4062. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive,
  4063. lpSqlNode, lpSqlNodeStmt->node.insert.Table,
  4064. NO_STRING);
  4065. else
  4066. err = ERR_COLUMNNOTFOUND;
  4067. break;
  4068. case NODE_TYPE_UPDATE:
  4069. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive, lpSqlNode,
  4070. lpSqlNodeStmt->node.update.Table, NO_STRING);
  4071. break;
  4072. case NODE_TYPE_DELETE:
  4073. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive, lpSqlNode,
  4074. lpSqlNodeStmt->node.delet.Table, NO_STRING);
  4075. break;
  4076. case NODE_TYPE_CREATEINDEX:
  4077. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive, lpSqlNode,
  4078. lpSqlNodeStmt->node.createindex.Table, NO_STRING);
  4079. break;
  4080. default:
  4081. return ERR_INTERNAL;
  4082. }
  4083. if ((err != ERR_SUCCESS) && (err != ERR_COLUMNNOTFOUND))
  4084. return err;
  4085. /* If the column was found in this statement, use it */
  4086. if (err == ERR_SUCCESS)
  4087. break;
  4088. /* Try looking in the enclosing statement (if any) */
  4089. if (lpSqlNodeStmt->sqlNodeType != NODE_TYPE_SELECT)
  4090. break;
  4091. idxStatement = lpSqlNodeStmt->node.select.EnclosingStatement;
  4092. }
  4093. /* If column not found, error */
  4094. if (err == ERR_COLUMNNOTFOUND) {
  4095. s_lstrcpy(lpstmt->szError,
  4096. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4097. return ERR_COLUMNNOTFOUND;
  4098. }
  4099. }
  4100. else {
  4101. /* Yes. Resolve it against the table lists */
  4102. STRINGIDX idxAlias;
  4103. STRINGIDX idxOriginalAlias;
  4104. BOOL fFoundMatch;
  4105. SQLNODEIDX idxTables;
  4106. LPSQLNODE lpSqlNodeTables;
  4107. SQLNODEIDX idxTable;
  4108. LPSQLNODE lpSqlNodeTable;
  4109. STRINGIDX idxQualifier, idxOriginalQualifier;
  4110. /* Save the table alias specified */
  4111. idxAlias = lpSqlNode->node.column.Tablealias;
  4112. idxOriginalAlias = lpSqlNode->node.column.Tablealias;
  4113. idxQualifier = idxOriginalQualifier = lpSqlNode->node.column.Qualifier;
  4114. /* Is the column in a table in the outer join expression? */
  4115. idxTables = idxNodeTableOuterJoinFromTables;
  4116. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  4117. idxTable = lpSqlNodeTables->node.tables.Table;
  4118. fFoundMatch = FALSE;
  4119. while (TRUE) {
  4120. /* Is it in this table? */
  4121. err = FindColumn(lpstmt, *lplpSql, fCaseSensitive,
  4122. lpSqlNode, idxTable, lpSqlNodeTables->node.column.Qualifier);
  4123. if (err == ERR_SUCCESS) {
  4124. /* Yes. Error if it matches another table too */
  4125. if (fFoundMatch) {
  4126. s_lstrcpy(lpstmt->szError,
  4127. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4128. return ERR_COLUMNFOUND;
  4129. }
  4130. /* Set flag */
  4131. fFoundMatch = TRUE;
  4132. /* Save the alias of the table found */
  4133. idxAlias = lpSqlNode->node.column.Tablealias;
  4134. idxQualifier = lpSqlNode->node.column.Qualifier;
  4135. /* Restore the original alias if need be */
  4136. //Added by Sai Wong
  4137. // if (idxOriginalAlias == NO_STRING)
  4138. lpSqlNode->node.column.Tablealias = idxOriginalAlias; //NO_STRING;
  4139. lpSqlNode->node.column.Qualifier = idxOriginalQualifier;
  4140. }
  4141. else if (err != ERR_COLUMNNOTFOUND)
  4142. return err;
  4143. /* Look in next table on list */
  4144. idxTables = lpSqlNodeTables->node.tables.Next;
  4145. if (idxTables == NO_SQLNODE)
  4146. break;
  4147. lpSqlNodeTables = ToNode(*lplpSql, idxTables);
  4148. idxTable = lpSqlNodeTables->node.tables.Table;
  4149. lpSqlNodeTable = ToNode(*lplpSql, idxTable);
  4150. /* If this table is not in the outer-join, stop looking */
  4151. if (lpSqlNodeTable->node.table.OuterJoinFromTables ==
  4152. NO_SQLNODE)
  4153. break;
  4154. }
  4155. /* Error if column was not found */
  4156. if (!fFoundMatch) {
  4157. s_lstrcpy(lpstmt->szError,
  4158. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4159. return ERR_COLUMNNOTFOUND;
  4160. }
  4161. /* Restore the alias found */
  4162. lpSqlNode->node.column.Tablealias = idxAlias;
  4163. lpSqlNode->node.column.Qualifier = idxQualifier;
  4164. err = ERR_SUCCESS;
  4165. }
  4166. /* Does the column have to be a group by column? */
  4167. if (fIsGroupby) {
  4168. LPUSTR lpszColumn;
  4169. LPUSTR lpszTable;
  4170. LPSQLNODE lpSqlNodeStmt;
  4171. SQLNODEIDX idxGroupbycolumns;
  4172. LPSQLNODE lpSqlNodeGroupbycolumns;
  4173. LPSQLNODE lpSqlNodeColumnGroupby;
  4174. LPUSTR lpszColumnGroupby;
  4175. LPUSTR lpszTableGroupby;
  4176. BOOL fMatch;
  4177. /* Yes. Get the name of the column and table */
  4178. lpszColumn = ToString(*lplpSql, lpSqlNode->node.column.Column);
  4179. lpszTable = ToString(*lplpSql, lpSqlNode->node.column.Tablealias);
  4180. /* Get list of group by columns */
  4181. lpSqlNodeStmt = ToNode(*lplpSql, idxEnclosingStatement);
  4182. if (lpSqlNodeStmt->sqlNodeType != NODE_TYPE_SELECT)
  4183. return ERR_INTERNAL;
  4184. idxGroupbycolumns = lpSqlNodeStmt->node.select.Groupbycolumns;
  4185. /* Error if implicit group by */
  4186. if (lpSqlNodeStmt->node.select.ImplicitGroupby) {
  4187. s_lstrcpy(lpstmt->szError,
  4188. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4189. return ERR_COLUMNNOTFOUND;
  4190. }
  4191. /* Find the column in the group by lists */
  4192. while (TRUE) {
  4193. /* Get this group by column */
  4194. lpSqlNodeGroupbycolumns = ToNode(*lplpSql, idxGroupbycolumns);
  4195. if (lpSqlNodeGroupbycolumns->node.groupbycolumns.Column !=
  4196. NO_SQLNODE) {
  4197. lpSqlNodeColumnGroupby = ToNode(*lplpSql,
  4198. lpSqlNodeGroupbycolumns->node.groupbycolumns.Column);
  4199. /* Get column name and table name of the group by column */
  4200. lpszTableGroupby = ToString(*lplpSql,
  4201. lpSqlNodeColumnGroupby->node.column.Tablealias);
  4202. lpszColumnGroupby = ToString(*lplpSql,
  4203. lpSqlNodeColumnGroupby->node.column.Column);
  4204. /* Do the column name match? */
  4205. fMatch = FALSE;
  4206. if (fCaseSensitive) {
  4207. if (!s_lstrcmp(lpszColumnGroupby, lpszColumn) &&
  4208. !s_lstrcmp(lpszTableGroupby, lpszTable))
  4209. fMatch = TRUE;
  4210. }
  4211. else {
  4212. if (!s_lstrcmpi(lpszColumnGroupby, lpszColumn) &&
  4213. !s_lstrcmpi(lpszTableGroupby, lpszTable))
  4214. fMatch = TRUE;
  4215. }
  4216. }
  4217. else
  4218. fMatch = FALSE;
  4219. /* Does this column match a group by column? */
  4220. if (fMatch) {
  4221. /* Yes. Fill in semantic information for the column */
  4222. lpSqlNode->node.column.InSortRecord = TRUE;
  4223. lpSqlNode->node.column.Offset =
  4224. lpSqlNodeColumnGroupby->node.column.Offset;
  4225. lpSqlNode->node.column.Length =
  4226. lpSqlNodeColumnGroupby->node.column.Length;
  4227. lpSqlNode->node.column.DistinctOffset =
  4228. lpSqlNodeColumnGroupby->node.column.DistinctOffset;
  4229. lpSqlNode->node.column.DistinctLength =
  4230. lpSqlNodeColumnGroupby->node.column.DistinctLength;
  4231. break;
  4232. }
  4233. /* Not found yet. Check next column */
  4234. idxGroupbycolumns =
  4235. lpSqlNodeGroupbycolumns->node.groupbycolumns.Next;
  4236. /* Error if column not found */
  4237. if (idxGroupbycolumns == NO_SQLNODE) {
  4238. s_lstrcpy((char*)lpstmt->szError,
  4239. ToString(*lplpSql, lpSqlNode->node.column.Column));
  4240. return ERR_COLUMNNOTFOUND;
  4241. }
  4242. }
  4243. }
  4244. /* Allocate space for the column value */
  4245. switch (lpSqlNode->sqlDataType) {
  4246. case TYPE_DOUBLE:
  4247. break;
  4248. case TYPE_NUMERIC:
  4249. lpSqlNode->node.column.Value = AllocateSpace(lplpSql,
  4250. (SWORD) (1 + 2 + lpSqlNode->sqlPrecision));
  4251. if (lpSqlNode->node.column.Value == NO_STRING)
  4252. return ERR_MEMALLOCFAIL;
  4253. break;
  4254. case TYPE_INTEGER:
  4255. break;
  4256. case TYPE_CHAR:
  4257. lpSqlNode->node.column.Value = AllocateSpace(lplpSql,
  4258. (SWORD) (1 + lpSqlNode->sqlPrecision));
  4259. if (lpSqlNode->node.column.Value == NO_STRING)
  4260. return ERR_MEMALLOCFAIL;
  4261. break;
  4262. case TYPE_BINARY:
  4263. lpSqlNode->node.column.Value = AllocateSpace(lplpSql,
  4264. (SWORD) (sizeof(SDWORD) + lpSqlNode->sqlPrecision));
  4265. if (lpSqlNode->node.column.Value == NO_STRING)
  4266. return ERR_MEMALLOCFAIL;
  4267. break;
  4268. case TYPE_DATE:
  4269. break;
  4270. case TYPE_TIME:
  4271. break;
  4272. case TYPE_TIMESTAMP:
  4273. break;
  4274. default:
  4275. return ERR_NOTSUPPORTED;
  4276. }
  4277. break;
  4278. case NODE_TYPE_STRING:
  4279. lpSqlNode->sqlDataType = TYPE_CHAR;
  4280. lpSqlNode->sqlSqlType = SQL_VARCHAR;
  4281. ptr = ToString(*lplpSql, lpSqlNode->node.string.Value);
  4282. lpSqlNode->sqlPrecision = s_lstrlen(ptr);
  4283. lpSqlNode->sqlScale = NO_SCALE;
  4284. break;
  4285. case NODE_TYPE_NUMERIC:
  4286. if (lpSqlNode->sqlDataType == TYPE_UNKNOWN) {
  4287. lpSqlNode->sqlDataType = TYPE_DOUBLE;
  4288. lpSqlNode->sqlSqlType = SQL_DOUBLE;
  4289. lpSqlNode->sqlPrecision = 15;
  4290. lpSqlNode->sqlScale = NO_SCALE;
  4291. }
  4292. break;
  4293. case NODE_TYPE_PARAMETER:
  4294. lpSqlNode->sqlDataType = TYPE_UNKNOWN;
  4295. lpSqlNode->sqlSqlType = SQL_TYPE_NULL;
  4296. lpSqlNode->sqlPrecision = 0;
  4297. lpSqlNode->sqlScale = NO_SCALE;
  4298. break;
  4299. case NODE_TYPE_USER:
  4300. lpSqlNode->sqlDataType = TYPE_CHAR;
  4301. lpSqlNode->sqlSqlType = SQL_VARCHAR;
  4302. lpSqlNode->sqlPrecision = s_lstrlen(
  4303. ISAMUser(ToNode(*lplpSql, ROOT_SQLNODE)->node.root.lpISAM));
  4304. lpSqlNode->sqlScale = NO_SCALE;
  4305. break;
  4306. case NODE_TYPE_NULL:
  4307. lpSqlNode->sqlDataType = TYPE_UNKNOWN;
  4308. lpSqlNode->sqlSqlType = SQL_TYPE_NULL;
  4309. lpSqlNode->sqlPrecision = 0;
  4310. lpSqlNode->sqlScale = NO_SCALE;
  4311. break;
  4312. case NODE_TYPE_DATE:
  4313. lpSqlNode->sqlDataType = TYPE_DATE;
  4314. if (lpSqlNode->sqlSqlType == SQL_TYPE_NULL) {
  4315. lpSqlNode->sqlSqlType = SQL_DATE;
  4316. lpSqlNode->sqlPrecision = 10;
  4317. lpSqlNode->sqlScale = NO_SCALE;
  4318. }
  4319. break;
  4320. case NODE_TYPE_TIME:
  4321. lpSqlNode->sqlDataType = TYPE_TIME;
  4322. if (lpSqlNode->sqlSqlType == SQL_TYPE_NULL) {
  4323. lpSqlNode->sqlSqlType = SQL_TIME;
  4324. lpSqlNode->sqlPrecision = 8;
  4325. lpSqlNode->sqlScale = NO_SCALE;
  4326. }
  4327. break;
  4328. case NODE_TYPE_TIMESTAMP:
  4329. lpSqlNode->sqlDataType = TYPE_TIMESTAMP;
  4330. if (lpSqlNode->sqlSqlType == SQL_TYPE_NULL) {
  4331. lpSqlNode->sqlSqlType = SQL_TIMESTAMP;
  4332. if (TIMESTAMP_SCALE != 0)
  4333. lpSqlNode->sqlPrecision = 20 + TIMESTAMP_SCALE;
  4334. else
  4335. lpSqlNode->sqlPrecision = 19;
  4336. lpSqlNode->sqlScale = TIMESTAMP_SCALE;
  4337. }
  4338. break;
  4339. default:
  4340. return ERR_INTERNAL;
  4341. }
  4342. return err;
  4343. }
  4344. /***************************************************************************/
  4345. void INTFUNC FreeTreeSemantic(LPSQLTREE lpSql, SQLNODEIDX idxNode)
  4346. /* Deallocates semantic information in a parse tree */
  4347. {
  4348. LPSQLNODE lpSqlNode;
  4349. SQLNODEIDX idxParameter;
  4350. SQLNODEIDX idxParameterNext;
  4351. if (idxNode == NO_SQLNODE)
  4352. return;
  4353. lpSqlNode = ToNode(lpSql, idxNode);
  4354. switch (lpSqlNode->sqlNodeType) {
  4355. case NODE_TYPE_NONE:
  4356. break;
  4357. case NODE_TYPE_ROOT:
  4358. FreeTreeSemantic(lpSql, lpSqlNode->node.root.sql);
  4359. if (lpSqlNode->node.root.passthroughParams) {
  4360. idxParameter = lpSqlNode->node.root.parameters;
  4361. while (idxParameter != NO_SQLNODE) {
  4362. lpSqlNode = ToNode(lpSql, idxParameter);
  4363. idxParameterNext = lpSqlNode->node.parameter.Next;
  4364. FreeTreeSemantic(lpSql, idxParameter);
  4365. idxParameter = idxParameterNext;
  4366. }
  4367. }
  4368. break;
  4369. case NODE_TYPE_CREATE:
  4370. FreeTreeSemantic(lpSql, lpSqlNode->node.create.Columns);
  4371. break;
  4372. case NODE_TYPE_DROP:
  4373. break;
  4374. case NODE_TYPE_SELECT:
  4375. FreeTreeSemantic(lpSql, lpSqlNode->node.select.Values);
  4376. FreeTreeSemantic(lpSql, lpSqlNode->node.select.Tables);
  4377. FreeTreeSemantic(lpSql, lpSqlNode->node.select.Predicate);
  4378. FreeTreeSemantic(lpSql, lpSqlNode->node.select.Groupbycolumns);
  4379. FreeTreeSemantic(lpSql, lpSqlNode->node.select.Sortcolumns);
  4380. if (lpSqlNode->node.select.Sortfile != HFILE_ERROR) {
  4381. LPUSTR lpszSortfile;
  4382. _lclose(lpSqlNode->node.select.Sortfile);
  4383. lpSqlNode->node.select.Sortfile = HFILE_ERROR;
  4384. lpszSortfile = ToString(lpSql,
  4385. lpSqlNode->node.select.SortfileName);
  4386. DeleteFile((LPCSTR) lpszSortfile);
  4387. s_lstrcpy(lpszSortfile, "");
  4388. }
  4389. break;
  4390. case NODE_TYPE_INSERT:
  4391. FreeTreeSemantic(lpSql, lpSqlNode->node.insert.Table);
  4392. FreeTreeSemantic(lpSql, lpSqlNode->node.insert.Columns);
  4393. FreeTreeSemantic(lpSql, lpSqlNode->node.insert.Values);
  4394. break;
  4395. case NODE_TYPE_DELETE:
  4396. FreeTreeSemantic(lpSql, lpSqlNode->node.delet.Table);
  4397. FreeTreeSemantic(lpSql, lpSqlNode->node.delet.Predicate);
  4398. break;
  4399. case NODE_TYPE_UPDATE:
  4400. FreeTreeSemantic(lpSql, lpSqlNode->node.update.Table);
  4401. FreeTreeSemantic(lpSql, lpSqlNode->node.update.Updatevalues);
  4402. FreeTreeSemantic(lpSql, lpSqlNode->node.update.Predicate);
  4403. break;
  4404. case NODE_TYPE_CREATEINDEX:
  4405. FreeTreeSemantic(lpSql, lpSqlNode->node.createindex.Table);
  4406. FreeTreeSemantic(lpSql, lpSqlNode->node.createindex.Columns);
  4407. break;
  4408. case NODE_TYPE_DROPINDEX:
  4409. break;
  4410. case NODE_TYPE_PASSTHROUGH:
  4411. break;
  4412. case NODE_TYPE_TABLES:
  4413. FreeTreeSemantic(lpSql, lpSqlNode->node.tables.Table);
  4414. FreeTreeSemantic(lpSql, lpSqlNode->node.tables.Next);
  4415. break;
  4416. case NODE_TYPE_VALUES:
  4417. while (TRUE) {
  4418. FreeTreeSemantic(lpSql, lpSqlNode->node.values.Value);
  4419. if (lpSqlNode->node.values.Next == NO_SQLNODE)
  4420. break;
  4421. lpSqlNode = ToNode(lpSql, lpSqlNode->node.values.Next);
  4422. }
  4423. break;
  4424. case NODE_TYPE_COLUMNS:
  4425. while (TRUE) {
  4426. FreeTreeSemantic(lpSql, lpSqlNode->node.columns.Column);
  4427. if (lpSqlNode->node.columns.Next == NO_SQLNODE)
  4428. break;
  4429. lpSqlNode = ToNode(lpSql, lpSqlNode->node.columns.Next);
  4430. }
  4431. break;
  4432. case NODE_TYPE_SORTCOLUMNS:
  4433. while (TRUE) {
  4434. FreeTreeSemantic(lpSql, lpSqlNode->node.sortcolumns.Column);
  4435. if (lpSqlNode->node.sortcolumns.Next == NO_SQLNODE)
  4436. break;
  4437. lpSqlNode = ToNode(lpSql, lpSqlNode->node.sortcolumns.Next);
  4438. }
  4439. break;
  4440. case NODE_TYPE_GROUPBYCOLUMNS:
  4441. while (TRUE) {
  4442. FreeTreeSemantic(lpSql, lpSqlNode->node.groupbycolumns.Column);
  4443. if (lpSqlNode->node.groupbycolumns.Next == NO_SQLNODE)
  4444. break;
  4445. lpSqlNode = ToNode(lpSql, lpSqlNode->node.groupbycolumns.Next);
  4446. }
  4447. break;
  4448. case NODE_TYPE_UPDATEVALUES:
  4449. while (TRUE) {
  4450. FreeTreeSemantic(lpSql, lpSqlNode->node.updatevalues.Column);
  4451. FreeTreeSemantic(lpSql, lpSqlNode->node.updatevalues.Value);
  4452. if (lpSqlNode->node.updatevalues.Next == NO_SQLNODE)
  4453. break;
  4454. lpSqlNode = ToNode(lpSql, lpSqlNode->node.updatevalues.Next);
  4455. }
  4456. break;
  4457. case NODE_TYPE_CREATECOLS:
  4458. while (TRUE) {
  4459. if (lpSqlNode->node.createcols.Next == NO_SQLNODE)
  4460. break;
  4461. lpSqlNode = ToNode(lpSql, lpSqlNode->node.createcols.Next);
  4462. }
  4463. break;
  4464. case NODE_TYPE_BOOLEAN:
  4465. FreeTreeSemantic(lpSql, lpSqlNode->node.boolean.Left);
  4466. FreeTreeSemantic(lpSql, lpSqlNode->node.boolean.Right);
  4467. break;
  4468. case NODE_TYPE_COMPARISON:
  4469. FreeTreeSemantic(lpSql, lpSqlNode->node.comparison.Left);
  4470. FreeTreeSemantic(lpSql, lpSqlNode->node.comparison.Right);
  4471. break;
  4472. case NODE_TYPE_ALGEBRAIC:
  4473. FreeTreeSemantic(lpSql, lpSqlNode->node.algebraic.Left);
  4474. FreeTreeSemantic(lpSql, lpSqlNode->node.algebraic.Right);
  4475. break;
  4476. case NODE_TYPE_SCALAR:
  4477. FreeTreeSemantic(lpSql, lpSqlNode->node.scalar.Arguments);
  4478. break;
  4479. case NODE_TYPE_AGGREGATE:
  4480. FreeTreeSemantic(lpSql, lpSqlNode->node.aggregate.Expression);
  4481. break;
  4482. case NODE_TYPE_TABLE:
  4483. if (lpSqlNode->node.table.Handle != NULL) {
  4484. ISAMCloseTable(lpSqlNode->node.table.Handle);
  4485. lpSqlNode->node.table.Handle = NULL;
  4486. }
  4487. FreeTreeSemantic(lpSql, lpSqlNode->node.table.OuterJoinPredicate);
  4488. break;
  4489. case NODE_TYPE_COLUMN:
  4490. break;
  4491. case NODE_TYPE_STRING:
  4492. break;
  4493. case NODE_TYPE_NUMERIC:
  4494. break;
  4495. case NODE_TYPE_PARAMETER:
  4496. break;
  4497. case NODE_TYPE_USER:
  4498. break;
  4499. case NODE_TYPE_NULL:
  4500. break;
  4501. case NODE_TYPE_DATE:
  4502. break;
  4503. case NODE_TYPE_TIME:
  4504. break;
  4505. case NODE_TYPE_TIMESTAMP:
  4506. break;
  4507. default:
  4508. break;
  4509. }
  4510. }
  4511. /***************************************************************************/