Age Owner Branch data TLA Line data Source code
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 : :
9 : : #include "ecpg-pthread-win32.h"
10 : : #include "ecpgerrno.h"
11 : : #include "ecpglib.h"
12 : : #include "ecpglib_extern.h"
13 : : #include "ecpgtype.h"
14 : : #include "pg_config_paths.h"
15 : : #include "pgtypes_date.h"
16 : : #include "pgtypes_interval.h"
17 : : #include "pgtypes_numeric.h"
18 : : #include "pgtypes_timestamp.h"
19 : : #include "sqlca.h"
20 : :
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 : :
29 : : bool ecpg_internal_regression_mode = false;
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 : : static pthread_key_t sqlca_key;
59 : : static pthread_once_t sqlca_key_once = PTHREAD_ONCE_INIT;
60 : :
61 : : static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
62 : : static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
63 : : static int simple_debug = 0;
64 : : static FILE *debugstream = NULL;
65 : :
66 : : void
2489 tgl@sss.pgh.pa.us 67 :CBC 1604237 : ecpg_init_sqlca(struct sqlca_t *sqlca)
68 : : {
7559 bruce@momjian.us 69 : 1604237 : memcpy((char *) sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
7700 meskes@postgresql.or 70 : 1604237 : }
71 : :
72 : : bool
2489 tgl@sss.pgh.pa.us 73 : 3842 : ecpg_init(const struct connection *con, const char *connection_name, const int lineno)
74 : : {
7609 bruce@momjian.us 75 : 3842 : struct sqlca_t *sqlca = ECPGget_sqlca();
76 : :
3226 meskes@postgresql.or 77 [ - + ]: 3842 : if (sqlca == NULL)
78 : : {
3226 meskes@postgresql.or 79 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY,
80 : : NULL);
2432 peter_e@gmx.net 81 : 0 : return false;
82 : : }
83 : :
6038 meskes@postgresql.or 84 :CBC 3842 : ecpg_init_sqlca(sqlca);
7700 85 [ + + ]: 3842 : if (con == NULL)
86 : : {
6038 87 [ + + ]: 20 : ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
5568 peter_e@gmx.net 88 : 6 : connection_name ? connection_name : ecpg_gettext("NULL"));
2432 89 : 14 : return false;
90 : : }
91 : :
92 : 3828 : return true;
93 : : }
94 : :
95 : : static void
7168 bruce@momjian.us 96 : 68 : ecpg_sqlca_key_destructor(void *arg)
97 : : {
5995 98 : 68 : free(arg); /* sqlca structure allocated in ECPGget_sqlca */
7336 meskes@postgresql.or 99 : 68 : }
100 : :
101 : : static void
7168 bruce@momjian.us 102 : 63 : ecpg_sqlca_key_init(void)
103 : : {
104 : 63 : pthread_key_create(&sqlca_key, ecpg_sqlca_key_destructor);
7609 105 : 63 : }
106 : :
107 : : struct sqlca_t *
108 : 3229314 : ECPGget_sqlca(void)
109 : : {
110 : : struct sqlca_t *sqlca;
111 : :
7559 112 : 3229314 : pthread_once(&sqlca_key_once, ecpg_sqlca_key_init);
113 : :
114 : 3229314 : sqlca = pthread_getspecific(sqlca_key);
115 [ + + ]: 3229314 : if (sqlca == NULL)
116 : : {
117 : 129 : sqlca = malloc(sizeof(struct sqlca_t));
3226 meskes@postgresql.or 118 [ - + ]: 129 : if (sqlca == NULL)
3226 meskes@postgresql.or 119 :UBC 0 : return NULL;
6038 meskes@postgresql.or 120 :CBC 129 : ecpg_init_sqlca(sqlca);
7559 bruce@momjian.us 121 : 129 : pthread_setspecific(sqlca_key, sqlca);
122 : : }
2432 peter_e@gmx.net 123 : 3229314 : return sqlca;
124 : : }
125 : :
126 : : bool
7700 meskes@postgresql.or 127 :UBC 0 : ECPGstatus(int lineno, const char *connection_name)
128 : : {
6038 129 : 0 : struct connection *con = ecpg_get_connection(connection_name);
130 : :
131 [ # # ]: 0 : if (!ecpg_init(con, connection_name, lineno))
2432 peter_e@gmx.net 132 : 0 : return false;
133 : :
134 : : /* are we connected? */
7700 meskes@postgresql.or 135 [ # # ]: 0 : if (con->connection == NULL)
136 : : {
6038 137 : 0 : ecpg_raise(lineno, ECPG_NOT_CONN, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, con->name);
7700 138 : 0 : return false;
139 : : }
140 : :
2432 peter_e@gmx.net 141 : 0 : return true;
142 : : }
143 : :
144 : : PGTransactionStatusType
5322 meskes@postgresql.or 145 : 0 : ECPGtransactionStatus(const char *connection_name)
146 : : {
147 : : const struct connection *con;
148 : :
149 : 0 : con = ecpg_get_connection(connection_name);
5161 bruce@momjian.us 150 [ # # ]: 0 : if (con == NULL)
151 : : {
152 : : /* transaction status is unknown */
5322 meskes@postgresql.or 153 : 0 : return PQTRANS_UNKNOWN;
154 : : }
155 : :
156 : 0 : return PQtransactionStatus(con->connection);
157 : : }
158 : :
159 : : bool
7700 meskes@postgresql.or 160 :CBC 123 : ECPGtrans(int lineno, const char *connection_name, const char *transaction)
161 : : {
162 : : PGresult *res;
6038 163 : 123 : struct connection *con = ecpg_get_connection(connection_name);
164 : :
165 [ - + ]: 123 : if (!ecpg_init(con, connection_name, lineno))
2432 peter_e@gmx.net 166 :UBC 0 : return false;
167 : :
5568 peter_e@gmx.net 168 [ + - ]:CBC 123 : ecpg_log("ECPGtrans on line %d: action \"%s\"; connection \"%s\"\n", lineno, transaction, con ? con->name : "null");
169 : :
170 : : /* if we have no connection we just simulate the command */
7700 meskes@postgresql.or 171 [ + - + - ]: 123 : if (con && con->connection)
172 : : {
173 : : /*
174 : : * If we got a transaction command but have no open transaction, we
175 : : * have to start one, unless we are in autocommit, where the
176 : : * developers have to take care themselves. However, if the command is
177 : : * a begin statement, we just execute it once. And if the command is
178 : : * commit or rollback prepared, we don't execute it.
179 : : */
2589 180 [ + + ]: 123 : if (PQtransactionStatus(con->connection) == PQTRANS_IDLE &&
181 [ + + ]: 27 : !con->autocommit &&
182 [ + + ]: 24 : strncmp(transaction, "begin", 5) != 0 &&
183 [ + - ]: 1 : strncmp(transaction, "start", 5) != 0 &&
184 [ - + ]: 1 : strncmp(transaction, "commit prepared", 15) != 0 &&
2589 meskes@postgresql.or 185 [ # # ]:UBC 0 : strncmp(transaction, "rollback prepared", 17) != 0)
186 : : {
6789 187 : 0 : res = PQexec(con->connection, "begin transaction");
6038 188 [ # # ]: 0 : if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL))
2433 peter_e@gmx.net 189 : 0 : return false;
7700 meskes@postgresql.or 190 : 0 : PQclear(res);
191 : : }
192 : :
6789 meskes@postgresql.or 193 :CBC 123 : res = PQexec(con->connection, transaction);
6038 194 [ - + ]: 123 : if (!ecpg_check_PQresult(res, lineno, con->connection, ECPG_COMPAT_PGSQL))
2433 peter_e@gmx.net 195 :UBC 0 : return false;
6789 meskes@postgresql.or 196 :CBC 123 : PQclear(res);
197 : : }
198 : :
7700 199 : 123 : return true;
200 : : }
201 : :
202 : :
203 : : void
204 : 58 : ECPGdebug(int n, FILE *dbgs)
205 : : {
7593 206 : 58 : pthread_mutex_lock(&debug_init_mutex);
207 : :
5995 bruce@momjian.us 208 [ + - ]: 58 : if (n > 100)
209 : : {
6302 meskes@postgresql.or 210 : 58 : ecpg_internal_regression_mode = true;
5995 bruce@momjian.us 211 : 58 : simple_debug = n - 100;
212 : : }
213 : : else
6302 meskes@postgresql.or 214 :UBC 0 : simple_debug = n;
215 : :
7700 meskes@postgresql.or 216 :CBC 58 : debugstream = dbgs;
217 : :
6038 218 : 58 : ecpg_log("ECPGdebug: set to %d\n", simple_debug);
219 : :
7593 220 : 58 : pthread_mutex_unlock(&debug_init_mutex);
7700 221 : 58 : }
222 : :
223 : : void
6038 224 : 14613 : ecpg_log(const char *format,...)
225 : : {
226 : : va_list ap;
5421 bruce@momjian.us 227 : 14613 : struct sqlca_t *sqlca = ECPGget_sqlca();
228 : : const char *intl_format;
229 : : int bufsize;
230 : : char *fmt;
231 : :
5599 tgl@sss.pgh.pa.us 232 [ + + ]: 14613 : if (!simple_debug)
meskes@postgresql.or 233 : 11271 : return;
234 : :
235 : : /* localize the error message string */
236 : 3342 : intl_format = ecpg_gettext(format);
237 : :
238 : : /*
239 : : * Insert PID into the format, unless ecpg_internal_regression_mode is set
240 : : * (regression tests want unchanging output).
241 : : */
tgl@sss.pgh.pa.us 242 : 3342 : bufsize = strlen(intl_format) + 100;
243 : 3342 : fmt = (char *) malloc(bufsize);
244 [ - + ]: 3342 : if (fmt == NULL)
5599 tgl@sss.pgh.pa.us 245 :UBC 0 : return;
246 : :
5599 meskes@postgresql.or 247 [ + - ]:CBC 3342 : if (ecpg_internal_regression_mode)
tgl@sss.pgh.pa.us 248 : 3342 : snprintf(fmt, bufsize, "[NO_PID]: %s", intl_format);
249 : : else
5599 tgl@sss.pgh.pa.us 250 :UBC 0 : snprintf(fmt, bufsize, "[%d]: %s", (int) getpid(), intl_format);
251 : :
5599 meskes@postgresql.or 252 :CBC 3342 : pthread_mutex_lock(&debug_mutex);
253 : :
254 : 3342 : va_start(ap, format);
tgl@sss.pgh.pa.us 255 : 3342 : vfprintf(debugstream, fmt, ap);
meskes@postgresql.or 256 : 3342 : va_end(ap);
257 : :
258 : : /* dump out internal sqlca variables */
3226 259 [ + - + - ]: 3342 : if (ecpg_internal_regression_mode && sqlca != NULL)
260 : : {
5599 261 : 3342 : fprintf(debugstream, "[NO_PID]: sqlca: code: %ld, state: %s\n",
262 : 3342 : sqlca->sqlcode, sqlca->sqlstate);
263 : : }
264 : :
265 : 3342 : fflush(debugstream);
266 : :
267 : 3342 : pthread_mutex_unlock(&debug_mutex);
268 : :
tgl@sss.pgh.pa.us 269 : 3342 : free(fmt);
270 : : }
271 : :
272 : : void
7231 meskes@postgresql.or 273 : 1785 : ECPGset_noind_null(enum ECPGttype type, void *ptr)
274 : : {
7599 275 [ + + + + : 1785 : switch (type)
- + + - -
+ + - +
+ ]
276 : : {
7559 bruce@momjian.us 277 : 945 : case ECPGt_char:
278 : : case ECPGt_unsigned_char:
279 : : case ECPGt_string:
7555 peter_e@gmx.net 280 : 945 : *((char *) ptr) = '\0';
7599 meskes@postgresql.or 281 : 945 : break;
282 : 2 : case ECPGt_short:
283 : : case ECPGt_unsigned_short:
284 : 2 : *((short int *) ptr) = SHRT_MIN;
285 : 2 : break;
286 : 2 : case ECPGt_int:
287 : : case ECPGt_unsigned_int:
288 : 2 : *((int *) ptr) = INT_MIN;
289 : 2 : break;
290 : 5 : case ECPGt_long:
291 : : case ECPGt_unsigned_long:
292 : : case ECPGt_date:
293 : 5 : *((long *) ptr) = LONG_MIN;
294 : 5 : break;
7599 meskes@postgresql.or 295 :UBC 0 : case ECPGt_long_long:
296 : : case ECPGt_unsigned_long_long:
297 : 0 : *((long long *) ptr) = LONG_LONG_MIN;
298 : 0 : break;
7599 meskes@postgresql.or 299 :CBC 2 : case ECPGt_float:
300 : 2 : memset((char *) ptr, 0xff, sizeof(float));
301 : 2 : break;
302 : 4 : case ECPGt_double:
303 : 4 : memset((char *) ptr, 0xff, sizeof(double));
304 : 4 : break;
7599 meskes@postgresql.or 305 :UBC 0 : case ECPGt_varchar:
306 : 0 : *(((struct ECPGgeneric_varchar *) ptr)->arr) = 0x00;
7231 307 : 0 : ((struct ECPGgeneric_varchar *) ptr)->len = 0;
7599 308 : 0 : break;
1882 309 : 0 : case ECPGt_bytea:
310 : 0 : ((struct ECPGgeneric_bytea *) ptr)->len = 0;
311 : 0 : break;
7593 meskes@postgresql.or 312 :CBC 819 : case ECPGt_decimal:
7523 313 : 819 : memset((char *) ptr, 0, sizeof(decimal));
5185 314 : 819 : ((decimal *) ptr)->sign = NUMERIC_NULL;
7593 315 : 819 : break;
7599 316 : 2 : case ECPGt_numeric:
7523 317 : 2 : memset((char *) ptr, 0, sizeof(numeric));
5185 318 : 2 : ((numeric *) ptr)->sign = NUMERIC_NULL;
7599 319 : 2 : break;
7599 meskes@postgresql.or 320 :UBC 0 : case ECPGt_interval:
7523 321 : 0 : memset((char *) ptr, 0xff, sizeof(interval));
7599 322 : 0 : break;
7599 meskes@postgresql.or 323 :CBC 3 : case ECPGt_timestamp:
7523 324 : 3 : memset((char *) ptr, 0xff, sizeof(timestamp));
7599 325 : 3 : break;
326 : 1 : default:
327 : 1 : break;
328 : : }
329 : 1785 : }
330 : :
331 : : static bool
2357 peter_e@gmx.net 332 : 11 : _check(const unsigned char *ptr, int length)
333 : : {
5255 meskes@postgresql.or 334 [ + + ]: 59 : for (length--; length >= 0; length--)
335 [ + + ]: 52 : if (ptr[length] != 0xff)
336 : 4 : return false;
337 : :
338 : 7 : return true;
339 : : }
340 : :
341 : : bool
2357 peter_e@gmx.net 342 : 2763 : ECPGis_noind_null(enum ECPGttype type, const void *ptr)
343 : : {
7599 meskes@postgresql.or 344 [ + + + + : 2763 : switch (type)
- + + - -
+ - - +
+ ]
345 : : {
7559 bruce@momjian.us 346 : 20 : case ECPGt_char:
347 : : case ECPGt_unsigned_char:
348 : : case ECPGt_string:
2357 peter_e@gmx.net 349 [ + + ]: 20 : if (*((const char *) ptr) == '\0')
7559 bruce@momjian.us 350 : 2 : return true;
7599 meskes@postgresql.or 351 : 18 : break;
352 : 4 : case ECPGt_short:
353 : : case ECPGt_unsigned_short:
2357 peter_e@gmx.net 354 [ + + ]: 4 : if (*((const short int *) ptr) == SHRT_MIN)
7559 bruce@momjian.us 355 : 2 : return true;
7599 meskes@postgresql.or 356 : 2 : break;
357 : 18 : case ECPGt_int:
358 : : case ECPGt_unsigned_int:
2357 peter_e@gmx.net 359 [ + + ]: 18 : if (*((const int *) ptr) == INT_MIN)
7559 bruce@momjian.us 360 : 2 : return true;
7599 meskes@postgresql.or 361 : 16 : break;
362 : 18 : case ECPGt_long:
363 : : case ECPGt_unsigned_long:
364 : : case ECPGt_date:
2357 peter_e@gmx.net 365 [ + + ]: 18 : if (*((const long *) ptr) == LONG_MIN)
7559 bruce@momjian.us 366 : 5 : return true;
7599 meskes@postgresql.or 367 : 13 : break;
7599 meskes@postgresql.or 368 :UBC 0 : case ECPGt_long_long:
369 : : case ECPGt_unsigned_long_long:
2357 peter_e@gmx.net 370 [ # # ]: 0 : if (*((const long long *) ptr) == LONG_LONG_MIN)
7559 bruce@momjian.us 371 : 0 : return true;
7599 meskes@postgresql.or 372 : 0 : break;
7599 meskes@postgresql.or 373 :CBC 4 : case ECPGt_float:
2432 peter_e@gmx.net 374 : 4 : return _check(ptr, sizeof(float));
375 : : break;
7599 meskes@postgresql.or 376 : 4 : case ECPGt_double:
2432 peter_e@gmx.net 377 : 4 : return _check(ptr, sizeof(double));
378 : : break;
7599 meskes@postgresql.or 379 :UBC 0 : case ECPGt_varchar:
2357 peter_e@gmx.net 380 [ # # ]: 0 : if (*(((const struct ECPGgeneric_varchar *) ptr)->arr) == 0x00)
7559 bruce@momjian.us 381 : 0 : return true;
7599 meskes@postgresql.or 382 : 0 : break;
1882 383 : 0 : case ECPGt_bytea:
1878 peter@eisentraut.org 384 [ # # ]: 0 : if (((const struct ECPGgeneric_bytea *) ptr)->len == 0)
1882 meskes@postgresql.or 385 : 0 : return true;
386 : 0 : break;
7593 meskes@postgresql.or 387 :CBC 2688 : case ECPGt_decimal:
2357 peter_e@gmx.net 388 [ + + ]: 2688 : if (((const decimal *) ptr)->sign == NUMERIC_NULL)
7559 bruce@momjian.us 389 : 260 : return true;
7593 meskes@postgresql.or 390 : 2428 : break;
7599 meskes@postgresql.or 391 :UBC 0 : case ECPGt_numeric:
2357 peter_e@gmx.net 392 [ # # ]: 0 : if (((const numeric *) ptr)->sign == NUMERIC_NULL)
7559 bruce@momjian.us 393 : 0 : return true;
7599 meskes@postgresql.or 394 : 0 : break;
395 : 0 : case ECPGt_interval:
2432 peter_e@gmx.net 396 : 0 : return _check(ptr, sizeof(interval));
397 : : break;
7599 meskes@postgresql.or 398 :CBC 3 : case ECPGt_timestamp:
2432 peter_e@gmx.net 399 : 3 : return _check(ptr, sizeof(timestamp));
400 : : break;
7599 meskes@postgresql.or 401 : 4 : default:
402 : 4 : break;
403 : : }
404 : :
405 : 2481 : return false;
406 : : }
407 : :
408 : : #ifdef WIN32
409 : :
410 : : int
411 : : pthread_mutex_init(pthread_mutex_t *mp, void *attr)
412 : : {
413 : : mp->initstate = 0;
414 : : return 0;
415 : : }
416 : :
417 : : int
418 : : pthread_mutex_lock(pthread_mutex_t *mp)
419 : : {
420 : : /* Initialize the csection if not already done */
421 : : if (mp->initstate != 1)
422 : : {
423 : : LONG istate;
424 : :
425 : : while ((istate = InterlockedExchange(&mp->initstate, 2)) == 2)
426 : : Sleep(0); /* wait, another thread is doing this */
427 : : if (istate != 1)
428 : : InitializeCriticalSection(&mp->csection);
429 : : InterlockedExchange(&mp->initstate, 1);
430 : : }
431 : : EnterCriticalSection(&mp->csection);
432 : : return 0;
433 : : }
434 : :
435 : : int
436 : : pthread_mutex_unlock(pthread_mutex_t *mp)
437 : : {
438 : : if (mp->initstate != 1)
439 : : return EINVAL;
440 : : LeaveCriticalSection(&mp->csection);
441 : : return 0;
442 : : }
443 : :
444 : : static pthread_mutex_t win32_pthread_once_lock = PTHREAD_MUTEX_INITIALIZER;
445 : :
446 : : void
447 : : win32_pthread_once(volatile pthread_once_t *once, void (*fn) (void))
448 : : {
449 : : if (!*once)
450 : : {
451 : : pthread_mutex_lock(&win32_pthread_once_lock);
452 : : if (!*once)
453 : : {
454 : : fn();
455 : : *once = true;
456 : : }
457 : : pthread_mutex_unlock(&win32_pthread_once_lock);
458 : : }
459 : : }
460 : : #endif /* WIN32 */
461 : :
462 : : #ifdef ENABLE_NLS
463 : :
464 : : char *
5812 peter_e@gmx.net 465 : 3410 : ecpg_gettext(const char *msgid)
466 : : {
467 : : /*
468 : : * At least on Windows, there are gettext implementations that fail if
469 : : * multiple threads call bindtextdomain() concurrently. Use a mutex and
470 : : * flag variable to ensure that we call it just once per process. It is
471 : : * not known that similar bugs exist on non-Windows platforms, but we
472 : : * might as well do it the same way everywhere.
473 : : */
474 : : static volatile bool already_bound = false;
475 : : static pthread_mutex_t binddomain_mutex = PTHREAD_MUTEX_INITIALIZER;
476 : :
477 [ + + ]: 3410 : if (!already_bound)
478 : : {
479 : : /* dgettext() preserves errno, but bindtextdomain() doesn't */
480 : : #ifdef WIN32
481 : : int save_errno = GetLastError();
482 : : #else
483 : 57 : int save_errno = errno;
484 : : #endif
485 : :
65 tgl@sss.pgh.pa.us 486 : 57 : (void) pthread_mutex_lock(&binddomain_mutex);
487 : :
488 [ + - ]: 57 : if (!already_bound)
489 : : {
490 : : const char *ldir;
491 : :
492 : : /*
493 : : * No relocatable lookup here because the calling executable could
494 : : * be anywhere
495 : : */
496 : 57 : ldir = getenv("PGLOCALEDIR");
497 [ - + ]: 57 : if (!ldir)
65 tgl@sss.pgh.pa.us 498 :UBC 0 : ldir = LOCALEDIR;
65 tgl@sss.pgh.pa.us 499 :CBC 57 : bindtextdomain(PG_TEXTDOMAIN("ecpglib"), ldir);
500 : 57 : already_bound = true;
501 : : }
502 : :
503 : 57 : (void) pthread_mutex_unlock(&binddomain_mutex);
504 : :
505 : : #ifdef WIN32
506 : : SetLastError(save_errno);
507 : : #else
5812 peter_e@gmx.net 508 : 57 : errno = save_errno;
509 : : #endif
510 : : }
511 : :
4095 meskes@postgresql.or 512 : 3410 : return dgettext(PG_TEXTDOMAIN("ecpglib"), msgid);
513 : : }
514 : : #endif /* ENABLE_NLS */
515 : :
516 : : struct var_list *ivlist = NULL;
517 : :
518 : : void
5192 519 : 14 : ECPGset_var(int number, void *pointer, int lineno)
520 : : {
521 : : struct var_list *ptr;
522 : :
1901 523 : 14 : struct sqlca_t *sqlca = ECPGget_sqlca();
524 : :
525 [ - + ]: 14 : if (sqlca == NULL)
526 : : {
1871 peter@eisentraut.org 527 :UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
528 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
529 : 0 : return;
530 : : }
531 : :
1871 peter@eisentraut.org 532 :CBC 14 : ecpg_init_sqlca(sqlca);
533 : :
5192 meskes@postgresql.or 534 [ + + ]: 39 : for (ptr = ivlist; ptr != NULL; ptr = ptr->next)
535 : : {
536 [ - + ]: 25 : if (ptr->number == number)
537 : : {
538 : : /* already known => just change pointer value */
5192 meskes@postgresql.or 539 :UBC 0 : ptr->pointer = pointer;
540 : 0 : return;
541 : : }
542 : : }
543 : :
544 : : /* a new one has to be added */
5192 meskes@postgresql.or 545 :CBC 14 : ptr = (struct var_list *) calloc(1L, sizeof(struct var_list));
546 [ - + ]: 14 : if (!ptr)
547 : : {
557 drowley@postgresql.o 548 :UBC 0 : sqlca = ECPGget_sqlca();
549 : :
3226 meskes@postgresql.or 550 [ # # ]: 0 : if (sqlca == NULL)
551 : : {
552 : 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
553 : : ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
554 : 0 : return;
555 : : }
556 : :
5192 557 : 0 : sqlca->sqlcode = ECPG_OUT_OF_MEMORY;
4420 peter_e@gmx.net 558 : 0 : strncpy(sqlca->sqlstate, "YE001", sizeof(sqlca->sqlstate));
5192 meskes@postgresql.or 559 : 0 : snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "out of memory on line %d", lineno);
560 : 0 : sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc);
561 : : /* free all memory we have allocated for the user */
562 : 0 : ECPGfree_auto_mem();
563 : : }
564 : : else
565 : : {
5192 meskes@postgresql.or 566 :CBC 14 : ptr->number = number;
567 : 14 : ptr->pointer = pointer;
568 : 14 : ptr->next = ivlist;
569 : 14 : ivlist = ptr;
570 : : }
571 : : }
572 : :
573 : : void *
574 : 51 : ECPGget_var(int number)
575 : : {
576 : : struct var_list *ptr;
577 : :
578 [ + - + + ]: 76 : for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next);
5161 bruce@momjian.us 579 [ + - ]: 51 : return (ptr) ? ptr->pointer : NULL;
580 : : }
|