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