PostgreSQL Source Code  git master
misc.c
Go to the documentation of this file.
1 /* src/interfaces/ecpg/ecpglib/misc.c */
2 
3 #define POSTGRES_ECPG_INTERNAL
4 #include "postgres_fe.h"
5 
6 #include <limits.h>
7 #include <unistd.h>
8 #include "ecpg-pthread-win32.h"
9 #include "ecpgtype.h"
10 #include "ecpglib.h"
11 #include "ecpgerrno.h"
12 #include "ecpglib_extern.h"
13 #include "sqlca.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"
19 
20 #ifdef HAVE_LONG_LONG_INT
21 #ifndef LONG_LONG_MIN
22 #ifdef LLONG_MIN
23 #define LONG_LONG_MIN LLONG_MIN
24 #else
25 #define LONG_LONG_MIN LONGLONG_MIN
26 #endif /* LLONG_MIN */
27 #endif /* LONG_LONG_MIN */
28 #endif /* HAVE_LONG_LONG_INT */
29 
31 
32 static struct sqlca_t sqlca_init =
33 {
34  {
35  'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
36  },
37  sizeof(struct sqlca_t),
38  0,
39  {
40  0,
41  {
42  0
43  }
44  },
45  {
46  'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
47  },
48  {
49  0, 0, 0, 0, 0, 0
50  },
51  {
52  0, 0, 0, 0, 0, 0, 0, 0
53  },
54  {
55  '0', '0', '0', '0', '0'
56  }
57 };
58 
59 #ifdef ENABLE_THREAD_SAFETY
60 static pthread_key_t sqlca_key;
61 static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
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 ecpg_init_sqlca(struct sqlca_t *sqlca)
100 {
101  memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
102 }
103 
104 bool
105 ecpg_init(const struct connection *con, const char *connection_name, const int lineno)
106 {
107  struct sqlca_t *sqlca = ECPGget_sqlca();
108 
109  if (sqlca == NULL)
110  {
112  NULL);
113  return false;
114  }
115 
116  ecpg_init_sqlca(sqlca);
117  if (con == NULL)
118  {
120  connection_name ? connection_name : ecpg_gettext("NULL"));
121  return false;
122  }
123 
124  return true;
125 }
126 
127 #ifdef ENABLE_THREAD_SAFETY
128 static void
129 ecpg_sqlca_key_destructor(void *arg)
130 {
131  free(arg); /* sqlca structure allocated in ECPGget_sqlca */
132 }
133 
134 static void
135 ecpg_sqlca_key_init(void)
136 {
137  pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor);
138 }
139 #endif
140 
141 struct sqlca_t *
143 {
144 #ifdef ENABLE_THREAD_SAFETY
145  struct sqlca_t *sqlca;
146 
147  pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
148 
149  sqlca = pthread_getspecific(sqlca_key);
150  if (sqlca == NULL)
151  {
152  sqlca = malloc(sizeof(struct sqlca_t));
153  if (sqlca == NULL)
154  return NULL;
155  ecpg_init_sqlca(sqlca);
156  pthread_setspecific(sqlca_key, sqlca);
157  }
158  return sqlca;
159 #else
160  return &sqlca;
161 #endif
162 }
163 
164 bool
165 ECPGstatus(int lineno, const char *connection_name)
166 {
167  struct connection *con = ecpg_get_connection(connection_name);
168 
169  if (!ecpg_init(con, connection_name, lineno))
170  return false;
171 
172  /* are we connected? */
173  if (con->connection == NULL)
174  {
176  return false;
177  }
178 
179  return true;
180 }
181 
183 ECPGtransactionStatus(const char *connection_name)
184 {
185  const struct connection *con;
186 
187  con = ecpg_get_connection(connection_name);
188  if (con == NULL)
189  {
190  /* transaction status is unknown */
191  return PQTRANS_UNKNOWN;
192  }
193 
194  return PQtransactionStatus(con->connection);
195 
196 }
197 
198 bool
199 ECPGtrans(int lineno, const char *connection_name, const char *transaction)
200 {
201  PGresult *res;
202  struct connection *con = ecpg_get_connection(connection_name);
203 
204  if (!ecpg_init(con, connection_name, lineno))
205  return false;
206 
207  ecpg_log("ECPGtrans on line %d: action \"%s\"; connection \"%s\"\n", lineno, transaction, con ? con->name : "null");
208 
209  /* if we have no connection we just simulate the command */
210  if (con && con->connection)
211  {
212  /*
213  * If we got a transaction command but have no open transaction, we
214  * have to start one, unless we are in autocommit, where the
215  * developers have to take care themselves. However, if the command is
216  * a begin statement, we just execute it once. And if the command is
217  * commit or rollback prepared, we don't execute it.
218  */
220  !con->autocommit &&
221  strncmp(transaction, "begin", 5) != 0 &&
222  strncmp(transaction, "start", 5) != 0 &&
223  strncmp(transaction, "commit prepared", 15) != 0 &&
224  strncmp(transaction, "rollback prepared", 17) != 0)
225  {
226  res = PQexec(con->connection, "begin transaction");
227  if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL))
228  return false;
229  PQclear(res);
230  }
231 
232  res = PQexec(con->connection, transaction);
233  if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL))
234  return false;
235  PQclear(res);
236  }
237 
238  return true;
239 }
240 
241 
242 void
243 ECPGdebug(int n, FILE *dbgs)
244 {
245 #ifdef ENABLE_THREAD_SAFETY
246  pthread_mutex_lock(&debug_init_mutex);
247 #endif
248 
249  if (n > 100)
250  {
252  simple_debug = n - 100;
253  }
254  else
255  simple_debug = n;
256 
257  debugstream = dbgs;
258 
259  ecpg_log("ECPGdebug: set to %d\n", simple_debug);
260 
261 #ifdef ENABLE_THREAD_SAFETY
262  pthread_mutex_unlock(&debug_init_mutex);
263 #endif
264 }
265 
266 void
267 ecpg_log(const char *format,...)
268 {
269  va_list ap;
270  struct sqlca_t *sqlca = ECPGget_sqlca();
271  const char *intl_format;
272  int bufsize;
273  char *fmt;
274 
275  if (!simple_debug)
276  return;
277 
278  /* localize the error message string */
279  intl_format = ecpg_gettext(format);
280 
281  /*
282  * Insert PID into the format, unless ecpg_internal_regression_mode is set
283  * (regression tests want unchanging output).
284  */
285  bufsize = strlen(intl_format) + 100;
286  fmt = (char *) malloc(bufsize);
287  if (fmt == NULL)
288  return;
289 
291  snprintf(fmt, bufsize, "[NO_PID]: %s", intl_format);
292  else
293  snprintf(fmt, bufsize, "[%d]: %s", (int) getpid(), intl_format);
294 
295 #ifdef ENABLE_THREAD_SAFETY
296  pthread_mutex_lock(&debug_mutex);
297 #endif
298 
299  va_start(ap, format);
300  vfprintf(debugstream, fmt, ap);
301  va_end(ap);
302 
303  /* dump out internal sqlca variables */
304  if (ecpg_internal_regression_mode && sqlca != NULL)
305  {
306  fprintf(debugstream, "[NO_PID]: sqlca: code: %ld, state: %s\n",
307  sqlca->sqlcode, sqlca->sqlstate);
308  }
309 
310  fflush(debugstream);
311 
312 #ifdef ENABLE_THREAD_SAFETY
313  pthread_mutex_unlock(&debug_mutex);
314 #endif
315 
316  free(fmt);
317 }
318 
319 void
321 {
322  switch (type)
323  {
324  case ECPGt_char:
325  case ECPGt_unsigned_char:
326  case ECPGt_string:
327  *((char *) ptr) = '\0';
328  break;
329  case ECPGt_short:
331  *((short int *) ptr) = SHRT_MIN;
332  break;
333  case ECPGt_int:
334  case ECPGt_unsigned_int:
335  *((int *) ptr) = INT_MIN;
336  break;
337  case ECPGt_long:
338  case ECPGt_unsigned_long:
339  case ECPGt_date:
340  *((long *) ptr) = LONG_MIN;
341  break;
342 #ifdef HAVE_LONG_LONG_INT
343  case ECPGt_long_long:
345  *((long long *) ptr) = LONG_LONG_MIN;
346  break;
347 #endif /* HAVE_LONG_LONG_INT */
348  case ECPGt_float:
349  memset((char *) ptr, 0xff, sizeof(float));
350  break;
351  case ECPGt_double:
352  memset((char *) ptr, 0xff, sizeof(double));
353  break;
354  case ECPGt_varchar:
355  *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
356  ((struct ECPGgeneric_varchar *) ptr)->len = 0;
357  break;
358  case ECPGt_bytea:
359  ((struct ECPGgeneric_bytea *) ptr)->len = 0;
360  break;
361  case ECPGt_decimal:
362  memset((char *) ptr, 0, sizeof(decimal));
363  ((decimal *) ptr)->sign = NUMERIC_NULL;
364  break;
365  case ECPGt_numeric:
366  memset((char *) ptr, 0, sizeof(numeric));
367  ((numeric *) ptr)->sign = NUMERIC_NULL;
368  break;
369  case ECPGt_interval:
370  memset((char *) ptr, 0xff, sizeof(interval));
371  break;
372  case ECPGt_timestamp:
373  memset((char *) ptr, 0xff, sizeof(timestamp));
374  break;
375  default:
376  break;
377  }
378 }
379 
380 static bool
381 _check(const unsigned char *ptr, int length)
382 {
383  for (length--; length >= 0; length--)
384  if (ptr[length] != 0xff)
385  return false;
386 
387  return true;
388 }
389 
390 bool
391 ECPGis_noind_null(enum ECPGttype type, const void *ptr)
392 {
393  switch (type)
394  {
395  case ECPGt_char:
396  case ECPGt_unsigned_char:
397  case ECPGt_string:
398  if (*((const char *) ptr) == '\0')
399  return true;
400  break;
401  case ECPGt_short:
403  if (*((const short int *) ptr) == SHRT_MIN)
404  return true;
405  break;
406  case ECPGt_int:
407  case ECPGt_unsigned_int:
408  if (*((const int *) ptr) == INT_MIN)
409  return true;
410  break;
411  case ECPGt_long:
412  case ECPGt_unsigned_long:
413  case ECPGt_date:
414  if (*((const long *) ptr) == LONG_MIN)
415  return true;
416  break;
417 #ifdef HAVE_LONG_LONG_INT
418  case ECPGt_long_long:
420  if (*((const long long *) ptr) == LONG_LONG_MIN)
421  return true;
422  break;
423 #endif /* HAVE_LONG_LONG_INT */
424  case ECPGt_float:
425  return _check(ptr, sizeof(float));
426  break;
427  case ECPGt_double:
428  return _check(ptr, sizeof(double));
429  break;
430  case ECPGt_varchar:
431  if (*(((const struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
432  return true;
433  break;
434  case ECPGt_bytea:
435  if (((const struct ECPGgeneric_bytea *) ptr)->len == 0)
436  return true;
437  break;
438  case ECPGt_decimal:
439  if (((const decimal *) ptr)->sign == NUMERIC_NULL)
440  return true;
441  break;
442  case ECPGt_numeric:
443  if (((const numeric *) ptr)->sign == NUMERIC_NULL)
444  return true;
445  break;
446  case ECPGt_interval:
447  return _check(ptr, sizeof(interval));
448  break;
449  case ECPGt_timestamp:
450  return _check(ptr, sizeof(timestamp));
451  break;
452  default:
453  break;
454  }
455 
456  return false;
457 }
458 
459 #ifdef WIN32
460 #ifdef ENABLE_THREAD_SAFETY
461 
462 void
463 win32_pthread_mutex(volatile pthread_mutex_t *mutex)
464 {
465  if (mutex->handle == NULL)
466  {
467  while (InterlockedExchange((LONG *) &mutex->initlock, 1) == 1)
468  Sleep(0);
469  if (mutex->handle == NULL)
470  mutex->handle = CreateMutex(NULL, FALSE, NULL);
471  InterlockedExchange((LONG *) &mutex->initlock, 0);
472  }
473 }
474 
475 static pthread_mutex_t win32_pthread_once_lock = PTHREAD_MUTEX_INITIALIZER;
476 
477 void
478 win32_pthread_once(volatile pthread_once_t *once, void (*fn) (void))
479 {
480  if (!*once)
481  {
482  pthread_mutex_lock(&win32_pthread_once_lock);
483  if (!*once)
484  {
485  *once = true;
486  fn();
487  }
488  pthread_mutex_unlock(&win32_pthread_once_lock);
489  }
490 }
491 #endif /* ENABLE_THREAD_SAFETY */
492 #endif /* WIN32 */
493 
494 #ifdef ENABLE_NLS
495 
496 char *
497 ecpg_gettext(const char *msgid)
498 {
499  static bool already_bound = false;
500 
501  if (!already_bound)
502  {
503  /* dgettext() preserves errno, but bindtextdomain() doesn't */
504 #ifdef WIN32
505  int save_errno = GetLastError();
506 #else
507  int save_errno = errno;
508 #endif
509  const char *ldir;
510 
511  already_bound = true;
512  /* No relocatable lookup here because the binary could be anywhere */
513  ldir = getenv("PGLOCALEDIR");
514  if (!ldir)
515  ldir = LOCALEDIR;
516  bindtextdomain(PG_TEXTDOMAIN("ecpglib"), ldir);
517 #ifdef WIN32
518  SetLastError(save_errno);
519 #else
520  errno = save_errno;
521 #endif
522  }
523 
524  return dgettext(PG_TEXTDOMAIN("ecpglib"), msgid);
525 }
526 #endif /* ENABLE_NLS */
527 
528 struct var_list *ivlist = NULL;
529 
530 void
531 ECPGset_var(int number, void *pointer, int lineno)
532 {
533  struct var_list *ptr;
534 
535  struct sqlca_t *sqlca = ECPGget_sqlca();
536 
537  if (sqlca == NULL)
538  {
541  return;
542  }
543 
544  ecpg_init_sqlca(sqlca);
545 
546  for (ptr = ivlist; ptr != NULL; ptr = ptr->next)
547  {
548  if (ptr->number == number)
549  {
550  /* already known => just change pointer value */
551  ptr->pointer = pointer;
552  return;
553  }
554  }
555 
556  /* a new one has to be added */
557  ptr = (struct var_list *) calloc(1L, sizeof(struct var_list));
558  if (!ptr)
559  {
560  struct sqlca_t *sqlca = ECPGget_sqlca();
561 
562  if (sqlca == NULL)
563  {
566  return;
567  }
568 
569  sqlca->sqlcode = ECPG_OUT_OF_MEMORY;
570  strncpy(sqlca->sqlstate, "YE001", sizeof(sqlca->sqlstate));
571  snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "out of memory on line %d", lineno);
572  sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
573  /* free all memory we have allocated for the user */
575  }
576  else
577  {
578  ptr->number = number;
579  ptr->pointer = pointer;
580  ptr->next = ivlist;
581  ivlist = ptr;
582  }
583 }
584 
585 void *
586 ECPGget_var(int number)
587 {
588  struct var_list *ptr;
589 
590  for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next);
591  return (ptr) ? ptr->pointer : NULL;
592 }
#define calloc(a, b)
Definition: header.h:55
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
struct var_list * next
bool ECPGstatus(int lineno, const char *connection_name)
Definition: misc.c:165
#define ECPG_NOT_CONN
Definition: ecpgerrno.h:37
void * ECPGget_var(int number)
Definition: misc.c:586
#define ECPG_SQLSTATE_ECPG_INTERNAL_ERROR
void ecpg_raise(int line, int code, const char *sqlstate, const char *str)
Definition: error.c:13
void ECPGfree_auto_mem(void)
Definition: memory.c:138
int64 timestamp
ULONG pthread_key_t
Definition: pthread-win32.h:7
#define FALSE
Definition: ecpglib.h:39
void * pointer
void ECPGset_var(int number, void *pointer, int lineno)
Definition: misc.c:531
void ecpg_init_sqlca(struct sqlca_t *sqlca)
Definition: misc.c:99
int sqlerrml
Definition: sqlca.h:26
#define NUMERIC_NULL
void ECPGdebug(int n, FILE *dbgs)
Definition: misc.c:243
#define fprintf
Definition: port.h:196
#define ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY
#define malloc(a)
Definition: header.h:50
static bool _check(const unsigned char *ptr, int length)
Definition: misc.c:381
#define ECPG_OUT_OF_MEMORY
Definition: ecpgerrno.h:15
struct sqlca_t * ECPGget_sqlca(void)
Definition: misc.c:142
Definition: sqlca.h:19
#define ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST
char sign
Definition: informix.c:688
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
PGTransactionStatusType ECPGtransactionStatus(const char *connection_name)
Definition: misc.c:183
static int simple_debug
Definition: misc.c:95
char sqlstate[5]
Definition: sqlca.h:53
PGTransactionStatusType PQtransactionStatus(const PGconn *conn)
Definition: fe-connect.c:6516
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1135
long sqlcode
Definition: sqlca.h:23
static FILE * debugstream
Definition: misc.c:96
struct sqlca_t::@147 sqlerrm
#define ecpg_gettext(x)
Definition: ecpglib.h:18
#define dgettext(d, x)
Definition: c.h:1102
static struct sqlca_t sqlca_init
Definition: misc.c:32
void ecpg_log(const char *format,...)
Definition: misc.c:267
void PQclear(PGresult *res)
Definition: fe-exec.c:695
static void * fn(void *arg)
#define free(a)
Definition: header.h:65
PGTransactionStatusType
Definition: libpq-fe.h:103
bool ecpg_check_PQresult(PGresult *, int, PGconn *, enum COMPAT_MODE)
Definition: error.c:283
PGconn * connection
bool ecpg_init(const struct connection *con, const char *connection_name, const int lineno)
Definition: misc.c:105
int pthread_once_t
Definition: pthread-win32.h:9
void * pthread_getspecific(pthread_key_t key)
Definition: pthread-win32.c:29
bool ECPGtrans(int lineno, const char *connection_name, const char *transaction)
Definition: misc.c:199
void ECPGset_noind_null(enum ECPGttype type, void *ptr)
Definition: misc.c:320
bool ECPGis_noind_null(enum ECPGttype type, const void *ptr)
Definition: misc.c:391
char arr[FLEXIBLE_ARRAY_MEMBER]
static struct sqlca_t sqlca
Definition: misc.c:63
void pthread_setspecific(pthread_key_t key, void *val)
Definition: pthread-win32.c:24
struct connection * ecpg_get_connection(const char *connection_name)
Definition: connect.c:74
char sqlerrmc[SQLERRMC_LEN]
Definition: sqlca.h:27
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1940
void * arg
bool ecpg_internal_regression_mode
Definition: misc.c:30
static char format
Definition: pg_basebackup.c:89
#define vfprintf
Definition: port.h:195
#define ECPG_NO_CONN
Definition: ecpgerrno.h:36
#define snprintf
Definition: port.h:192
struct var_list * ivlist
Definition: misc.c:528
ECPGttype
Definition: ecpgtype.h:41