2 /* Module: connection.c
4 * Description: This module contains routines related to
5 * connecting to and disconnecting from the Postgres DBMS.
7 * Classes: ConnectionClass (Functions prefix: "CC_")
9 * API functions: SQLAllocConnect, SQLConnect, SQLDisconnect, SQLFreeConnect,
10 * SQLBrowseConnect(NI)
12 * Comments: See "notice.txt" for copyright and license information.
17 #include "connection.h"
19 #include "statement.h"
22 #include "dlg_specific.h"
30 #define STMT_INCREMENT 16 /* how many statement holders to allocate at a time */
32 extern GLOBAL_VALUES globals;
34 // void CC_test(ConnectionClass *self);
36 RETCODE SQL_API SQLAllocConnect(
40 EnvironmentClass *env = (EnvironmentClass *)henv;
41 ConnectionClass *conn;
42 char *func="SQLAllocConnect";
44 conn = CC_Constructor();
45 mylog("**** SQLAllocConnect: henv = %u, conn = %u\n", henv, conn);
48 env->errormsg = "Couldn't allocate memory for Connection object.";
49 env->errornumber = ENV_ALLOC_ERROR;
50 *phdbc = SQL_NULL_HDBC;
51 EN_log_error(func, "", env);
55 if ( ! EN_add_connection(env, conn)) {
56 env->errormsg = "Maximum number of connections exceeded.";
57 env->errornumber = ENV_ALLOC_ERROR;
59 *phdbc = SQL_NULL_HDBC;
60 EN_log_error(func, "", env);
72 RETCODE SQL_API SQLConnect(
81 ConnectionClass *conn = (ConnectionClass *) hdbc;
83 char *func = "SQLConnect";
86 CC_log_error(func, "", NULL);
87 return SQL_INVALID_HANDLE;
92 make_string(szDSN, cbDSN, ci->dsn);
94 /* get the values for the DSN from the registry */
95 getDSNinfo(ci, CONN_OVERWRITE);
97 /* override values from DSN info with UID and authStr(pwd)
98 This only occurs if the values are actually there.
100 make_string(szUID, cbUID, ci->username);
101 make_string(szAuthStr, cbAuthStr, ci->password);
103 /* fill in any defaults */
106 qlog("conn = %u, SQLConnect(DSN='%s', UID='%s', PWD='%s')\n", conn, ci->dsn, ci->username, ci->password);
108 if ( CC_connect(conn, FALSE) <= 0) {
109 // Error messages are filled in
110 CC_log_error(func, "Error on CC_connect", conn);
119 RETCODE SQL_API SQLBrowseConnect(
121 UCHAR FAR *szConnStrIn,
123 UCHAR FAR *szConnStrOut,
124 SWORD cbConnStrOutMax,
125 SWORD FAR *pcbConnStrOut)
132 /* Drop any hstmts open on hdbc and disconnect from database */
133 RETCODE SQL_API SQLDisconnect(
136 ConnectionClass *conn = (ConnectionClass *) hdbc;
137 char *func = "SQLDisconnect";
139 mylog("**** in SQLDisconnect\n");
142 CC_log_error(func, "", NULL);
143 return SQL_INVALID_HANDLE;
146 qlog("conn=%u, SQLDisconnect\n", conn);
148 if (conn->status == CONN_EXECUTING) {
149 conn->errornumber = CONN_IN_USE;
150 conn->errormsg = "A transaction is currently being executed";
151 CC_log_error(func, "", conn);
155 mylog("SQLDisconnect: about to CC_cleanup\n");
157 /* Close the connection and free statements */
160 mylog("SQLDisconnect: done CC_cleanup\n");
161 mylog("exit SQLDisconnect\n");
169 RETCODE SQL_API SQLFreeConnect(
172 ConnectionClass *conn = (ConnectionClass *) hdbc;
173 char *func = "SQLFreeConnect";
175 mylog("**** in SQLFreeConnect: hdbc=%u\n", hdbc);
178 CC_log_error(func, "", NULL);
179 return SQL_INVALID_HANDLE;
182 /* Remove the connection from the environment */
183 if ( ! EN_remove_connection(conn->henv, conn)) {
184 conn->errornumber = CONN_IN_USE;
185 conn->errormsg = "A transaction is currently being executed";
186 CC_log_error(func, "", conn);
192 mylog("exit SQLFreeConnect\n");
200 * IMPLEMENTATION CONNECTION CLASS
209 rv = (ConnectionClass *)malloc(sizeof(ConnectionClass));
213 rv->henv = NULL; /* not yet associated with an environment */
217 rv->errormsg_created = FALSE;
219 rv->status = CONN_NOT_CONNECTED;
220 rv->transact_status = CONN_IN_AUTOCOMMIT; // autocommit by default
222 memset(&rv->connInfo, 0, sizeof(ConnInfo));
224 rv->sock = SOCK_Constructor();
228 rv->stmts = (StatementClass **) malloc( sizeof(StatementClass *) * STMT_INCREMENT);
231 memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
233 rv->num_stmts = STMT_INCREMENT;
235 rv->lobj_type = PG_TYPE_LO;
240 rv->translation_option = 0;
241 rv->translation_handle = NULL;
242 rv->DataSourceToDriver = NULL;
243 rv->DriverToDataSource = NULL;
250 CC_Destructor(ConnectionClass *self)
253 mylog("enter CC_Destructor, self=%u\n", self);
255 if (self->status == CONN_EXECUTING)
258 CC_cleanup(self); /* cleanup socket and statements */
260 mylog("after CC_Cleanup\n");
262 /* Free up statement holders */
267 mylog("after free statement holders\n");
269 /* Free cached table info */
270 if (self->col_info) {
272 for (i = 0; i < self->ntables; i++) {
273 if (self->col_info[i]->result) /* Free the SQLColumns result structure */
274 QR_Destructor(self->col_info[i]->result);
276 free(self->col_info[i]);
278 free(self->col_info);
284 mylog("exit CC_Destructor\n");
289 /* Return how many cursors are opened on this connection */
291 CC_cursor_count(ConnectionClass *self)
293 StatementClass *stmt;
296 mylog("CC_cursor_count: self=%u, num_stmts=%d\n", self, self->num_stmts);
298 for (i = 0; i < self->num_stmts; i++) {
299 stmt = self->stmts[i];
300 if (stmt && stmt->result && stmt->result->cursor)
304 mylog("CC_cursor_count: returning %d\n", count);
310 CC_clear_error(ConnectionClass *self)
312 self->errornumber = 0;
313 self->errormsg = NULL;
314 self->errormsg_created = FALSE;
317 // Used to cancel a transaction
318 // We are almost always in the middle of a transaction.
320 CC_abort(ConnectionClass *self)
324 if ( CC_is_in_trans(self)) {
327 mylog("CC_abort: sending ABORT!\n");
329 res = CC_send_query(self, "ABORT", NULL, NULL);
330 CC_set_no_trans(self);
342 /* This is called by SQLDisconnect also */
344 CC_cleanup(ConnectionClass *self)
347 StatementClass *stmt;
349 if (self->status == CONN_EXECUTING)
352 mylog("in CC_Cleanup, self=%u\n", self);
354 // Cancel an ongoing transaction
355 // We are always in the middle of a transaction,
356 // even if we are in auto commit.
360 mylog("after CC_abort\n");
362 /* This actually closes the connection to the dbase */
364 SOCK_Destructor(self->sock);
368 mylog("after SOCK destructor\n");
370 /* Free all the stmts on this connection */
371 for (i = 0; i < self->num_stmts; i++) {
372 stmt = self->stmts[i];
375 stmt->hdbc = NULL; /* prevent any more dbase interactions */
379 self->stmts[i] = NULL;
383 /* Check for translation dll */
384 if ( self->translation_handle) {
385 FreeLibrary (self->translation_handle);
386 self->translation_handle = NULL;
389 mylog("exit CC_Cleanup\n");
394 CC_set_translation (ConnectionClass *self)
397 if (self->translation_handle != NULL) {
398 FreeLibrary (self->translation_handle);
399 self->translation_handle = NULL;
402 if (self->connInfo.translation_dll[0] == 0)
405 self->translation_option = atoi (self->connInfo.translation_option);
406 self->translation_handle = LoadLibrary (self->connInfo.translation_dll);
408 if (self->translation_handle == NULL) {
409 self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
410 self->errormsg = "Could not load the translation DLL.";
414 self->DataSourceToDriver
415 = (DataSourceToDriverProc) GetProcAddress (self->translation_handle,
416 "SQLDataSourceToDriver");
418 self->DriverToDataSource
419 = (DriverToDataSourceProc) GetProcAddress (self->translation_handle,
420 "SQLDriverToDataSource");
422 if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL) {
423 self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
424 self->errormsg = "Could not find translation DLL functions.";
432 CC_connect(ConnectionClass *self, char do_password)
435 StartupPacket6_2 sp62;
438 ConnInfo *ci = &(self->connInfo);
441 char msgbuffer[ERROR_MSG_LENGTH];
446 sock = self->sock; /* already connected, just authenticate */
450 qlog("Global Options: fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
452 globals.socket_buffersize,
453 globals.unknown_sizes,
454 globals.max_varchar_size,
455 globals.max_longvarchar_size);
456 qlog(" disable_optimizer=%d, unique_index=%d, use_declarefetch=%d\n",
457 globals.disable_optimizer,
458 globals.unique_index,
459 globals.use_declarefetch);
460 qlog(" text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d\n",
461 globals.text_as_longvarchar,
462 globals.unknowns_as_longvarchar,
463 globals.bools_as_char);
464 qlog(" extra_systable_prefixes='%s', conn_settings='%s'\n",
465 globals.extra_systable_prefixes,
466 globals.conn_settings);
468 if (self->status != CONN_NOT_CONNECTED) {
469 self->errormsg = "Already connected.";
470 self->errornumber = CONN_OPENDB_ERROR;
474 if ( ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0') {
475 self->errornumber = CONN_INIREAD_ERROR;
476 self->errormsg = "Missing server name, port, or database name in call to CC_connect.";
480 mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n",
481 ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
483 /* If the socket was closed for some reason (like a SQLDisconnect, but no SQLFreeConnect
484 then create a socket now.
487 self->sock = SOCK_Constructor();
489 self->errornumber = CONNECTION_SERVER_NOT_REACHED;
490 self->errormsg = "Could not open a socket to the server";
497 mylog("connecting to the server socket...\n");
499 SOCK_connect_to(sock, (short) atoi(ci->port), ci->server);
500 if (SOCK_get_errcode(sock) != 0) {
501 mylog("connection to the server socket failed.\n");
502 self->errornumber = CONNECTION_SERVER_NOT_REACHED;
503 self->errormsg = "Could not connect to the server";
506 mylog("connection to the server socket succeeded.\n");
508 if ( PROTOCOL_62(ci)) {
509 sock->reverse = TRUE; /* make put_int and get_int work for 6.2 */
511 memset(&sp62, 0, sizeof(StartupPacket6_2));
512 SOCK_put_int(sock, htonl(4+sizeof(StartupPacket6_2)), 4);
513 sp62.authtype = htonl(NO_AUTHENTICATION);
514 strncpy(sp62.database, ci->database, PATH_SIZE);
515 strncpy(sp62.user, ci->username, NAMEDATALEN);
516 SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));
517 SOCK_flush_output(sock);
520 memset(&sp, 0, sizeof(StartupPacket));
522 mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));
524 // Send length of Authentication Block
525 SOCK_put_int(sock, 4+sizeof(StartupPacket), 4);
527 sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);
528 strncpy(sp.database, ci->database, SM_DATABASE);
529 strncpy(sp.user, ci->username, SM_USER);
531 SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));
532 SOCK_flush_output(sock);
535 mylog("sent the authentication block.\n");
537 if (sock->errornumber != 0) {
538 mylog("couldn't send the authentication block properly.\n");
539 self->errornumber = CONN_INVALID_AUTHENTICATION;
540 self->errormsg = "Sending the authentication packet failed";
543 mylog("sent the authentication block successfully.\n");
547 mylog("gonna do authentication\n");
550 // ***************************************************
551 // Now get the authentication request from backend
552 // ***************************************************
554 if ( ! PROTOCOL_62(ci)) do {
559 beresp = SOCK_get_char(sock);
563 mylog("auth got 'E'\n");
565 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
566 self->errornumber = CONN_INVALID_AUTHENTICATION;
567 self->errormsg = msgbuffer;
568 qlog("ERROR from backend during authentication: '%s'\n", self->errormsg);
573 mylog("in 'R' do_password\n");
574 areq = AUTH_REQ_PASSWORD;
578 mylog("auth got 'R'\n");
580 areq = SOCK_get_int(sock, 4);
581 if (areq == AUTH_REQ_CRYPT)
582 SOCK_get_n_char(sock, salt, 2);
584 mylog("areq = %d\n", areq);
591 self->errormsg = "Kerberos 4 authentication not supported";
592 self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
596 self->errormsg = "Kerberos 5 authentication not supported";
597 self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
600 case AUTH_REQ_PASSWORD:
601 mylog("in AUTH_REQ_PASSWORD\n");
603 if (ci->password[0] == '\0') {
604 self->errornumber = CONNECTION_NEED_PASSWORD;
605 self->errormsg = "A password is required for this connection.";
606 return -1; /* need password */
609 mylog("past need password\n");
611 SOCK_put_int(sock, 4+strlen(ci->password)+1, 4);
612 SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);
613 SOCK_flush_output(sock);
615 mylog("past flush\n");
619 self->errormsg = "Password crypt authentication not supported";
620 self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
624 self->errormsg = "Unknown authentication type";
625 self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
630 self->errormsg = "Unexpected protocol character during authentication";
631 self->errornumber = CONN_INVALID_AUTHENTICATION;
635 } while (areq != AUTH_REQ_OK);
638 CC_clear_error(self); /* clear any password error */
640 /* send an empty query in order to find out whether the specified */
641 /* database really exists on the server machine */
642 mylog("sending an empty query...\n");
644 res = CC_send_query(self, " ", NULL, NULL);
645 if ( res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY) {
646 mylog("got no result from the empty query. (probably database does not exist)\n");
647 self->errornumber = CONNECTION_NO_SUCH_DATABASE;
648 self->errormsg = "The database does not exist on the server\nor user authentication failed.";
656 mylog("empty query seems to be OK.\n");
658 CC_set_translation (self);
660 /**********************************************/
661 /******* Send any initial settings *********/
662 /**********************************************/
664 /* Since these functions allocate statements, and since the connection is not
665 established yet, it would violate odbc state transition rules. Therefore,
666 these functions call the corresponding local function instead.
668 CC_send_settings(self);
669 CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */
673 CC_clear_error(self); /* clear any initial command errors */
674 self->status = CONN_CONNECTED;
681 CC_add_statement(ConnectionClass *self, StatementClass *stmt)
685 mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt);
687 for (i = 0; i < self->num_stmts; i++) {
688 if ( ! self->stmts[i]) {
690 self->stmts[i] = stmt;
695 /* no more room -- allocate more memory */
696 self->stmts = (StatementClass **) realloc( self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));
700 memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);
703 self->stmts[self->num_stmts] = stmt;
705 self->num_stmts += STMT_INCREMENT;
711 CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
715 for (i = 0; i < self->num_stmts; i++) {
716 if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) {
717 self->stmts[i] = NULL;
725 /* Create a more informative error message by concatenating the connection
726 error message with its socket error message.
729 CC_create_errormsg(ConnectionClass *self)
731 SocketClass *sock = self->sock;
733 static char msg[4096];
735 mylog("enter CC_create_errormsg\n");
740 strcpy(msg, self->errormsg);
742 mylog("msg = '%s'\n", msg);
744 if (sock && sock->errormsg && sock->errormsg[0] != '\0') {
746 sprintf(&msg[pos], ";\n%s", sock->errormsg);
749 mylog("exit CC_create_errormsg\n");
755 CC_get_error(ConnectionClass *self, int *number, char **message)
759 mylog("enter CC_get_error\n");
761 // Create a very informative errormsg if it hasn't been done yet.
762 if ( ! self->errormsg_created) {
763 self->errormsg = CC_create_errormsg(self);
764 self->errormsg_created = TRUE;
767 if (self->errornumber) {
768 *number = self->errornumber;
769 *message = self->errormsg;
771 rv = (self->errornumber != 0);
773 self->errornumber = 0; // clear the error
775 mylog("exit CC_get_error\n");
781 /* The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
782 the same existing QResultClass (this occurs when the tuple cache is depleted and
783 needs to be re-filled).
785 The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
786 (i.e., C3326857) for SQL select statements. This cursor is then used in future
787 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
790 CC_send_query(ConnectionClass *self, char *query, QResultClass *result_in, char *cursor)
792 QResultClass *res = NULL;
794 SocketClass *sock = self->sock;
795 static char msgbuffer[MAX_MESSAGE_LEN+1];
796 char cmdbuffer[MAX_MESSAGE_LEN+1]; // QR_set_command() dups this string so dont need static
799 mylog("send_query(): conn=%u, query='%s'\n", self, query);
800 qlog("conn=%u, query='%s'\n", self, query);
802 // Indicate that we are sending a query to the backend
803 if(strlen(query) > MAX_MESSAGE_LEN-2) {
804 self->errornumber = CONNECTION_MSG_TOO_LONG;
805 self->errormsg = "Query string is too long";
809 if ((NULL == query) || (query[0] == '\0'))
812 if (SOCK_get_errcode(sock) != 0) {
813 self->errornumber = CONNECTION_COULD_NOT_SEND;
814 self->errormsg = "Could not send Query to backend";
815 CC_set_no_trans(self);
819 SOCK_put_char(sock, 'Q');
820 if (SOCK_get_errcode(sock) != 0) {
821 self->errornumber = CONNECTION_COULD_NOT_SEND;
822 self->errormsg = "Could not send Query to backend";
823 CC_set_no_trans(self);
827 SOCK_put_string(sock, query);
828 SOCK_flush_output(sock);
830 if (SOCK_get_errcode(sock) != 0) {
831 self->errornumber = CONNECTION_COULD_NOT_SEND;
832 self->errormsg = "Could not send Query to backend";
833 CC_set_no_trans(self);
837 mylog("send_query: done sending query\n");
840 /* what type of message is comming now ? */
841 id = SOCK_get_char(sock);
843 if ((SOCK_get_errcode(sock) != 0) || (id == EOF)) {
844 self->errornumber = CONNECTION_NO_RESPONSE;
845 self->errormsg = "No response from the backend";
849 mylog("send_query: 'id' - %s\n", self->errormsg);
850 CC_set_no_trans(self);
854 mylog("send_query: got id = '%c'\n", id);
857 case 'A' : /* Asynchronous Messages are ignored */
858 (void)SOCK_get_int(sock, 4); /* id of notification */
859 SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
860 /* name of the relation the message comes from */
862 case 'C' : /* portal query command, no tuples returned */
863 /* read in the return message from the backend */
864 SOCK_get_string(sock, cmdbuffer, MAX_MESSAGE_LEN);
865 if (SOCK_get_errcode(sock) != 0) {
866 self->errornumber = CONNECTION_NO_RESPONSE;
867 self->errormsg = "No response from backend while receiving a portal query command";
868 mylog("send_query: 'C' - %s\n", self->errormsg);
869 CC_set_no_trans(self);
875 mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
877 if (res == NULL) /* allow for "show" style notices */
878 res = QR_Constructor();
880 mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
882 /* Only save the first command */
883 QR_set_status(res, PGRES_COMMAND_OK);
884 QR_set_command(res, cmdbuffer);
886 /* (Quotation from the original comments)
887 since backend may produze more than one result for some commands
888 we need to poll until clear
889 so we send an empty query, and keep reading out of the pipe
890 until an 'I' is received
894 SOCK_put_string(sock, "Q ");
895 SOCK_flush_output(sock);
897 SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
898 mylog("send_query: read command '%s'\n", cmdbuffer);
899 clear = (cmdbuffer[0] == 'I');
901 if (cmdbuffer[0] == 'N')
902 qlog("NOTICE from backend during send_query: '%s'\n", &cmdbuffer[1]);
903 else if (cmdbuffer[0] == 'E')
904 qlog("ERROR from backend during send_query: '%s'\n", &cmdbuffer[1]);
905 else if (cmdbuffer[0] == 'C')
906 qlog("Command response: '%s'\n", &cmdbuffer[1]);
909 mylog("send_query: returning res = %u\n", res);
912 case 'N' : /* NOTICE: */
913 SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
915 res = QR_Constructor();
916 QR_set_status(res, PGRES_NONFATAL_ERROR);
917 QR_set_notice(res, cmdbuffer); /* will dup this string */
919 mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
920 qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
922 continue; // dont return a result -- continue reading
924 case 'I' : /* The server sends an empty query */
925 /* There is a closing '\0' following the 'I', so we eat it */
926 swallow = SOCK_get_char(sock);
927 if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) {
928 self->errornumber = CONNECTION_BACKEND_CRAZY;
929 self->errormsg = "Unexpected protocol character from backend";
930 res = QR_Constructor();
931 QR_set_status(res, PGRES_FATAL_ERROR);
934 /* We return the empty query */
935 res = QR_Constructor();
936 QR_set_status(res, PGRES_EMPTY_QUERY);
941 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
943 /* Remove a newline */
944 if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer)-1] == '\n')
945 msgbuffer[strlen(msgbuffer)-1] = '\0';
947 self->errormsg = msgbuffer;
949 mylog("send_query: 'E' - %s\n", self->errormsg);
950 qlog("ERROR from backend during send_query: '%s'\n", self->errormsg);
952 if ( ! strncmp(self->errormsg, "FATAL", 5)) {
953 self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
954 CC_set_no_trans(self);
957 self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
961 case 'P' : /* get the Portal name */
962 SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN);
964 case 'T': /* Tuple results start here */
965 if (result_in == NULL) {
966 result_in = QR_Constructor();
967 mylog("send_query: 'T' no result_in: res = %u\n", result_in);
969 self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
970 self->errormsg = "Could not create result info in send_query.";
974 if ( ! QR_fetch_tuples(result_in, self, cursor)) {
975 self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
976 self->errormsg = QR_get_message(result_in);
980 else { // next fetch, so reuse an existing result
981 if ( ! QR_fetch_tuples(result_in, NULL, NULL)) {
982 self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
983 self->errormsg = QR_get_message(result_in);
989 case 'D': /* Copy in command began successfully */
990 res = QR_Constructor();
991 QR_set_status(res, PGRES_COPY_IN);
993 case 'B': /* Copy out command began successfully */
994 res = QR_Constructor();
995 QR_set_status(res, PGRES_COPY_OUT);
998 self->errornumber = CONNECTION_BACKEND_CRAZY;
999 self->errormsg = "Unexpected protocol character from backend";
1000 CC_set_no_trans(self);
1002 mylog("send_query: error - %s\n", self->errormsg);
1009 CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
1012 SocketClass *sock = self->sock;
1013 static char msgbuffer[MAX_MESSAGE_LEN+1];
1016 mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
1017 // qlog("conn=%u, func=%d\n", self, fnid);
1019 if (SOCK_get_errcode(sock) != 0) {
1020 self->errornumber = CONNECTION_COULD_NOT_SEND;
1021 self->errormsg = "Could not send function to backend";
1022 CC_set_no_trans(self);
1026 SOCK_put_string(sock, "F ");
1027 if (SOCK_get_errcode(sock) != 0) {
1028 self->errornumber = CONNECTION_COULD_NOT_SEND;
1029 self->errormsg = "Could not send function to backend";
1030 CC_set_no_trans(self);
1034 SOCK_put_int(sock, fnid, 4);
1035 SOCK_put_int(sock, nargs, 4);
1038 mylog("send_function: done sending function\n");
1040 for (i = 0; i < nargs; ++i) {
1042 mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n",
1043 i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
1045 SOCK_put_int(sock, args[i].len, 4);
1047 SOCK_put_int(sock, args[i].u.integer, 4);
1049 SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len);
1054 mylog(" done sending args\n");
1056 SOCK_flush_output(sock);
1057 mylog(" after flush output\n");
1061 id = SOCK_get_char(sock);
1062 mylog(" got id = %c\n", id);
1070 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
1071 mylog("send_function(V): 'N' - %s\n", msgbuffer);
1072 /* continue reading */
1076 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
1077 self->errormsg = msgbuffer;
1079 mylog("send_function(V): 'E' - %s\n", self->errormsg);
1080 qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
1085 self->errornumber = CONNECTION_BACKEND_CRAZY;
1086 self->errormsg = "Unexpected protocol character from backend";
1087 CC_set_no_trans(self);
1089 mylog("send_function: error - %s\n", self->errormsg);
1094 id = SOCK_get_char(sock);
1097 case 'G': /* function returned properly */
1100 *actual_result_len = SOCK_get_int(sock, 4);
1101 mylog(" actual_result_len = %d\n", *actual_result_len);
1104 *((int *) result_buf) = SOCK_get_int(sock, 4);
1106 SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len);
1108 mylog(" after get result\n");
1110 c = SOCK_get_char(sock); /* get the last '0' */
1112 mylog(" after get 0\n");
1117 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
1118 self->errormsg = msgbuffer;
1120 mylog("send_function(G): 'E' - %s\n", self->errormsg);
1121 qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
1126 SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
1128 mylog("send_function(G): 'N' - %s\n", msgbuffer);
1129 qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
1131 continue; // dont return a result -- continue reading
1133 case '0': /* empty result */
1137 self->errornumber = CONNECTION_BACKEND_CRAZY;
1138 self->errormsg = "Unexpected protocol character from backend";
1139 CC_set_no_trans(self);
1141 mylog("send_function: error - %s\n", self->errormsg);
1149 CC_send_settings(ConnectionClass *self)
1151 char ini_query[MAX_MESSAGE_LEN];
1152 ConnInfo *ci = &(self->connInfo);
1153 // QResultClass *res;
1155 StatementClass *stmt;
1159 /* This function must use the local odbc API functions since the odbc state
1160 has not transitioned to "connected" yet.
1162 result = _SQLAllocStmt( self, &hstmt);
1163 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1166 stmt = (StatementClass *) hstmt;
1168 ini_query[0] = '\0';
1170 /* Set the Datestyle to the format the driver expects it to be in */
1171 sprintf(ini_query, "set DateStyle to 'ISO'");
1173 /* Disable genetic optimizer based on global flag */
1174 if (globals.disable_optimizer)
1175 sprintf(&ini_query[strlen(ini_query)], "%sset geqo to 'OFF'",
1176 ini_query[0] != '\0' ? "; " : "");
1178 /* Global settings */
1179 if (globals.conn_settings[0] != '\0')
1180 sprintf(&ini_query[strlen(ini_query)], "%s%s",
1181 ini_query[0] != '\0' ? "; " : "",
1182 globals.conn_settings);
1184 /* Per Datasource settings */
1185 if (ci->conn_settings[0] != '\0')
1186 sprintf(&ini_query[strlen(ini_query)], "%s%s",
1187 ini_query[0] != '\0' ? "; " : "",
1190 if (ini_query[0] != '\0') {
1191 mylog("Sending Initial Connection query: '%s'\n", ini_query);
1193 result = _SQLExecDirect(hstmt, ini_query, SQL_NTS);
1194 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1195 _SQLFreeStmt(hstmt, SQL_DROP);
1199 _SQLFreeStmt(hstmt, SQL_DROP);
1205 /* This function is just a hack to get the oid of our Large Object oid type.
1206 If a real Large Object oid type is made part of Postgres, this function
1207 will go away and the define 'PG_TYPE_LO' will be updated.
1210 CC_lookup_lo(ConnectionClass *self)
1213 StatementClass *stmt;
1216 /* This function must use the local odbc API functions since the odbc state
1217 has not transitioned to "connected" yet.
1219 result = _SQLAllocStmt( self, &hstmt);
1220 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1223 stmt = (StatementClass *) hstmt;
1225 result = _SQLExecDirect(hstmt, "select oid from pg_type where typname='" \
1228 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1229 _SQLFreeStmt(hstmt, SQL_DROP);
1233 result = _SQLFetch(hstmt);
1234 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1235 _SQLFreeStmt(hstmt, SQL_DROP);
1239 result = _SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
1240 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1241 _SQLFreeStmt(hstmt, SQL_DROP);
1245 mylog("Got the large object oid: %d\n", self->lobj_type);
1246 qlog(" [ Large Object oid = %d ]\n", self->lobj_type);
1248 result = _SQLFreeStmt(hstmt, SQL_DROP);
1252 CC_log_error(char *func, char *desc, ConnectionClass *self)
1255 qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg);
1256 qlog(" ------------------------------------------------------------\n");
1257 qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
1258 qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
1260 qlog(" ---------------- Socket Info -------------------------------\n");
1262 SocketClass *sock = self->sock;
1263 qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, sock->errormsg);
1264 qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
1265 qlog(" buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
1269 qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
1274 CC_test(ConnectionClass *self)
1281 char name[255], type[255];
1282 SDWORD namelen, typelen;
1285 result = SQLAllocStmt( self, &hstmt1);
1286 if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
1290 result = SQLTables(hstmt1, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS, "", SQL_NTS);
1291 qlog("SQLTables result = %d\n", result);
1293 result = SQLNumResultCols(hstmt1, &cols);
1294 qlog("cols SQLTables result = %d\n", result);
1296 result = SQLBindCol(hstmt1, 3, SQL_C_CHAR, name, sizeof(name), &namelen);
1297 qlog("bind result = %d\n", result);
1299 result = SQLBindCol(hstmt1, 4, SQL_C_CHAR, type, sizeof(type), &typelen);
1300 qlog("bind result = %d\n", result);
1302 result = SQLFetch(hstmt1);
1303 qlog("SQLFetch result = %d\n", result);
1304 while (result != SQL_NO_DATA_FOUND) {
1305 qlog("fetch on stmt1: result=%d, namelen=%d: name='%s', typelen=%d, type='%s'\n", result, namelen, name, typelen, type);
1307 result = SQLFetch(hstmt1);
1309 qlog("SQLFetch result = %d\n", result);
1310 SQLFreeStmt(hstmt1, SQL_DROP);