LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - misc.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB
Current: Differential Code Coverage HEAD vs 15 Lines: 69.8 % 235 164 1 70 164 1
Current Date: 2023-04-08 15:15:32 Functions: 87.5 % 16 14 2 1 13
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a