LCOV - code coverage report
Current view: top level - src/odbc - descriptor.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 93 104 89.4 %
Date: 2025-02-21 09:36:06 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 2003  Steve Murphree
       3             :  * Copyright (C) 2004, 2005  Ziglio Frediano
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdarg.h>
      24             : #include <stdio.h>
      25             : 
      26             : #if HAVE_STDLIB_H
      27             : #include <stdlib.h>
      28             : #endif /* HAVE_STDLIB_H */
      29             : 
      30             : #if HAVE_STRING_H
      31             : #include <string.h>
      32             : #endif /* HAVE_STRING_H */
      33             : 
      34             : #include <freetds/odbc.h>
      35             : #include <freetds/utils/string.h>
      36             : #include <odbcss.h>
      37             : 
      38             : static void desc_free_record(struct _drecord *drec);
      39             : 
      40             : TDS_DESC *
      41       78992 : desc_alloc(SQLHANDLE parent, int desc_type, SQLSMALLINT alloc_type)
      42             : {
      43             :         TDS_DESC *desc;
      44             : 
      45       78992 :         desc = tds_new0(TDS_DESC, 1);
      46      157984 :         if (!desc || tds_mutex_init(&desc->mtx)) {
      47           0 :                 free(desc);
      48           0 :                 return NULL;
      49             :         }
      50             : 
      51             :         /* set default header values */
      52       78992 :         desc->htype = SQL_HANDLE_DESC;
      53       78992 :         desc->type = desc_type;
      54       78992 :         desc->parent = parent;
      55       78992 :         desc->header.sql_desc_alloc_type = alloc_type;
      56       78992 :         desc->header.sql_desc_count = 0;
      57       78992 :         desc->records = NULL;
      58             : 
      59       78992 :         switch (desc_type) {
      60             :         case DESC_IRD:
      61             :         case DESC_IPD:
      62             :                 break;
      63       39506 :         case DESC_ARD:
      64             :         case DESC_APD:
      65       39506 :                 desc->header.sql_desc_bind_type = SQL_BIND_BY_COLUMN;
      66       39506 :                 desc->header.sql_desc_array_size = 1;
      67       39506 :                 break;
      68           0 :         default:
      69           0 :                 free(desc);
      70           0 :                 return NULL;
      71             :         }
      72       78992 :         CHECK_DESC_EXTRA(desc);
      73       78992 :         return desc;
      74             : }
      75             : 
      76             : #define SQL_DESC_STRINGS \
      77             :         STR_OP(sql_desc_base_column_name); \
      78             :         STR_OP(sql_desc_base_table_name); \
      79             :         STR_OP(sql_desc_catalog_name); \
      80             :         STR_OP(sql_desc_label); \
      81             :         STR_OP(sql_desc_local_type_name); \
      82             :         STR_OP(sql_desc_name); \
      83             :         STR_OP(sql_desc_schema_name); \
      84             :         STR_OP(sql_desc_table_name)
      85             : 
      86             : SQLRETURN
      87       33309 : desc_alloc_records(TDS_DESC * desc, unsigned count)
      88             : {
      89             :         struct _drecord *drec;
      90             :         int i;
      91             : 
      92             :         /* shrink records */
      93       33309 :         if (desc->header.sql_desc_count >= count) {
      94        4456 :                 for (i = count; i < desc->header.sql_desc_count; ++i)
      95          10 :                         desc_free_record(&desc->records[i]);
      96        4446 :                 desc->header.sql_desc_count = count;
      97        4446 :                 return SQL_SUCCESS;
      98             :         }
      99             : 
     100       28863 :         if (!TDS_RESIZE(desc->records, count))
     101             :                 return SQL_ERROR;
     102       28863 :         memset(desc->records + desc->header.sql_desc_count, 0, sizeof(struct _drecord) * (count - desc->header.sql_desc_count));
     103             : 
     104       65268 :         for (i = desc->header.sql_desc_count; i < count; ++i) {
     105       36405 :                 drec = &desc->records[i];
     106             : 
     107             : #define STR_OP(name) tds_dstr_init(&drec->name)
     108      327645 :                 SQL_DESC_STRINGS;
     109             : #undef STR_OP
     110             : 
     111       36405 :                 switch (desc->type) {
     112       24297 :                 case DESC_IRD:
     113             :                 case DESC_IPD:
     114       24297 :                         drec->sql_desc_parameter_type = SQL_PARAM_INPUT;
     115       24297 :                         break;
     116       12108 :                 case DESC_ARD:
     117             :                 case DESC_APD:
     118       12108 :                         drec->sql_desc_concise_type = SQL_C_DEFAULT;
     119       12108 :                         drec->sql_desc_type = SQL_C_DEFAULT;
     120       12108 :                         break;
     121             :                 }
     122             :         }
     123       28863 :         desc->header.sql_desc_count = count;
     124       28863 :         return SQL_SUCCESS;
     125             : }
     126             : 
     127             : static void
     128       36405 : desc_free_record(struct _drecord *drec)
     129             : {
     130             : #define STR_OP(name) tds_dstr_free(&drec->name)
     131       36405 :         SQL_DESC_STRINGS;
     132             : #undef STR_OP
     133       36405 :         if (drec->sql_desc_concise_type == SQL_SS_TABLE)
     134          32 :                 tvp_free((SQLTVP *) drec->sql_desc_data_ptr);
     135       36405 : }
     136             : 
     137             : SQLRETURN
     138      178063 : desc_free_records(TDS_DESC * desc)
     139             : {
     140             :         int i;
     141             : 
     142      178063 :         if (desc->records) {
     143       36395 :                 for (i = 0; i < desc->header.sql_desc_count; i++)
     144       36395 :                         desc_free_record(&desc->records[i]);
     145       26875 :                 TDS_ZERO_FREE(desc->records);
     146             :         }
     147             : 
     148      178063 :         desc->header.sql_desc_count = 0;
     149      178063 :         return SQL_SUCCESS;
     150             : }
     151             : 
     152             : SQLRETURN
     153          10 : desc_copy(TDS_DESC * dest, TDS_DESC * src)
     154             : {
     155             :         int i;
     156          10 :         TDS_DESC tmp = *dest;
     157             : 
     158             :         /* copy header */
     159          10 :         tmp.header = src->header;
     160             : 
     161             :         /* sql_desc_alloc_type should remain unchanged */
     162          10 :         tmp.header.sql_desc_alloc_type = dest->header.sql_desc_alloc_type;
     163             : 
     164             :         /* set no records */
     165          10 :         tmp.header.sql_desc_count = 0;
     166          10 :         tmp.records = NULL;
     167             : 
     168          10 :         tmp.errs.num_errors = 0;
     169          10 :         tmp.errs.errs = NULL;
     170             : 
     171          10 :         if (desc_alloc_records(&tmp, src->header.sql_desc_count) != SQL_SUCCESS)
     172             :                 return SQL_ERROR;
     173             : 
     174          20 :         for (i = 0; i < src->header.sql_desc_count; ++i) {
     175          20 :                 struct _drecord *src_rec = &src->records[i];
     176          20 :                 struct _drecord *dest_rec = &tmp.records[i];
     177             : 
     178             :                 /* copy all integers at once ! */
     179          20 :                 memcpy(dest_rec, src_rec, sizeof(struct _drecord));
     180             : 
     181             :                 /* reinitialize string, avoid doubling pointers */
     182             : #define STR_OP(name) tds_dstr_init(&dest_rec->name)
     183         180 :                 SQL_DESC_STRINGS;
     184             : #undef STR_OP
     185             : 
     186             :                 /* copy strings */
     187             : #define STR_OP(name) if (!tds_dstr_dup(&dest_rec->name, &src_rec->name)) goto Cleanup
     188         140 :                 SQL_DESC_STRINGS;
     189             : #undef STR_OP
     190             :         }
     191             : 
     192             :         /* success, copy back to our descriptor */
     193          10 :         desc_free_records(dest);
     194          10 :         odbc_errs_reset(&dest->errs);
     195          10 :         *dest = tmp;
     196          10 :         return SQL_SUCCESS;
     197             : 
     198           0 : Cleanup:
     199           0 :         desc_free_records(&tmp);
     200           0 :         odbc_errs_reset(&tmp.errs);
     201           0 :         return SQL_ERROR;
     202             : }
     203             : 
     204             : SQLRETURN
     205       78992 : desc_free(TDS_DESC * desc)
     206             : {
     207       78992 :         if (desc) {
     208       78992 :                 desc_free_records(desc);
     209       78992 :                 odbc_errs_reset(&desc->errs);
     210       78992 :                 tds_mutex_free(&desc->mtx);
     211       78992 :                 free(desc);
     212             :         }
     213       78992 :         return SQL_SUCCESS;
     214             : }
     215             : 
     216             : TDS_DBC *
     217          10 : desc_get_dbc(TDS_DESC *desc)
     218             : {
     219          10 :         if (IS_HSTMT(desc->parent))
     220          10 :                 return ((TDS_STMT *) desc->parent)->dbc;
     221             : 
     222             :         return (TDS_DBC *) desc->parent;
     223             : }
     224             : 
     225             : SQLTVP *
     226        4128 : tvp_alloc(TDS_STMT *stmt)
     227             : {
     228        4128 :         SQLTVP *tvp = tds_new0(SQLTVP, 1);
     229        8256 :         tds_dstr_init(&tvp->type_name);
     230        4128 :         tvp->ipd = desc_alloc(stmt, DESC_IPD, SQL_DESC_ALLOC_AUTO);
     231        4128 :         tvp->apd = desc_alloc(stmt, DESC_APD, SQL_DESC_ALLOC_AUTO);
     232        4128 :         if (!tvp->ipd || !tvp->apd) {
     233           0 :                 tvp_free(tvp);
     234           0 :                 return NULL;
     235             :         }
     236        4128 :         tvp->ipd->focus = -1;
     237        4128 :         tvp->apd->focus = -1;
     238        4128 :         return tvp;
     239             : }
     240             : 
     241             : void
     242        4128 : tvp_free(SQLTVP *tvp)
     243             : {
     244        4128 :         if (!tvp)
     245             :                 return;
     246             : 
     247        4128 :         desc_free(tvp->ipd);
     248        4128 :         desc_free(tvp->apd);
     249        4128 :         tds_dstr_free(&tvp->type_name);
     250        4128 :         free(tvp);
     251             : }

Generated by: LCOV version 1.13