diff options
Diffstat (limited to 'src/interfaces/ecpg/lib/connect.c')
-rw-r--r-- | src/interfaces/ecpg/lib/connect.c | 123 |
1 files changed, 122 insertions, 1 deletions
diff --git a/src/interfaces/ecpg/lib/connect.c b/src/interfaces/ecpg/lib/connect.c index 416fcf17dd4..59a3f794851 100644 --- a/src/interfaces/ecpg/lib/connect.c +++ b/src/interfaces/ecpg/lib/connect.c @@ -27,6 +27,8 @@ ecpg_finish(struct connection * act) { if (act != NULL) { + struct ECPGtype_information_cache *cache, *ptr; + ECPGlog("ecpg_finish: finishing %s.\n", act->name); PQfinish(act->connection); @@ -45,6 +47,7 @@ ecpg_finish(struct connection * act) if (actual_connection == act) actual_connection = all_connections; + for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, free(ptr)); free(act->name); free(act); } @@ -107,6 +110,120 @@ ECPGsetconn(int lineno, const char *connection_name) return true; } +static void +ECPGnoticeProcessor_raise(int code, const char *message) +{ + sqlca.sqlcode = code; + strncpy(sqlca.sqlerrm.sqlerrmc, message, sizeof(sqlca.sqlerrm.sqlerrmc)); + sqlca.sqlerrm.sqlerrmc[sizeof(sqlca.sqlerrm.sqlerrmc)-1]=0; + sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); + + // remove trailing newline + if (sqlca.sqlerrm.sqlerrml + && sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml-1]=='\n') + { + sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml-1]=0; + sqlca.sqlerrm.sqlerrml--; + } + + ECPGlog("raising sqlcode %d\n",code); +} + +/* + * I know this is a mess, but we can't redesign the backend + */ + +static void +ECPGnoticeProcessor(void *arg, const char *message) +{ + /* these notices raise an error */ + if (strncmp(message,"NOTICE: ",8)) + { + ECPGlog("ECPGnoticeProcessor: strange notice '%s'\n", message); + ECPGnoticeProcessor_raise(ECPG_NOTICE_UNRECOGNIZED, message); + return; + } + + message+=8; + while (*message==' ') message++; + ECPGlog("NOTICE: %s", message); + + /* NOTICE: (transaction aborted): queries ignored until END */ + /* NOTICE: current transaction is aborted, queries ignored until end of transaction block */ + if (strstr(message,"queries ignored") && strstr(message,"transaction") + && strstr(message,"aborted")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_QUERY_IGNORED, message); + return; + } + + /* NOTICE: PerformPortalClose: portal "*" not found */ + if (!strncmp(message,"PerformPortalClose: portal",26) + && strstr(message+26,"not found")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_UNKNOWN_PORTAL, message); + return; + } + + /* NOTICE: BEGIN: already a transaction in progress */ + if (!strncmp(message,"BEGIN: already a transaction in progress",40)) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_IN_TRANSACTION, message); + return; + } + + /* NOTICE: AbortTransaction and not in in-progress state */ + /* NOTICE: COMMIT: no transaction in progress */ + /* NOTICE: ROLLBACK: no transaction in progress */ + if (!strncmp(message,"AbortTransaction and not in in-progress state",45) + || !strncmp(message,"COMMIT: no transaction in progress",34) + || !strncmp(message,"ROLLBACK: no transaction in progress",36)) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_NO_TRANSACTION, message); + return; + } + + /* NOTICE: BlankPortalAssignName: portal * already exists */ + if (!strncmp(message,"BlankPortalAssignName: portal",29) + && strstr(message+29,"already exists")) + { + ECPGnoticeProcessor_raise(ECPG_NOTICE_PORTAL_EXISTS, message); + return; + } + + /* these are harmless - do nothing */ + /* NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index '*' for table '*' */ + /* NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) */ + /* NOTICE: CREATE TABLE will create implicit sequence '*' for SERIAL column '*.*' */ + /* NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) */ + if ((!strncmp(message,"CREATE TABLE",12) || !strncmp(message,"ALTER TABLE",11)) + && strstr(message+11,"will create implicit")) + return; + + /* NOTICE: QUERY PLAN: */ + if (!strncmp(message,"QUERY PLAN:",11)) // do we really see these? + return; + + /* NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "*" */ + if (!strncmp(message,"DROP TABLE implicitly drops",27)) + return; + + /* NOTICE: Caution: DROP INDEX cannot be rolled back, so don't abort now */ + if (strstr(message,"cannot be rolled back")) + return; + + /* these and other unmentioned should set sqlca.sqlwarn[2] */ + /* NOTICE: The ':' operator is deprecated. Use exp(x) instead. */ + /* NOTICE: Rel *: Uninitialized page 0 - fixing */ + /* NOTICE: PortalHeapMemoryFree: * not in alloc set! */ + /* NOTICE: Too old parent tuple found - can't continue vc_repair_frag */ + /* NOTICE: identifier "*" will be truncated to "*" */ + /* NOTICE: InvalidateSharedInvalid: cache state reset */ + /* NOTICE: RegisterSharedInvalid: SI buffer overflow */ + sqlca.sqlwarn[2]='W'; + sqlca.sqlwarn[0]='W'; +} + bool ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char *connection_name, int autocommit) { @@ -119,12 +236,14 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd if (dbname == NULL && connection_name == NULL) connection_name = "DEFAULT"; - + /* add connection to our list */ if (connection_name != NULL) this->name = ecpg_strdup(connection_name, lineno); else this->name = ecpg_strdup(dbname, lineno); + + this->cache_head = NULL; if (all_connections == NULL) this->next = NULL; @@ -147,6 +266,8 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd this->committed = true; this->autocommit = autocommit; + + PQsetNoticeProcessor(this->connection,&ECPGnoticeProcessor,(void*)this); return true; } |