]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/ecpglib/misc.c
63d4d969b1557a1c27b8cec64cf6c76b50a248a2
[postgresql] / src / interfaces / ecpg / ecpglib / misc.c
1 /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.14 2003/08/08 13:17:58 petere Exp $ */
2
3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
5
6 #include <limits.h>
7 #include <unistd.h>
8 #ifdef USE_THREADS
9 #include <pthread.h>
10 #endif
11 #include "ecpgtype.h"
12 #include "ecpglib.h"
13 #include "ecpgerrno.h"
14 #include "extern.h"
15 #include "sqlca.h"
16 #include "pgtypes_numeric.h"
17 #include "pgtypes_date.h"
18 #include "pgtypes_timestamp.h"
19 #include "pgtypes_interval.h"
20
21 #ifdef HAVE_LONG_LONG_INT_64
22 #ifndef LONG_LONG_MIN
23 #define LONG_LONG_MIN LLONG_MIN
24 #endif
25 #endif
26
27 static struct sqlca_t sqlca_init =
28 {
29         {
30                 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
31         },
32         sizeof(struct sqlca_t),
33         0,
34         {
35                 0,
36                 {
37                         0
38                 }
39         },
40         {
41                 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
42         },
43         {
44                 0, 0, 0, 0, 0, 0
45         },
46         {
47                 0, 0, 0, 0, 0, 0, 0, 0
48         },
49         {
50                 '0', '0', '0', '0', '0'
51         }
52 };
53
54 #ifdef USE_THREADS
55 static pthread_key_t sqlca_key;
56 static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
57
58 #else
59 static struct sqlca_t sqlca =
60 {
61         {
62                 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
63         },
64         sizeof(struct sqlca_t),
65         0,
66         {
67                 0,
68                 {
69                         0
70                 }
71         },
72         {
73                 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
74         },
75         {
76                 0, 0, 0, 0, 0, 0
77         },
78         {
79                 0, 0, 0, 0, 0, 0, 0, 0
80         },
81         {
82                 '0', '0', '0', '0', '0'
83         }
84 };
85 #endif
86
87 #ifdef USE_THREADS
88 static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
89 static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
90 #endif
91 static int      simple_debug = 0;
92 static FILE *debugstream = NULL;
93
94 void
95 ECPGinit_sqlca(struct sqlca_t * sqlca)
96 {
97         memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
98 }
99
100 bool
101 ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
102 {
103         struct sqlca_t *sqlca = ECPGget_sqlca();
104
105         ECPGinit_sqlca(sqlca);
106         if (con == NULL)
107         {
108                 ECPGraise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
109                                   connection_name ? connection_name : "NULL");
110                 return (false);
111         }
112
113         return (true);
114 }
115
116 #ifdef USE_THREADS
117 static void
118 ecpg_sqlca_key_init(void)
119 {
120         pthread_key_create(&sqlca_key, NULL);
121 }
122 #endif
123
124 struct sqlca_t *
125 ECPGget_sqlca(void)
126 {
127 #ifdef USE_THREADS
128         struct sqlca_t *sqlca;
129
130         pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
131
132         sqlca = pthread_getspecific(sqlca_key);
133         if (sqlca == NULL)
134         {
135                 sqlca = malloc(sizeof(struct sqlca_t));
136                 ECPGinit_sqlca(sqlca);
137                 pthread_setspecific(sqlca_key, sqlca);
138         }
139         return (sqlca);
140 #else
141         return (&sqlca);
142 #endif
143 }
144
145 bool
146 ECPGstatus(int lineno, const char *connection_name)
147 {
148         struct connection *con = ECPGget_connection(connection_name);
149
150         if (!ECPGinit(con, connection_name, lineno))
151                 return (false);
152
153         /* are we connected? */
154         if (con->connection == NULL)
155         {
156                 ECPGraise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, con->name);
157                 return false;
158         }
159
160         return (true);
161 }
162
163 bool
164 ECPGtrans(int lineno, const char *connection_name, const char *transaction)
165 {
166         PGresult   *res;
167         struct connection *con = ECPGget_connection(connection_name);
168
169         if (!ECPGinit(con, connection_name, lineno))
170                 return (false);
171
172         ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
173
174         /* if we have no connection we just simulate the command */
175         if (con && con->connection)
176         {
177                 /*
178                  * if we are not in autocommit mode, already have committed the
179                  * transaction and get another commit, just ignore it
180                  */
181                 if (!con->committed || con->autocommit)
182                 {
183                         if ((res = PQexec(con->connection, transaction)) == NULL)
184                         {
185                                 ECPGraise(lineno, ECPG_TRANS, ECPG_SQLSTATE_TRANSACTION_RESOLUTION_UNKNOWN, NULL);
186                                 return FALSE;
187                         }
188                         PQclear(res);
189                 }
190         }
191
192         if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
193         {
194                 con->committed = true;
195
196 #if 0
197                 /* deallocate all prepared statements */
198                 if (!ECPGdeallocate_all(lineno))
199                         return false;
200 #endif
201         }
202
203         return true;
204 }
205
206
207 void
208 ECPGdebug(int n, FILE *dbgs)
209 {
210 #ifdef USE_THREADS
211         pthread_mutex_lock(&debug_init_mutex);
212 #endif
213
214         simple_debug = n;
215         debugstream = dbgs;
216         ECPGlog("ECPGdebug: set to %d\n", simple_debug);
217
218 #ifdef USE_THREADS
219         pthread_mutex_unlock(&debug_init_mutex);
220 #endif
221 }
222
223 void
224 ECPGlog(const char *format,...)
225 {
226         va_list         ap;
227
228 #ifdef USE_THREADS
229         pthread_mutex_lock(&debug_mutex);
230 #endif
231
232         if (simple_debug)
233         {
234                 char       *f = (char *) malloc(strlen(format) + 100);
235
236                 if (f == NULL)
237                 {
238 #ifdef USE_THREADS
239                         pthread_mutex_unlock(&debug_mutex);
240 #endif
241                         return;
242                 }
243
244                 sprintf(f, "[%d]: %s", (int) getpid(), format);
245
246                 va_start(ap, format);
247                 vfprintf(debugstream, f, ap);
248                 va_end(ap);
249                 fflush(debugstream);
250
251                 ECPGfree(f);
252         }
253
254 #ifdef USE_THREADS
255         pthread_mutex_unlock(&debug_mutex);
256 #endif
257 }
258
259 void
260 ECPGset_informix_null(enum ECPGttype type, void *ptr)
261 {
262         switch (type)
263         {
264                 case ECPGt_char:
265                 case ECPGt_unsigned_char:
266                         *((char *) ptr) = '\0';
267                         break;
268                 case ECPGt_short:
269                 case ECPGt_unsigned_short:
270                         *((short int *) ptr) = SHRT_MIN;
271                         break;
272                 case ECPGt_int:
273                 case ECPGt_unsigned_int:
274                         *((int *) ptr) = INT_MIN;
275                         break;
276                 case ECPGt_long:
277                 case ECPGt_unsigned_long:
278                 case ECPGt_date:
279                         *((long *) ptr) = LONG_MIN;
280                         break;
281 #ifdef HAVE_LONG_LONG_INT_64
282                 case ECPGt_long_long:
283                 case ECPGt_unsigned_long_long:
284                         *((long long *) ptr) = LONG_LONG_MIN;
285                         break;
286 #endif   /* HAVE_LONG_LONG_INT_64 */
287                 case ECPGt_float:
288                         memset((char *) ptr, 0xff, sizeof(float));
289                         break;
290                 case ECPGt_double:
291                         memset((char *) ptr, 0xff, sizeof(double));
292                         break;
293                 case ECPGt_varchar:
294                         *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
295                         break;
296                 case ECPGt_decimal:
297                         memset((char *) ptr, 0, sizeof(Decimal));
298                         ((Decimal *) ptr)->sign = NUMERIC_NAN;
299                         break;
300                 case ECPGt_numeric:
301                         memset((char *) ptr, 0, sizeof(Numeric));
302                         ((Numeric *) ptr)->sign = NUMERIC_NAN;
303                         break;
304                 case ECPGt_interval:
305                         memset((char *) ptr, 0xff, sizeof(Interval));
306                         break;
307                 case ECPGt_timestamp:
308                         memset((char *) ptr, 0xff, sizeof(Timestamp));
309                         break;
310                 default:
311                         break;
312         }
313 }
314
315 static bool
316 _check(unsigned char *ptr, int length)
317 {
318         for (; ptr[--length] == 0xff && length >= 0; length--);
319         if (length < 0)
320                 return true;
321         return false;
322 }
323
324 bool
325 ECPGis_informix_null(enum ECPGttype type, void *ptr)
326 {
327         switch (type)
328         {
329                 case ECPGt_char:
330                 case ECPGt_unsigned_char:
331                         if (*((char *) ptr) == '\0')
332                                 return true;
333                         break;
334                 case ECPGt_short:
335                 case ECPGt_unsigned_short:
336                         if (*((short int *) ptr) == SHRT_MIN)
337                                 return true;
338                         break;
339                 case ECPGt_int:
340                 case ECPGt_unsigned_int:
341                         if (*((int *) ptr) == INT_MIN)
342                                 return true;
343                         break;
344                 case ECPGt_long:
345                 case ECPGt_unsigned_long:
346                 case ECPGt_date:
347                         if (*((long *) ptr) == LONG_MIN)
348                                 return true;
349                         break;
350 #ifdef HAVE_LONG_LONG_INT_64
351                 case ECPGt_long_long:
352                 case ECPGt_unsigned_long_long:
353                         if (*((long long *) ptr) == LONG_LONG_MIN)
354                                 return true;
355                         break;
356 #endif   /* HAVE_LONG_LONG_INT_64 */
357                 case ECPGt_float:
358                         return (_check(ptr, sizeof(float)));
359                         break;
360                 case ECPGt_double:
361                         return (_check(ptr, sizeof(double)));
362                         break;
363                 case ECPGt_varchar:
364                         if (*(((struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
365                                 return true;
366                         break;
367                 case ECPGt_decimal:
368                         if (((Decimal *) ptr)->sign == NUMERIC_NAN)
369                                 return true;
370                         break;
371                 case ECPGt_numeric:
372                         if (((Numeric *) ptr)->sign == NUMERIC_NAN)
373                                 return true;
374                         break;
375                 case ECPGt_interval:
376                         return (_check(ptr, sizeof(Interval)));
377                         break;
378                 case ECPGt_timestamp:
379                         return (_check(ptr, sizeof(Timestamp)));
380                         break;
381                 default:
382                         break;
383         }
384
385         return false;
386 }