1 /* File: connection.h 2 * 3 * Description: See "connection.c" 4 * 5 * Comments: See "readme.txt" for copyright and license information. 6 * 7 */ 8 9 #ifndef __CONNECTION_H__ 10 #define __CONNECTION_H__ 11 12 #include "psqlodbc.h" 13 #include <libpq-fe.h> 14 #include "pqexpbuffer.h" 15 16 #include <time.h> 17 18 #include <stdlib.h> 19 #include <string.h> 20 #include "descriptor.h" 21 22 #if defined (POSIX_MULTITHREAD_SUPPORT) 23 #include <pthread.h> 24 #endif 25 26 #ifdef __cplusplus 27 extern "C" { 28 #endif 29 typedef enum 30 { 31 CONN_NOT_CONNECTED, /* Connection has not been established */ 32 CONN_CONNECTED, /* Connection is up and has been established */ 33 CONN_DOWN, /* Connection is broken */ 34 CONN_EXECUTING /* the connection is currently executing a 35 * statement */ 36 } CONN_Status; 37 38 /* These errors have general sql error state */ 39 #define CONNECTION_SERVER_NOT_REACHED 101 40 #define CONNECTION_MSG_TOO_LONG 103 41 #define CONNECTION_COULD_NOT_SEND 104 42 #define CONNECTION_NO_SUCH_DATABASE 105 43 #define CONNECTION_BACKEND_CRAZY 106 44 #define CONNECTION_NO_RESPONSE 107 45 #define CONNECTION_SERVER_REPORTED_SEVERITY_FATAL 108 46 #define CONNECTION_COULD_NOT_RECEIVE 109 47 #define CONNECTION_SERVER_REPORTED_SEVERITY_ERROR 110 48 #define CONNECTION_NEED_PASSWORD 112 49 #define CONNECTION_COMMUNICATION_ERROR 113 50 51 #define CONN_ERROR_IGNORED (-3) 52 #define CONN_TRUNCATED (-2) 53 #define CONN_OPTION_VALUE_CHANGED (-1) 54 /* These errors correspond to specific SQL states */ 55 #define CONN_INIREAD_ERROR 201 56 #define CONN_OPENDB_ERROR 202 57 #define CONN_STMT_ALLOC_ERROR 203 58 #define CONN_IN_USE 204 59 #define CONN_UNSUPPORTED_OPTION 205 60 /* Used by SetConnectoption to indicate unsupported options */ 61 #define CONN_INVALID_ARGUMENT_NO 206 62 /* SetConnectOption: corresponds to ODBC--"S1009" */ 63 #define CONN_TRANSACT_IN_PROGRES 207 64 #define CONN_NO_MEMORY_ERROR 208 65 #define CONN_NOT_IMPLEMENTED_ERROR 209 66 #define CONN_INVALID_AUTHENTICATION 210 67 #define CONN_AUTH_TYPE_UNSUPPORTED 211 68 #define CONN_UNABLE_TO_LOAD_DLL 212 69 #define CONN_ILLEGAL_TRANSACT_STATE 213 70 #define CONN_VALUE_OUT_OF_RANGE 214 71 72 #define CONN_OPTION_NOT_FOR_THE_DRIVER 216 73 #define CONN_EXEC_ERROR 217 74 75 /* Conn_status defines */ 76 #define CONN_IN_AUTOCOMMIT 1L 77 #define CONN_IN_TRANSACTION (1L<<1) 78 #define CONN_IN_MANUAL_TRANSACTION (1L<<2) 79 #define CONN_IN_ERROR_BEFORE_IDLE (1L<<3) 80 81 /* not connected yet || already disconnected */ 82 #define CC_not_connected(x) (!(x) || CONN_DOWN == (x)->status || CONN_NOT_CONNECTED == (x)->status) 83 84 /* AutoCommit functions */ 85 #define CC_is_in_autocommit(x) (x->transact_status & CONN_IN_AUTOCOMMIT) 86 #define CC_does_autocommit(x) (CONN_IN_AUTOCOMMIT == ((x)->transact_status & (CONN_IN_AUTOCOMMIT | CONN_IN_MANUAL_TRANSACTION))) 87 #define CC_loves_visible_trans(x) ((0 == ((x)->transact_status & CONN_IN_AUTOCOMMIT)) || (0 != ((x)->transact_status & CONN_IN_MANUAL_TRANSACTION))) 88 89 /* Transaction in/not functions */ 90 #define CC_set_in_trans(x) (x->transact_status |= CONN_IN_TRANSACTION) 91 #define CC_set_no_trans(x) (x->transact_status &= ~(CONN_IN_TRANSACTION | CONN_IN_ERROR_BEFORE_IDLE)) 92 #define CC_is_in_trans(x) (0 != (x->transact_status & CONN_IN_TRANSACTION)) 93 94 /* Manual transaction in/not functions */ 95 #define CC_set_in_manual_trans(x) (x->transact_status |= CONN_IN_MANUAL_TRANSACTION) 96 #define CC_set_no_manual_trans(x) (x->transact_status &= ~CONN_IN_MANUAL_TRANSACTION) 97 #define CC_is_in_manual_trans(x) (0 != (x->transact_status & CONN_IN_MANUAL_TRANSACTION)) 98 99 /* Error waiting for ROLLBACK */ 100 #define CC_set_in_error_trans(x) (x->transact_status |= CONN_IN_ERROR_BEFORE_IDLE) 101 #define CC_set_no_error_trans(x) (x->transact_status &= ~CONN_IN_ERROR_BEFORE_IDLE) 102 #define CC_is_in_error_trans(x) (x->transact_status & CONN_IN_ERROR_BEFORE_IDLE) 103 104 #define CC_get_errornumber(x) (x->__error_number) 105 #define CC_get_errormsg(x) (x->__error_message) 106 #define CC_set_errornumber(x, n) (x->__error_number = n) 107 108 /* Unicode handling */ 109 #define CONN_UNICODE_DRIVER (1L) 110 #define CONN_ANSI_APP (1L << 1) 111 #define CONN_DISALLOW_WCHAR (1L << 2) 112 #define CC_set_in_unicode_driver(x) (x->unicode |= CONN_UNICODE_DRIVER) 113 #define CC_set_in_ansi_app(x) (x->unicode |= CONN_ANSI_APP) 114 #define CC_is_in_unicode_driver(x) (0 != (x->unicode & CONN_UNICODE_DRIVER)) 115 #define CC_is_in_ansi_app(x) (0 != (x->unicode & CONN_ANSI_APP)) 116 #define CC_is_in_global_trans(x) (NULL != (x)->asdum) 117 #define ALLOW_WCHAR(x) (0 != (x->unicode & CONN_UNICODE_DRIVER) && 0 == (x->unicode & CONN_DISALLOW_WCHAR)) 118 119 #define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \ 120 do { \ 121 if (t = malloc(s), NULL == t) \ 122 { \ 123 CC_set_error(x, CONN_NO_MEMORY_ERROR, m, ""); \ 124 return ret; \ 125 } \ 126 } while (0) 127 #define CC_REALLOC_return_with_error(t, tp, s, x, m, ret) \ 128 do { \ 129 tp *tmp; \ 130 if (tmp = (tp *) realloc(t, s), NULL == tmp) \ 131 { \ 132 CC_set_error(x, CONN_NO_MEMORY_ERROR, m, ""); \ 133 return ret; \ 134 } \ 135 t = tmp; \ 136 } while (0) 137 138 /* For Multi-thread */ 139 #if defined(WIN_MULTITHREAD_SUPPORT) 140 #define INIT_CONN_CS(x) InitializeCriticalSection(&((x)->cs)) 141 #define INIT_CONNLOCK(x) InitializeCriticalSection(&((x)->slock)) 142 #define ENTER_CONN_CS(x) EnterCriticalSection(&((x)->cs)) 143 #define CONNLOCK_ACQUIRE(x) EnterCriticalSection(&((x)->slock)) 144 #define TRY_ENTER_CONN_CS(x) TryEnterCriticalSection(&((x)->cs)) 145 #define ENTER_INNER_CONN_CS(x, entered) \ 146 do { \ 147 EnterCriticalSection(&((x)->cs)); \ 148 entered++; \ 149 } while (0) 150 #define LEAVE_CONN_CS(x) LeaveCriticalSection(&((x)->cs)) 151 #define CONNLOCK_RELEASE(x) LeaveCriticalSection(&((x)->slock)) 152 #define DELETE_CONN_CS(x) DeleteCriticalSection(&((x)->cs)) 153 #define DELETE_CONNLOCK(x) DeleteCriticalSection(&((x)->slock)) 154 #elif defined(POSIX_THREADMUTEX_SUPPORT) 155 #define INIT_CONN_CS(x) pthread_mutex_init(&((x)->cs), getMutexAttr()) 156 #define INIT_CONNLOCK(x) pthread_mutex_init(&((x)->slock), getMutexAttr()) 157 #define ENTER_CONN_CS(x) pthread_mutex_lock(&((x)->cs)) 158 #define CONNLOCK_ACQUIRE(x) pthread_mutex_lock(&((x)->slock)) 159 #define TRY_ENTER_CONN_CS(x) (0 == pthread_mutex_trylock(&((x)->cs))) 160 #define ENTER_INNER_CONN_CS(x, entered) \ 161 do { \ 162 if (getMutexAttr()) \ 163 { \ 164 if (pthread_mutex_lock(&((x)->cs)) == 0) \ 165 entered++; \ 166 } \ 167 } while (0) 168 #define LEAVE_CONN_CS(x) pthread_mutex_unlock(&((x)->cs)) 169 #define CONNLOCK_RELEASE(x) pthread_mutex_unlock(&((x)->slock)) 170 #define DELETE_CONN_CS(x) pthread_mutex_destroy(&((x)->cs)) 171 #define DELETE_CONNLOCK(x) pthread_mutex_destroy(&((x)->slock)) 172 #else 173 #define INIT_CONN_CS(x) 174 #define INIT_CONNLOCK(x) 175 #define TRY_ENTER_CONN_CS(x) (1) 176 #define ENTER_CONN_CS(x) 177 #define CONNLOCK_ACQUIRE(x) 178 #define ENTER_INNER_CONN_CS(x, entered) 179 #define LEAVE_CONN_CS(x) 180 #define CONNLOCK_RELEASE(x) 181 #define DELETE_CONN_CS(x) 182 #define DELETE_CONNLOCK(x) 183 #endif /* WIN_MULTITHREAD_SUPPORT */ 184 185 #define LEAVE_INNER_CONN_CS(entered, conn) \ 186 do { \ 187 if (entered > 0) \ 188 { \ 189 LEAVE_CONN_CS(conn); \ 190 entered--; \ 191 } \ 192 } while (0) 193 #define CLEANUP_FUNC_CONN_CS(entered, conn) \ 194 do { \ 195 while (entered > 0) \ 196 { \ 197 LEAVE_CONN_CS(conn); \ 198 entered--; \ 199 } \ 200 } while (0) 201 202 /* 203 * Macros to compare the server's version with a specified version 204 * 1st parameter: pointer to a ConnectionClass object 205 * 2nd parameter: major version number 206 * 3rd parameter: minor version number 207 */ 208 #define SERVER_VERSION_GT(conn, major, minor) \ 209 ((conn)->pg_version_major > major || \ 210 ((conn)->pg_version_major == major && (conn)->pg_version_minor > minor)) 211 #define SERVER_VERSION_GE(conn, major, minor) \ 212 ((conn)->pg_version_major > major || \ 213 ((conn)->pg_version_major == major && (conn)->pg_version_minor >= minor)) 214 #define SERVER_VERSION_EQ(conn, major, minor) \ 215 ((conn)->pg_version_major == major && (conn)->pg_version_minor == minor) 216 #define STRING_AFTER_DOT(string) (strchr(#string, '.') + 1) 217 218 /* 219 * Simplified macros to compare the server's version with a 220 * specified version 221 * Note: Never pass a variable as the second parameter. 222 * It must be a decimal constant of the form %d.%d . 223 */ 224 #define PG_VERSION_GT(conn, ver) \ 225 (SERVER_VERSION_GT(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) 226 #define PG_VERSION_GE(conn, ver) \ 227 (SERVER_VERSION_GE(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) 228 #define PG_VERSION_EQ(conn, ver) \ 229 (SERVER_VERSION_EQ(conn, (int) ver, atoi(STRING_AFTER_DOT(ver)))) 230 #define PG_VERSION_LE(conn, ver) (! PG_VERSION_GT(conn, ver)) 231 #define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver)) 232 233 /* This is used to store cached table information in the connection */ 234 struct col_info 235 { 236 Int2 refcnt; 237 QResultClass *result; 238 pgNAME schema_name; 239 pgNAME table_name; 240 OID table_oid; 241 int table_info; 242 time_t acc_time; 243 }; 244 enum { 245 TBINFO_HASOIDS = 1L 246 ,TBINFO_HASSUBCLASS = (1L << 1) 247 }; 248 #define free_col_info_contents(coli) \ 249 { \ 250 if (NULL != coli->result) \ 251 QR_Destructor(coli->result); \ 252 coli->result = NULL; \ 253 NULL_THE_NAME(coli->schema_name); \ 254 NULL_THE_NAME(coli->table_name); \ 255 coli->table_oid = 0; \ 256 coli->refcnt = 0; \ 257 coli->acc_time = 0; \ 258 } 259 #define col_info_initialize(coli) (memset(coli, 0, sizeof(COL_INFO))) 260 261 /* Translation DLL entry points */ 262 #ifdef WIN32 263 #define DLLHANDLE HINSTANCE 264 #else 265 #define WINAPI CALLBACK 266 #define DLLHANDLE void * 267 #define HINSTANCE void * 268 #endif 269 270 typedef BOOL (WINAPI * DataSourceToDriverProc) (UDWORD, SWORD, PTR, 271 SDWORD, PTR, SDWORD, SDWORD *, UCHAR *, SWORD, 272 SWORD *); 273 typedef BOOL (WINAPI * DriverToDataSourceProc) (UDWORD, SWORD, PTR, 274 SDWORD, PTR, SDWORD, SDWORD *, UCHAR *, SWORD, 275 SWORD *); 276 277 /******* The Connection handle ************/ 278 struct ConnectionClass_ 279 { 280 HENV henv; /* environment this connection was 281 * created on */ 282 SQLUINTEGER login_timeout; 283 signed char autocommit_public; 284 StatementOptions stmtOptions; 285 ARDFields ardOptions; 286 APDFields apdOptions; 287 char *__error_message; 288 int __error_number; 289 char sqlstate[8]; 290 CONN_Status status; 291 ConnInfo connInfo; 292 StatementClass **stmts; 293 Int2 num_stmts; 294 Int2 ncursors; 295 PGconn *pqconn; 296 Int4 lobj_type; 297 Int2 coli_allocated; 298 Int2 ntables; 299 COL_INFO **col_info; 300 long translation_option; 301 HINSTANCE translation_handle; 302 DataSourceToDriverProc DataSourceToDriver; 303 DriverToDataSourceProc DriverToDataSource; 304 char transact_status; /* Is a transaction is currently 305 * in progress */ 306 char pg_version[MAX_INFO_STRING]; /* Version of PostgreSQL 307 * we're connected to - 308 * DJP 25-1-2001 */ 309 Int2 pg_version_major; 310 Int2 pg_version_minor; 311 char ms_jet; 312 char unicode; 313 char result_uncommitted; 314 char lo_is_domain; 315 char current_schema_valid; /* is current_schema valid? TRUE when 316 * current_schema == NULL means it's 317 * really NULL, while FALSE means it's 318 * unknown */ 319 unsigned char on_commit_in_progress; 320 /* for per statement rollback */ 321 char internal_svp; /* is set? */ 322 char internal_op; /* operation being executed as to internal savepoint */ 323 unsigned char rbonerr; 324 unsigned char opt_in_progress; 325 unsigned char opt_previous; 326 327 char *original_client_encoding; 328 char *locale_encoding; 329 char *server_encoding; 330 Int2 ccsc; 331 Int2 mb_maxbyte_per_char; 332 SQLUINTEGER isolation; /* isolation level initially unknown */ 333 SQLUINTEGER server_isolation; /* isolation at server initially unknown */ 334 char *current_schema; 335 StatementClass *unnamed_prepared_stmt; 336 Int2 max_identifier_length; 337 Int2 num_discardp; 338 char **discardp; 339 int num_descs; 340 SQLUINTEGER default_isolation; /* server's default isolation initially unkown */ 341 DescriptorClass **descs; 342 pgNAME schemaIns; 343 pgNAME tableIns; 344 SQLULEN stmt_timeout_in_effect; 345 #if defined(WIN_MULTITHREAD_SUPPORT) 346 CRITICAL_SECTION cs; 347 CRITICAL_SECTION slock; 348 #elif defined(POSIX_THREADMUTEX_SUPPORT) 349 pthread_mutex_t cs; 350 pthread_mutex_t slock; 351 #endif /* WIN_MULTITHREAD_SUPPORT */ 352 #ifdef _HANDLE_ENLIST_IN_DTC_ 353 UInt4 gTranInfo; 354 void *asdum; 355 #endif /* _HANDLE_ENLIST_IN_DTC_ */ 356 }; 357 358 359 /* Accessor functions */ 360 #define CC_get_env(x) ((x)->henv) 361 #define CC_get_database(x) (x->connInfo.database) 362 #define CC_get_server(x) (x->connInfo.server) 363 #define CC_get_DSN(x) (x->connInfo.dsn) 364 #define CC_get_username(x) (x->connInfo.username) 365 #define CC_is_onlyread(x) (x->connInfo.onlyread[0] == '1') 366 #define CC_fake_mss(x) (/* 0 != (x)->ms_jet && */ 0 < (x)->connInfo.fake_mss) 367 #define CC_accessible_only(x) (0 < (x)->connInfo.accessible_only) 368 #define CC_default_is_c(x) (CC_is_in_ansi_app(x) || x->ms_jet /* not only */ || TRUE /* but for any other ? */) 369 370 #ifdef _HANDLE_ENLIST_IN_DTC_ 371 enum { 372 DTC_IN_PROGRESS = 1L 373 ,DTC_ENLISTED = (1L << 1) 374 ,DTC_REQUEST_EXECUTING = (1L << 2) 375 ,DTC_ISOLATED = (1L << 3) 376 ,DTC_PREPARE_REQUESTED = (1L << 4) 377 }; 378 #define CC_set_dtc_clear(x) ((x)->gTranInfo = 0) 379 #define CC_set_dtc_enlisted(x) ((x)->gTranInfo |= (DTC_IN_PROGRESS | DTC_ENLISTED)) 380 #define CC_no_dtc_enlisted(x) ((x)->gTranInfo &= (~DTC_ENLISTED)) 381 #define CC_is_dtc_enlisted(x) (0 != ((x)->gTranInfo & DTC_ENLISTED)) 382 #define CC_set_dtc_executing(x) ((x)->gTranInfo |= DTC_REQUEST_EXECUTING) 383 #define CC_no_dtc_executing(x) ((x)->gTranInfo &= (~DTC_REQUEST_EXECUTING)) 384 #define CC_is_dtc_executing(x) (0 != ((x)->gTranInfo & DTC_REQUEST_EXECUTING)) 385 #define CC_set_dtc_prepareRequested(x) ((x)->gTranInfo |= (DTC_PREPARE_REQUESTED)) 386 #define CC_no_dtc_prepareRequested(x) ((x)->gTranInfo &= (~DTC_PREPARE_REQUESTED)) 387 #define CC_is_dtc_prepareRequested(x) (0 != ((x)->gTranInfo & DTC_PREPARE_REQUESTED)) 388 #define CC_is_dtc_executing(x) (0 != ((x)->gTranInfo & DTC_REQUEST_EXECUTING)) 389 #define CC_set_dtc_isolated(x) ((x)->gTranInfo |= DTC_ISOLATED) 390 #define CC_is_idle_in_global_transaction(x) (0 != ((x)->gTranInfo & DTC_PREPARE_REQUESTED) || (x)->gTranInfo == DTC_IN_PROGRESS) 391 #endif /* _HANDLE_ENLIST_IN_DTC_ */ 392 /* statement callback */ 393 #define CC_start_stmt(a) ((a)->rbonerr = 0) 394 #define CC_start_tc_stmt(a) ((a)->rbonerr = (1L << 1)) 395 #define CC_is_tc_stmt(a) (((a)->rbonerr & (1L << 1)) != 0) 396 #define CC_start_rb_stmt(a) ((a)->rbonerr = (1L << 2)) 397 #define CC_is_rb_stmt(a) (((a)->rbonerr & (1L << 2)) != 0) 398 #define CC_set_accessed_db(a) ((a)->rbonerr |= (1L << 3)) 399 #define CC_accessed_db(a) (((a)->rbonerr & (1L << 3)) != 0) 400 #define CC_start_rbpoint(a) ((a)->rbonerr |= (1L << 4), (a)->internal_svp = 1) 401 #define CC_started_rbpoint(a) (((a)->rbonerr & (1L << 4)) != 0) 402 403 /* prototypes */ 404 ConnectionClass *CC_Constructor(void); 405 char CC_Destructor(ConnectionClass *self); 406 int CC_cursor_count(ConnectionClass *self); 407 char CC_cleanup(ConnectionClass *self, BOOL keepCommunication); 408 char CC_begin(ConnectionClass *self); 409 char CC_commit(ConnectionClass *self); 410 char CC_abort(ConnectionClass *self); 411 char CC_set_autocommit(ConnectionClass *self, BOOL on); 412 int CC_set_translation(ConnectionClass *self); 413 char CC_connect(ConnectionClass *self, char *salt); 414 char CC_add_statement(ConnectionClass *self, StatementClass *stmt); 415 char CC_remove_statement(ConnectionClass *self, StatementClass *stmt) 416 ; 417 char CC_add_descriptor(ConnectionClass *self, DescriptorClass *desc); 418 char CC_remove_descriptor(ConnectionClass *self, DescriptorClass *desc); 419 void CC_set_error(ConnectionClass *self, int number, const char *message, const char *func); 420 void CC_set_errormsg(ConnectionClass *self, const char *message); 421 char CC_get_error(ConnectionClass *self, int *number, char **message); 422 QResultHold CC_send_query_append(ConnectionClass *self, const char *query, QueryInfo *qi, UDWORD flag, StatementClass *stmt, const char *appendq); 423 #define CC_send_query(self, query, qi, flag, stmt) CC_send_query_append(self, query, qi, flag, stmt, NULL).first 424 void handle_pgres_error(ConnectionClass *self, const PGresult *pgres, 425 const char *comment, 426 QResultClass *res, BOOL error_not_a_notice); 427 void CC_clear_error(ConnectionClass *self); 428 int CC_send_function(ConnectionClass *conn, const char *fn_name, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs); 429 char CC_send_settings(ConnectionClass *self, const char *set_query); 430 void CC_initialize_pg_version(ConnectionClass *conn); 431 void CC_log_error(const char *func, const char *desc, const ConnectionClass *self); 432 int CC_send_cancel_request(const ConnectionClass *conn); 433 void CC_on_commit(ConnectionClass *conn); 434 void CC_on_abort(ConnectionClass *conn, unsigned int opt); 435 void CC_on_abort_partial(ConnectionClass *conn); 436 void ProcessRollback(ConnectionClass *conn, BOOL undo, BOOL partial); 437 const char *CC_get_current_schema(ConnectionClass *conn); 438 int CC_mark_a_object_to_discard(ConnectionClass *conn, int type, const char *plan); 439 int CC_discard_marked_objects(ConnectionClass *conn); 440 441 int CC_get_max_idlen(ConnectionClass *self); 442 char CC_get_escape(const ConnectionClass *self); 443 char * identifierEscape(const SQLCHAR *src, SQLLEN srclen, const ConnectionClass *conn, char *buf, size_t bufsize, BOOL double_quote); 444 int findIdentifier(const UCHAR *str, int ccsc, const UCHAR **next_token); 445 int eatTableIdentifiers(const UCHAR *str, int ccsc, pgNAME *table, pgNAME *schema); 446 447 448 const char *CurrCat(const ConnectionClass *self); 449 const char *CurrCatString(const ConnectionClass *self); 450 SQLUINTEGER CC_get_isolation(ConnectionClass *self); 451 452 SQLCHAR *make_lstring_ifneeded(ConnectionClass *, const SQLCHAR *s, ssize_t len, BOOL); 453 454 #define TABLE_IS_VALID(tbname, tblen) ((tbname) && (tblen > 0 || SQL_NTS == tblen)) 455 int schema_str(char *buf, int buflen, const SQLCHAR *s, SQLLEN len, BOOL table_is_valid, ConnectionClass *conn); 456 char *schema_strcat(char *buf, int buflen, const char *fmt, const SQLCHAR *s, SQLLEN len, 457 BOOL table_is_valid, ConnectionClass *conn); 458 char *schema_strcat1(char *buf, int buflen, const char *fmt, const char *s1, 459 const char *s, 460 const SQLCHAR *, int, ConnectionClass *conn); 461 462 void schema_appendPQExpBuffer(PQExpBufferData *buf, const char *fmt, const SQLCHAR *s, SQLLEN len, 463 BOOL table_is_valid, ConnectionClass *conn); 464 void schema_appendPQExpBuffer1(PQExpBufferData *buf, const char *fmt, const char *s1, const char *s, 465 BOOL table_is_valid, ConnectionClass *conn); 466 467 void CC_examine_global_transaction(ConnectionClass *self); 468 469 470 BOOL CC_set_transact(ConnectionClass *self, UInt4 isolation); 471 int CC_send_client_encoding(ConnectionClass *self, const char *encoding); 472 473 /* CC_send_query options */ 474 enum { 475 IGNORE_ABORT_ON_CONN = 1L /* not set the error result even when */ 476 ,CREATE_KEYSET = (1L << 1) /* create keyset for updatable cursors */ 477 ,GO_INTO_TRANSACTION = (1L << 2) /* issue BEGIN in advance */ 478 ,ROLLBACK_ON_ERROR = (1L << 3) /* rollback the query when an error occurs */ 479 ,END_WITH_COMMIT = (1L << 4) /* the query ends with COMMIT command */ 480 ,READ_ONLY_QUERY = (1L << 5) /* the query is read-only */ 481 }; 482 /* CC_on_abort options */ 483 #define NO_TRANS 1L 484 #define CONN_DEAD (1L << 1) /* connection is no longer valid */ 485 486 /* 487 * This is a libpq notice receiver callback, for handling incoming NOTICE 488 * messages while processing a query. 489 */ 490 typedef struct 491 { 492 ConnectionClass *conn; 493 const char *comment; 494 QResultClass *res; 495 StatementClass *stmt; 496 } notice_receiver_arg; 497 498 void receive_libpq_notice(void *arg, const PGresult *pgres); 499 500 /* 501 * internal savepoint related 502 */ 503 504 #define _RELEASE_INTERNAL_SAVEPOINT 505 506 /* Internal rollback */ 507 enum { 508 PER_STATEMENT_ROLLBACK = 1 509 ,PER_QUERY_ROLLBACK 510 }; 511 int CC_internal_rollback(ConnectionClass *, int rollback_type, BOOL ignore_abort); 512 513 /* Commands generated */ 514 enum { 515 INTERNAL_SAVEPOINT_OPERATION = 1 516 ,INTERNAL_ROLLBACK_OPERATION 517 }; 518 int GenerateSvpCommand(ConnectionClass *conn, int type, char *cmd, int bufsize); 519 520 /* Operations in progress */ 521 enum { 522 SAVEPOINT_IN_PROGRESS = 1 523 ,PREPEND_IN_PROGRESS 524 }; 525 /* StatementSvp entry option */ 526 enum { 527 SVPOPT_RDONLY = 1L 528 ,SVPOPT_REDUCE_ROUNDTRIP = (1L << 1) 529 }; 530 #define INIT_SVPOPT (SVPOPT_RDONLY) 531 #define CC_svp_init(a) ((a)->internal_svp = (a)->internal_op = 0, (a)->opt_in_progress = (a)->opt_previous = INIT_SVPOPT) 532 #define CC_init_opt_in_progress(a) ((a)->opt_in_progress = INIT_SVPOPT) 533 #define CC_init_opt_previous(a) ((a)->opt_previous = INIT_SVPOPT) 534 535 #ifdef __cplusplus 536 } 537 #endif 538 #endif /* __CONNECTION_H__ */ 539