aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/lib/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/lib/connect.c')
-rw-r--r--src/interfaces/ecpg/lib/connect.c123
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;
}