Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f8da399

Browse files
author
Hiroshi Inoue
committed
[HACKERS] Proposed patch for ODBC driver w/ C-a-n-c-e-l
From: Bradley McLean <brad@bradm.net> Patch against 7,2 submitted for comment. This seems to work just fine; Now, when our users submit a 2 hour query with four million row sorts by accident, then cancel it 30 seconds later, it doesn't bog down the server ...
1 parent c26a44d commit f8da399

File tree

12 files changed

+455
-107
lines changed

12 files changed

+455
-107
lines changed

src/interfaces/odbc/connection.c

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include <stdio.h>
2020
#include <string.h>
2121
#include <ctype.h>
22+
#ifndef WIN32
23+
#include <errno.h>
24+
#endif /* WIN32 */
2225

2326
#include "environ.h"
2427
#include "socket.h"
@@ -289,6 +292,7 @@ CC_Constructor()
289292
rv->ms_jet = 0;
290293
rv->unicode = 0;
291294
rv->result_uncommitted = 0;
295+
rv->schema_support = 0;
292296
#ifdef MULTIBYTE
293297
rv->client_encoding = NULL;
294298
rv->server_encoding = NULL;
@@ -882,8 +886,8 @@ CC_connect(ConnectionClass *self, char do_password)
882886
}
883887
break;
884888
case 'K': /* Secret key (6.4 protocol) */
885-
(void) SOCK_get_int(sock, 4); /* pid */
886-
(void) SOCK_get_int(sock, 4); /* key */
889+
self->be_pid = SOCK_get_int(sock, 4); /* pid */
890+
self->be_key = SOCK_get_int(sock, 4); /* key */
887891

888892
break;
889893
case 'Z': /* Backend is ready for new query (6.4) */
@@ -1960,6 +1964,8 @@ CC_lookup_pg_version(ConnectionClass *self)
19601964
self->pg_version_minor = minor;
19611965
}
19621966
self->pg_version_number = (float) atof(szVersion);
1967+
if (PG_VERSION_GE(self, 7.3))
1968+
self->schema_support = 1;
19631969

19641970
mylog("Got the PostgreSQL version string: '%s'\n", self->pg_version);
19651971
mylog("Extracted PostgreSQL version number: '%1.1f'\n", self->pg_version_number);
@@ -2019,3 +2025,64 @@ CC_get_max_query_len(const ConnectionClass *conn)
20192025
value = BLCKSZ;
20202026
return value;
20212027
}
2028+
2029+
int
2030+
CC_send_cancel_request(const ConnectionClass *conn)
2031+
{
2032+
#ifdef WIN32
2033+
int save_errno = (WSAGetLastError());
2034+
#else
2035+
int save_errno = errno;
2036+
#endif
2037+
int tmpsock = -1;
2038+
struct
2039+
{
2040+
uint32 packetlen;
2041+
CancelRequestPacket cp;
2042+
} crp;
2043+
2044+
/* Check we have an open connection */
2045+
if (!conn)
2046+
return FALSE;
2047+
2048+
if (conn->sock == NULL )
2049+
{
2050+
return FALSE;
2051+
}
2052+
2053+
/*
2054+
* We need to open a temporary connection to the postmaster. Use the
2055+
* information saved by connectDB to do this with only kernel calls.
2056+
*/
2057+
if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
2058+
{
2059+
return FALSE;
2060+
}
2061+
if (connect(tmpsock, (struct sockaddr *)&(conn->sock->sadr),
2062+
sizeof(conn->sock->sadr)) < 0)
2063+
{
2064+
return FALSE;
2065+
}
2066+
2067+
/*
2068+
* We needn't set nonblocking I/O or NODELAY options here.
2069+
*/
2070+
crp.packetlen = htonl((uint32) sizeof(crp));
2071+
crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
2072+
crp.cp.backendPID = htonl(conn->be_pid);
2073+
crp.cp.cancelAuthCode = htonl(conn->be_key);
2074+
2075+
if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
2076+
{
2077+
return FALSE;
2078+
}
2079+
2080+
/* Sent it, done */
2081+
closesocket(tmpsock);
2082+
#ifdef WIN32
2083+
WSASetLastError(save_errno);
2084+
#else
2085+
errno = save_errno;
2086+
#endif
2087+
return TRUE;
2088+
}

src/interfaces/odbc/connection.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ typedef struct _StartupPacket6_2
126126
char tty[PATH_SIZE];
127127
} StartupPacket6_2;
128128

129+
/* Transferred from pqcomm.h: */
130+
131+
132+
typedef ProtocolVersion MsgType;
133+
134+
#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
135+
#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
136+
137+
typedef struct CancelRequestPacket
138+
{
139+
/* Note that each field is stored in network byte order! */
140+
MsgType cancelRequestCode; /* code to identify a cancel request */
141+
unsigned int backendPID; /* PID of client's backend */
142+
unsigned int cancelAuthCode; /* secret key to authorize cancel */
143+
} CancelRequestPacket;
129144

130145
/* Structure to hold all the connection attributes for a specific
131146
connection (used for both registry and file, DSN and DRIVER)
@@ -273,11 +288,14 @@ struct ConnectionClass_
273288
char ms_jet;
274289
char unicode;
275290
char result_uncommitted;
291+
char schema_support;
276292
#ifdef MULTIBYTE
277293
char *client_encoding;
278294
char *server_encoding;
279295
#endif /* MULTIBYTE */
280296
int ccsc;
297+
int be_pid; /* pid returned by backend */
298+
int be_key; /* auth code needed to send cancel */
281299
};
282300

283301

@@ -319,6 +337,7 @@ void CC_lookup_pg_version(ConnectionClass *conn);
319337
void CC_initialize_pg_version(ConnectionClass *conn);
320338
void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
321339
int CC_get_max_query_len(const ConnectionClass *self);
340+
int CC_send_cancel_request(const ConnectionClass *conn);
322341
void CC_on_commit(ConnectionClass *conn);
323342
void CC_on_abort(ConnectionClass *conn, BOOL set_no_trans);
324343
void ProcessRollback(ConnectionClass *conn, BOOL undo);

src/interfaces/odbc/descriptor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Comments: See "notice.txt" for copyright and license information.
77
*
8-
* $Id: descriptor.h,v 1.2 2002/04/01 03:01:14 inoue Exp $
8+
* $Id: descriptor.h,v 1.3 2002/04/02 10:50:44 inoue Exp $
99
*
1010
*/
1111

@@ -17,6 +17,7 @@
1717
typedef struct
1818
{
1919
COL_INFO *col_info; /* cached SQLColumns info for this table */
20+
char schema[MAX_TABLE_LEN + 1];
2021
char name[MAX_TABLE_LEN + 1];
2122
char alias[MAX_TABLE_LEN + 1];
2223
} TABLE_INFO;

src/interfaces/odbc/execute.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ PGAPI_Cancel(
573573
{
574574
static char *func = "PGAPI_Cancel";
575575
StatementClass *stmt = (StatementClass *) hstmt;
576+
ConnectionClass *conn;
576577
RETCODE result;
577578
ConnInfo *ci;
578579

@@ -589,14 +590,20 @@ PGAPI_Cancel(
589590
SC_log_error(func, "", NULL);
590591
return SQL_INVALID_HANDLE;
591592
}
592-
ci = &(SC_get_conn(stmt)->connInfo);
593+
conn = SC_get_conn(stmt);
594+
ci = &(conn->connInfo);
593595

594596
/*
595597
* Not in the middle of SQLParamData/SQLPutData so cancel like a
596598
* close.
597599
*/
598600
if (stmt->data_at_exec < 0)
599601
{
602+
/*
603+
* Tell the Backend that we're cancelling this request
604+
*/
605+
if (stmt->status == STMT_EXECUTING)
606+
CC_send_cancel_request(conn);
600607
/*
601608
* MAJOR HACK for Windows to reset the driver manager's cursor
602609
* state: Because of what seems like a bug in the Odbc driver

0 commit comments

Comments
 (0)