@@ -27,6 +27,8 @@ ecpg_finish(struct connection * act)
27
27
{
28
28
if (act != NULL )
29
29
{
30
+ struct ECPGtype_information_cache * cache ,* ptr ;
31
+
30
32
ECPGlog ("ecpg_finish: finishing %s.\n" ,act -> name );
31
33
PQfinish (act -> connection );
32
34
@@ -45,6 +47,7 @@ ecpg_finish(struct connection * act)
45
47
if (actual_connection == act )
46
48
actual_connection = all_connections ;
47
49
50
+ for (cache = act -> cache_head ;cache ;ptr = cache ,cache = cache -> next ,free (ptr ));
48
51
free (act -> name );
49
52
free (act );
50
53
}
@@ -107,6 +110,120 @@ ECPGsetconn(int lineno, const char *connection_name)
107
110
return true;
108
111
}
109
112
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
+
110
227
bool
111
228
ECPGconnect (int lineno ,const char * dbname ,const char * user ,const char * passwd ,const char * connection_name ,int autocommit )
112
229
{
@@ -119,12 +236,14 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
119
236
120
237
if (dbname == NULL && connection_name == NULL )
121
238
connection_name = "DEFAULT" ;
122
-
239
+
123
240
/* add connection to our list */
124
241
if (connection_name != NULL )
125
242
this -> name = ecpg_strdup (connection_name ,lineno );
126
243
else
127
244
this -> name = ecpg_strdup (dbname ,lineno );
245
+
246
+ this -> cache_head = NULL ;
128
247
129
248
if (all_connections == NULL )
130
249
this -> next = NULL ;
@@ -147,6 +266,8 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
147
266
148
267
this -> committed = true;
149
268
this -> autocommit = autocommit ;
269
+
270
+ PQsetNoticeProcessor (this -> connection ,& ECPGnoticeProcessor ,(void * )this );
150
271
151
272
return true;
152
273
}