parse.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:19k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          parse.c
  2.  *
  3.  * Description:     This module contains routines related to parsing SQL statements.
  4.  *                  This can be useful for two reasons:
  5.  *
  6.  *                  1. So the query does not actually have to be executed to return data about it
  7.  *
  8.  *                  2. To be able to return information about precision, nullability, aliases, etc.
  9.  *                     in the functions SQLDescribeCol and SQLColAttributes.  Currently, Postgres
  10.  *                     doesn't return any information about these things in a query.
  11.  *
  12.  * Classes:         none
  13.  *
  14.  * API functions:   none
  15.  *
  16.  * Comments:        See "notice.txt" for copyright and license information.
  17.  *
  18.  */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include "statement.h"
  23. #include "connection.h"
  24. #include "qresult.h"
  25. #include "pgtypes.h"
  26. #ifndef WIN32
  27. #ifndef HAVE_STRICMP
  28. #define stricmp(s1,s2)  strcasecmp(s1,s2)
  29. #define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
  30. #endif
  31. #endif
  32. #define FLD_INCR 32
  33. #define TAB_INCR 8
  34. #define COL_INCR 16
  35. char *getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
  36. void getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
  37. char searchColInfo(COL_INFO *col_info, FIELD_INFO *fi);
  38. char *
  39. getNextToken(char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric)
  40. {
  41. int i = 0;
  42. int out = 0;
  43. char qc, in_escape = FALSE;
  44. if (smax <= 1)
  45. return NULL;
  46. smax--;
  47. /* skip leading delimiters */
  48. while (isspace(s[i]) || s[i] == ',') {
  49. // mylog("skipping '%c'n", s[i]);
  50. i++;
  51. }
  52. if (s[0] == '') {
  53. token[0] = '';
  54. return NULL;
  55. }
  56. if (quote) *quote = FALSE;
  57. if (dquote) *dquote = FALSE;
  58. if (numeric) *numeric = FALSE;
  59. /* get the next token */
  60. while ( ! isspace(s[i]) && s[i] != ',' && s[i] != '' && out != smax) {
  61. /* Handle quoted stuff */
  62. if ( out == 0 && (s[i] == '"' || s[i] == ''')) {
  63. qc = s[i];
  64. if (qc == '"') {
  65. if (dquote) *dquote = TRUE;
  66. }
  67. if (qc == ''') {
  68. if (quote) *quote = TRUE;
  69. }
  70. i++; /* dont return the quote */
  71. while (s[i] != '' && out != smax) {  
  72. if (s[i] == qc && ! in_escape) {
  73. break;
  74. }
  75. if (s[i] == '\' && ! in_escape) {
  76. in_escape = TRUE;
  77. }
  78. else {
  79. in_escape = FALSE;
  80. token[out++] = s[i];
  81. }
  82. i++;
  83. }
  84. if (s[i] == qc)
  85. i++;
  86. break;
  87. }
  88. /* Check for numeric literals */
  89. if ( out == 0 && isdigit(s[i])) {
  90. if (numeric) *numeric = TRUE;
  91. token[out++] = s[i++];
  92. while ( isalnum(s[i]) || s[i] == '.')
  93. token[out++] = s[i++];
  94. break;
  95. }
  96. if ( ispunct(s[i]) && s[i] != '_') {
  97. mylog("got ispunct: s[%d] = '%c'n", i, s[i]);
  98. if (out == 0) {
  99. token[out++] = s[i++];
  100. break;
  101. }
  102. else
  103. break;
  104. }
  105. if (out != smax)
  106. token[out++] = s[i];
  107. i++;
  108. }
  109. // mylog("done -- s[%d] = '%c'n", i, s[i]);
  110. token[out] = '';
  111. /* find the delimiter  */
  112. while ( isspace(s[i]))
  113. i++;
  114. /* return the most priority delimiter */
  115. if (s[i] == ',')  {
  116. if (delim) *delim = s[i];
  117. }
  118. else if (s[i] == '') {
  119. if (delim) *delim = '';
  120. }
  121. else  {
  122. if (delim) *delim = ' ';
  123. }
  124. /* skip trailing blanks  */
  125. while ( isspace(s[i])) {
  126. i++;
  127. }
  128. return &s[i];
  129. }
  130. /*
  131. QR_set_num_fields(stmt->result, 14);
  132. QR_set_field_info(stmt->result, 0, "TABLE_QUALIFIER", PG_TYPE_TEXT, MAX_INFO_STRING);
  133. QR_set_field_info(stmt->result, 1, "TABLE_OWNER", PG_TYPE_TEXT, MAX_INFO_STRING);
  134. QR_set_field_info(stmt->result, 2, "TABLE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
  135. QR_set_field_info(stmt->result, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
  136. QR_set_field_info(stmt->result, 4, "DATA_TYPE", PG_TYPE_INT2, 2);
  137. QR_set_field_info(stmt->result, 5, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
  138. QR_set_field_info(stmt->result, 6, "PRECISION", PG_TYPE_INT4, 4);
  139. QR_set_field_info(stmt->result, 7, "LENGTH", PG_TYPE_INT4, 4);
  140. QR_set_field_info(stmt->result, 8, "SCALE", PG_TYPE_INT2, 2);
  141. QR_set_field_info(stmt->result, 9, "RADIX", PG_TYPE_INT2, 2);
  142. QR_set_field_info(stmt->result, 10, "NULLABLE", PG_TYPE_INT2, 2);
  143. QR_set_field_info(stmt->result, 11, "REMARKS", PG_TYPE_TEXT, 254);
  144. // User defined fields
  145. QR_set_field_info(stmt->result, 12, "DISPLAY_SIZE", PG_TYPE_INT4, 4);
  146. QR_set_field_info(stmt->result, 13, "FIELD_TYPE", PG_TYPE_INT4, 4);
  147. */
  148. void
  149. getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k)
  150. {
  151. if (fi->name[0] == '')
  152. strcpy(fi->name, QR_get_value_manual(col_info->result, k, 3));
  153. fi->type = atoi( QR_get_value_manual(col_info->result, k, 13));
  154. fi->precision = atoi( QR_get_value_manual(col_info->result, k, 6));
  155. fi->length = atoi( QR_get_value_manual(col_info->result, k, 7));
  156. fi->nullable = atoi( QR_get_value_manual(col_info->result, k, 10));
  157. fi->display_size = atoi( QR_get_value_manual(col_info->result, k, 12));
  158. }
  159. char
  160. searchColInfo(COL_INFO *col_info, FIELD_INFO *fi)
  161. {
  162. int k;
  163. char *col;
  164. for (k = 0; k < QR_get_num_tuples(col_info->result); k++) {
  165. col = QR_get_value_manual(col_info->result, k, 3);
  166. if ( ! strcmp(col, fi->name)) {
  167. getColInfo(col_info, fi, k);
  168. mylog("PARSE: searchColInfo: n");
  169. return TRUE;
  170. }
  171. }
  172. return FALSE;
  173. }
  174. char
  175. parse_statement(StatementClass *stmt)
  176. {
  177. static char *func="parse_statement";
  178. char token[256];
  179. char delim, quote, dquote, numeric, unquoted;
  180. char *ptr;
  181. char in_select = FALSE, in_distinct = FALSE, in_on = FALSE, in_from = FALSE, in_where = FALSE, in_table = FALSE;
  182. char in_field = FALSE, in_expr = FALSE, in_func = FALSE, in_dot = FALSE, in_as = FALSE;
  183. int j, i, k = 0, n, blevel = 0;
  184. FIELD_INFO **fi;
  185. TABLE_INFO **ti;
  186. char parse;
  187. ConnectionClass *conn = stmt->hdbc;
  188. HSTMT hcol_stmt;
  189. StatementClass *col_stmt;
  190. RETCODE result;
  191. mylog("%s: entering...n", func);
  192. ptr = stmt->statement;
  193. fi = stmt->fi;
  194. ti = stmt->ti;
  195. stmt->nfld = 0;
  196. stmt->ntab = 0;
  197. while ((ptr = getNextToken(ptr, token, sizeof(token), &delim, &quote, &dquote, &numeric)) != NULL) {
  198. unquoted = ! ( quote || dquote );
  199. mylog("unquoted=%d, quote=%d, dquote=%d, numeric=%d, delim='%c', token='%s', ptr='%s'n", unquoted, quote, dquote, numeric, delim, token, ptr);
  200. if ( unquoted && ! stricmp(token, "select")) {
  201. in_select = TRUE;
  202. mylog("SELECTn");
  203. continue;
  204. }
  205. if ( unquoted && in_select && ! stricmp(token, "distinct")) {
  206. in_distinct = TRUE;
  207. mylog("DISTINCTn");
  208. continue;
  209. }
  210. if ( unquoted && ! stricmp(token, "into")) {
  211. in_select = FALSE;
  212. mylog("INTOn");
  213. continue;
  214. }
  215. if ( unquoted && ! stricmp(token, "from")) {
  216. in_select = FALSE;
  217. in_from = TRUE;
  218. mylog("FROMn");
  219. continue;
  220. }
  221. if ( unquoted && (! stricmp(token, "where") ||
  222. ! stricmp(token, "union") || 
  223. ! stricmp(token, "order") || 
  224. ! stricmp(token, "group") || 
  225. ! stricmp(token, "having"))) {
  226. in_select = FALSE;
  227. in_from = FALSE;
  228. in_where = TRUE;
  229. mylog("WHERE...n");
  230. break;
  231. }
  232. if (in_select) {
  233. if ( in_distinct) {
  234. mylog("in distinctn");
  235. if (unquoted && ! stricmp(token, "on")) {
  236. in_on = TRUE;
  237. mylog("got onn");
  238. continue;
  239. }
  240. if (in_on) {
  241. in_distinct = FALSE;
  242. in_on = FALSE;
  243. continue; /* just skip the unique on field */
  244. }
  245. mylog("done distinctn");
  246. in_distinct = FALSE;
  247. }
  248. if ( in_expr || in_func) { /* just eat the expression */
  249. mylog("in_expr=%d or func=%dn", in_expr, in_func);
  250. if (quote || dquote)
  251. continue;
  252. if (in_expr && blevel == 0 && delim == ',') {
  253. mylog("**** in_expr and Got comman");
  254. in_expr = FALSE;
  255. in_field = FALSE;
  256. }
  257. else if (token[0] == '(') {
  258. blevel++;
  259. mylog("blevel++ = %dn", blevel);
  260. }
  261. else if (token[0] == ')') {
  262. blevel--;
  263. mylog("blevel-- = %dn", blevel);
  264. if (delim==',') {
  265. in_func = FALSE;
  266. in_expr = FALSE;
  267. in_field = FALSE;
  268. }
  269. }
  270. continue;
  271. }
  272. if ( ! in_field) {
  273. if ( ! token[0])
  274. continue;
  275. if ( ! (stmt->nfld % FLD_INCR)) {
  276. mylog("reallocing at nfld=%dn", stmt->nfld);
  277. fi = (FIELD_INFO **) realloc(fi, (stmt->nfld + FLD_INCR) * sizeof(FIELD_INFO *));
  278. if ( ! fi) {
  279. stmt->parse_status = STMT_PARSE_FATAL;
  280. return FALSE;
  281. }
  282. stmt->fi = fi;
  283. }
  284. fi[stmt->nfld] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
  285. if (fi[stmt->nfld] == NULL) {
  286. stmt->parse_status = STMT_PARSE_FATAL;
  287. return FALSE;
  288. }
  289. /* Initialize the field info */
  290. memset(fi[stmt->nfld], 0, sizeof(FIELD_INFO));
  291. /* double quotes are for qualifiers */
  292. if (dquote)
  293. fi[stmt->nfld]->dquote = TRUE;
  294. if (quote) {
  295. fi[stmt->nfld++]->quote = TRUE;
  296. continue;
  297. }
  298. else if (numeric) {
  299. mylog("**** got numeric: nfld = %dn", stmt->nfld);
  300. fi[stmt->nfld]->numeric = TRUE;
  301. }
  302. else if (token[0] == '(') { /* expression */
  303. mylog("got EXPRESSIONn");
  304. fi[stmt->nfld++]->expr = TRUE;
  305. in_expr = TRUE;
  306. blevel = 1;
  307. continue;
  308. }
  309. else {
  310. strcpy(fi[stmt->nfld]->name, token);
  311. fi[stmt->nfld]->dot[0] = '';
  312. }
  313. mylog("got field='%s', dot='%s'n", fi[stmt->nfld]->name, fi[stmt->nfld]->dot);
  314. if (delim == ',') {
  315. mylog("comma (1)n");
  316. }
  317. else {
  318. in_field = TRUE;
  319. }
  320. stmt->nfld++;
  321. continue;
  322. }
  323. /**************************/
  324. /* We are in a field now */
  325. /**************************/
  326. if (in_dot) {
  327. stmt->nfld--;
  328. strcpy(fi[stmt->nfld]->dot, fi[stmt->nfld]->name);
  329. strcpy(fi[stmt->nfld]->name, token);
  330. stmt->nfld++;
  331. in_dot = FALSE;
  332. if (delim == ',') {
  333. mylog("in_dot: got comman");
  334. in_field = FALSE;
  335. }
  336. continue;
  337. }
  338. if (in_as) {
  339. stmt->nfld--;
  340. strcpy(fi[stmt->nfld]->alias, token);
  341. mylog("alias for field '%s' is '%s'n", fi[stmt->nfld]->name, fi[stmt->nfld]->alias);
  342. in_as = FALSE;
  343. in_field = FALSE;
  344. stmt->nfld++;
  345. if (delim == ',') {
  346. mylog("comma(2)n");
  347. }
  348. continue;
  349. }
  350. /* Function */
  351. if (token[0] == '(') {
  352. in_func = TRUE;
  353. blevel = 1;
  354. fi[stmt->nfld-1]->func = TRUE;
  355. /* name will have the function name -- maybe useful some day */
  356. mylog("**** got function = '%s'n", fi[stmt->nfld-1]->name);
  357. continue;
  358. }
  359. if (token[0] == '.') {
  360. in_dot = TRUE;
  361. mylog("got dotn");
  362. continue;
  363. }
  364. if ( ! stricmp(token, "as")) {
  365. in_as = TRUE;
  366. mylog("got ASn");
  367. continue;
  368. }
  369. /* otherwise, its probably an expression */
  370. in_expr = TRUE;
  371. fi[stmt->nfld-1]->expr = TRUE;
  372. fi[stmt->nfld-1]->name[0] = '';
  373. mylog("*** setting expressionn");
  374. }
  375. if (in_from) {
  376. if ( ! in_table) {
  377. if ( ! token[0])
  378. continue;
  379. if ( ! (stmt->ntab % TAB_INCR)) {
  380. ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
  381. if ( ! ti) {
  382. stmt->parse_status = STMT_PARSE_FATAL;
  383. return FALSE;
  384. }
  385. stmt->ti = ti;
  386. }
  387. ti[stmt->ntab] = (TABLE_INFO *) malloc(sizeof(TABLE_INFO));
  388. if (ti[stmt->ntab] == NULL) {
  389. stmt->parse_status = STMT_PARSE_FATAL;
  390. return FALSE;
  391. }
  392. ti[stmt->ntab]->alias[0] = '';
  393. strcpy(ti[stmt->ntab]->name, token);
  394. mylog("got table = '%s'n", ti[stmt->ntab]->name);
  395. if (delim == ',') {
  396. mylog("more than 1 tablesn");
  397. }
  398. else {
  399. in_table = TRUE;
  400. }
  401. stmt->ntab++;
  402. continue;
  403. }
  404. strcpy(ti[stmt->ntab-1]->alias, token);
  405. mylog("alias for table '%s' is '%s'n", ti[stmt->ntab-1]->name, ti[stmt->ntab-1]->alias);
  406. in_table = FALSE;
  407. if (delim == ',') {
  408. mylog("more than 1 tablesn");
  409. }
  410. }
  411. }
  412. /*************************************************/
  413. /* Resolve any possible field names with tables */
  414. /*************************************************/
  415. parse = TRUE;
  416. /* Resolve field names with tables */
  417. for (i = 0; i < stmt->nfld; i++) {
  418. if (fi[i]->func || fi[i]->expr || fi[i]->numeric) {
  419. fi[i]->ti = NULL;
  420. fi[i]->type = -1;
  421. parse = FALSE;
  422. continue;
  423. }
  424. else if (fi[i]->quote) { /* handle as text */
  425. fi[i]->ti = NULL;
  426. fi[i]->type = PG_TYPE_TEXT;
  427. fi[i]->precision = 0;
  428. continue;
  429. /* its a dot, resolve to table or alias */
  430. else if (fi[i]->dot[0]) {
  431. for (k = 0; k < stmt->ntab; k++) {
  432. if ( ! stricmp(ti[k]->name, fi[i]->dot)) {
  433. fi[i]->ti = ti[k];
  434. break;
  435. }
  436. else if ( ! stricmp(ti[k]->alias, fi[i]->dot)) {
  437. fi[i]->ti = ti[k];
  438. break;
  439. }
  440. }
  441. }
  442. else if (stmt->ntab == 1)
  443. fi[i]->ti = ti[0];
  444. }
  445. mylog("--------------------------------------------n");
  446. mylog("nfld=%d, ntab=%dn", stmt->nfld, stmt->ntab);
  447. for (i=0; i < stmt->nfld; i++) {
  448. mylog("Field %d:  expr=%d, func=%d, quote=%d, dquote=%d, numeric=%d, name='%s', alias='%s', dot='%s'n", i, fi[i]->expr, fi[i]->func, fi[i]->quote, fi[i]->dquote, fi[i]->numeric, fi[i]->name, fi[i]->alias, fi[i]->dot);
  449. if (fi[i]->ti)
  450. mylog("     ----> table_name='%s', table_alias='%s'n", fi[i]->ti->name, fi[i]->ti->alias);
  451. }
  452. for (i=0; i < stmt->ntab; i++) {
  453. mylog("Table %d: name='%s', alias='%s'n", i, ti[i]->name, ti[i]->alias);
  454. }
  455. /******************************************************/
  456. /* Now save the SQLColumns Info for the parse tables */
  457. /******************************************************/
  458. /* Call SQLColumns for each table and store the result */
  459. for (i = 0; i < stmt->ntab; i++) {
  460. /* See if already got it */
  461. char found = FALSE;
  462. for (k = 0; k < conn->ntables; k++) {
  463. if ( ! stricmp(conn->col_info[k]->name, ti[i]->name)) {
  464. mylog("FOUND col_info table='%s'n", ti[i]->name);
  465. found = TRUE;
  466. break;
  467. }
  468. }
  469. if ( ! found) {
  470. mylog("PARSE: Getting SQLColumns for table[%d]='%s'n", i, ti[i]->name);
  471. result = SQLAllocStmt( stmt->hdbc, &hcol_stmt);
  472. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  473. stmt->errormsg = "SQLAllocStmt failed in parse_statement for columns.";
  474. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  475. stmt->parse_status = STMT_PARSE_FATAL;
  476. return FALSE;
  477. }
  478. col_stmt = (StatementClass *) hcol_stmt;
  479. col_stmt->internal = TRUE;
  480. result = SQLColumns(hcol_stmt, "", 0, "", 0, 
  481. ti[i]->name, (SWORD) strlen(ti[i]->name), "", 0);
  482. mylog("        Past SQLColumnsn");
  483. if (result == SQL_SUCCESS) {
  484. mylog("      Successn");
  485. if ( ! (conn->ntables % COL_INCR)) {
  486. mylog("PARSE: Allocing col_info at ntables=%dn", conn->ntables);
  487. conn->col_info = (COL_INFO **) realloc(conn->col_info, (conn->ntables + COL_INCR) * sizeof(COL_INFO *));
  488. if ( ! conn->col_info) {
  489. stmt->parse_status = STMT_PARSE_FATAL;
  490. return FALSE;
  491. }
  492. }
  493. mylog("PARSE: malloc at conn->col_info[%d]n", conn->ntables);
  494. conn->col_info[conn->ntables] = (COL_INFO *) malloc(sizeof(COL_INFO));
  495. if ( ! conn->col_info[conn->ntables]) {
  496. stmt->parse_status = STMT_PARSE_FATAL;
  497. return FALSE;
  498. }
  499. /* Store the table name and the SQLColumns result structure */
  500. strcpy(conn->col_info[conn->ntables]->name, ti[i]->name);
  501. conn->col_info[conn->ntables]->result = col_stmt->result;
  502. /* The connection will now free the result structures, so make
  503. sure that the statement doesn't free it 
  504. */
  505. col_stmt->result = NULL;
  506. conn->ntables++;
  507. SQLFreeStmt(hcol_stmt, SQL_DROP);
  508. mylog("Created col_info table='%s', ntables=%dn", ti[i]->name, conn->ntables);
  509. }
  510. else {
  511. SQLFreeStmt(hcol_stmt, SQL_DROP);
  512. break;
  513. }
  514. }
  515. /* Associate a table from the statement with a SQLColumn info */
  516. ti[i]->col_info = conn->col_info[k];
  517. mylog("associate col_info: i=%d, k=%dn", i, k);
  518. }
  519. mylog("Done SQLColumnsn");
  520. /******************************************************/
  521. /* Now resolve the fields to point to column info    */
  522. /******************************************************/
  523. for (i = 0; i < stmt->nfld;) {
  524. /* Dont worry about functions or quotes */
  525. if (fi[i]->func || fi[i]->quote || fi[i]->numeric) {
  526. i++;
  527. continue;
  528. }
  529. /* Stars get expanded to all fields in the table */
  530. else if (fi[i]->name[0] == '*') {
  531. char do_all_tables;
  532. int total_cols, old_size, need, cols;
  533. mylog("expanding field %dn", i);
  534. total_cols = 0;
  535. if (fi[i]->ti) /* The star represents only the qualified table */
  536. total_cols = QR_get_num_tuples(fi[i]->ti->col_info->result);
  537. else { /* The star represents all tables */
  538. /* Calculate the total number of columns after expansion */
  539. for (k = 0; k < stmt->ntab; k++) {
  540. total_cols += QR_get_num_tuples(ti[k]->col_info->result);
  541. }
  542. }
  543. total_cols--; /* makes up for the star  */
  544. /* Allocate some more field pointers if necessary */
  545. //-------------------------------------------------------------
  546. old_size = (stmt->nfld / FLD_INCR * FLD_INCR + FLD_INCR);
  547. need = total_cols - (old_size - stmt->nfld);
  548. mylog("k=%d, total_cols=%d, old_size=%d, need=%dn", k,total_cols,old_size,need);
  549. if (need > 0) {
  550. int new_size = need / FLD_INCR * FLD_INCR + FLD_INCR;
  551. mylog("need more cols: new_size = %dn", new_size);
  552. fi = (FIELD_INFO **) realloc(fi, (old_size + new_size) * sizeof(FIELD_INFO *));
  553. if ( ! fi) {
  554. stmt->parse_status = STMT_PARSE_FATAL;
  555. return FALSE;
  556. }
  557. }
  558. //-------------------------------------------------------------
  559. // copy any other fields (if there are any) up past the expansion
  560. for (j = stmt->nfld - 1; j > i; j--) {
  561. mylog("copying field %d to %dn", j, total_cols + j);
  562. fi[total_cols + j] = fi[j];
  563. }
  564. mylog("done copying fieldsn");
  565. //-------------------------------------------------------------
  566. // Set the new number of fields
  567. stmt->nfld += total_cols;
  568. mylog("stmt->nfld now at %dn", stmt->nfld);
  569. //-------------------------------------------------------------
  570. // copy the new field info
  571. do_all_tables = (fi[i]->ti ? FALSE : TRUE);
  572. for (k = 0; k < (do_all_tables ? stmt->ntab : 1); k++) {
  573. TABLE_INFO *the_ti = do_all_tables ? ti[k] : fi[i]->ti;
  574. cols = QR_get_num_tuples(the_ti->col_info->result);
  575. for (n = 0; n < cols; n++) {
  576. mylog("creating field info: n=%dn", n);
  577. // skip malloc (already did it for the Star)
  578. if (k > 0 || n > 0) {
  579. mylog("allocating field info at %dn", n + i);
  580. fi[n + i] = (FIELD_INFO *) malloc( sizeof(FIELD_INFO));
  581. if (fi[n + i] == NULL) {
  582. stmt->parse_status = STMT_PARSE_FATAL;
  583. return FALSE;
  584. }
  585. }
  586. /* Initialize the new space (or the * field) */
  587. memset(fi[n + i], 0, sizeof(FIELD_INFO));
  588. fi[n + i]->ti = the_ti;
  589. mylog("about to copy at %dn", n + i);
  590. getColInfo(the_ti->col_info, fi[n + i], n);
  591. mylog("done copyingn");
  592. }
  593. i += cols;
  594. mylog("i now at %dn", i);
  595. }
  596. //-------------------------------------------------------------
  597. }
  598. /* We either know which table the field was in because it was qualified 
  599. with a table name or alias -OR- there was only 1 table.
  600. */
  601. else if (fi[i]->ti) {
  602. if ( ! searchColInfo(fi[i]->ti->col_info, fi[i]))
  603. parse = FALSE;
  604. i++;
  605. }
  606. /* Don't know the table -- search all tables in "from" list */
  607. else {
  608. parse = FALSE;
  609. for (k = 0; k < stmt->ntab; k++) {
  610. if ( searchColInfo(ti[k]->col_info, fi[i])) {
  611. fi[i]->ti = ti[k]; /* now know the table */
  612. parse = TRUE;
  613. break;
  614. }
  615. }
  616. i++;
  617. }
  618. }
  619. if ( ! parse)
  620. stmt->parse_status = STMT_PARSE_INCOMPLETE;
  621. else
  622. stmt->parse_status = STMT_PARSE_COMPLETE;
  623. mylog("done parse_statement: parse=%d, parse_status=%dn", parse, stmt->parse_status);
  624. return parse;
  625. }