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

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          qresult.c
  2.  *
  3.  * Description:     This module contains functions related to 
  4.  *                  managing result information (i.e, fetching rows from the backend,
  5.  *                  managing the tuple cache, etc.) and retrieving it.
  6.  *                  Depending on the situation, a QResultClass will hold either data
  7.  *                  from the backend or a manually built result (see "qresult.h" to
  8.  *                  see which functions/macros are for manual or backend results.
  9.  *                  For manually built results, the QResultClass simply points to 
  10.  *                  TupleList and ColumnInfo structures, which actually hold the data.
  11.  *
  12.  * Classes:         QResultClass (Functions prefix: "QR_")
  13.  *
  14.  * API functions:   none
  15.  *
  16.  * Comments:        See "notice.txt" for copyright and license information.
  17.  *
  18.  */
  19. #include "qresult.h"
  20. #include "misc.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. #ifndef TRUE
  24. #define TRUE (BOOL)1
  25. #endif
  26. #ifndef FALSE
  27. #define FALSE (BOOL)0
  28. #endif
  29. extern GLOBAL_VALUES globals;
  30. /*  Used for building a Manual Result only */
  31. /* All info functions call this function to create the manual result set. */
  32. void 
  33. QR_set_num_fields(QResultClass *self, int new_num_fields)
  34. {
  35. mylog("in QR_set_num_fieldsn");
  36.     CI_set_num_fields(self->fields, new_num_fields);
  37.     if(self->manual_tuples) 
  38.         TL_Destructor(self->manual_tuples);
  39.     self->manual_tuples = TL_Constructor(new_num_fields);
  40. mylog("exit QR_set_num_fieldsn");
  41. }
  42. void 
  43. QR_set_position(QResultClass *self, int pos)
  44. {
  45. self->tupleField = self->backend_tuples + ((self->base + pos) * self->num_fields);
  46. }
  47. void
  48. QR_set_cache_size(QResultClass *self, int cache_size)
  49. {
  50. self->cache_size = cache_size;
  51. }
  52. void 
  53. QR_set_rowset_size(QResultClass *self, int rowset_size)
  54. {
  55. self->rowset_size = rowset_size;
  56. }
  57. void
  58. QR_inc_base(QResultClass *self, int base_inc)
  59. {
  60. self->base += base_inc;
  61. }
  62. /************************************/
  63. /* CLASS QResult                    */
  64. /************************************/
  65. QResultClass *
  66. QR_Constructor(void)
  67. {
  68. QResultClass *rv;
  69. mylog("in QR_Constructorn");
  70. rv = (QResultClass *) malloc(sizeof(QResultClass));
  71. if (rv != NULL) {
  72. rv->status = PGRES_EMPTY_QUERY;
  73. /* construct the column info */
  74. if ( ! (rv->fields = CI_Constructor())) {
  75. free(rv);
  76. return NULL;
  77. }
  78. rv->manual_tuples = NULL;
  79. rv->backend_tuples = NULL;
  80. rv->message = NULL;
  81. rv->command = NULL;
  82. rv->notice = NULL;
  83. rv->conn = NULL;
  84. rv->inTuples = FALSE;
  85. rv->fcount = 0;
  86. rv->fetch_count = 0;
  87. rv->base = 0;
  88. rv->currTuple = -1;
  89. rv->num_fields = 0;
  90. rv->tupleField = NULL;
  91. rv->cursor = NULL;
  92. rv->cache_size = globals.fetch_max;
  93. rv->rowset_size = 1;
  94. }
  95. mylog("exit QR_Constructorn");
  96. return rv;
  97. }
  98. void
  99. QR_Destructor(QResultClass *self)
  100. {
  101. mylog("QResult: in DESTRUCTORn");
  102. /* manual result set tuples */
  103. if (self->manual_tuples)
  104. TL_Destructor(self->manual_tuples);
  105. // If conn is defined, then we may have used "backend_tuples",
  106. // so in case we need to, free it up.  Also, close the cursor.
  107. if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
  108. QR_close(self); // close the cursor if there is one
  109. QR_free_memory(self); // safe to call anyway
  110. // Should have been freed in the close() but just in case...
  111. if (self->cursor)
  112. free(self->cursor);
  113. /* Free up column info */
  114. if (self->fields)
  115. CI_Destructor(self->fields);
  116. /* Free command info (this is from strdup()) */
  117. if (self->command)
  118. free(self->command);
  119. /* Free notice info (this is from strdup()) */
  120. if (self->notice)
  121. free(self->notice);
  122. free(self);
  123. mylog("QResult: exit DESTRUCTORn");
  124. }
  125. void
  126. QR_set_command(QResultClass *self, char *msg)
  127. {
  128. if (self->command)
  129. free(self->command);
  130. self->command = msg ? strdup(msg) : NULL;
  131. }
  132. void 
  133. QR_set_notice(QResultClass *self, char *msg)
  134. {
  135. if (self->notice)
  136. free(self->notice);
  137. self->notice = msg ? strdup(msg) : NULL;
  138. }
  139. void 
  140. QR_free_memory(QResultClass *self)
  141. {
  142. register int lf, row;
  143. register TupleField *tuple = self->backend_tuples;
  144. int fcount = self->fcount;
  145. int num_fields = self->num_fields;
  146. mylog("QResult: free memory in, fcount=%dn", fcount);
  147. if ( self->backend_tuples) {
  148. for (row = 0; row < fcount; row++) {
  149. mylog("row = %d, num_fields = %dn", row, num_fields);
  150. for (lf=0; lf < num_fields; lf++) {
  151. if (tuple[lf].value != NULL) {
  152. mylog("free [lf=%d] %un", lf, tuple[lf].value);
  153. free(tuple[lf].value);
  154. }
  155. }
  156. tuple += num_fields;  // next row
  157. }
  158. free(self->backend_tuples);
  159. self->backend_tuples = NULL;
  160. }
  161. self->fcount = 0;
  162. mylog("QResult: free memory outn");
  163. }
  164. // This function is called by send_query()
  165. char
  166. QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
  167. {
  168. int tuple_size;
  169. // If called from send_query the first time (conn != NULL), 
  170. // then set the inTuples state,
  171. // and read the tuples.  If conn is NULL,
  172. // it implies that we are being called from next_tuple(),
  173. // like to get more rows so don't call next_tuple again!
  174. if (conn != NULL) {
  175. self->conn = conn;
  176. mylog("QR_fetch_tuples: cursor = '%s', self->cursor=%un",  (cursor==NULL)?"":cursor, self->cursor);
  177. if (self->cursor)
  178. free(self->cursor);
  179. if ( globals.use_declarefetch) {
  180. if (! cursor || cursor[0] == '') {
  181. self->status = PGRES_INTERNAL_ERROR;
  182. QR_set_message(self, "Internal Error -- no cursor for fetch");
  183. return FALSE;
  184. }
  185. self->cursor = strdup(cursor);
  186. }
  187.  
  188. // Read the field attributes.
  189. // $$$$ Should do some error control HERE! $$$$
  190. if ( CI_read_fields(self->fields, self->conn)) {
  191. self->status = PGRES_FIELDS_OK;
  192. self->num_fields = CI_get_num_fields(self->fields);
  193. }
  194. else {
  195. self->status = PGRES_BAD_RESPONSE;
  196. QR_set_message(self, "Error reading field information");
  197. return FALSE;
  198. }
  199. mylog("QR_fetch_tuples: past CI_read_fields: num_fields = %dn", self->num_fields);
  200. if (globals.use_declarefetch) 
  201. tuple_size = self->cache_size;
  202. else
  203. tuple_size = TUPLE_MALLOC_INC;
  204. /* allocate memory for the tuple cache */
  205. mylog("MALLOC: tuple_size = %d, size = %dn", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
  206. self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
  207. if ( ! self->backend_tuples) {
  208. self->status = PGRES_FATAL_ERROR; 
  209. QR_set_message(self, "Could not get memory for tuple cache.");
  210. return FALSE;
  211. }
  212. self->inTuples = TRUE;
  213. /*  Force a read to occur in next_tuple */
  214. self->fcount = tuple_size+1;
  215. self->fetch_count = tuple_size+1;
  216. self->base = 0;
  217. return QR_next_tuple(self);
  218. }
  219. else {
  220. // Always have to read the field attributes.
  221. // But we dont have to reallocate memory for them!
  222. if ( ! CI_read_fields(NULL, self->conn)) {
  223. self->status = PGRES_BAD_RESPONSE;
  224. QR_set_message(self, "Error reading field information");
  225. return FALSE;
  226. }
  227. return TRUE;
  228. }
  229. }
  230. // Close the cursor and end the transaction (if no cursors left)
  231. // We only close cursor/end the transaction if a cursor was used.
  232. int
  233. QR_close(QResultClass *self)
  234. {
  235. QResultClass *res;
  236. if (globals.use_declarefetch && self->conn && self->cursor) {
  237. char buf[64];
  238. sprintf(buf, "close %s", self->cursor);
  239. mylog("QResult: closing cursor: '%s'n", buf);
  240. res = CC_send_query(self->conn, buf, NULL);
  241. self->inTuples = FALSE;
  242. self->currTuple = -1;
  243. free(self->cursor);
  244. self->cursor = NULL;
  245. if (res == NULL) {
  246. self->status = PGRES_FATAL_ERROR;
  247. QR_set_message(self, "Error closing cursor.");
  248. return FALSE;
  249. }
  250. /* End the transaction if there are no cursors left on this conn */
  251. if (CC_cursor_count(self->conn) == 0) {
  252. mylog("QResult: END transaction on conn=%un", self->conn);
  253. res = CC_send_query(self->conn, "END", NULL);
  254. CC_set_no_trans(self->conn);
  255. if (res == NULL) {
  256. self->status = PGRES_FATAL_ERROR;
  257. QR_set_message(self, "Error ending transaction.");
  258. return FALSE;
  259. }
  260. }
  261. }
  262. return TRUE;
  263. }
  264. // This function is called by fetch_tuples() AND SQLFetch()
  265. int
  266. QR_next_tuple(QResultClass *self)
  267. {
  268. int id;
  269. QResultClass *res;
  270. SocketClass *sock;
  271. /* Speed up access */
  272. int fetch_count = self->fetch_count;
  273. int fcount = self->fcount;
  274. int fetch_size, offset= 0;
  275. int end_tuple = self->rowset_size + self->base;
  276. char corrected = FALSE;
  277. TupleField *the_tuples = self->backend_tuples;
  278. static char msgbuffer[MAX_MESSAGE_LEN+1];
  279. char cmdbuffer[MAX_MESSAGE_LEN+1]; // QR_set_command() dups this string so dont need static
  280. char fetch[128];
  281. QueryInfo qi;
  282. if (fetch_count < fcount) { /* return a row from cache */
  283. mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %dn", fetch_count, fcount);
  284. self->tupleField = the_tuples + (fetch_count * self->num_fields); /* next row */
  285. self->fetch_count++;
  286. return TRUE;
  287. }
  288. else if (self->fcount < self->cache_size) {   /* last row from cache */
  289. // We are done because we didn't even get CACHE_SIZE tuples
  290.   mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %dn", fcount, fetch_count);
  291.   self->tupleField = NULL;
  292.   self->status = PGRES_END_TUPLES;
  293.   return -1; /* end of tuples */
  294. }
  295. else {
  296. /* See if we need to fetch another group of rows.
  297. We may be being called from send_query(), and
  298. if so, don't send another fetch, just fall through
  299. and read the tuples.
  300. */
  301. self->tupleField = NULL;
  302. if ( ! self->inTuples) {
  303. if ( ! globals.use_declarefetch) {
  304. mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %dn", fcount, fetch_count);
  305. self->tupleField = NULL;
  306. self->status = PGRES_END_TUPLES;
  307. return -1; /* end of tuples */
  308. }
  309. if (self->base == fcount) { /* not a correction */
  310. /* Determine the optimum cache size.  */
  311. if (globals.fetch_max % self->rowset_size == 0)
  312. fetch_size = globals.fetch_max;
  313. else if (self->rowset_size < globals.fetch_max)
  314. fetch_size = (globals.fetch_max / self->rowset_size) * self->rowset_size;
  315. else
  316. fetch_size = self->rowset_size;
  317. self->cache_size = fetch_size;
  318. self->fetch_count = 1;
  319. else { /* need to correct */
  320. corrected = TRUE;
  321. fetch_size = end_tuple - fcount;
  322. self->cache_size += fetch_size;
  323. offset = self->fetch_count;
  324. self->fetch_count++;
  325. }
  326. self->backend_tuples = (TupleField *) realloc(self->backend_tuples, self->num_fields * sizeof(TupleField) * self->cache_size);
  327. if ( ! self->backend_tuples) {
  328. self->status = PGRES_FATAL_ERROR; 
  329. QR_set_message(self, "Out of memory while reading tuples.");
  330. return FALSE;
  331. }
  332. sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
  333. mylog("next_tuple: sending actual fetch (%d) query '%s'n", fetch_size, fetch);
  334. // don't read ahead for the next tuple (self) !
  335. qi.row_size = self->cache_size;
  336. qi.result_in = self;
  337. qi.cursor = NULL;
  338. res = CC_send_query(self->conn, fetch, &qi);
  339. if (res == NULL) {
  340. self->status = PGRES_FATAL_ERROR;
  341. QR_set_message(self, "Error fetching next group.");
  342. return FALSE;
  343. }
  344. self->inTuples = TRUE;
  345. }
  346. else {
  347. mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %dn", self->fcount, self->fetch_count);
  348. /* This is a pre-fetch (fetching rows right after query
  349. but before any real SQLFetch() calls.  This is done
  350. so the field attributes are available.
  351. */
  352. self->fetch_count = 0;
  353. }
  354. }
  355. if ( ! corrected) {
  356. self->base = 0;
  357. self->fcount = 0;
  358. }
  359. sock = CC_get_socket(self->conn);
  360. self->tupleField = NULL;
  361. for ( ; ;) {
  362. id = SOCK_get_char(sock);
  363. switch (id) {
  364. case 'T': /* Tuples within tuples cannot be handled */
  365. self->status = PGRES_BAD_RESPONSE;
  366. QR_set_message(self, "Tuples within tuples cannot be handled");
  367. return FALSE;
  368. case 'B': /* Tuples in binary format */
  369. case 'D': /* Tuples in ASCII format  */
  370. if ( ! globals.use_declarefetch && self->fcount > 0 && ! (self->fcount % TUPLE_MALLOC_INC)) {
  371. size_t old_size = self->fcount * self->num_fields * sizeof(TupleField);
  372. mylog("REALLOC: old_size = %dn", old_size);
  373. self->backend_tuples = (TupleField *) realloc(self->backend_tuples, old_size + (self->num_fields * sizeof(TupleField) * TUPLE_MALLOC_INC));
  374. if ( ! self->backend_tuples) {
  375. self->status = PGRES_FATAL_ERROR; 
  376. QR_set_message(self, "Out of memory while reading tuples.");
  377. return FALSE;
  378. }
  379. }
  380. if ( ! QR_read_tuple(self, (char) (id == 0))) {
  381. self->status = PGRES_BAD_RESPONSE;
  382. QR_set_message(self, "Error reading the tuple");
  383. return FALSE;
  384. }
  385. self->fcount++;
  386. break; // continue reading
  387. case 'C': /* End of tuple list */
  388. SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
  389. QR_set_command(self, cmdbuffer);
  390. mylog("end of tuple list -- setting inUse to false: this = %un", self);
  391. self->inTuples = FALSE;
  392. if (self->fcount > 0) {
  393. qlog("    [ fetched %d rows ]n", self->fcount);
  394. mylog("_next_tuple: 'C' fetch_max && fcount = %dn", self->fcount);
  395. /*  set to first row */
  396. self->tupleField = self->backend_tuples + (offset * self->num_fields);
  397. return TRUE;
  398. else { // We are surely done here (we read 0 tuples)
  399. qlog("    [ fetched 0 rows ]n");
  400. mylog("_next_tuple: 'C': DONE (fcount == 0)n");
  401. return -1; /* end of tuples */
  402. }
  403. case 'E': /* Error */
  404. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  405. QR_set_message(self, msgbuffer);
  406. self->status = PGRES_FATAL_ERROR;
  407. if ( ! strncmp(msgbuffer, "FATAL", 5))
  408. CC_set_no_trans(self->conn);
  409. qlog("ERROR from backend in next_tuple: '%s'n", msgbuffer);
  410. return FALSE;
  411. case 'N': /* Notice */
  412. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  413. QR_set_message(self, msgbuffer);
  414. self->status = PGRES_NONFATAL_ERROR;
  415. qlog("NOTICE from backend in next_tuple: '%s'n", msgbuffer);
  416. continue;
  417. default: /* this should only happen if the backend dumped core */
  418. mylog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)n", id, id);
  419. qlog("QR_next_tuple: Unexpected result from backend: id = '%c' (%d)n", id, id);
  420. QR_set_message(self, "Unexpected result from backend. It probably crashed");
  421. self->status = PGRES_FATAL_ERROR;
  422. CC_set_no_trans(self->conn);
  423. return FALSE;
  424. }
  425. }
  426. return TRUE;
  427. }
  428. char
  429. QR_read_tuple(QResultClass *self, char binary)
  430. {
  431. Int2 field_lf;
  432. TupleField *this_tuplefield;
  433. char bmp, bitmap[MAX_FIELDS];        /* Max. len of the bitmap */
  434. Int2 bitmaplen;                       /* len of the bitmap in bytes */
  435. Int2 bitmap_pos;
  436. Int2 bitcnt;
  437. Int4 len;
  438. char *buffer;
  439. int num_fields = self->num_fields; // speed up access
  440. SocketClass *sock = CC_get_socket(self->conn);
  441. ColumnInfoClass *flds;
  442. /* set the current row to read the fields into */
  443. this_tuplefield = self->backend_tuples + (self->fcount * num_fields);
  444. bitmaplen = (Int2) num_fields / BYTELEN;
  445. if ((num_fields % BYTELEN) > 0)
  446. bitmaplen++;
  447. /*
  448. At first the server sends a bitmap that indicates which
  449. database fields are null
  450. */
  451. SOCK_get_n_char(sock, bitmap, bitmaplen);
  452. bitmap_pos = 0;
  453. bitcnt = 0;
  454. bmp = bitmap[bitmap_pos];
  455. for(field_lf = 0; field_lf < num_fields; field_lf++) {
  456. /* Check if the current field is NULL */
  457. if(!(bmp & 0200)) {
  458. /* YES, it is NULL ! */
  459. this_tuplefield[field_lf].len = 0;
  460. this_tuplefield[field_lf].value = 0;
  461. } else {
  462. /*
  463. NO, the field is not null. so get at first the
  464. length of the field (four bytes)
  465. */
  466. len = SOCK_get_int(sock, VARHDRSZ);
  467. if (!binary)
  468. len -= VARHDRSZ;
  469. buffer = (char *)malloc(len+1);
  470. SOCK_get_n_char(sock, buffer, len);
  471. buffer[len] = '';
  472. mylog("qresult: len=%d, buffer='%s'n", len, buffer);
  473. this_tuplefield[field_lf].len = len;
  474. this_tuplefield[field_lf].value = buffer;
  475. /* This can be used to set the longest length of the column for any
  476. row in the tuple cache.  It would not be accurate for varchar and
  477. text fields to use this since a tuple cache is only 100 rows.
  478. Bpchar can be handled since the strlen of all rows is fixed,
  479. assuming there are not 100 nulls in a row!
  480. */
  481. flds = self->fields;
  482. if (flds->display_size[field_lf] < len)
  483. flds->display_size[field_lf] = len;
  484. }
  485. /*
  486. Now adjust for the next bit to be scanned in the
  487. next loop.
  488. */
  489. bitcnt++;
  490. if (BYTELEN == bitcnt) {
  491. bitmap_pos++;
  492. bmp = bitmap[bitmap_pos];
  493. bitcnt = 0;
  494. } else
  495. bmp <<= 1;
  496. }
  497. self->currTuple++;
  498. return TRUE;
  499. }