LTP GCOV extension - code coverage report
Current view: directory - odbc - prepare_query.c
Test: FreeTDS coverage
Date: 2008-11-21 Instrumented lines: 129
Code covered: 82.9 % Executed lines: 107

       1                 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2                 :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Brian Bruns
       3                 :  * Copyright (C) 2005  Frediano Ziglio
       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                 : #if HAVE_CONFIG_H
      22                 : #include <config.h>
      23                 : #endif
      24                 : 
      25                 : #include <stdio.h>
      26                 : #include <assert.h>
      27                 : 
      28                 : #if HAVE_STDLIB_H
      29                 : #include <stdlib.h>
      30                 : #endif /* HAVE_STDLIB_H */
      31                 : 
      32                 : #if HAVE_STRING_H
      33                 : #include <string.h>
      34                 : #endif /* HAVE_STRING_H */
      35                 : 
      36                 : #include <ctype.h>
      37                 : 
      38                 : #include "tdsodbc.h"
      39                 : #include "tdsconvert.h"
      40                 : 
      41                 : #ifdef DMALLOC
      42                 : #include <dmalloc.h>
      43                 : #endif
      44                 : 
      45                 : TDS_RCSID(var, "$Id: prepare_query.c,v 1.58.2.2 2007/12/21 11:19:04 freddy77 Exp $");
      46                 : 
      47                 : #define TDS_ISSPACE(c) isspace((unsigned char) (c))
      48                 : 
      49                 : static int
      50                 : prepared_rpc(struct _hstmt *stmt, int compute_row)
      51              33 : {
      52              33 :         int nparam = stmt->params ? stmt->params->num_cols : 0;
      53              33 :         const char *p = stmt->prepared_pos - 1;
      54                 : 
      55                 :         for (;;) {
      56                 :                 TDSPARAMINFO *temp_params;
      57                 :                 TDSCOLUMN *curcol;
      58                 :                 TDS_SERVER_TYPE type;
      59                 :                 const char *start;
      60                 : 
      61             118 :                 while (TDS_ISSPACE(*++p));
      62              67 :                 if (!*p)
      63               0 :                         return SQL_SUCCESS;
      64                 : 
      65                 :                 /* we have certainly a parameter */
      66              67 :                 if (!(temp_params = tds_alloc_param_result(stmt->params))) {
      67               0 :                         odbc_errs_add(&stmt->errs, "HY001", NULL);
      68               0 :                         return SQL_ERROR;
      69                 :                 }
      70              67 :                 stmt->params = temp_params;
      71              67 :                 curcol = temp_params->columns[nparam];
      72                 : 
      73              67 :                 switch (*p) {
      74                 :                 case ',':
      75               3 :                         if (IS_TDS7_PLUS(stmt->dbc->tds_socket)) {
      76               1 :                                 tds_set_param_type(stmt->dbc->tds_socket, curcol, SYBVOID);
      77               1 :                                 curcol->column_size = curcol->column_cur_size = 0;
      78                 :                         } else {
      79                 :                                 /* TODO is there a better type ? */
      80               1 :                                 tds_set_param_type(stmt->dbc->tds_socket, curcol, SYBINTN);
      81               1 :                                 curcol->column_size = curcol->on_server.column_size = 4;
      82               1 :                                 curcol->column_cur_size = -1;
      83                 :                         }
      84               2 :                         if (compute_row)
      85               2 :                                 if (!tds_alloc_param_row(temp_params, curcol))
      86               0 :                                         return SQL_ERROR;
      87               2 :                         --p;
      88               2 :                         break;
      89                 :                 default:
      90                 :                         /* add next parameter to list */
      91              16 :                         start = p;
      92                 : 
      93              16 :                         if (!(p = parse_const_param(p, &type)))
      94               0 :                                 return SQL_ERROR;
      95              16 :                         tds_set_param_type(stmt->dbc->tds_socket, curcol, type);
      96              16 :                         switch (type) {
      97                 :                         case SYBVARCHAR:
      98              10 :                                 curcol->column_size = p - start;
      99              10 :                                 break;
     100                 :                         case SYBVARBINARY:
     101               2 :                                 curcol->column_size = (p - start) / 2 -1;
     102               2 :                                 break;
     103                 :                         default:
     104               0 :                                 assert(0);
     105                 :                         case SYBINT4:
     106                 :                         case SYBFLT8:
     107               4 :                                 curcol->column_cur_size = curcol->column_size;
     108                 :                                 break;
     109                 :                         }
     110                 :                         /* TODO support other type other than VARCHAR, do not strip escape in prepare_call */
     111              16 :                         if (compute_row) {
     112                 :                                 char *dest;
     113                 :                                 int len;
     114                 :                                 CONV_RESULT cr;
     115                 : 
     116              16 :                                 if (!tds_alloc_param_row(temp_params, curcol))
     117               0 :                                         return SQL_ERROR;
     118              16 :                                 dest = (char *) &temp_params->current_row[curcol->column_offset];
     119              16 :                                 switch (type) {
     120                 :                                 case SYBVARCHAR:
     121              10 :                                         if (*start != '\'') {
     122               0 :                                                 memcpy(dest, start, p - start);
     123               0 :                                                 curcol->column_cur_size = p - start;
     124                 :                                         } else {
     125              10 :                                                 ++start;
     126                 :                                                 for (;;) {
     127             108 :                                                         if (*start == '\'')
     128              10 :                                                                 ++start;
     129             108 :                                                         if (start >= p)
     130              10 :                                                                 break;
     131              98 :                                                         *dest++ = *start++;
     132              98 :                                                 }
     133              10 :                                                 curcol->column_cur_size =
     134                 :                                                         dest - (char *) (&temp_params->current_row[curcol->column_offset]);
     135                 :                                         }
     136              10 :                                         break;
     137                 :                                 case SYBVARBINARY:
     138               2 :                                         len = tds_convert(NULL, SYBVARCHAR, start, p - start, SYBVARBINARY, &cr);
     139               2 :                                         if (len >= 0) {
     140               2 :                                                 curcol->column_cur_size = len;
     141               2 :                                                 memcpy(dest, cr.ib, len);
     142               2 :                                                 free(cr.ib);
     143                 :                                         }
     144               2 :                                         break;
     145                 :                                 case SYBINT4:
     146               2 :                                         *((TDS_INT *) dest) = strtol(start, NULL, 10);
     147               2 :                                         break;
     148                 :                                 case SYBFLT8:
     149               2 :                                         *((TDS_FLOAT *) dest) = strtod(start, NULL);
     150                 :                                         break;
     151                 :                                 default:
     152                 :                                         break;
     153                 :                                 }
     154                 :                         }
     155              16 :                         --p;
     156              16 :                         break;
     157                 :                 case '?':
     158                 :                         /* find binded parameter */
     159              49 :                         if (stmt->param_num > stmt->apd->header.sql_desc_count
     160                 :                             || stmt->param_num > stmt->ipd->header.sql_desc_count) {
     161                 :                                 /* TODO set error */
     162               0 :                                 return SQL_ERROR;
     163                 :                         }
     164                 : 
     165                 :                         switch (sql2tds
     166                 :                                 (stmt, &stmt->ipd->records[stmt->param_num - 1], &stmt->apd->records[stmt->param_num - 1],
     167              49 :                                  stmt->params, nparam, compute_row, stmt->apd, stmt->curr_param_row)) {
     168                 :                         case SQL_ERROR:
     169               0 :                                 return SQL_ERROR;
     170                 :                         case SQL_NEED_DATA:
     171               0 :                                 return SQL_NEED_DATA;
     172                 :                         }
     173              49 :                         ++stmt->param_num;
     174                 :                         break;
     175                 :                 }
     176              67 :                 ++nparam;
     177                 : 
     178             100 :                 while (TDS_ISSPACE(*++p));
     179              67 :                 if (!*p || *p != ',')
     180              33 :                         return SQL_SUCCESS;
     181              34 :                 stmt->prepared_pos = (char *) p + 1;
     182              34 :         }
     183                 : }
     184                 : 
     185                 : int
     186                 : parse_prepared_query(struct _hstmt *stmt, int compute_row)
     187             925 : {
     188                 :         /* try setting this parameter */
     189                 :         TDSPARAMINFO *temp_params;
     190             925 :         int nparam = stmt->params ? stmt->params->num_cols : 0;
     191                 : 
     192             925 :         if (stmt->prepared_pos)
     193              33 :                 return prepared_rpc(stmt, compute_row);
     194                 : 
     195            1269 :         for (; stmt->param_num <= stmt->param_count; ++nparam, ++stmt->param_num) {
     196                 :                 /* find binded parameter */
     197             408 :                 if (stmt->param_num > stmt->apd->header.sql_desc_count || stmt->param_num > stmt->ipd->header.sql_desc_count) {
     198                 :                         /* TODO set error */
     199              25 :                         return SQL_ERROR;
     200                 :                 }
     201                 : 
     202                 :                 /* add a column to parameters */
     203             383 :                 if (!(temp_params = tds_alloc_param_result(stmt->params))) {
     204               0 :                         odbc_errs_add(&stmt->errs, "HY001", NULL);
     205               0 :                         return SQL_ERROR;
     206                 :                 }
     207             383 :                 stmt->params = temp_params;
     208                 : 
     209                 :                 switch (sql2tds
     210                 :                         (stmt, &stmt->ipd->records[stmt->param_num - 1], &stmt->apd->records[stmt->param_num - 1],
     211             383 :                          stmt->params, nparam, compute_row, stmt->apd, stmt->curr_param_row)) {
     212                 :                 case SQL_ERROR:
     213               0 :                         return SQL_ERROR;
     214                 :                 case SQL_NEED_DATA:
     215               6 :                         return SQL_NEED_DATA;
     216                 :                 }
     217                 :         }
     218             861 :         return SQL_SUCCESS;
     219                 : }
     220                 : 
     221                 : int
     222                 : start_parse_prepared_query(struct _hstmt *stmt, int compute_row)
     223             919 : {
     224                 :         /* TODO should be NULL already ?? */
     225             919 :         tds_free_param_results(stmt->params);
     226             919 :         stmt->params = NULL;
     227             919 :         stmt->param_num = 0;
     228                 : 
     229             919 :         stmt->param_num = stmt->prepared_query_is_func ? 2 : 1;
     230             919 :         return parse_prepared_query(stmt, compute_row);
     231                 : }
     232                 : 
     233                 : int
     234                 : continue_parse_prepared_query(struct _hstmt *stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or_Ind)
     235              24 : {
     236                 :         struct _drecord *drec_apd, *drec_ipd;
     237                 :         SQLLEN len;
     238                 :         int need_bytes;
     239                 :         TDSCOLUMN *curcol;
     240                 :         TDSBLOB *blob;
     241                 : 
     242              24 :         if (!stmt->params)
     243               0 :                 return SQL_ERROR;
     244                 : 
     245              24 :         if (stmt->param_num > stmt->apd->header.sql_desc_count || stmt->param_num > stmt->ipd->header.sql_desc_count)
     246               0 :                 return SQL_ERROR;
     247              24 :         drec_apd = &stmt->apd->records[stmt->param_num - 1];
     248              24 :         drec_ipd = &stmt->ipd->records[stmt->param_num - 1];
     249                 : 
     250              24 :         curcol = stmt->params->columns[stmt->param_num - (stmt->prepared_query_is_func ? 2 : 1)];
     251              24 :         blob = NULL;
     252              24 :         if (is_blob_type(curcol->column_type))
     253              24 :                 blob = (TDSBLOB *) (stmt->params->current_row + curcol->column_offset);
     254              24 :         assert(curcol->column_cur_size <= curcol->column_size);
     255              24 :         need_bytes = curcol->column_size - curcol->column_cur_size;
     256                 : 
     257              24 :         if (SQL_NTS == StrLen_or_Ind)
     258               0 :                 len = strlen((char *) DataPtr);
     259              24 :         else if (SQL_DEFAULT_PARAM == StrLen_or_Ind || StrLen_or_Ind < 0)
     260                 :                 /* FIXME: I don't know what to do */
     261               0 :                 return SQL_ERROR;
     262                 :         else
     263              24 :                 len = StrLen_or_Ind;
     264                 : 
     265              24 :         if (!blob && len > need_bytes)
     266               0 :                 len = need_bytes;
     267                 : 
     268                 :         /* copy to destination */
     269              24 :         if (blob) {
     270                 :                 TDS_CHAR *p;
     271                 : 
     272              24 :                 if (blob->textvalue)
     273              18 :                         p = (TDS_CHAR *) realloc(blob->textvalue, len + curcol->column_cur_size);
     274                 :                 else {
     275               6 :                         assert(curcol->column_cur_size == 0);
     276               6 :                         p = (TDS_CHAR *) malloc(len);
     277                 :                 }
     278              24 :                 if (!p)
     279               0 :                         return SQL_ERROR;
     280              24 :                 blob->textvalue = p;
     281              24 :                 memcpy(blob->textvalue + curcol->column_cur_size, DataPtr, len);
     282                 :         } else {
     283               0 :                 memcpy(stmt->params->current_row + curcol->column_offset + curcol->column_cur_size, DataPtr, len);
     284                 :         }
     285              24 :         curcol->column_cur_size += len;
     286              24 :         if (blob && curcol->column_cur_size > curcol->column_size)
     287              24 :                 curcol->column_size = curcol->column_cur_size;
     288                 : 
     289              24 :         return SQL_SUCCESS;
     290                 : }

Generated by: LTP GCOV extension version 1.6