connection.c
来自「postgresql-odbc,跨平台应用」· C语言 代码 · 共 2,634 行 · 第 1/5 页
C
2,634 行
if (PROTOCOL_74(&(self->connInfo))) SOCK_put_char(sock, 'p'); SOCK_put_int(sock, (Int4) (4 + strlen(ci->password) + 1), 4); SOCK_put_n_char(sock, ci->password, (Int4) strlen(ci->password) + 1); sockerr = SOCK_flush_output(sock); mylog("past flush %dbytes\n", sockerr); break; case AUTH_REQ_CRYPT: CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Password crypt authentication not supported", func); return 0; case AUTH_REQ_MD5: mylog("in AUTH_REQ_MD5\n"); if (ci->password[0] == '\0') { CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.", func); if (salt_para) memcpy(salt_para, salt, sizeof(salt)); return -areq; /* need password */ } if (md5_auth_send(self, salt)) { CC_set_error(self, CONN_INVALID_AUTHENTICATION, "md5 hashing failed", func); return 0; } break; case AUTH_REQ_SCM_CREDS: CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unix socket credential authentication not supported", func); return 0; default: CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unknown authentication type", func); return 0; } break; case 'S': /* parameter status */ getParameterValues(self); break; case 'K': /* Secret key (6.4 protocol) */ self->be_pid = SOCK_get_int(sock, 4); /* pid */ self->be_key = SOCK_get_int(sock, 4); /* key */ break; case 'Z': /* Backend is ready for new query (6.4) */ EatReadyForQuery(self); ReadyForQuery = TRUE; break; case 'N': /* Notices may come */ handle_notice_message(self, notice, sizeof(notice), self->sqlstate, "CC_connect", NULL); break; default: snprintf(notice, sizeof(notice), "Unexpected protocol character='%c' during authentication", beresp); CC_set_error(self, CONN_INVALID_AUTHENTICATION, notice, func); return 0; } if (retry) { /* retry older version */ if (PROTOCOL_63(ci)) strncpy(ci->protocol, PG62, sizeof(ci->protocol)); else if (PROTOCOL_64(ci)) strncpy(ci->protocol, PG63, sizeof(ci->protocol)); else strncpy(ci->protocol, PG64, sizeof(ci->protocol)); SOCK_Destructor(sock); self->sock = (SocketClass *) 0; CC_initialize_pg_version(self); goto another_version_retry; } /* * There were no ReadyForQuery responce before 6.4. */ if (beforeV2 && areq == AUTH_REQ_OK) ReadyForQuery = TRUE; } while (!ReadyForQuery); }sockerr_proc: if (0 != (sockerr = SOCK_get_errcode(sock))) { if (0 == CC_get_errornumber(self)) { if (SOCKET_CLOSED == sockerr) CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Communication closed during authentication", func); else CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Communication error during authentication", func); } return 0; } CC_clear_error(self); /* clear any password error */ /* * send an empty query in order to find out whether the specified * database really exists on the server machine */ if (!PROTOCOL_74(ci)) { mylog("sending an empty query...\n"); res = CC_send_query(self, " ", NULL, 0, NULL); if (res == NULL || (QR_get_rstatus(res) != PORES_EMPTY_QUERY && QR_command_nonfatal(res))) { CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.", func); QR_Destructor(res); return 0; } QR_Destructor(res); mylog("empty query seems to be OK.\n"); /* * Get the version number first so we can check it before * sending options that are now obsolete. DJP 21/06/2002 */inolog("CC_lookup_pg_version\n"); CC_lookup_pg_version(self); /* Get PostgreSQL version for SQLGetInfo use */ CC_setenv(self); } return 1;} charCC_connect(ConnectionClass *self, char password_req, char *salt_para){ // StartupPacket sp; // StartupPacket6_2 sp62; // QResultClass *res; // SocketClass *sock; ConnInfo *ci = &(self->connInfo); // int areq = -1; // int beresp; // char msgbuffer[ERROR_MSG_LENGTH]; // char salt[5], notice[512]; CSTR func = "CC_connect"; char ret; // char *encoding; // BOOL startPacketReceived = FALSE; mylog("%s: entering...\n", func); mylog("sslmode=%s\n", self->connInfo.sslmode); if (self->connInfo.sslmode[0] != 'd' || self->connInfo.username[0] == '\0') ret = LIBPQ_CC_connect(self, password_req, salt_para); else { ret = original_CC_connect(self, password_req, salt_para); if (0 == ret && CONN_AUTH_TYPE_UNSUPPORTED == CC_get_errornumber(self)) { SOCK_Destructor(self->sock); self->sock = (SocketClass *) 0; ret = LIBPQ_CC_connect(self, password_req, salt_para); } } if (ret <= 0) return ret; CC_set_translation(self); /* * Send any initial settings */ /* * Since these functions allocate statements, and since the connection * is not established yet, it would violate odbc state transition * rules. Therefore, these functions call the corresponding local * function instead. */inolog("CC_send_settings\n"); CC_send_settings(self); CC_clear_error(self); /* clear any error */ CC_lookup_lo(self); /* a hack to get the oid of our large object oid type */ /* * Multibyte handling is available ? */ if (PG_VERSION_GE(self, 6.4)) { CC_lookup_characterset(self); if (CC_get_errornumber(self) > 0) return 0;#ifdef UNICODE_SUPPORT if (CC_is_in_unicode_driver(self)) { if (!self->original_client_encoding || UTF8 != self->ccsc) { QResultClass *res; if (PG_VERSION_LT(self, 7.1)) { CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1", func); return 0; } if (self->original_client_encoding) free(self->original_client_encoding); self->original_client_encoding = NULL; if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, 0, NULL), QR_command_maybe_successful(res)) { self->original_client_encoding = strdup("UNICODE"); self->ccsc = pg_CS_code(self->original_client_encoding); } QR_Destructor(res); } }#else { }#endif /* UNICODE_SUPPORT */ }#ifdef UNICODE_SUPPORT else if (CC_is_in_unicode_driver(self)) { CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4", func); return 0; }#endif /* UNICODE_SUPPORT */ ci->updatable_cursors = DISALLOW_UPDATABLE_CURSORS; if (ci->allow_keyset && PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */ { if (ci->drivers.lie || !ci->drivers.use_declarefetch) ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | ALLOW_KEYSET_DRIVEN_CURSORS | ALLOW_BULK_OPERATIONS | SENSE_SELF_OPERATIONS); else { if (PG_VERSION_GE(self, 7.4)) /* HOLDABLE CURSORS since 7.4 */ ci->updatable_cursors |= (ALLOW_STATIC_CURSORS | SENSE_SELF_OPERATIONS); } } if (CC_get_errornumber(self) > 0) CC_clear_error(self); /* clear any initial command errors */ self->status = CONN_CONNECTED; if (CC_is_in_unicode_driver(self) && 0 < ci->bde_environment) self->unicode |= CONN_DISALLOW_WCHAR;mylog("conn->unicode=%d\n", self->unicode); mylog("%s: returning...\n", func); return 1;}charCC_add_statement(ConnectionClass *self, StatementClass *stmt){ int i; char ret = TRUE; mylog("CC_add_statement: self=%p, stmt=%p\n", self, stmt); CONNLOCK_ACQUIRE(self); for (i = 0; i < self->num_stmts; i++) { if (!self->stmts[i]) { stmt->hdbc = self; self->stmts[i] = stmt; break; } } if (i >= self->num_stmts) /* no more room -- allocate more memory */ { self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts)); if (!self->stmts) ret = FALSE; else { memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT); stmt->hdbc = self; self->stmts[self->num_stmts] = stmt; self->num_stmts += STMT_INCREMENT; } } CONNLOCK_RELEASE(self); return TRUE;}static voidCC_set_error_statements(ConnectionClass *self){ int i; mylog("CC_error_statements: self=%p\n", self); for (i = 0; i < self->num_stmts; i++) { if (NULL != self->stmts[i]) SC_ref_CC_error(self->stmts[i]); }}charCC_remove_statement(ConnectionClass *self, StatementClass *stmt){ int i; char ret = FALSE; CONNLOCK_ACQUIRE(self); for (i = 0; i < self->num_stmts; i++) { if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING) { self->stmts[i] = NULL; ret = TRUE; break; } } CONNLOCK_RELEASE(self); return ret;}int CC_get_max_idlen(ConnectionClass *self){ int len = self->max_identifier_length; if (len < 0) { QResultClass *res; res = CC_send_query(self, "show max_identifier_length", NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL); if (QR_command_maybe_successful(res)) len = self->max_identifier_length = atoi(res->command); QR_Destructor(res); }mylog("max_identifier_length=%d\n", len); return len < 0 ? 0 : len; }/* * Create a more informative error message by concatenating the connection * error message with its socket error message. */static char *CC_create_errormsg(ConnectionClass *self){ SocketClass *sock = self->sock; size_t pos; char msg[4096]; const char *sockerrmsg; mylog("enter CC_create_errormsg\n"); msg[0] = '\0'; if (CC_get_errormsg(self)) strncpy(msg, CC_get_errormsg(self), sizeof(msg)); mylog("msg = '%s'\n", msg); if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0]) { pos = strlen(msg); snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg); } mylog("exit CC_create_errormsg\n"); return msg ? strdup(msg) : NULL;}voidCC_set_error(ConnectionClass *self, int number, const char *message, const char *func){ CONNLOCK_ACQUIRE(self); if (self->__error_message) free(self->__error_message); self->__error_number = number; self->__error_message = message ? strdup(message) : NULL; if (0 != number) CC_set_error_statements(self); if (func && number != 0) CC_log_error(func, "", self); CONNLOCK_RELEASE(self);}voidCC_set_errormsg(ConnectionClass *self, const char *message){ CONNLOCK_ACQUIRE(self); if (self->__error_message) free(self->__error_message); self->__error_message = message ? strdup(message) : NULL; CONNLOCK_RELEASE(self);}charCC_get_error(ConnectionClass *self, int *number, char **message){ int rv; char *msgcrt; mylog("enter CC_get_error\n"); CONNLOCK_ACQUIRE(self); /* Create a very informative errormsg if it hasn't been done yet. */ if (!self->errormsg_created) { msgcrt = CC_create_errormsg(self); if (self->__error_message) free(self->__error_message); self->__error_message = msgcrt; self->errormsg_created = TRUE; } if (CC_get_errornumber(self)) { *number = CC_get_errornumber(self); *message = CC_get_errormsg(self); } rv = (CC_get_errornumber(self) != 0); self->__error_number = 0; /* clear the error */ CONNLOCK_RELEASE(self); mylog("exit CC_get_error\n"); return rv;}static void CC_clear_cursors(ConnectionClass *self, BOOL on_abort){ int i; StatementClass *stmt; QResultClass *res; if (!self->ncursors) return; CONNLOCK_ACQUIRE(self); for (i = 0; i < self->num_stmts; i++) { stmt = self->stmts[i]; if (stmt && (res = SC_get_Result(stmt)) && QR_get_cursor(res)) { if ((on_abort && !QR_is_permanent(res)) || !QR_is_withhold(res)) /* * non-holdable cursors are automatically closed * at commit time. * all non-permanent cursors are automatically closed * at rollback time. */ QR_set_cursor(res, NULL); else if (!QR_is_permanent(res)) { QResultClass *wres; char cmd[64]; snprintf(cmd, sizeof(cmd), "MOVE 0 in \"%s\"", QR_get_cursor(res)); CONNLOCK_RELEASE(self); wres = CC_send_query(self, cmd, NULL, ROLLBACK_ON_ERROR | IGNORE_ABORT_ON_CONN, NULL); if (QR_command_maybe_successful(wres)) QR_set_permanent(res); else QR_set_cursor(res, NULL); QR_Destructor(wres); CONNLOCK_ACQUIRE(self); } } } CONNLOCK_RELEASE(self);} void CC_on_commit(ConnectionClass *conn){ CONNLOCK_ACQUIRE(conn); if (CC_is_in_trans(conn)) { CC_set_no_trans(conn); CC_set_no_manual_trans(conn); } CC_clear_cursors(conn, FALSE); CONNLOCK_RELEASE(conn); CC_discard_marked_objects(conn); CONNLOCK_ACQUIRE(conn); if (conn->result_uncommitted) { CONNLOCK_RELEASE(conn); ProcessRollback(conn, FALSE, FALSE); CONNLOCK_ACQUIRE(conn); conn->result_uncommitted = 0; } CONNLOCK_RELEASE(conn);}void CC_on_abort(ConnectionClass *conn, UDWORD opt){ BOOL set_no_trans = FALSE;mylog("CC_on_abort in\n"); CONNLOCK_ACQUIRE(conn); if (0 != (opt & CONN_DEAD)) /* CONN_DEAD implies NO_TRANS also */ opt |= NO_TRANS; if (CC_is_in_trans(conn)) { if (0 != (opt & NO_TRANS)) { CC_set_no_trans(conn); CC_set_no_manual_trans(conn); set_no_trans = TRUE; } } CC_clear_cursors(conn, TRUE); if (0 != (opt & CONN_DEAD)) { conn->status = CONN_DOWN; if (conn->sock) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?