📄 connection.c
字号:
QR_set_status(res, PGRES_COMMAND_OK); QR_set_command(res, cmdbuffer); /* (Quotation from the original comments) since backend may produce more than one result for some commands we need to poll until clear so we send an empty query, and keep reading out of the pipe until an 'I' is received */ SOCK_put_string(sock, "Q "); SOCK_flush_output(sock); while( ! clear) { id = SOCK_get_char(sock); switch(id) { case 'I': (void) SOCK_get_char(sock); clear = TRUE; break; case 'Z': break; case 'C': SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); qlog("Command response: '%s'\n", cmdbuffer); break; case 'N': SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); qlog("NOTICE from backend during clear: '%s'\n", cmdbuffer); break; case 'E': SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); qlog("ERROR from backend during clear: '%s'\n", cmdbuffer); break; } } mylog("send_query: returning res = %u\n", res); return res; } case 'K': /* Secret key (6.4 protocol) */ (void)SOCK_get_int(sock, 4); /* pid */ (void)SOCK_get_int(sock, 4); /* key */ break; case 'Z': /* Backend is ready for new query (6.4) */ break; case 'N' : /* NOTICE: */ SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH); res = QR_Constructor(); QR_set_status(res, PGRES_NONFATAL_ERROR); QR_set_notice(res, cmdbuffer); /* will dup this string */ mylog("~~~ NOTICE: '%s'\n", cmdbuffer); qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer); continue; // dont return a result -- continue reading case 'I' : /* The server sends an empty query */ /* There is a closing '\0' following the 'I', so we eat it */ swallow = SOCK_get_char(sock); if ((swallow != '\0') || SOCK_get_errcode(sock) != 0) { self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_query - I)"; res = QR_Constructor(); QR_set_status(res, PGRES_FATAL_ERROR); return res; } else { /* We return the empty query */ res = QR_Constructor(); QR_set_status(res, PGRES_EMPTY_QUERY); return res; } break; case 'E' : SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); /* Remove a newline */ if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer)-1] == '\n') msgbuffer[strlen(msgbuffer)-1] = '\0'; self->errormsg = msgbuffer; mylog("send_query: 'E' - %s\n", self->errormsg); qlog("ERROR from backend during send_query: '%s'\n", self->errormsg); if ( ! strncmp(self->errormsg, "FATAL", 5)) { self->errornumber = CONNECTION_SERVER_REPORTED_ERROR; CC_set_no_trans(self); } else self->errornumber = CONNECTION_SERVER_REPORTED_WARNING; return NULL; case 'P' : /* get the Portal name */ SOCK_get_string(sock, msgbuffer, MAX_MESSAGE_LEN); break; case 'T': /* Tuple results start here */ result_in = qi ? qi->result_in : NULL; if ( result_in == NULL) { result_in = QR_Constructor(); mylog("send_query: 'T' no result_in: res = %u\n", result_in); if ( ! result_in) { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = "Could not create result info in send_query."; return NULL; } if (qi) QR_set_cache_size(result_in, qi->row_size); if ( ! QR_fetch_tuples(result_in, self, qi ? qi->cursor : NULL)) { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = QR_get_message(result_in); return NULL; } } else { // next fetch, so reuse an existing result if ( ! QR_fetch_tuples(result_in, NULL, NULL)) { self->errornumber = CONNECTION_COULD_NOT_RECEIVE; self->errormsg = QR_get_message(result_in); return NULL; } } return result_in; case 'D': /* Copy in command began successfully */ res = QR_Constructor(); QR_set_status(res, PGRES_COPY_IN); return res; case 'B': /* Copy out command began successfully */ res = QR_Constructor(); QR_set_status(res, PGRES_COPY_OUT); return res; default: self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_query)"; CC_set_no_trans(self); mylog("send_query: error - %s\n", self->errormsg); return NULL; } }}intCC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs){char id, c, done;SocketClass *sock = self->sock;static char msgbuffer[MAX_MESSAGE_LEN+1];int i; mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs); if (SOCK_get_errcode(sock) != 0) { self->errornumber = CONNECTION_COULD_NOT_SEND; self->errormsg = "Could not send function to backend"; CC_set_no_trans(self); return FALSE; } SOCK_put_string(sock, "F "); if (SOCK_get_errcode(sock) != 0) { self->errornumber = CONNECTION_COULD_NOT_SEND; self->errormsg = "Could not send function to backend"; CC_set_no_trans(self); return FALSE; } SOCK_put_int(sock, fnid, 4); SOCK_put_int(sock, nargs, 4); mylog("send_function: done sending function\n"); for (i = 0; i < nargs; ++i) { mylog(" arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr); SOCK_put_int(sock, args[i].len, 4); if (args[i].isint) SOCK_put_int(sock, args[i].u.integer, 4); else SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len); } mylog(" done sending args\n"); SOCK_flush_output(sock); mylog(" after flush output\n"); done = FALSE; while ( ! done) { id = SOCK_get_char(sock); mylog(" got id = %c\n", id); switch(id) { case 'V': done = TRUE; break; /* ok */ case 'N': SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); mylog("send_function(V): 'N' - %s\n", msgbuffer); /* continue reading */ break; case 'E': SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); self->errormsg = msgbuffer; mylog("send_function(V): 'E' - %s\n", self->errormsg); qlog("ERROR from backend during send_function: '%s'\n", self->errormsg); return FALSE; case 'Z': break; default: self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_function, args)"; CC_set_no_trans(self); mylog("send_function: error - %s\n", self->errormsg); return FALSE; } } id = SOCK_get_char(sock); for (;;) { switch (id) { case 'G': /* function returned properly */ mylog(" got G!\n"); *actual_result_len = SOCK_get_int(sock, 4); mylog(" actual_result_len = %d\n", *actual_result_len); if (result_is_int) *((int *) result_buf) = SOCK_get_int(sock, 4); else SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len); mylog(" after get result\n"); c = SOCK_get_char(sock); /* get the last '0' */ mylog(" after get 0\n"); return TRUE; case 'E': SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); self->errormsg = msgbuffer; mylog("send_function(G): 'E' - %s\n", self->errormsg); qlog("ERROR from backend during send_function: '%s'\n", self->errormsg); return FALSE; case 'N': SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH); mylog("send_function(G): 'N' - %s\n", msgbuffer); qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer); continue; // dont return a result -- continue reading case '0': /* empty result */ return TRUE; default: self->errornumber = CONNECTION_BACKEND_CRAZY; self->errormsg = "Unexpected protocol character from backend (send_function, result)"; CC_set_no_trans(self); mylog("send_function: error - %s\n", self->errormsg); return FALSE; } }}charCC_send_settings(ConnectionClass *self){// char ini_query[MAX_MESSAGE_LEN];ConnInfo *ci = &(self->connInfo);// QResultClass *res;HSTMT hstmt;StatementClass *stmt;RETCODE result;char status = TRUE;char *cs, *ptr;static char *func="CC_send_settings"; mylog("%s: entering...\n", func);/* This function must use the local odbc API functions since the odbc state has not transitioned to "connected" yet.*/ result = SQLAllocStmt( self, &hstmt); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { return FALSE; } stmt = (StatementClass *) hstmt; stmt->internal = TRUE; /* ensure no BEGIN/COMMIT/ABORT stuff */ /* Set the Datestyle to the format the driver expects it to be in */ result = SQLExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) status = FALSE; mylog("%s: result %d, status %d from set DateStyle\n", func, result, status); /* Disable genetic optimizer based on global flag */ if (globals.disable_optimizer) { result = SQLExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) status = FALSE; mylog("%s: result %d, status %d from set geqo\n", func, result, status); } /* KSQO */ if (globals.ksqo) { result = SQLExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) status = FALSE; mylog("%s: result %d, status %d from set ksqo\n", func, result, status); } /* Global settings */ if (globals.conn_settings[0] != '\0') { cs = strdup(globals.conn_settings); ptr = strtok(cs, ";"); while (ptr) { result = SQLExecDirect(hstmt, ptr, SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) status = FALSE; mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); ptr = strtok(NULL, ";"); } free(cs); } /* Per Datasource settings */ if (ci->conn_settings[0] != '\0') { cs = strdup(ci->conn_settings); ptr = strtok(cs, ";"); while (ptr) { result = SQLExecDirect(hstmt, ptr, SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) status = FALSE; mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr); ptr = strtok(NULL, ";"); } free(cs); } SQLFreeStmt(hstmt, SQL_DROP); return status;}/* This function is just a hack to get the oid of our Large Object oid type. If a real Large Object oid type is made part of Postgres, this function will go away and the define 'PG_TYPE_LO' will be updated.*/voidCC_lookup_lo(ConnectionClass *self) {HSTMT hstmt;StatementClass *stmt;RETCODE result;static char *func = "CC_lookup_lo"; mylog( "%s: entering...\n", func);/* This function must use the local odbc API functions since the odbc state has not transitioned to "connected" yet.*/ result = SQLAllocStmt( self, &hstmt); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { return; } stmt = (StatementClass *) hstmt; result = SQLExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { SQLFreeStmt(hstmt, SQL_DROP); return; } result = SQLFetch(hstmt); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { SQLFreeStmt(hstmt, SQL_DROP); return; } result = SQLGetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL); if((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) { SQLFreeStmt(hstmt, SQL_DROP); return; } mylog("Got the large object oid: %d\n", self->lobj_type); qlog(" [ Large Object oid = %d ]\n", self->lobj_type); result = SQLFreeStmt(hstmt, SQL_DROP);}voidCC_log_error(char *func, char *desc, ConnectionClass *self){ if (self) { qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg); mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, self->errormsg); qlog(" ------------------------------------------------------------\n"); qlog(" henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts); qlog(" sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type); qlog(" ---------------- Socket Info -------------------------------\n"); if (self->sock) { SocketClass *sock = self->sock; qlog(" socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, sock->errormsg); qlog(" buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out); 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); } } else qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -