3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
8 #include "ecpg-pthread-win32.h"
11 #include "ecpgerrno.h"
14 #include "pgtypes_numeric.h"
15 #include "pgtypes_date.h"
16 #include "pgtypes_timestamp.h"
17 #include "pgtypes_interval.h"
18 #include "pg_config_paths.h"
20 #ifdef HAVE_LONG_LONG_INT_64
23 #define LONG_LONG_MIN LLONG_MIN
25 #define LONG_LONG_MIN LONGLONG_MIN
30 bool ecpg_internal_regression_mode
= false;
32 static struct sqlca_t sqlca_init
=
35 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
37 sizeof(struct sqlca_t
),
46 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
52 0, 0, 0, 0, 0, 0, 0, 0
55 '0', '0', '0', '0', '0'
59 #ifdef ENABLE_THREAD_SAFETY
60 static pthread_key_t sqlca_key
;
61 static pthread_once_t sqlca_key_once
= PTHREAD_ONCE_INIT
;
63 static struct sqlca_t sqlca
=
66 'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
68 sizeof(struct sqlca_t
),
77 'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
83 0, 0, 0, 0, 0, 0, 0, 0
86 '0', '0', '0', '0', '0'
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
;
95 static int simple_debug
= 0;
96 static FILE *debugstream
= NULL
;
99 ecpg_init_sqlca(struct sqlca_t
* sqlca
)
101 memcpy((char *) sqlca
, (char *) &sqlca_init
, sizeof(struct sqlca_t
));
105 ecpg_init(const struct connection
* con
, const char *connection_name
, const int lineno
)
107 struct sqlca_t
*sqlca
= ECPGget_sqlca();
109 ecpg_init_sqlca(sqlca
);
112 ecpg_raise(lineno
, ECPG_NO_CONN
, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST
,
113 connection_name
? connection_name
: _("NULL"));
120 #ifdef ENABLE_THREAD_SAFETY
122 ecpg_sqlca_key_destructor(void *arg
)
124 free(arg
); /* sqlca structure allocated in ECPGget_sqlca */
128 ecpg_sqlca_key_init(void)
130 pthread_key_create(&sqlca_key
, ecpg_sqlca_key_destructor
);
137 #ifdef ENABLE_THREAD_SAFETY
138 struct sqlca_t
*sqlca
;
140 pthread_once(&sqlca_key_once
, ecpg_sqlca_key_init
);
142 sqlca
= pthread_getspecific(sqlca_key
);
145 sqlca
= malloc(sizeof(struct sqlca_t
));
146 ecpg_init_sqlca(sqlca
);
147 pthread_setspecific(sqlca_key
, sqlca
);
156 ECPGstatus(int lineno
, const char *connection_name
)
158 struct connection
*con
= ecpg_get_connection(connection_name
);
160 if (!ecpg_init(con
, connection_name
, lineno
))
163 /* are we connected? */
164 if (con
->connection
== NULL
)
166 ecpg_raise(lineno
, ECPG_NOT_CONN
, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
, con
->name
);
174 ECPGtrans(int lineno
, const char *connection_name
, const char *transaction
)
177 struct connection
*con
= ecpg_get_connection(connection_name
);
179 if (!ecpg_init(con
, connection_name
, lineno
))
182 ecpg_log("ECPGtrans on line %d: action \"%s\"; connection \"%s\"\n", lineno
, transaction
, con
? con
->name
: _("null"));
184 /* if we have no connection we just simulate the command */
185 if (con
&& con
->connection
)
188 * If we got a transaction command but have no open transaction, we
189 * have to start one, unless we are in autocommit, where the
190 * developers have to take care themselves. However, if the command is
191 * a begin statement, we just execute it once.
193 if (con
->committed
&& !con
->autocommit
&& strncmp(transaction
, "begin", 5) != 0 && strncmp(transaction
, "start", 5) != 0)
195 res
= PQexec(con
->connection
, "begin transaction");
196 if (!ecpg_check_PQresult(res
, lineno
, con
->connection
, ECPG_COMPAT_PGSQL
))
201 res
= PQexec(con
->connection
, transaction
);
202 if (!ecpg_check_PQresult(res
, lineno
, con
->connection
, ECPG_COMPAT_PGSQL
))
207 if (strncmp(transaction
, "commit", 6) == 0 || strncmp(transaction
, "rollback", 8) == 0)
208 con
->committed
= true;
210 con
->committed
= false;
217 ECPGdebug(int n
, FILE *dbgs
)
219 #ifdef ENABLE_THREAD_SAFETY
220 pthread_mutex_lock(&debug_init_mutex
);
225 ecpg_internal_regression_mode
= true;
226 simple_debug
= n
- 100;
233 ecpg_log("ECPGdebug: set to %d\n", simple_debug
);
235 #ifdef ENABLE_THREAD_SAFETY
236 pthread_mutex_unlock(&debug_init_mutex
);
241 ecpg_log(const char *format
,...)
244 struct sqlca_t
*sqlca
= ECPGget_sqlca();
246 /* internationalize the error message string */
247 format
= ecpg_gettext(format
);
251 int bufsize
= strlen(format
) + 100;
252 char *f
= (char *) malloc(bufsize
);
258 * regression tests set this environment variable to get the same
259 * output for every run.
261 if (ecpg_internal_regression_mode
)
262 snprintf(f
, bufsize
, "[NO_PID]: %s", format
);
264 snprintf(f
, bufsize
, "[%d]: %s", (int) getpid(), format
);
266 #ifdef ENABLE_THREAD_SAFETY
267 pthread_mutex_lock(&debug_mutex
);
270 va_start(ap
, format
);
271 vfprintf(debugstream
, f
, ap
);
274 /* dump out internal sqlca variables */
275 if (ecpg_internal_regression_mode
)
276 fprintf(debugstream
, "[NO_PID]: sqlca: code: %ld, state: %s\n",
277 sqlca
->sqlcode
, sqlca
->sqlstate
);
281 #ifdef ENABLE_THREAD_SAFETY
282 pthread_mutex_unlock(&debug_mutex
);
290 ECPGset_noind_null(enum ECPGttype type
, void *ptr
)
295 case ECPGt_unsigned_char
:
296 *((char *) ptr
) = '\0';
299 case ECPGt_unsigned_short
:
300 *((short int *) ptr
) = SHRT_MIN
;
303 case ECPGt_unsigned_int
:
304 *((int *) ptr
) = INT_MIN
;
307 case ECPGt_unsigned_long
:
309 *((long *) ptr
) = LONG_MIN
;
311 #ifdef HAVE_LONG_LONG_INT_64
312 case ECPGt_long_long
:
313 case ECPGt_unsigned_long_long
:
314 *((long long *) ptr
) = LONG_LONG_MIN
;
316 #endif /* HAVE_LONG_LONG_INT_64 */
318 memset((char *) ptr
, 0xff, sizeof(float));
321 memset((char *) ptr
, 0xff, sizeof(double));
324 *(((struct ECPGgeneric_varchar
*) ptr
)->arr
) = 0x00;
325 ((struct ECPGgeneric_varchar
*) ptr
)->len
= 0;
328 memset((char *) ptr
, 0, sizeof(decimal
));
329 ((decimal
*) ptr
)->sign
= NUMERIC_NAN
;
332 memset((char *) ptr
, 0, sizeof(numeric
));
333 ((numeric
*) ptr
)->sign
= NUMERIC_NAN
;
336 memset((char *) ptr
, 0xff, sizeof(interval
));
338 case ECPGt_timestamp
:
339 memset((char *) ptr
, 0xff, sizeof(timestamp
));
347 _check(unsigned char *ptr
, int length
)
349 for (; length
> 0 && ptr
[--length
] == 0xff;);
356 ECPGis_noind_null(enum ECPGttype type
, void *ptr
)
361 case ECPGt_unsigned_char
:
362 if (*((char *) ptr
) == '\0')
366 case ECPGt_unsigned_short
:
367 if (*((short int *) ptr
) == SHRT_MIN
)
371 case ECPGt_unsigned_int
:
372 if (*((int *) ptr
) == INT_MIN
)
376 case ECPGt_unsigned_long
:
378 if (*((long *) ptr
) == LONG_MIN
)
381 #ifdef HAVE_LONG_LONG_INT_64
382 case ECPGt_long_long
:
383 case ECPGt_unsigned_long_long
:
384 if (*((long long *) ptr
) == LONG_LONG_MIN
)
387 #endif /* HAVE_LONG_LONG_INT_64 */
389 return (_check(ptr
, sizeof(float)));
392 return (_check(ptr
, sizeof(double)));
395 if (*(((struct ECPGgeneric_varchar
*) ptr
)->arr
) == 0x00)
399 if (((decimal
*) ptr
)->sign
== NUMERIC_NAN
)
403 if (((numeric
*) ptr
)->sign
== NUMERIC_NAN
)
407 return (_check(ptr
, sizeof(interval
)));
409 case ECPGt_timestamp
:
410 return (_check(ptr
, sizeof(timestamp
)));
420 #ifdef ENABLE_THREAD_SAFETY
423 win32_pthread_mutex(volatile pthread_mutex_t
*mutex
)
425 if (mutex
->handle
== NULL
)
427 while (InterlockedExchange((LONG
*) & mutex
->initlock
, 1) == 1)
429 if (mutex
->handle
== NULL
)
430 mutex
->handle
= CreateMutex(NULL
, FALSE
, NULL
);
431 InterlockedExchange((LONG
*) & mutex
->initlock
, 0);
435 static pthread_mutex_t win32_pthread_once_lock
= PTHREAD_MUTEX_INITIALIZER
;
438 win32_pthread_once(volatile pthread_once_t
*once
, void (*fn
) (void))
442 pthread_mutex_lock(&win32_pthread_once_lock
);
448 pthread_mutex_unlock(&win32_pthread_once_lock
);
451 #endif /* ENABLE_THREAD_SAFETY */
458 ecpg_gettext(const char *msgid
)
460 static bool already_bound
= false;
464 /* dgettext() preserves errno, but bindtextdomain() doesn't */
466 int save_errno
= GetLastError();
468 int save_errno
= errno
;
472 already_bound
= true;
473 /* No relocatable lookup here because the binary could be anywhere */
474 ldir
= getenv("PGLOCALEDIR");
477 bindtextdomain("ecpg", ldir
);
479 SetLastError(save_errno
);
485 return dgettext("ecpg", msgid
);
488 #endif /* ENABLE_NLS */