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

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          connection.c
  2.  *
  3.  * Description:     This module contains routines related to 
  4.  *                  connecting to and disconnecting from the Postgres DBMS.
  5.  *
  6.  * Classes:         ConnectionClass (Functions prefix: "CC_")
  7.  *
  8.  * API functions:   SQLAllocConnect, SQLConnect, SQLDisconnect, SQLFreeConnect,
  9.  *                  SQLBrowseConnect(NI)
  10.  *
  11.  * Comments:        See "notice.txt" for copyright and license information.
  12.  *
  13.  */
  14. #include "environ.h"
  15. #include "connection.h"
  16. #include "socket.h"
  17. #include "statement.h"
  18. #include "qresult.h"
  19. #include "lobj.h"
  20. #include "dlg_specific.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. #ifdef WIN32
  24. #include <odbcinst.h>
  25. #endif
  26. #define STMT_INCREMENT 16  /* how many statement holders to allocate at a time */
  27. extern GLOBAL_VALUES globals;
  28. RETCODE SQL_API SQLAllocConnect(
  29.                                 HENV     henv,
  30.                                 HDBC FAR *phdbc)
  31. {
  32. EnvironmentClass *env = (EnvironmentClass *)henv;
  33. ConnectionClass *conn;
  34. static char *func="SQLAllocConnect";
  35. mylog( "%s: entering...n", func);
  36. conn = CC_Constructor();
  37. mylog("**** %s: henv = %u, conn = %un", func, henv, conn);
  38.     if( ! conn) {
  39.         env->errormsg = "Couldn't allocate memory for Connection object.";
  40.         env->errornumber = ENV_ALLOC_ERROR;
  41. *phdbc = SQL_NULL_HDBC;
  42. EN_log_error(func, "", env);
  43.         return SQL_ERROR;
  44.     }
  45.     if ( ! EN_add_connection(env, conn)) {
  46.         env->errormsg = "Maximum number of connections exceeded.";
  47.         env->errornumber = ENV_ALLOC_ERROR;
  48.         CC_Destructor(conn);
  49. *phdbc = SQL_NULL_HDBC;
  50. EN_log_error(func, "", env);
  51.         return SQL_ERROR;
  52.     }
  53. *phdbc = (HDBC) conn;
  54.     return SQL_SUCCESS;
  55. }
  56. //      -       -       -       -       -       -       -       -       -
  57. RETCODE SQL_API SQLConnect(
  58.                            HDBC      hdbc,
  59.                            UCHAR FAR *szDSN,
  60.                            SWORD     cbDSN,
  61.                            UCHAR FAR *szUID,
  62.                            SWORD     cbUID,
  63.                            UCHAR FAR *szAuthStr,
  64.                            SWORD     cbAuthStr)
  65. {
  66. ConnectionClass *conn = (ConnectionClass *) hdbc;
  67. ConnInfo *ci;
  68. static char *func = "SQLConnect";
  69. mylog( "%s: entering...n", func);
  70. if ( ! conn) {
  71. CC_log_error(func, "", NULL);
  72. return SQL_INVALID_HANDLE;
  73. }
  74. ci = &conn->connInfo;
  75. make_string(szDSN, cbDSN, ci->dsn);
  76. /* get the values for the DSN from the registry */
  77. getDSNinfo(ci, CONN_OVERWRITE);
  78. /* override values from DSN info with UID and authStr(pwd) 
  79. This only occurs if the values are actually there.
  80. */
  81. make_string(szUID, cbUID, ci->username);
  82. make_string(szAuthStr, cbAuthStr, ci->password);
  83. /* fill in any defaults */
  84. getDSNdefaults(ci);
  85. qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')n", conn, func, ci->dsn, ci->username, ci->password);
  86. if ( CC_connect(conn, FALSE) <= 0) {
  87. // Error messages are filled in
  88. CC_log_error(func, "Error on CC_connect", conn);
  89. return SQL_ERROR;
  90. }
  91. mylog( "%s: returning...n", func);
  92. return SQL_SUCCESS;
  93. }
  94. //      -       -       -       -       -       -       -       -       -
  95. RETCODE SQL_API SQLBrowseConnect(
  96.         HDBC      hdbc,
  97.         UCHAR FAR *szConnStrIn,
  98.         SWORD     cbConnStrIn,
  99.         UCHAR FAR *szConnStrOut,
  100.         SWORD     cbConnStrOutMax,
  101.         SWORD FAR *pcbConnStrOut)
  102. {
  103. static char *func="SQLBrowseConnect";
  104. mylog( "%s: entering...n", func);
  105. return SQL_SUCCESS;
  106. }
  107. //      -       -       -       -       -       -       -       -       -
  108. /* Drop any hstmts open on hdbc and disconnect from database */
  109. RETCODE SQL_API SQLDisconnect(
  110.         HDBC      hdbc)
  111. {
  112. ConnectionClass *conn = (ConnectionClass *) hdbc;
  113. static char *func = "SQLDisconnect";
  114. mylog( "%s: entering...n", func);
  115. if ( ! conn) {
  116. CC_log_error(func, "", NULL);
  117. return SQL_INVALID_HANDLE;
  118. }
  119. qlog("conn=%u, %sn", conn, func);
  120. if (conn->status == CONN_EXECUTING) {
  121. conn->errornumber = CONN_IN_USE;
  122. conn->errormsg = "A transaction is currently being executed";
  123. CC_log_error(func, "", conn);
  124. return SQL_ERROR;
  125. }
  126. mylog("%s: about to CC_cleanupn", func);
  127. /*  Close the connection and free statements */
  128. CC_cleanup(conn);
  129. mylog("%s: done CC_cleanupn", func);
  130. mylog("%s: returning...n", func);
  131. return SQL_SUCCESS;
  132. }
  133. //      -       -       -       -       -       -       -       -       -
  134. RETCODE SQL_API SQLFreeConnect(
  135.         HDBC      hdbc)
  136. {
  137. ConnectionClass *conn = (ConnectionClass *) hdbc;
  138. static char *func = "SQLFreeConnect";
  139. mylog( "%s: entering...n", func);
  140. mylog("**** in %s: hdbc=%un", func, hdbc);
  141. if ( ! conn) {
  142. CC_log_error(func, "", NULL);
  143. return SQL_INVALID_HANDLE;
  144. }
  145. /*  Remove the connection from the environment */
  146. if ( ! EN_remove_connection(conn->henv, conn)) {
  147. conn->errornumber = CONN_IN_USE;
  148. conn->errormsg = "A transaction is currently being executed";
  149. CC_log_error(func, "", conn);
  150. return SQL_ERROR;
  151. }
  152. CC_Destructor(conn);
  153. mylog("%s: returning...n", func);
  154. return SQL_SUCCESS;
  155. }
  156. /*
  157. *
  158. *       IMPLEMENTATION CONNECTION CLASS
  159. *
  160. */
  161. ConnectionClass *CC_Constructor()
  162. {
  163. ConnectionClass *rv;
  164.     rv = (ConnectionClass *)malloc(sizeof(ConnectionClass));
  165.     if (rv != NULL) {
  166. rv->henv = NULL; /* not yet associated with an environment */
  167.         rv->errormsg = NULL;
  168.         rv->errornumber = 0;
  169. rv->errormsg_created = FALSE;
  170.         rv->status = CONN_NOT_CONNECTED;
  171.         rv->transact_status = CONN_IN_AUTOCOMMIT; // autocommit by default
  172. memset(&rv->connInfo, 0, sizeof(ConnInfo));
  173. rv->sock = SOCK_Constructor();
  174. if ( ! rv->sock)
  175. return NULL;
  176. rv->stmts = (StatementClass **) malloc( sizeof(StatementClass *) * STMT_INCREMENT);
  177. if ( ! rv->stmts)
  178. return NULL;
  179. memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
  180. rv->num_stmts = STMT_INCREMENT;
  181. rv->lobj_type = PG_TYPE_LO;
  182. rv->ntables = 0;
  183. rv->col_info = NULL;
  184. rv->translation_option = 0;
  185. rv->translation_handle = NULL;
  186. rv->DataSourceToDriver = NULL;
  187. rv->DriverToDataSource = NULL;
  188. /* Initialize statement options to defaults */
  189. /* Statements under this conn will inherit these options */
  190. InitializeStatementOptions(&rv->stmtOptions);
  191.     } 
  192.     return rv;
  193. }
  194. char
  195. CC_Destructor(ConnectionClass *self)
  196. {
  197. mylog("enter CC_Destructor, self=%un", self);
  198. if (self->status == CONN_EXECUTING)
  199. return 0;
  200. CC_cleanup(self);   /* cleanup socket and statements */
  201. mylog("after CC_Cleanupn");
  202. /*  Free up statement holders */
  203. if (self->stmts) {
  204. free(self->stmts);
  205. self->stmts = NULL;
  206. }
  207. mylog("after free statement holdersn");
  208. /* Free cached table info */
  209. if (self->col_info) {
  210. int i;
  211. for (i = 0; i < self->ntables; i++) {
  212. if (self->col_info[i]->result) /* Free the SQLColumns result structure */
  213. QR_Destructor(self->col_info[i]->result);
  214. free(self->col_info[i]);
  215. }
  216. free(self->col_info);
  217. }
  218. free(self);
  219. mylog("exit CC_Destructorn");
  220. return 1;
  221. }
  222. /* Return how many cursors are opened on this connection */
  223. int
  224. CC_cursor_count(ConnectionClass *self)
  225. {
  226. StatementClass *stmt;
  227. int i, count = 0;
  228. mylog("CC_cursor_count: self=%u, num_stmts=%dn", self, self->num_stmts);
  229. for (i = 0; i < self->num_stmts; i++) {
  230. stmt = self->stmts[i];
  231. if (stmt && stmt->result && stmt->result->cursor)
  232. count++;
  233. }
  234. mylog("CC_cursor_count: returning %dn", count);
  235. return count;
  236. }
  237. void 
  238. CC_clear_error(ConnectionClass *self)
  239. {
  240. self->errornumber = 0; 
  241. self->errormsg = NULL; 
  242. self->errormsg_created = FALSE;
  243. }
  244. // Used to cancel a transaction
  245. // We are almost always in the middle of a transaction.
  246. char
  247. CC_abort(ConnectionClass *self)
  248. {
  249. QResultClass *res;
  250. if ( CC_is_in_trans(self)) {
  251. res = NULL;
  252. mylog("CC_abort:  sending ABORT!n");
  253. res = CC_send_query(self, "ABORT", NULL);
  254. CC_set_no_trans(self);
  255. if (res != NULL)
  256. QR_Destructor(res);
  257. else
  258. return FALSE;
  259. }
  260. return TRUE;
  261. }
  262. /* This is called by SQLDisconnect also */
  263. char
  264. CC_cleanup(ConnectionClass *self)
  265. {
  266. int i;
  267. StatementClass *stmt;
  268. if (self->status == CONN_EXECUTING)
  269. return FALSE;
  270. mylog("in CC_Cleanup, self=%un", self);
  271. // Cancel an ongoing transaction
  272. // We are always in the middle of a transaction,
  273. // even if we are in auto commit.
  274. if (self->sock)
  275. CC_abort(self);
  276. mylog("after CC_abortn");
  277. /*  This actually closes the connection to the dbase */
  278. if (self->sock) {
  279.     SOCK_Destructor(self->sock);
  280. self->sock = NULL;
  281. }
  282. mylog("after SOCK destructorn");
  283. /*  Free all the stmts on this connection */
  284. for (i = 0; i < self->num_stmts; i++) {
  285. stmt = self->stmts[i];
  286. if (stmt) {
  287. stmt->hdbc = NULL; /* prevent any more dbase interactions */
  288. SC_Destructor(stmt);
  289. self->stmts[i] = NULL;
  290. }
  291. }
  292. /* Check for translation dll */
  293. #ifdef WIN32
  294. if ( self->translation_handle) {
  295. FreeLibrary (self->translation_handle);
  296. self->translation_handle = NULL;
  297. }
  298. #endif
  299. mylog("exit CC_Cleanupn");
  300. return TRUE;
  301. }
  302. int
  303. CC_set_translation (ConnectionClass *self)
  304. {
  305. #ifdef WIN32
  306. if (self->translation_handle != NULL) {
  307. FreeLibrary (self->translation_handle);
  308. self->translation_handle = NULL;
  309. }
  310. if (self->connInfo.translation_dll[0] == 0)
  311. return TRUE;
  312. self->translation_option = atoi (self->connInfo.translation_option);
  313. self->translation_handle = LoadLibrary (self->connInfo.translation_dll);
  314. if (self->translation_handle == NULL) {
  315. self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
  316. self->errormsg = "Could not load the translation DLL.";
  317. return FALSE;
  318. }
  319. self->DataSourceToDriver
  320.  = (DataSourceToDriverProc) GetProcAddress (self->translation_handle,
  321. "SQLDataSourceToDriver");
  322. self->DriverToDataSource
  323.  = (DriverToDataSourceProc) GetProcAddress (self->translation_handle,
  324. "SQLDriverToDataSource");
  325. if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) {
  326. self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
  327. self->errormsg = "Could not find translation DLL functions.";
  328. return FALSE;
  329. }
  330. #endif
  331. return TRUE;
  332. }
  333. char 
  334. CC_connect(ConnectionClass *self, char do_password)
  335. {
  336. StartupPacket sp;
  337. StartupPacket6_2 sp62;
  338. QResultClass *res;
  339. SocketClass *sock;
  340. ConnInfo *ci = &(self->connInfo);
  341. int areq = -1;
  342. int beresp;
  343. char msgbuffer[ERROR_MSG_LENGTH]; 
  344. char salt[2];
  345. static char *func="CC_connect";
  346. mylog("%s: entering...n", func);
  347. if ( do_password)
  348. sock = self->sock; /* already connected, just authenticate */
  349. else {
  350. qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%dn",
  351. POSTGRESDRIVERVERSION,
  352. globals.fetch_max, 
  353. globals.socket_buffersize, 
  354. globals.unknown_sizes, 
  355. globals.max_varchar_size, 
  356. globals.max_longvarchar_size);
  357. qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%dn",
  358. globals.disable_optimizer,
  359. globals.ksqo,
  360. globals.unique_index,
  361. globals.use_declarefetch);
  362. qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%dn",
  363. globals.text_as_longvarchar, 
  364. globals.unknowns_as_longvarchar, 
  365. globals.bools_as_char);
  366. qlog("                extra_systable_prefixes='%s', conn_settings='%s'n",
  367. globals.extra_systable_prefixes, 
  368. globals.conn_settings);
  369. if (self->status != CONN_NOT_CONNECTED) {
  370. self->errormsg = "Already connected.";
  371. self->errornumber = CONN_OPENDB_ERROR;
  372. return 0;
  373. }
  374. if ( ci->server[0] == '' || ci->port[0] == '' || ci->database[0] == '') {
  375. self->errornumber = CONN_INIREAD_ERROR;
  376. self->errormsg = "Missing server name, port, or database name in call to CC_connect.";
  377. return 0;
  378. }
  379. mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
  380. /* If the socket was closed for some reason (like a SQLDisconnect, but no SQLFreeConnect
  381. then create a socket now.
  382. */
  383. if ( ! self->sock) {
  384. self->sock = SOCK_Constructor();
  385. if ( ! self->sock) {
  386.  self->errornumber = CONNECTION_SERVER_NOT_REACHED;
  387.  self->errormsg = "Could not open a socket to the server";
  388.  return 0;
  389. }
  390. }
  391. sock = self->sock;
  392. mylog("connecting to the server socket...n");
  393. SOCK_connect_to(sock, (short) atoi(ci->port), ci->server);
  394. if (SOCK_get_errcode(sock) != 0) {
  395. mylog("connection to the server socket failed.n");
  396. self->errornumber = CONNECTION_SERVER_NOT_REACHED;
  397. self->errormsg = "Could not connect to the server";
  398. return 0;
  399. }
  400. mylog("connection to the server socket succeeded.n");
  401. if ( PROTOCOL_62(ci)) {
  402. sock->reverse = TRUE; /* make put_int and get_int work for 6.2 */
  403. memset(&sp62, 0, sizeof(StartupPacket6_2));
  404. SOCK_put_int(sock, htonl(4+sizeof(StartupPacket6_2)), 4);
  405. sp62.authtype = htonl(NO_AUTHENTICATION);
  406. strncpy(sp62.database, ci->database, PATH_SIZE);
  407. strncpy(sp62.user, ci->username, NAMEDATALEN);
  408. SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));
  409. SOCK_flush_output(sock);
  410. }
  411. else {
  412. memset(&sp, 0, sizeof(StartupPacket));
  413. mylog("sizeof startup packet = %dn", sizeof(StartupPacket));
  414. // Send length of Authentication Block
  415. SOCK_put_int(sock, 4+sizeof(StartupPacket), 4); 
  416. if ( PROTOCOL_63(ci))
  417. sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_63);
  418. else
  419. sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);
  420. strncpy(sp.database, ci->database, SM_DATABASE);
  421. strncpy(sp.user, ci->username, SM_USER);
  422. SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));
  423. SOCK_flush_output(sock);
  424. }
  425. mylog("sent the authentication block.n");
  426. if (sock->errornumber != 0) {
  427. mylog("couldn't send the authentication block properly.n");
  428. self->errornumber = CONN_INVALID_AUTHENTICATION;
  429. self->errormsg = "Sending the authentication packet failed";
  430. return 0;
  431. }
  432. mylog("sent the authentication block successfully.n");
  433. }
  434. mylog("gonna do authenticationn");
  435. // ***************************************************
  436. // Now get the authentication request from backend
  437. // ***************************************************
  438. if ( ! PROTOCOL_62(ci)) do {
  439. if (do_password)
  440. beresp = 'R';
  441. else
  442. beresp = SOCK_get_char(sock);
  443. switch(beresp) {
  444. case 'E':
  445. mylog("auth got 'E'n");
  446. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  447. self->errornumber = CONN_INVALID_AUTHENTICATION;
  448. self->errormsg = msgbuffer;
  449. qlog("ERROR from backend during authentication: '%s'n", self->errormsg);
  450. return 0;
  451. case 'R':
  452. if (do_password) {
  453. mylog("in 'R' do_passwordn");
  454. areq = AUTH_REQ_PASSWORD;
  455. do_password = FALSE;
  456. }
  457. else {
  458. mylog("auth got 'R'n");
  459. areq = SOCK_get_int(sock, 4);
  460. if (areq == AUTH_REQ_CRYPT)
  461. SOCK_get_n_char(sock, salt, 2);
  462. mylog("areq = %dn", areq);
  463. }
  464. switch(areq) {
  465. case AUTH_REQ_OK:
  466. break;
  467. case AUTH_REQ_KRB4:
  468. self->errormsg = "Kerberos 4 authentication not supported";
  469. self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
  470. return 0;
  471. case AUTH_REQ_KRB5:
  472. self->errormsg = "Kerberos 5 authentication not supported";
  473. self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
  474. return 0;
  475. case AUTH_REQ_PASSWORD:
  476. mylog("in AUTH_REQ_PASSWORDn");
  477. if (ci->password[0] == '') {
  478. self->errornumber = CONNECTION_NEED_PASSWORD;
  479. self->errormsg = "A password is required for this connection.";
  480. return -1; /* need password */
  481. }
  482. mylog("past need passwordn");
  483. SOCK_put_int(sock, 4+strlen(ci->password)+1, 4);
  484. SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);
  485. SOCK_flush_output(sock);
  486. mylog("past flushn");
  487. break;
  488. case AUTH_REQ_CRYPT:
  489. self->errormsg = "Password crypt authentication not supported";
  490. self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
  491. return 0;
  492. default:
  493. self->errormsg = "Unknown authentication type";
  494. self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
  495. return 0;
  496. }
  497. break;
  498. default:
  499. self->errormsg = "Unexpected protocol character during authentication";
  500. self->errornumber = CONN_INVALID_AUTHENTICATION;
  501. return 0;
  502. }
  503. } while (areq != AUTH_REQ_OK);
  504. CC_clear_error(self); /* clear any password error */
  505. /* send an empty query in order to find out whether the specified */
  506. /* database really exists on the server machine */
  507. mylog("sending an empty query...n");
  508. res = CC_send_query(self, " ", NULL);
  509. if ( res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) {
  510. mylog("got no result from the empty query.  (probably database does not exist)n");
  511. self->errornumber = CONNECTION_NO_SUCH_DATABASE;
  512. self->errormsg = "The database does not exist on the servernor user authentication failed.";
  513. if (res != NULL)
  514. QR_Destructor(res);
  515. return 0;
  516. }
  517. if (res)
  518. QR_Destructor(res);
  519. mylog("empty query seems to be OK.n");
  520. CC_set_translation (self);
  521. /**********************************************/
  522. /*******   Send any initial settings  *********/
  523. /**********************************************/
  524. /* Since these functions allocate statements, and since the connection is not
  525. established yet, it would violate odbc state transition rules.  Therefore,
  526. these functions call the corresponding local function instead.
  527. */
  528. CC_send_settings(self);
  529. CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
  530. CC_clear_error(self); /* clear any initial command errors */
  531. self->status = CONN_CONNECTED;
  532. mylog("%s: returning...n", func);
  533. return 1;
  534. }
  535. char
  536. CC_add_statement(ConnectionClass *self, StatementClass *stmt)
  537. {
  538. int i;
  539. mylog("CC_add_statement: self=%u, stmt=%un", self, stmt);
  540. for (i = 0; i < self->num_stmts; i++) {
  541. if ( ! self->stmts[i]) {
  542. stmt->hdbc = self;
  543. self->stmts[i] = stmt;
  544. return TRUE;
  545. }
  546. }
  547. /* no more room -- allocate more memory */
  548. self->stmts = (StatementClass **) realloc( self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));
  549. if ( ! self->stmts)
  550. return FALSE;
  551. memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);
  552. stmt->hdbc = self;
  553. self->stmts[self->num_stmts] = stmt;
  554. self->num_stmts += STMT_INCREMENT;
  555. return TRUE;
  556. }
  557. char 
  558. CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
  559. {
  560. int i;
  561. for (i = 0; i < self->num_stmts; i++) {
  562. if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) {
  563. self->stmts[i] = NULL;
  564. return TRUE;
  565. }
  566. }
  567. return FALSE;
  568. }
  569. /* Create a more informative error message by concatenating the connection
  570. error message with its socket error message.
  571. */
  572. char *
  573. CC_create_errormsg(ConnectionClass *self)
  574. {
  575. SocketClass *sock = self->sock;
  576. int pos;
  577. static char msg[4096];
  578. mylog("enter CC_create_errormsgn");
  579. msg[0] = '';
  580. if (self->errormsg)
  581. strcpy(msg, self->errormsg);
  582. mylog("msg = '%s'n", msg);
  583. if (sock && sock->errormsg && sock->errormsg[0] != '') {
  584. pos = strlen(msg);
  585. sprintf(&msg[pos], ";n%s", sock->errormsg);
  586. }
  587. mylog("exit CC_create_errormsgn");
  588. return msg;
  589. }
  590. char 
  591. CC_get_error(ConnectionClass *self, int *number, char **message)
  592. {
  593. int rv;
  594. mylog("enter CC_get_errorn");
  595. // Create a very informative errormsg if it hasn't been done yet.
  596. if ( ! self->errormsg_created) {
  597. self->errormsg = CC_create_errormsg(self);
  598. self->errormsg_created = TRUE;
  599. }
  600. if (self->errornumber) {
  601. *number = self->errornumber;
  602. *message = self->errormsg;
  603. }
  604. rv = (self->errornumber != 0);
  605. self->errornumber = 0; // clear the error
  606. mylog("exit CC_get_errorn");
  607. return rv;
  608. }
  609. /* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
  610. the same existing QResultClass (this occurs when the tuple cache is depleted and
  611. needs to be re-filled).
  612. The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
  613. (i.e., C3326857) for SQL select statements.  This cursor is then used in future 
  614. 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
  615. */
  616. QResultClass *
  617. CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi)
  618. {
  619. QResultClass *result_in, *res = NULL;
  620. char id, swallow;
  621. SocketClass *sock = self->sock;
  622. static char msgbuffer[MAX_MESSAGE_LEN+1];
  623. char cmdbuffer[MAX_MESSAGE_LEN+1]; // QR_set_command() dups this string so dont need static
  624. mylog("send_query(): conn=%u, query='%s'n", self, query);
  625. qlog("conn=%u, query='%s'n", self, query);
  626. // Indicate that we are sending a query to the backend
  627. if(strlen(query) > MAX_MESSAGE_LEN-2) {
  628. self->errornumber = CONNECTION_MSG_TOO_LONG;
  629. self->errormsg = "Query string is too long";
  630. return NULL;
  631. }
  632. if ((NULL == query) || (query[0] == ''))
  633. return NULL;
  634. if (SOCK_get_errcode(sock) != 0) {
  635. self->errornumber = CONNECTION_COULD_NOT_SEND;
  636. self->errormsg = "Could not send Query to backend";
  637. CC_set_no_trans(self);
  638. return NULL;
  639. }
  640. SOCK_put_char(sock, 'Q');
  641. if (SOCK_get_errcode(sock) != 0) {
  642. self->errornumber = CONNECTION_COULD_NOT_SEND;
  643. self->errormsg = "Could not send Query to backend";
  644. CC_set_no_trans(self);
  645. return NULL;
  646. }
  647. SOCK_put_string(sock, query);
  648. SOCK_flush_output(sock);
  649. if (SOCK_get_errcode(sock) != 0) {
  650. self->errornumber = CONNECTION_COULD_NOT_SEND;
  651. self->errormsg = "Could not send Query to backend";
  652. CC_set_no_trans(self);
  653. return NULL;
  654. }
  655. mylog("send_query: done sending queryn");
  656. while(1) {
  657. /* what type of message is coming now ? */
  658. id = SOCK_get_char(sock);
  659. if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) {
  660. self->errornumber = CONNECTION_NO_RESPONSE;
  661. self->errormsg = "No response from the backend";
  662. if (res)
  663. QR_Destructor(res);
  664. mylog("send_query: 'id' - %sn", self->errormsg);
  665. CC_set_no_trans(self);
  666. return NULL;
  667. }
  668. mylog("send_query: got id = '%c'n", id);
  669. switch (id) {
  670. case 'A' : /* Asynchronous Messages are ignored */
  671. (void)SOCK_get_int(sock, 4); /* id of notification */
  672. SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
  673. /* name of the relation the message comes from */
  674. break;
  675. case 'C' : /* portal query command, no tuples returned */
  676. /* read in the return message from the backend */
  677. SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
  678. if (SOCK_get_errcode(sock) != 0) {
  679. self->errornumber = CONNECTION_NO_RESPONSE;
  680. self->errormsg = "No response from backend while receiving a portal query command";
  681. mylog("send_query: 'C' - %sn", self->errormsg);
  682. CC_set_no_trans(self);
  683. return NULL;
  684. } else {
  685. char clear = 0;
  686. mylog("send_query: ok - 'C' - %sn", cmdbuffer);
  687. if (res == NULL) /* allow for "show" style notices */
  688. res = QR_Constructor();
  689. mylog("send_query: setting cmdbuffer = '%s'n", cmdbuffer);
  690. /* Only save the first command */
  691. QR_set_status(res, PGRES_COMMAND_OK);
  692. QR_set_command(res, cmdbuffer);
  693. /* (Quotation from the original comments)
  694. since backend may produce more than one result for some commands
  695. we need to poll until clear
  696. so we send an empty query, and keep reading out of the pipe
  697. until an 'I' is received
  698. */
  699. SOCK_put_string(sock, "Q ");
  700. SOCK_flush_output(sock);
  701. while( ! clear) {
  702. id = SOCK_get_char(sock);
  703. switch(id) {
  704. case 'I':
  705. (void) SOCK_get_char(sock);
  706. clear = TRUE;
  707. break;
  708. case 'Z':
  709. break;
  710. case 'C':
  711. SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
  712. qlog("Command response: '%s'n", cmdbuffer);
  713. break;
  714. case 'N':
  715. SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
  716. qlog("NOTICE from backend during clear: '%s'n", cmdbuffer);
  717. break;
  718. case 'E':
  719. SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
  720. qlog("ERROR from backend during clear: '%s'n", cmdbuffer);
  721. break;
  722. }
  723. }
  724. mylog("send_query: returning res = %un", res);
  725. return res;
  726. }
  727. case 'K': /* Secret key (6.4 protocol) */
  728. (void)SOCK_get_int(sock, 4); /* pid */
  729. (void)SOCK_get_int(sock, 4); /* key */
  730. break;
  731. case 'Z': /* Backend is ready for new query (6.4) */
  732. break;
  733. case 'N' : /* NOTICE: */
  734. SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
  735. res = QR_Constructor();
  736. QR_set_status(res, PGRES_NONFATAL_ERROR);
  737. QR_set_notice(res, cmdbuffer); /* will dup this string */
  738. mylog("~~~ NOTICE: '%s'n", cmdbuffer);
  739. qlog("NOTICE from backend during send_query: '%s'n", cmdbuffer);
  740. continue; // dont return a result -- continue reading
  741. case 'I' : /* The server sends an empty query */
  742. /* There is a closing '' following the 'I', so we eat it */
  743. swallow = SOCK_get_char(sock);
  744. if ((swallow != '') || SOCK_get_errcode(sock) != 0) {
  745. self->errornumber = CONNECTION_BACKEND_CRAZY;
  746. self->errormsg = "Unexpected protocol character from backend (send_query - I)";
  747. res = QR_Constructor();
  748. QR_set_status(res, PGRES_FATAL_ERROR);
  749. return res;
  750. } else {
  751. /* We return the empty query */
  752. res = QR_Constructor();
  753. QR_set_status(res, PGRES_EMPTY_QUERY);
  754. return res;
  755. }
  756. break;
  757. case 'E' : 
  758. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  759. /* Remove a newline */
  760. if (msgbuffer[0] != '' && msgbuffer[strlen(msgbuffer)-1] == 'n')
  761. msgbuffer[strlen(msgbuffer)-1] = '';
  762. self->errormsg = msgbuffer;
  763. mylog("send_query: 'E' - %sn", self->errormsg);
  764. qlog("ERROR from backend during send_query: '%s'n", self->errormsg);
  765. if ( ! strncmp(self->errormsg, "FATAL", 5)) {
  766. self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
  767. CC_set_no_trans(self);
  768. }
  769. else
  770. self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
  771. return NULL;
  772. case 'P' : /* get the Portal name */
  773. SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
  774. break;
  775. case 'T': /* Tuple results start here */
  776. result_in = qi ? qi->result_in : NULL;
  777. if ( result_in == NULL) {
  778. result_in = QR_Constructor();
  779. mylog("send_query: 'T' no result_in: res = %un", result_in);
  780. if ( ! result_in) {
  781. self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
  782. self->errormsg = "Could not create result info in send_query.";
  783. return NULL;
  784. }
  785. if (qi)
  786. QR_set_cache_size(result_in, qi->row_size);
  787. if ( ! QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL)) {
  788. self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
  789. self->errormsg = QR_get_message(result_in);
  790. return NULL;
  791. }
  792. }
  793. else {  // next fetch, so reuse an existing result
  794. if ( ! QR_fetch_tuples(result_in, NULL, NULL)) {
  795. self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
  796. self->errormsg = QR_get_message(result_in);
  797. return NULL;
  798. }
  799. }
  800. return result_in;
  801. case 'D': /* Copy in command began successfully */
  802. res = QR_Constructor();
  803. QR_set_status(res, PGRES_COPY_IN);
  804. return res;
  805. case 'B': /* Copy out command began successfully */
  806. res = QR_Constructor();
  807. QR_set_status(res, PGRES_COPY_OUT);
  808. return res;
  809. default:
  810. self->errornumber = CONNECTION_BACKEND_CRAZY;
  811. self->errormsg = "Unexpected protocol character from backend (send_query)";
  812. CC_set_no_trans(self);
  813. mylog("send_query: error - %sn", self->errormsg);
  814. return NULL;
  815. }
  816. }
  817. }
  818. int
  819. CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
  820. {
  821. char id, c, done;
  822. SocketClass *sock = self->sock;
  823. static char msgbuffer[MAX_MESSAGE_LEN+1];
  824. int i;
  825. mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%dn", self, fnid, result_is_int, nargs);
  826. if (SOCK_get_errcode(sock) != 0) {
  827. self->errornumber = CONNECTION_COULD_NOT_SEND;
  828. self->errormsg = "Could not send function to backend";
  829. CC_set_no_trans(self);
  830. return FALSE;
  831. }
  832. SOCK_put_string(sock, "F ");
  833. if (SOCK_get_errcode(sock) != 0) {
  834. self->errornumber = CONNECTION_COULD_NOT_SEND;
  835. self->errormsg = "Could not send function to backend";
  836. CC_set_no_trans(self);
  837. return FALSE;
  838. }
  839. SOCK_put_int(sock, fnid, 4); 
  840. SOCK_put_int(sock, nargs, 4); 
  841. mylog("send_function: done sending functionn");
  842. for (i = 0; i < nargs; ++i) {
  843. mylog("  arg[%d]: len = %d, isint = %d, integer = %d, ptr = %un", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
  844. SOCK_put_int(sock, args[i].len, 4);
  845. if (args[i].isint) 
  846. SOCK_put_int(sock, args[i].u.integer, 4);
  847. else
  848. SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len);
  849. }
  850. mylog("    done sending argsn");
  851. SOCK_flush_output(sock);
  852. mylog("  after flush outputn");
  853. done = FALSE;
  854. while ( ! done) {
  855. id = SOCK_get_char(sock);
  856. mylog("   got id = %cn", id);
  857. switch(id) {
  858. case 'V':
  859. done = TRUE;
  860. break; /* ok */
  861. case 'N':
  862. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  863. mylog("send_function(V): 'N' - %sn", msgbuffer);
  864. /* continue reading */
  865. break;
  866. case 'E':
  867. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  868. self->errormsg = msgbuffer;
  869. mylog("send_function(V): 'E' - %sn", self->errormsg);
  870. qlog("ERROR from backend during send_function: '%s'n", self->errormsg);
  871. return FALSE;
  872. case 'Z':
  873. break;
  874. default:
  875. self->errornumber = CONNECTION_BACKEND_CRAZY;
  876. self->errormsg = "Unexpected protocol character from backend (send_function, args)";
  877. CC_set_no_trans(self);
  878. mylog("send_function: error - %sn", self->errormsg);
  879. return FALSE;
  880. }
  881. }
  882. id = SOCK_get_char(sock);
  883. for (;;) {
  884. switch (id) {
  885. case 'G': /* function returned properly */
  886. mylog("  got G!n");
  887. *actual_result_len = SOCK_get_int(sock, 4);
  888. mylog("  actual_result_len = %dn", *actual_result_len);
  889. if (result_is_int)
  890. *((int *) result_buf) = SOCK_get_int(sock, 4);
  891. else
  892. SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len);
  893. mylog("  after get resultn");
  894. c = SOCK_get_char(sock); /* get the last '0' */
  895. mylog("   after get 0n");
  896. return TRUE;
  897. case 'E':
  898. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  899. self->errormsg = msgbuffer;
  900. mylog("send_function(G): 'E' - %sn", self->errormsg);
  901. qlog("ERROR from backend during send_function: '%s'n", self->errormsg);
  902. return FALSE;
  903. case 'N':
  904. SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
  905. mylog("send_function(G): 'N' - %sn", msgbuffer);
  906. qlog("NOTICE from backend during send_function: '%s'n", msgbuffer);
  907. continue; // dont return a result -- continue reading
  908. case '0': /* empty result */
  909. return TRUE;
  910. default:
  911. self->errornumber = CONNECTION_BACKEND_CRAZY;
  912. self->errormsg = "Unexpected protocol character from backend (send_function, result)";
  913. CC_set_no_trans(self);
  914. mylog("send_function: error - %sn", self->errormsg);
  915. return FALSE;
  916. }
  917. }
  918. }
  919. char
  920. CC_send_settings(ConnectionClass *self)
  921. {
  922. // char ini_query[MAX_MESSAGE_LEN];
  923. ConnInfo *ci = &(self->connInfo);
  924. // QResultClass *res;
  925. HSTMT hstmt;
  926. StatementClass *stmt;
  927. RETCODE result;
  928. char status = TRUE;
  929. char *cs, *ptr;
  930. static char *func="CC_send_settings";
  931. mylog("%s: entering...n", func);
  932. /* This function must use the local odbc API functions since the odbc state 
  933. has not transitioned to "connected" yet.
  934. */
  935. result = SQLAllocStmt( self, &hstmt);
  936. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  937. return FALSE;
  938. }
  939. stmt = (StatementClass *) hstmt;
  940. stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */
  941. /* Set the Datestyle to the format the driver expects it to be in */
  942. result = SQLExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS);
  943. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
  944. status = FALSE;
  945. mylog("%s: result %d, status %d from set DateStylen", func, result, status);
  946. /* Disable genetic optimizer based on global flag */
  947. if (globals.disable_optimizer) {
  948. result = SQLExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS);
  949. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
  950. status = FALSE;
  951. mylog("%s: result %d, status %d from set geqon", func, result, status);
  952. }
  953. /* KSQO */
  954. if (globals.ksqo) {
  955. result = SQLExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS);
  956. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
  957. status = FALSE;
  958. mylog("%s: result %d, status %d from set ksqon", func, result, status);
  959. }
  960. /* Global settings */
  961. if (globals.conn_settings[0] != '') {
  962. cs = strdup(globals.conn_settings);
  963. ptr = strtok(cs, ";");
  964. while (ptr) {
  965. result = SQLExecDirect(hstmt, ptr, SQL_NTS);
  966. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
  967. status = FALSE;
  968. mylog("%s: result %d, status %d from '%s'n", func, result, status, ptr);
  969. ptr = strtok(NULL, ";");
  970. }
  971. free(cs);
  972. }
  973. /* Per Datasource settings */
  974. if (ci->conn_settings[0] != '') {
  975. cs = strdup(ci->conn_settings);
  976. ptr = strtok(cs, ";");
  977. while (ptr) {
  978. result = SQLExecDirect(hstmt, ptr, SQL_NTS);
  979. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
  980. status = FALSE;
  981. mylog("%s: result %d, status %d from '%s'n", func, result, status, ptr);
  982. ptr = strtok(NULL, ";");
  983. }
  984. free(cs);
  985. }
  986. SQLFreeStmt(hstmt, SQL_DROP);
  987. return status;
  988. }
  989. /* This function is just a hack to get the oid of our Large Object oid type.
  990. If a real Large Object oid type is made part of Postgres, this function
  991. will go away and the define 'PG_TYPE_LO' will be updated.
  992. */
  993. void
  994. CC_lookup_lo(ConnectionClass *self) 
  995. {
  996. HSTMT hstmt;
  997. StatementClass *stmt;
  998. RETCODE result;
  999. static char *func = "CC_lookup_lo";
  1000. mylog( "%s: entering...n", func);
  1001. /* This function must use the local odbc API functions since the odbc state 
  1002. has not transitioned to "connected" yet.
  1003. */
  1004. result = SQLAllocStmt( self, &hstmt);
  1005. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  1006. return;
  1007. }
  1008. stmt = (StatementClass *) hstmt;
  1009. result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS);
  1010. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  1011. SQLFreeStmt(hstmt, SQL_DROP);
  1012. return;
  1013. }
  1014. result = SQLFetch(hstmt);
  1015. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  1016. SQLFreeStmt(hstmt, SQL_DROP);
  1017. return;
  1018. }
  1019. result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
  1020. if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
  1021. SQLFreeStmt(hstmt, SQL_DROP);
  1022. return;
  1023. }
  1024. mylog("Got the large object oid: %dn", self->lobj_type);
  1025. qlog("    [ Large Object oid = %d ]n", self->lobj_type);
  1026. result = SQLFreeStmt(hstmt, SQL_DROP);
  1027. }
  1028. void
  1029. CC_log_error(char *func, char *desc, ConnectionClass *self)
  1030. {
  1031. if (self) {
  1032. qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'n", func, desc, self->errornumber, self->errormsg);
  1033. mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'n", func, desc, self->errornumber, self->errormsg);
  1034. qlog("            ------------------------------------------------------------n");
  1035. qlog("            henv=%u, conn=%u, status=%u, num_stmts=%dn", self->henv, self, self->status, self->num_stmts);
  1036. qlog("            sock=%u, stmts=%u, lobj_type=%dn", self->sock, self->stmts, self->lobj_type);
  1037. qlog("            ---------------- Socket Info -------------------------------n");
  1038. if (self->sock) {
  1039. SocketClass *sock = self->sock;
  1040. qlog("            socket=%d, reverse=%d, errornumber=%d, errormsg='%s'n", sock->socket, sock->reverse, sock->errornumber, sock->errormsg);
  1041. qlog("            buffer_in=%u, buffer_out=%un", sock->buffer_in, sock->buffer_out);
  1042. qlog("            buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%dn", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
  1043. }
  1044. }
  1045. else
  1046. qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'n", func, desc);
  1047. }