Merge commit 'origin/master'
[versaplex.git] / vxodbc / connection.h
blob0872440f2403e235bb1e7cf9fdbf0c86d5aa796e
1 /* File: connection.h
3 * Description: See "connection.c"
5 * Comments: See "notice.txt" for copyright and license information.
7 */
9 #ifndef __CONNECTION_H__
10 #define __CONNECTION_H__
12 #include "psqlodbc.h"
14 #include <stdlib.h>
15 #include <string.h>
16 #include "descriptor.h"
18 #if defined (POSIX_MULTITHREAD_SUPPORT)
19 #include <pthread.h>
20 #endif
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 typedef enum
27 CONN_NOT_CONNECTED, /* Connection has not been established */
28 CONN_CONNECTED, /* Connection is up and has been established */
29 CONN_DOWN, /* Connection is broken */
30 CONN_EXECUTING /* the connection is currently executing a
31 * statement */
32 } CONN_Status;
34 enum
36 DISALLOW_UPDATABLE_CURSORS = 0, /* No cursors are updatable */
37 ALLOW_STATIC_CURSORS = 1L, /* Static cursors are updatable */
38 ALLOW_KEYSET_DRIVEN_CURSORS = (1L << 1), /* Keyset-driven cursors are updatable */
39 ALLOW_DYNAMIC_CURSORS = (1L << 2), /* Dynamic cursors are updatable */
40 ALLOW_BULK_OPERATIONS = (1L << 3), /* Bulk operations available */
41 SENSE_SELF_OPERATIONS = (1L << 4), /* Sense self update/delete/add */
44 /* These errors have general sql error state */
45 #define CONNECTION_SERVER_NOT_REACHED 101
46 #define CONNECTION_MSG_TOO_LONG 103
47 #define CONNECTION_COULD_NOT_SEND 104
48 #define CONNECTION_NO_SUCH_DATABASE 105
49 #define CONNECTION_BACKEND_CRAZY 106
50 #define CONNECTION_NO_RESPONSE 107
51 #define CONNECTION_SERVER_REPORTED_ERROR 108
52 #define CONNECTION_COULD_NOT_RECEIVE 109
53 #define CONNECTION_SERVER_REPORTED_WARNING 110
54 #define CONNECTION_NEED_PASSWORD 112
55 #define CONNECTION_COMMUNICATION_ERROR 113
57 #define CONN_TRUNCATED (-2)
58 #define CONN_OPTION_VALUE_CHANGED (-1)
59 /* These errors correspond to specific SQL states */
60 #define CONN_INIREAD_ERROR 201
61 #define CONN_OPENDB_ERROR 202
62 #define CONN_STMT_ALLOC_ERROR 203
63 #define CONN_IN_USE 204
64 #define CONN_UNSUPPORTED_OPTION 205
65 /* Used by SetConnectoption to indicate unsupported options */
66 #define CONN_INVALID_ARGUMENT_NO 206
67 /* SetConnectOption: corresponds to ODBC--"S1009" */
68 #define CONN_TRANSACT_IN_PROGRES 207
69 #define CONN_NO_MEMORY_ERROR 208
70 #define CONN_NOT_IMPLEMENTED_ERROR 209
71 #define CONN_INVALID_AUTHENTICATION 210
72 #define CONN_AUTH_TYPE_UNSUPPORTED 211
73 #define CONN_UNABLE_TO_LOAD_DLL 212
75 #define CONN_VALUE_OUT_OF_RANGE 214
77 #define CONN_OPTION_NOT_FOR_THE_DRIVER 216
78 #define CONN_EXEC_ERROR 217
80 /* Conn_status defines */
81 #define CONN_IN_AUTOCOMMIT 1L
82 #define CONN_IN_TRANSACTION (1L<<1)
83 #define CONN_IN_MANUAL_TRANSACTION (1L<<2)
84 #define CONN_IN_ERROR_BEFORE_IDLE (1L<<3)
86 #define CC_get_errornumber(x) (x->__error_number)
87 #define CC_get_errormsg(x) (x->__error_message)
88 #define CC_set_errornumber(x, n) (x->__error_number = n)
90 /* Unicode handling */
91 #define CONN_UNICODE_DRIVER (1L)
92 #define CONN_ANSI_APP (1L << 1)
93 #define CONN_DISALLOW_WCHAR (1L << 2)
94 #define CC_set_in_unicode_driver(x) (x->unicode |= CONN_UNICODE_DRIVER)
95 #define CC_set_in_ansi_app(x) (x->unicode |= CONN_ANSI_APP)
96 #define CC_is_in_unicode_driver(x) (0 != (x->unicode & CONN_UNICODE_DRIVER))
97 #define CC_is_in_ansi_app(x) (0 != (x->unicode & CONN_ANSI_APP))
98 #define ALLOW_WCHAR(x) (0 != (x->unicode & CONN_UNICODE_DRIVER) && 0 == (x->unicode & CONN_DISALLOW_WCHAR))
100 #define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \
101 do { \
102 if (t = (char *)malloc(s), NULL == t) \
104 CC_set_error(x, CONN_NO_MEMORY_ERROR, m, ""); \
105 return ret; \
107 } while (0)
108 #define CC_REALLOC_return_with_error(t, tp, s, x, m, ret) \
109 do { \
110 if (t = (tp *) realloc(t, s), NULL == t) \
112 CC_set_error(x, CONN_NO_MEMORY_ERROR, m, ""); \
113 return ret; \
115 } while (0)
117 /* For Multi-thread */
118 #if defined(WIN_MULTITHREAD_SUPPORT)
119 #define INIT_CONN_CS(x) InitializeCriticalSection(&((x)->cs))
120 #define INIT_CONNLOCK(x) InitializeCriticalSection(&((x)->slock))
121 #define ENTER_CONN_CS(x) EnterCriticalSection(&((x)->cs))
122 #define CONNLOCK_ACQUIRE(x) EnterCriticalSection(&((x)->slock))
123 #define TRY_ENTER_CONN_CS(x) TryEnterCriticalSection(&((x)->cs))
124 #define ENTER_INNER_CONN_CS(x, entered) \
125 do { \
126 EnterCriticalSection(&((x)->cs)); \
127 entered++; \
128 } while (0)
129 #define LEAVE_CONN_CS(x) LeaveCriticalSection(&((x)->cs))
130 #define CONNLOCK_RELEASE(x) LeaveCriticalSection(&((x)->slock))
131 #define DELETE_CONN_CS(x) DeleteCriticalSection(&((x)->cs))
132 #define DELETE_CONNLOCK(x) DeleteCriticalSection(&((x)->slock))
133 #elif defined(POSIX_THREADMUTEX_SUPPORT)
134 #define INIT_CONN_CS(x) pthread_mutex_init(&((x)->cs), getMutexAttr())
135 #define INIT_CONNLOCK(x) pthread_mutex_init(&((x)->slock), getMutexAttr())
136 #define ENTER_CONN_CS(x) pthread_mutex_lock(&((x)->cs))
137 #define CONNLOCK_ACQUIRE(x) pthread_mutex_lock(&((x)->slock))
138 #define TRY_ENTER_CONN_CS(x) (0 == pthread_mutex_trylock(&((x)->cs)))
139 #define ENTER_INNER_CONN_CS(x, entered) \
140 do { \
141 if (getMutexAttr()) \
143 if (pthread_mutex_lock(&((x)->cs)) == 0) \
144 entered++; \
146 } while (0)
147 #define LEAVE_CONN_CS(x) pthread_mutex_unlock(&((x)->cs))
148 #define CONNLOCK_RELEASE(x) pthread_mutex_unlock(&((x)->slock))
149 #define DELETE_CONN_CS(x) pthread_mutex_destroy(&((x)->cs))
150 #define DELETE_CONNLOCK(x) pthread_mutex_destroy(&((x)->slock))
151 #else
152 #define INIT_CONN_CS(x)
153 #define INIT_CONNLOCK(x)
154 #define TRY_ENTER_CONN_CS(x)
155 #define ENTER_CONN_CS(x)
156 #define CONNLOCK_ACQUIRE(x)
157 #define ENTER_INNER_CONN_CS(x, entered)
158 #define LEAVE_CONN_CS(x)
159 #define CONNLOCK_RELEASE(x)
160 #define DELETE_CONN_CS(x)
161 #define DELETE_CONNLOCK(x)
162 #endif /* WIN_MULTITHREAD_SUPPORT */
164 #define LEAVE_INNER_CONN_CS(entered, conn) \
165 do { \
166 if (entered > 0) \
168 LEAVE_CONN_CS(conn); \
169 entered--; \
171 } while (0)
172 #define CLEANUP_FUNC_CONN_CS(entered, conn) \
173 do { \
174 while (entered > 0) \
176 LEAVE_CONN_CS(conn); \
177 entered--; \
179 } while (0)
181 /* Authentication types */
182 #define AUTH_REQ_OK 0
183 #define AUTH_REQ_KRB4 1
184 #define AUTH_REQ_KRB5 2
185 #define AUTH_REQ_PASSWORD 3
186 #define AUTH_REQ_CRYPT 4
187 #define AUTH_REQ_MD5 5
188 #define AUTH_REQ_SCM_CREDS 6
190 /* Startup Packet sizes */
191 #define SM_DATABASE 64
192 #define SM_USER 32
193 #define SM_OPTIONS 64
194 #define SM_UNUSED 64
195 #define SM_TTY 64
197 /* Old 6.2 protocol defines */
198 #define NO_AUTHENTICATION 7
199 #define PATH_SIZE 64
200 #define ARGV_SIZE 64
201 #define USRNAMEDATALEN 16
203 typedef unsigned int ProtocolVersion;
205 #define PG_PROTOCOL(major, minor) (((major) << 16) | (minor))
206 #define PG_PROTOCOL_LATEST PG_PROTOCOL(3, 0)
207 #define PG_PROTOCOL_74 PG_PROTOCOL(3, 0)
208 #define PG_PROTOCOL_64 PG_PROTOCOL(2, 0)
209 #define PG_PROTOCOL_63 PG_PROTOCOL(1, 0)
210 #define PG_PROTOCOL_62 PG_PROTOCOL(0, 0)
212 /* This startup packet is to support latest Postgres protocol (6.4, 6.3) */
213 typedef struct _StartupPacket
215 ProtocolVersion protoVersion;
216 char database[SM_DATABASE];
217 char user[SM_USER];
218 char options[SM_OPTIONS];
219 char unused[SM_UNUSED];
220 char tty[SM_TTY];
221 } StartupPacket;
224 /* This startup packet is to support pre-Postgres 6.3 protocol */
225 typedef struct _StartupPacket6_2
227 unsigned int authtype;
228 char database[PATH_SIZE];
229 char user[USRNAMEDATALEN];
230 char options[ARGV_SIZE];
231 char execfile[ARGV_SIZE];
232 char tty[PATH_SIZE];
233 } StartupPacket6_2;
235 /* Transferred from pqcomm.h: */
238 typedef ProtocolVersion MsgType;
240 #define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
242 typedef struct CancelRequestPacket
244 /* Note that each field is stored in network byte order! */
245 MsgType cancelRequestCode; /* code to identify a cancel request */
246 unsigned int backendPID; /* PID of client's backend */
247 unsigned int cancelAuthCode; /* secret key to authorize cancel */
248 } CancelRequestPacket;
250 /* Structure to hold all the connection attributes for a specific
251 connection (used for both registry and file, DSN and DRIVER)
253 typedef struct
255 char dsn[MEDIUM_REGISTRY_LEN];
256 char desc[MEDIUM_REGISTRY_LEN];
257 char drivername[MEDIUM_REGISTRY_LEN];
258 char server[MEDIUM_REGISTRY_LEN];
259 char database[MEDIUM_REGISTRY_LEN];
260 char username[MEDIUM_REGISTRY_LEN];
261 char password[MEDIUM_REGISTRY_LEN];
262 char conn_settings[LARGE_REGISTRY_LEN];
263 char protocol[SMALL_REGISTRY_LEN];
264 char port[SMALL_REGISTRY_LEN];
265 char dbus_moniker[MEDIUM_REGISTRY_LEN];
266 char sslmode[SMALL_REGISTRY_LEN];
267 char onlyread[SMALL_REGISTRY_LEN];
268 char fake_oid_index[SMALL_REGISTRY_LEN];
269 char show_oid_column[SMALL_REGISTRY_LEN];
270 char row_versioning[SMALL_REGISTRY_LEN];
271 char show_system_tables[SMALL_REGISTRY_LEN];
272 char translation_dll[MEDIUM_REGISTRY_LEN];
273 char translation_option[SMALL_REGISTRY_LEN];
274 char focus_password;
275 signed char disallow_premature;
276 signed char allow_keyset;
277 signed char updatable_cursors;
278 signed char lf_conversion;
279 signed char true_is_minus1;
280 signed char int8_as;
281 signed char bytea_as_longvarbinary;
282 signed char use_server_side_prepare;
283 signed char lower_case_identifier;
284 signed char rollback_on_error;
285 signed char force_abbrev_connstr;
286 signed char bde_environment;
287 signed char fake_mss;
288 signed char cvt_null_date_string;
289 #ifdef _HANDLE_ENLIST_IN_DTC_
290 signed char xa_opt;
291 #endif /* _HANDLE_ENLIST_IN_DTC_ */
292 GLOBAL_VALUES drivers; /* moved from driver's option */
293 } ConnInfo;
295 /* Macro to determine is the connection using 6.2 protocol? */
296 #define PROTOCOL_62(conninfo_) (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0)
298 /* Macro to determine is the connection using 6.3 protocol? */
299 #define PROTOCOL_63(conninfo_) (strncmp((conninfo_)->protocol, PG63, strlen(PG63)) == 0)
301 /* Macro to determine is the connection using 6.4 protocol? */
302 #define PROTOCOL_64(conninfo_) (strncmp((conninfo_)->protocol, PG64, strlen(PG64)) == 0)
304 /* Macro to determine is the connection using 7.4 protocol? */
305 #define PROTOCOL_74(conninfo_) (strncmp((conninfo_)->protocol, PG74, strlen(PG74)) == 0)
307 #define SUPPORT_DESCRIBE_PARAM(conninfo_) (PROTOCOL_74(conninfo_) && conninfo_->use_server_side_prepare)
309 * Macros to compare the server's version with a specified version
310 * 1st parameter: pointer to a ConnectionClass object
311 * 2nd parameter: major version number
312 * 3rd parameter: minor version number
314 #define SERVER_VERSION_GT(conn, major, minor) \
315 ((conn)->pg_version_major > major || \
316 ((conn)->pg_version_major == major && (conn)->pg_version_minor > minor))
317 #define SERVER_VERSION_GE(conn, major, minor) \
318 ((conn)->pg_version_major > major || \
319 ((conn)->pg_version_major == major && (conn)->pg_version_minor >= minor))
320 #define SERVER_VERSION_EQ(conn, major, minor) \
321 ((conn)->pg_version_major == major && (conn)->pg_version_minor == minor)
322 #define SERVER_VERSION_LE(conn, major, minor) (! SERVER_VERSION_GT(conn, major, minor))
323 #define SERVER_VERSION_LT(conn, major, minor) (! SERVER_VERSION_GE(conn, major, minor))
324 /*#if ! defined(HAVE_CONFIG_H) || defined(HAVE_STRINGIZE)*/
325 #define STRING_AFTER_DOT(string) (strchr(#string, '.') + 1)
326 /*#else
327 #define STRING_AFTER_DOT(str) (strchr("str", '.') + 1)
328 #endif*/
330 * Simplified macros to compare the server's version with a
331 * specified version
332 * Note: Never pass a variable as the second parameter.
333 * It must be a decimal constant of the form %d.%d .
335 #define PG_VERSION_GT(conn, ver) \
336 (SERVER_VERSION_GT(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
337 #define PG_VERSION_GE(conn, ver) \
338 (SERVER_VERSION_GE(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
339 #define PG_VERSION_EQ(conn, ver) \
340 (SERVER_VERSION_EQ(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
341 #define PG_VERSION_LE(conn, ver) (! PG_VERSION_GT(conn, ver))
342 #define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver))
344 /* This is used to store cached table information in the connection */
345 struct col_info
347 Int2 num_reserved_cols;
348 QResultClass *result;
349 pgNAME schema_name;
350 pgNAME table_name;
351 OID table_oid;
353 #define col_info_initialize(coli) (memset(coli, 0, sizeof(COL_INFO)))
355 /* Translation DLL entry points */
356 #ifdef WIN32
357 #define DLLHANDLE HINSTANCE
358 #else
359 #define WINAPI CALLBACK
360 #define DLLHANDLE void *
361 #define HINSTANCE void *
362 #endif
364 typedef BOOL (FAR WINAPI * DataSourceToDriverProc) (UDWORD, SWORD, PTR,
365 SDWORD, PTR, SDWORD, SDWORD FAR *, UCHAR FAR *, SWORD,
366 SWORD FAR *);
367 typedef BOOL (FAR WINAPI * DriverToDataSourceProc) (UDWORD, SWORD, PTR,
368 SDWORD, PTR, SDWORD, SDWORD FAR *, UCHAR FAR *, SWORD,
369 SWORD FAR *);
371 class WvDBusConn;
373 /******* The Connection handle ************/
374 struct ConnectionClass_
376 EnvironmentClass *henv; /* environment this connection was
377 * created on */
378 WvDBusConn *dbus;
379 SQLUINTEGER login_timeout;
380 StatementOptions stmtOptions;
381 ARDFields ardOptions;
382 APDFields apdOptions;
383 char *__error_message;
384 int __error_number;
385 char sqlstate[8];
386 CONN_Status status;
387 ConnInfo connInfo;
388 StatementClass **stmts;
389 Int2 num_stmts;
390 Int2 ncursors;
391 Int2 coli_allocated;
392 Int2 ntables;
393 COL_INFO **col_info;
394 long translation_option;
395 HINSTANCE translation_handle;
396 DataSourceToDriverProc DataSourceToDriver;
397 DriverToDataSourceProc DriverToDataSource;
398 Int2 driver_version; /* prepared for ODBC3.0 */
399 char errormsg_created; /* has an informative error msg
400 * been created ? */
401 char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL
402 * we're connected to -
403 * DJP 25-1-2001 */
404 float pg_version_number;
405 Int2 pg_version_major;
406 Int2 pg_version_minor;
407 char ms_jet;
408 char unicode;
409 char schema_support;
410 char lo_is_domain;
411 char escape_in_literal;
412 char *original_client_encoding;
413 char *current_client_encoding;
414 char *server_encoding;
415 Int2 ccsc;
416 Int2 mb_maxbyte_per_char;
417 int be_pid; /* pid returned by backend */
418 int be_key; /* auth code needed to send cancel */
419 UInt4 isolation;
420 char *current_schema;
421 Int2 max_identifier_length;
422 Int2 num_discardp;
423 char **discardp;
424 int num_descs;
425 DescriptorClass **descs;
426 pgNAME schemaIns;
427 pgNAME tableIns;
428 #if defined(WIN_MULTITHREAD_SUPPORT)
429 CRITICAL_SECTION cs;
430 CRITICAL_SECTION slock;
431 #elif defined(POSIX_THREADMUTEX_SUPPORT)
432 pthread_mutex_t cs;
433 pthread_mutex_t slock;
434 #endif /* WIN_MULTITHREAD_SUPPORT */
435 #ifdef _HANDLE_ENLIST_IN_DTC_
436 void *asdum;
437 #endif /* _HANDLE_ENLIST_IN_DTC_ */
441 /* Accessor functions */
442 #define CC_get_socket(x) (x->sock)
443 #define CC_get_database(x) (x->connInfo.database)
444 #define CC_get_server(x) (x->connInfo.server)
445 #define CC_get_DSN(x) (x->connInfo.dsn)
446 #define CC_get_username(x) (x->connInfo.username)
447 #define CC_is_onlyread(x) (x->connInfo.onlyread[0] == '1')
448 #define CC_get_escape(x) (x->escape_in_literal)
449 #define CC_fake_mss(x) (/* 0 != (x)->ms_jet && */ 0 < (x)->connInfo.fake_mss)
450 #define CC_default_is_c(x) (CC_is_in_ansi_app(x) || x->ms_jet /* not only */ || TRUE /* but for any other ? */)
451 /* for CC_DSN_info */
452 #define CONN_DONT_OVERWRITE 0
453 #define CONN_OVERWRITE 1
456 /* prototypes */
457 ConnectionClass *CC_Constructor(void);
458 void CC_conninfo_init(ConnInfo *conninfo);
459 char CC_Destructor(ConnectionClass *self);
460 int CC_cursor_count(ConnectionClass *self);
461 char CC_cleanup(ConnectionClass *self);
462 char CC_begin(ConnectionClass *self);
463 char CC_commit(ConnectionClass *self);
464 char CC_abort(ConnectionClass *self);
465 int CC_set_translation(ConnectionClass *self);
466 char CC_add_statement(ConnectionClass *self, StatementClass *stmt);
467 char CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
469 char CC_add_descriptor(ConnectionClass *self, DescriptorClass *desc);
470 char CC_remove_descriptor(ConnectionClass *self, DescriptorClass *desc);
471 void CC_set_error(ConnectionClass *self, int number, const char *message, const char *func);
472 void CC_set_errormsg(ConnectionClass *self, const char *message);
473 char CC_get_error(ConnectionClass *self, int *number, char **message);
474 QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag, StatementClass *stmt);
475 void CC_clear_error(ConnectionClass *self);
476 char CC_send_settings(ConnectionClass *self);
477 void CC_initialize_pg_version(ConnectionClass *conn);
478 void CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
479 int CC_get_max_query_len(const ConnectionClass *self);
480 int CC_send_cancel_request(const ConnectionClass *conn);
481 void ProcessRollback(ConnectionClass *conn, BOOL undo, BOOL partial);
482 const char *CC_get_current_schema(ConnectionClass *conn);
483 int CC_mark_a_object_to_discard(ConnectionClass *conn, int type, const char *plan);
484 int CC_discard_marked_objects(ConnectionClass *conn);
486 const char *CurrCat(const ConnectionClass *self);
487 const char *CurrCatString(const ConnectionClass *self);
489 /* CC_send_query options */
490 enum {
491 IGNORE_ABORT_ON_CONN = 1L /* not set the error result even when */
492 ,CREATE_KEYSET = (1L << 1) /* create keyset for updatable curosrs */
493 // VX_CLEANUP: Neither GO_INTO_TRANSACTION nor ROLLBACK_ON_ERROR make
494 // sense any more
495 ,GO_INTO_TRANSACTION = (1L << 2) /* issue begin in advance */
496 , ROLLBACK_ON_ERROR = (1L << 3) /* rollback the query when an error occurs */
498 /* CC_on_abort options */
499 #define NO_TRANS 1L
500 #define CONN_DEAD (1L << 1) /* connection is no longer valid */
502 #ifdef __cplusplus
504 #endif
505 #endif /* __CONNECTION_H__ */