@@ -27,6 +27,8 @@ ecpg_finish(struct connection * act)
2727{
2828if (act != NULL )
2929{
30+ struct ECPGtype_information_cache * cache ,* ptr ;
31+
3032ECPGlog ("ecpg_finish: finishing %s.\n" ,act -> name );
3133PQfinish (act -> connection );
3234
@@ -45,6 +47,7 @@ ecpg_finish(struct connection * act)
4547if (actual_connection == act )
4648actual_connection = all_connections ;
4749
50+ for (cache = act -> cache_head ;cache ;ptr = cache ,cache = cache -> next ,free (ptr ));
4851free (act -> name );
4952free (act );
5053}
@@ -107,6 +110,120 @@ ECPGsetconn(int lineno, const char *connection_name)
107110return true;
108111}
109112
113+ static void
114+ ECPGnoticeProcessor_raise (int code ,const char * message )
115+ {
116+ sqlca .sqlcode = code ;
117+ strncpy (sqlca .sqlerrm .sqlerrmc ,message ,sizeof (sqlca .sqlerrm .sqlerrmc ));
118+ sqlca .sqlerrm .sqlerrmc [sizeof (sqlca .sqlerrm .sqlerrmc )- 1 ]= 0 ;
119+ sqlca .sqlerrm .sqlerrml = strlen (sqlca .sqlerrm .sqlerrmc );
120+
121+ // remove trailing newline
122+ if (sqlca .sqlerrm .sqlerrml
123+ && sqlca .sqlerrm .sqlerrmc [sqlca .sqlerrm .sqlerrml - 1 ]== '\n' )
124+ {
125+ sqlca .sqlerrm .sqlerrmc [sqlca .sqlerrm .sqlerrml - 1 ]= 0 ;
126+ sqlca .sqlerrm .sqlerrml -- ;
127+ }
128+
129+ ECPGlog ("raising sqlcode %d\n" ,code );
130+ }
131+
132+ /*
133+ * I know this is a mess, but we can't redesign the backend
134+ */
135+
136+ static void
137+ ECPGnoticeProcessor (void * arg ,const char * message )
138+ {
139+ /* these notices raise an error */
140+ if (strncmp (message ,"NOTICE: " ,8 ))
141+ {
142+ ECPGlog ("ECPGnoticeProcessor: strange notice '%s'\n" ,message );
143+ ECPGnoticeProcessor_raise (ECPG_NOTICE_UNRECOGNIZED ,message );
144+ return ;
145+ }
146+
147+ message += 8 ;
148+ while (* message == ' ' )message ++ ;
149+ ECPGlog ("NOTICE: %s" ,message );
150+
151+ /* NOTICE: (transaction aborted): queries ignored until END */
152+ /* NOTICE: current transaction is aborted, queries ignored until end of transaction block */
153+ if (strstr (message ,"queries ignored" )&& strstr (message ,"transaction" )
154+ && strstr (message ,"aborted" ))
155+ {
156+ ECPGnoticeProcessor_raise (ECPG_NOTICE_QUERY_IGNORED ,message );
157+ return ;
158+ }
159+
160+ /* NOTICE: PerformPortalClose: portal "*" not found */
161+ if (!strncmp (message ,"PerformPortalClose: portal" ,26 )
162+ && strstr (message + 26 ,"not found" ))
163+ {
164+ ECPGnoticeProcessor_raise (ECPG_NOTICE_UNKNOWN_PORTAL ,message );
165+ return ;
166+ }
167+
168+ /* NOTICE: BEGIN: already a transaction in progress */
169+ if (!strncmp (message ,"BEGIN: already a transaction in progress" ,40 ))
170+ {
171+ ECPGnoticeProcessor_raise (ECPG_NOTICE_IN_TRANSACTION ,message );
172+ return ;
173+ }
174+
175+ /* NOTICE: AbortTransaction and not in in-progress state */
176+ /* NOTICE: COMMIT: no transaction in progress */
177+ /* NOTICE: ROLLBACK: no transaction in progress */
178+ if (!strncmp (message ,"AbortTransaction and not in in-progress state" ,45 )
179+ || !strncmp (message ,"COMMIT: no transaction in progress" ,34 )
180+ || !strncmp (message ,"ROLLBACK: no transaction in progress" ,36 ))
181+ {
182+ ECPGnoticeProcessor_raise (ECPG_NOTICE_NO_TRANSACTION ,message );
183+ return ;
184+ }
185+
186+ /* NOTICE: BlankPortalAssignName: portal * already exists */
187+ if (!strncmp (message ,"BlankPortalAssignName: portal" ,29 )
188+ && strstr (message + 29 ,"already exists" ))
189+ {
190+ ECPGnoticeProcessor_raise (ECPG_NOTICE_PORTAL_EXISTS ,message );
191+ return ;
192+ }
193+
194+ /* these are harmless - do nothing */
195+ /* NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index '*' for table '*' */
196+ /* NOTICE: ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s) */
197+ /* NOTICE: CREATE TABLE will create implicit sequence '*' for SERIAL column '*.*' */
198+ /* NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) */
199+ if ((!strncmp (message ,"CREATE TABLE" ,12 )|| !strncmp (message ,"ALTER TABLE" ,11 ))
200+ && strstr (message + 11 ,"will create implicit" ))
201+ return ;
202+
203+ /* NOTICE: QUERY PLAN: */
204+ if (!strncmp (message ,"QUERY PLAN:" ,11 ))// do we really see these?
205+ return ;
206+
207+ /* NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "*" */
208+ if (!strncmp (message ,"DROP TABLE implicitly drops" ,27 ))
209+ return ;
210+
211+ /* NOTICE: Caution: DROP INDEX cannot be rolled back, so don't abort now */
212+ if (strstr (message ,"cannot be rolled back" ))
213+ return ;
214+
215+ /* these and other unmentioned should set sqlca.sqlwarn[2] */
216+ /* NOTICE: The ':' operator is deprecated. Use exp(x) instead. */
217+ /* NOTICE: Rel *: Uninitialized page 0 - fixing */
218+ /* NOTICE: PortalHeapMemoryFree: * not in alloc set! */
219+ /* NOTICE: Too old parent tuple found - can't continue vc_repair_frag */
220+ /* NOTICE: identifier "*" will be truncated to "*" */
221+ /* NOTICE: InvalidateSharedInvalid: cache state reset */
222+ /* NOTICE: RegisterSharedInvalid: SI buffer overflow */
223+ sqlca .sqlwarn [2 ]= 'W' ;
224+ sqlca .sqlwarn [0 ]= 'W' ;
225+ }
226+
110227bool
111228ECPGconnect (int lineno ,const char * dbname ,const char * user ,const char * passwd ,const char * connection_name ,int autocommit )
112229{
@@ -119,12 +236,14 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
119236
120237if (dbname == NULL && connection_name == NULL )
121238connection_name = "DEFAULT" ;
122-
239+
123240/* add connection to our list */
124241if (connection_name != NULL )
125242this -> name = ecpg_strdup (connection_name ,lineno );
126243else
127244this -> name = ecpg_strdup (dbname ,lineno );
245+
246+ this -> cache_head = NULL ;
128247
129248if (all_connections == NULL )
130249this -> next = NULL ;
@@ -147,6 +266,8 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
147266
148267this -> committed = true;
149268this -> autocommit = autocommit ;
269+
270+ PQsetNoticeProcessor (this -> connection ,& ECPGnoticeProcessor ,(void * )this );
150271
151272return true;
152273}