LCOV - code coverage report
Current view: top level - src/ctlib - blk.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 179 318 56.3 %
Date: 2024-04-20 13:37:27 Functions: 11 23 47.8 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998-2004, 2005, 2010  Brian Bruns, Bill Thompson
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Library General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2 of the License, or (at your option) any later version.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * Library General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Library General Public
      15             :  * License along with this library; if not, write to the
      16             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      17             :  * Boston, MA 02111-1307, USA.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #include <stdarg.h>
      23             : #include <stdio.h>
      24             : 
      25             : #if HAVE_STDLIB_H
      26             : #include <stdlib.h>
      27             : #endif /* HAVE_STDLIB_H */
      28             : 
      29             : #if HAVE_STRING_H
      30             : #include <string.h>
      31             : #endif /* HAVE_STRING_H */
      32             : 
      33             : #include <freetds/utils.h>
      34             : #include <freetds/replacements.h>
      35             : 
      36             : #include "bkpublic.h"
      37             : 
      38             : #include "ctpublic.h"
      39             : #include "ctlib.h"
      40             : 
      41             : static void _blk_null_error(TDSBCPINFO *bcpinfo, int index, int offset);
      42             : static TDSRET _blk_get_col_data(TDSBCPINFO *bulk, TDSCOLUMN *bcpcol, int offset);
      43             : static CS_RETCODE _blk_rowxfer_in(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred);
      44             : static CS_RETCODE _blk_rowxfer_out(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred);
      45             : 
      46             : #define CONN(bulk) ((CS_CONNECTION *) (bulk)->bcpinfo.parent)
      47             : 
      48             : TDS_COMPILE_CHECK(same_size, sizeof(CS_BLKDESC) == sizeof(TDSBCPINFO));
      49             : TDS_COMPILE_CHECK(nested_type, TDS_OFFSET(CS_BLKDESC, bcpinfo) == 0);
      50             : 
      51             : CS_RETCODE
      52          24 : blk_alloc(CS_CONNECTION * connection, CS_INT version, CS_BLKDESC ** blk_pointer)
      53             : {
      54             :         CS_BLKDESC *blkdesc;
      55             : 
      56          24 :         tdsdump_log(TDS_DBG_FUNC, "blk_alloc(%p, %d, %p)\n", connection, version, blk_pointer);
      57             : 
      58          24 :         if (!connection || !connection->tds_socket)
      59             :                 return CS_FAIL;
      60             : 
      61          24 :         if (connection->tds_socket->conn->tds_version < 0x500)
      62             :                 return CS_FAIL;
      63             : 
      64          24 :         blkdesc = (CS_BLKDESC *) tds_alloc_bcpinfo();
      65          24 :         if (!blkdesc)
      66             :                 return CS_FAIL;
      67             : 
      68             :         /* so we know who we belong to */
      69          24 :         blkdesc->bcpinfo.parent = connection;
      70             : 
      71          24 :         *blk_pointer = blkdesc;
      72          24 :         return CS_SUCCEED;
      73             : }
      74             : 
      75             : 
      76             : CS_RETCODE
      77         320 : blk_bind(CS_BLKDESC * blkdesc, CS_INT item, CS_DATAFMT * datafmt_arg, CS_VOID * buffer, CS_INT * datalen, CS_SMALLINT * indicator)
      78             : {
      79             :         TDSCOLUMN *colinfo;
      80             :         CS_CONNECTION *con;
      81             :         CS_INT bind_count;
      82             :         const CS_DATAFMT_COMMON * datafmt;
      83             :         int i;
      84             : 
      85         320 :         tdsdump_log(TDS_DBG_FUNC, "blk_bind(%p, %d, %p, %p, %p, %p)\n", blkdesc, item, datafmt_arg, buffer, datalen, indicator);
      86             : 
      87         320 :         if (!blkdesc)
      88             :                 return CS_FAIL;
      89             : 
      90         320 :         con = CONN(blkdesc);
      91             : 
      92         320 :         datafmt = _ct_datafmt_common(con->ctx, datafmt_arg);
      93             : 
      94         320 :         if (item == CS_UNUSED) {
      95             :                 /* clear all bindings */
      96           0 :                 if (datafmt == NULL && buffer == NULL && datalen == NULL && indicator == NULL ) { 
      97           0 :                         blkdesc->bcpinfo.bind_count = CS_UNUSED;
      98           0 :                         for (i = 0; i < blkdesc->bcpinfo.bindinfo->num_cols; i++ ) {
      99           0 :                                 colinfo = blkdesc->bcpinfo.bindinfo->columns[i];
     100           0 :                                 colinfo->column_varaddr  = NULL;
     101           0 :                                 colinfo->column_bindtype = 0;
     102           0 :                                 colinfo->column_bindfmt  = 0;
     103           0 :                                 colinfo->column_bindlen  = 0;
     104           0 :                                 colinfo->column_nullbind = NULL;
     105           0 :                                 colinfo->column_lenbind  = NULL;
     106             :                         }
     107             :                 }
     108             :                 return CS_SUCCEED;
     109             :         }
     110             : 
     111             :         /* check item value */
     112             : 
     113         320 :         if (item < 1 || item > blkdesc->bcpinfo.bindinfo->num_cols) {
     114           0 :                 _ctclient_msg(con, "blk_bind", 2, 5, 1, 141, "%s, %d", "colnum", item);
     115           0 :                 return CS_FAIL;
     116             :         }
     117             : 
     118             :         /* clear bindings for this column */
     119             : 
     120         320 :         if (datafmt == NULL && buffer == NULL && datalen == NULL && indicator == NULL ) { 
     121             : 
     122           0 :                 colinfo = blkdesc->bcpinfo.bindinfo->columns[item - 1];
     123           0 :                 colinfo->column_varaddr  = NULL;
     124           0 :                 colinfo->column_bindtype = 0;
     125           0 :                 colinfo->column_bindfmt  = 0;
     126           0 :                 colinfo->column_bindlen  = 0;
     127           0 :                 colinfo->column_nullbind = NULL;
     128           0 :                 colinfo->column_lenbind  = NULL;
     129             : 
     130           0 :                 return CS_SUCCEED;
     131             :         }
     132             : 
     133         320 :         if (datafmt == NULL)
     134             :                 return CS_FAIL;
     135             : 
     136             :         /*
     137             :          * check whether the request is for array binding and ensure that user
     138             :          * supplies the same datafmt->count to the subsequent ct_bind calls
     139             :          */
     140             : 
     141         320 :         bind_count = (datafmt->count == 0) ? 1 : datafmt->count;
     142             : 
     143             :         /* first bind for this result set */
     144             : 
     145         320 :         if (blkdesc->bcpinfo.bind_count == CS_UNUSED) {
     146          96 :                 blkdesc->bcpinfo.bind_count = bind_count;
     147             :         } else {
     148             :                 /* all subsequent binds for this result set - the bind counts must be the same */
     149         224 :                 if (blkdesc->bcpinfo.bind_count != bind_count) {
     150           0 :                         _ctclient_msg(con, "blk_bind", 1, 1, 1, 137, "%d, %d", bind_count, blkdesc->bcpinfo.bind_count);
     151           0 :                         return CS_FAIL;
     152             :                 }
     153             :         }
     154             : 
     155             :         /* bind the column_varaddr to the address of the buffer */
     156             : 
     157         320 :         colinfo = blkdesc->bcpinfo.bindinfo->columns[item - 1];
     158             : 
     159         320 :         colinfo->column_varaddr = (char *) buffer;
     160         320 :         colinfo->column_bindtype = datafmt->datatype;
     161         320 :         colinfo->column_bindfmt = datafmt->format;
     162         320 :         colinfo->column_bindlen = datafmt->maxlength;
     163         320 :         if (indicator) {
     164         240 :                 colinfo->column_nullbind = indicator;
     165             :         }
     166         320 :         if (datalen) {
     167         320 :                 colinfo->column_lenbind = datalen;
     168             :         }
     169             :         return CS_SUCCEED;
     170             : }
     171             : 
     172             : CS_RETCODE
     173           0 : blk_colval(SRV_PROC * srvproc, CS_BLKDESC * blkdescp, CS_BLK_ROW * rowp, CS_INT colnum, CS_VOID * valuep, CS_INT valuelen,
     174             :            CS_INT * outlenp)
     175             : {
     176             : 
     177           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_colval(%p, %p, %p, %d, %p, %d, %p)\n", 
     178             :                                 srvproc, blkdescp, rowp, colnum, valuep, valuelen, outlenp);
     179             : 
     180           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_colval()\n");
     181           0 :         return CS_FAIL;
     182             : }
     183             : 
     184             : CS_RETCODE
     185           0 : blk_default(CS_BLKDESC * blkdesc, CS_INT colnum, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
     186             : {
     187             : 
     188           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_default(%p, %d, %p, %d, %p)\n", blkdesc, colnum, buffer, buflen, outlen);
     189             : 
     190           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_default()\n");
     191           0 :         return CS_FAIL;
     192             : }
     193             : 
     194             : CS_RETCODE
     195         240 : blk_describe(CS_BLKDESC * blkdesc, CS_INT item, CS_DATAFMT * datafmt_arg)
     196             : {
     197             :         TDSCOLUMN *curcol;
     198             :         CS_INT status, datatype;
     199             :         CS_DATAFMT_LARGE *datafmt;
     200             :         CS_DATAFMT_LARGE datafmt_buf;
     201             : 
     202         240 :         tdsdump_log(TDS_DBG_FUNC, "blk_describe(%p, %d, %p)\n", blkdesc, item, datafmt_arg);
     203             : 
     204         240 :         if (!blkdesc)
     205             :                 return CS_FAIL;
     206             : 
     207         240 :         datafmt = _ct_datafmt_conv_prepare(CONN(blkdesc)->ctx, datafmt_arg, &datafmt_buf);
     208             : 
     209         240 :         if (item < 1 || item > blkdesc->bcpinfo.bindinfo->num_cols) {
     210           0 :                 _ctclient_msg(CONN(blkdesc), "blk_describe", 2, 5, 1, 141, "%s, %d", "colnum", item);
     211           0 :                 return CS_FAIL;
     212             :         }
     213             : 
     214         240 :         curcol = blkdesc->bcpinfo.bindinfo->columns[item - 1];
     215             :         /* name is always null terminated */
     216         480 :         strlcpy(datafmt->name, tds_dstr_cstr(&curcol->column_name), sizeof(datafmt->name));
     217         240 :         datafmt->namelen = strlen(datafmt->name);
     218             :         /* need to turn the SYBxxx into a CS_xxx_TYPE */
     219         240 :         datatype = _ct_get_client_type(curcol, true);
     220         240 :         if (datatype == CS_ILLEGAL_TYPE)
     221             :                 return CS_FAIL;
     222         240 :         datafmt->datatype = datatype;
     223         240 :         tdsdump_log(TDS_DBG_INFO1, "blk_describe() datafmt->datatype = %d server type %d\n", datatype,
     224           0 :                         curcol->column_type);
     225             :         /* FIXME is ok this value for numeric/decimal? */
     226         240 :         datafmt->maxlength = curcol->column_size;
     227         240 :         datafmt->usertype = curcol->column_usertype;
     228         240 :         datafmt->precision = curcol->column_prec;
     229         240 :         datafmt->scale = curcol->column_scale;
     230             : 
     231             :         /*
     232             :          * There are other options that can be returned, but these are the
     233             :          * only two being noted via the TDS layer.
     234             :          */
     235         240 :         status = 0;
     236         240 :         if (curcol->column_nullable)
     237         112 :                 status |= CS_CANBENULL;
     238         240 :         if (curcol->column_identity)
     239           0 :                 status |= CS_IDENTITY;
     240         240 :         datafmt->status = status;
     241             : 
     242         240 :         datafmt->count = 1;
     243         240 :         datafmt->locale = NULL;
     244             : 
     245         240 :         _ct_datafmt_conv_back(datafmt_arg, datafmt);
     246         240 :         return CS_SUCCEED;
     247             : }
     248             : 
     249             : CS_RETCODE
     250          88 : blk_done(CS_BLKDESC * blkdesc, CS_INT type, CS_INT * outrow)
     251             : {
     252             :         TDSSOCKET *tds;
     253             :         int rows_copied;
     254             : 
     255          88 :         tdsdump_log(TDS_DBG_FUNC, "blk_done(%p, %d, %p)\n", blkdesc, type, outrow);
     256             : 
     257          88 :         tds = CONN(blkdesc)->tds_socket;
     258             : 
     259          88 :         switch (type) {
     260           0 :         case CS_BLK_BATCH:
     261           0 :                 if (TDS_FAILED(tds_bcp_done(tds, &rows_copied))) {
     262           0 :                         _ctclient_msg(CONN(blkdesc), "blk_done", 2, 5, 1, 140, "");
     263           0 :                         return CS_FAIL;
     264             :                 }
     265             :                 
     266           0 :                 if (outrow) 
     267           0 :                         *outrow = rows_copied;
     268             :                 
     269           0 :                 if (TDS_FAILED(tds_bcp_start(tds, &blkdesc->bcpinfo))) {
     270           0 :                         _ctclient_msg(CONN(blkdesc), "blk_done", 2, 5, 1, 140, "");
     271           0 :                         return CS_FAIL;
     272             :                 }
     273             :                 break;
     274             :                 
     275          88 :         case CS_BLK_ALL:
     276          88 :                 if (TDS_FAILED(tds_bcp_done(tds, &rows_copied))) {
     277           0 :                         _ctclient_msg(CONN(blkdesc), "blk_done", 2, 5, 1, 140, "");
     278           0 :                         return CS_FAIL;
     279             :                 }
     280             :                 
     281          88 :                 if (outrow) 
     282          88 :                         *outrow = rows_copied;
     283             :                 
     284             :                 /* free allocated storage in blkdesc & initialise flags, etc. */
     285          88 :                 tds_deinit_bcpinfo(&blkdesc->bcpinfo);
     286             :         
     287          88 :                 blkdesc->bcpinfo.direction = 0;
     288          88 :                 blkdesc->bcpinfo.bind_count = CS_UNUSED;
     289          88 :                 blkdesc->bcpinfo.xfer_init = 0;
     290             : 
     291          88 :                 break;
     292             : 
     293             :         }
     294             : 
     295             :         return CS_SUCCEED;
     296             : }
     297             : 
     298             : CS_RETCODE
     299          24 : blk_drop(CS_BLKDESC * blkdesc)
     300             : {
     301          24 :         tdsdump_log(TDS_DBG_FUNC, "blk_drop(%p)\n", blkdesc);
     302             : 
     303             :         /* this is possible as CS_BLKDESC contains just bcpinfo field */
     304          24 :         tds_free_bcpinfo(&blkdesc->bcpinfo);
     305             : 
     306          24 :         return CS_SUCCEED;
     307             : }
     308             : 
     309             : CS_RETCODE
     310           0 : blk_getrow(SRV_PROC * srvproc, CS_BLKDESC * blkdescp, CS_BLK_ROW * rowp)
     311             : {
     312           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_getrow(%p, %p, %p)\n", srvproc, blkdescp, rowp);
     313             : 
     314           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_getrow()\n");
     315           0 :         return CS_FAIL;
     316             : }
     317             : 
     318             : CS_RETCODE
     319           0 : blk_gettext(SRV_PROC * srvproc, CS_BLKDESC * blkdescp, CS_BLK_ROW * rowp, CS_INT bufsize, CS_INT * outlenp)
     320             : {
     321             : 
     322           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_gettext(%p, %p, %p, %d, %p)\n", srvproc, blkdescp, rowp, bufsize, outlenp);
     323             : 
     324           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_gettext()\n");
     325           0 :         return CS_FAIL;
     326             : }
     327             : 
     328             : CS_RETCODE
     329          96 : blk_init(CS_BLKDESC * blkdesc, CS_INT direction, CS_CHAR * tablename, CS_INT tnamelen)
     330             : {
     331          96 :         tdsdump_log(TDS_DBG_FUNC, "blk_init(%p, %d, %p, %d)\n", blkdesc, direction, tablename, tnamelen);
     332             : 
     333          96 :         if (!blkdesc) {
     334             :                 return CS_FAIL;
     335             :         }
     336             : 
     337          96 :         if (direction != CS_BLK_IN && direction != CS_BLK_OUT ) {
     338           0 :                 _ctclient_msg(CONN(blkdesc), "blk_init", 2, 6, 1, 138, "");
     339           0 :                 return CS_FAIL;
     340             :         }
     341             : 
     342          96 :         if (!tablename) {
     343           0 :                 _ctclient_msg(CONN(blkdesc), "blk_init", 2, 6, 1, 139, "");
     344           0 :                 return CS_FAIL;
     345             :         }
     346          96 :         if (tnamelen == CS_NULLTERM)
     347          96 :                 tnamelen = strlen(tablename);
     348             : 
     349             :         /* free allocated storage in blkdesc & initialise flags, etc. */
     350          96 :         tds_deinit_bcpinfo(&blkdesc->bcpinfo);
     351             : 
     352             :         /* string can be no-nul terminated so copy with memcpy */
     353          96 :         if (!tds_dstr_copyn(&blkdesc->bcpinfo.tablename, tablename, tnamelen)) {
     354             :                 return CS_FAIL;
     355             :         }
     356             : 
     357          96 :         blkdesc->bcpinfo.direction = direction;
     358          96 :         blkdesc->bcpinfo.bind_count = CS_UNUSED;
     359          96 :         blkdesc->bcpinfo.xfer_init = 0;
     360             : 
     361          96 :         if (TDS_FAILED(tds_bcp_init(CONN(blkdesc)->tds_socket, &blkdesc->bcpinfo))) {
     362           0 :                 _ctclient_msg(CONN(blkdesc), "blk_init", 2, 5, 1, 140, "");
     363           0 :                 return CS_FAIL;
     364             :         }
     365          96 :         blkdesc->bcpinfo.bind_count = CS_UNUSED;
     366             : 
     367          96 :         return CS_SUCCEED;
     368             : }
     369             : 
     370             : CS_RETCODE
     371           0 : blk_props(CS_BLKDESC * blkdesc, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
     372             : {
     373             :         int retval, intval;
     374             : 
     375           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_props(%p, %d, %d, %p, %d, %p)\n", blkdesc, action, property, buffer, buflen, outlen);
     376             : 
     377           0 :         switch (property) {
     378           0 :         case BLK_IDENTITY: 
     379           0 :                 switch (action) {
     380           0 :                 case CS_SET: 
     381           0 :                         if (buffer) {
     382           0 :                                 memcpy(&intval, buffer, sizeof(intval));
     383           0 :                                 if (intval == CS_TRUE)
     384           0 :                                         blkdesc->bcpinfo.identity_insert_on = 1;
     385           0 :                                 if (intval == CS_FALSE)
     386           0 :                                         blkdesc->bcpinfo.identity_insert_on = 0;
     387             :                         }
     388             :                         return CS_SUCCEED;
     389             :                         break;
     390           0 :                 case CS_GET:
     391           0 :                         retval = blkdesc->bcpinfo.identity_insert_on == 1 ? CS_TRUE : CS_FALSE ;
     392           0 :                         if (buffer) {
     393           0 :                                 memcpy (buffer, &retval, sizeof(retval));
     394           0 :                                 if (outlen)
     395           0 :                                         *outlen = sizeof(retval);
     396             :                         }
     397             :                         return CS_SUCCEED;
     398             :                         break;
     399           0 :                 default:
     400           0 :                         _ctclient_msg(CONN(blkdesc), "blk_props", 2, 5, 1, 141, "%s, %d", "action", action);
     401             :                         break;
     402             :                 }
     403           0 :                 break;
     404             : 
     405           0 :         default:
     406           0 :                 _ctclient_msg(CONN(blkdesc), "blk_props", 2, 5, 1, 141, "%s, %d", "property", property);
     407           0 :                 break;
     408             :         }
     409             :         return CS_FAIL;
     410             : }
     411             : 
     412             : CS_RETCODE
     413           0 : blk_rowalloc(SRV_PROC * srvproc, CS_BLK_ROW ** row)
     414             : {
     415           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowalloc(%p, %p)\n", srvproc, row);
     416             : 
     417           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_rowalloc()\n");
     418           0 :         return CS_FAIL;
     419             : }
     420             : 
     421             : CS_RETCODE
     422           0 : blk_rowdrop(SRV_PROC * srvproc, CS_BLK_ROW * row)
     423             : {
     424           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowdrop(%p, %p)\n", srvproc, row);
     425             : 
     426           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_rowdrop()\n");
     427           0 :         return CS_FAIL;
     428             : }
     429             : 
     430             : CS_RETCODE
     431         160 : blk_rowxfer(CS_BLKDESC * blkdesc)
     432             : {
     433         160 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer(%p)\n", blkdesc);
     434             : 
     435         160 :         return blk_rowxfer_mult(blkdesc, NULL);
     436             : }
     437             : 
     438             : CS_RETCODE
     439         184 : blk_rowxfer_mult(CS_BLKDESC * blkdesc, CS_INT * row_count)
     440             : {
     441         184 :         CS_INT rows_to_xfer = 0;
     442         184 :         CS_INT rows_xferred = 0;
     443             :         CS_RETCODE ret;
     444             : 
     445         184 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer_mult(%p, %p)\n", blkdesc, row_count);
     446             : 
     447         184 :         if (!row_count || *row_count == 0 )
     448         168 :                 rows_to_xfer = blkdesc->bcpinfo.bind_count;
     449             :         else
     450             :                 rows_to_xfer = *row_count;
     451             : 
     452         184 :         if (blkdesc->bcpinfo.direction == CS_BLK_IN) {
     453         160 :                 ret = _blk_rowxfer_in(blkdesc, rows_to_xfer, &rows_xferred);
     454             :         } else {
     455          24 :                 ret = _blk_rowxfer_out(blkdesc, rows_to_xfer, &rows_xferred);
     456             :         }
     457         184 :         if (row_count)
     458          24 :                 *row_count = rows_xferred;
     459         184 :         return ret;
     460             : 
     461             : }
     462             : 
     463             : CS_RETCODE
     464           0 : blk_sendrow(CS_BLKDESC * blkdesc, CS_BLK_ROW * row)
     465             : {
     466             : 
     467           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_sendrow(%p, %p)\n", blkdesc, row);
     468             : 
     469           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_sendrow()\n");
     470           0 :         return CS_FAIL;
     471             : }
     472             : 
     473             : CS_RETCODE
     474           0 : blk_sendtext(CS_BLKDESC * blkdesc, CS_BLK_ROW * row, CS_BYTE * buffer, CS_INT buflen)
     475             : {
     476           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_sendtext(%p, %p, %p, %d)\n", blkdesc, row, buffer, buflen);
     477             : 
     478           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_sendtext()\n");
     479           0 :         return CS_FAIL;
     480             : }
     481             : 
     482             : CS_RETCODE
     483           0 : blk_srvinit(SRV_PROC * srvproc, CS_BLKDESC * blkdescp)
     484             : {
     485           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_srvinit(%p, %p)\n", srvproc, blkdescp);
     486             : 
     487           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_srvinit()\n");
     488           0 :         return CS_FAIL;
     489             : }
     490             : 
     491             : CS_RETCODE
     492           0 : blk_textxfer(CS_BLKDESC * blkdesc, CS_BYTE * buffer, CS_INT buflen, CS_INT * outlen)
     493             : {
     494           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_textxfer(%p, %p, %d, %p)\n", blkdesc, buffer, buflen, outlen);
     495             : 
     496           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_textxfer()\n");
     497           0 :         return CS_FAIL;
     498             : }
     499             : 
     500             : static CS_RETCODE
     501          24 : _blk_rowxfer_out(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred)
     502             : {
     503             :         TDSSOCKET *tds;
     504             :         TDS_INT result_type;
     505             :         TDSRET ret;
     506             :         TDS_INT temp_count;
     507             : 
     508          24 :         tdsdump_log(TDS_DBG_FUNC, "_blk_rowxfer_out(%p, %d, %p)\n", blkdesc, rows_to_xfer, rows_xferred);
     509             : 
     510          24 :         if (!blkdesc || !CONN(blkdesc))
     511             :                 return CS_FAIL;
     512             : 
     513          24 :         tds = CONN(blkdesc)->tds_socket;
     514             : 
     515             :         /*
     516             :          * the first time blk_xfer called after blk_init()
     517             :          * do the query and get to the row data...
     518             :          */
     519             : 
     520          24 :         if (blkdesc->bcpinfo.xfer_init == 0) {
     521             : 
     522          16 :                 if (TDS_FAILED(tds_submit_queryf(tds, "select * from %s", tds_dstr_cstr(&blkdesc->bcpinfo.tablename)))) {
     523           0 :                         _ctclient_msg(CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     524           0 :                         return CS_FAIL;
     525             :                 }
     526             : 
     527          16 :                 while ((ret = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCESS) {
     528          16 :                         if (result_type == TDS_ROW_RESULT)
     529             :                                 break;
     530             :                 }
     531             :         
     532           8 :                 if (ret != TDS_SUCCESS || result_type != TDS_ROW_RESULT) {
     533           0 :                         _ctclient_msg(CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     534           0 :                         return CS_FAIL;
     535             :                 }
     536             : 
     537           8 :                 blkdesc->bcpinfo.xfer_init = 1;
     538             :         }
     539             : 
     540          24 :         if (rows_xferred)
     541          24 :                 *rows_xferred = 0;
     542             : 
     543          40 :         for (temp_count = 0; temp_count < rows_to_xfer; temp_count++) {
     544             : 
     545          48 :                 ret = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_STOPAT_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
     546             : 
     547          48 :                 tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer_out() process_row_tokens returned %d\n", ret);
     548             : 
     549          48 :                 switch (ret) {
     550          48 :                 case TDS_SUCCESS:
     551          48 :                         if (result_type == TDS_ROW_RESULT || result_type == TDS_COMPUTE_RESULT) {
     552          40 :                                 if (result_type == TDS_ROW_RESULT) {
     553          40 :                                         if (_ct_bind_data( CONN(blkdesc)->ctx, tds->current_results, blkdesc->bcpinfo.bindinfo, temp_count))
     554             :                                                 return CS_ROW_FAIL;
     555          40 :                                         if (rows_xferred)
     556          40 :                                                 *rows_xferred = *rows_xferred + 1;
     557             :                                 }
     558             :                                 break;
     559             :                         }
     560             :                 case TDS_NO_MORE_RESULTS: 
     561             :                         return CS_END_DATA;
     562             :                         break;
     563             : 
     564           0 :                 default:
     565           0 :                         _ctclient_msg(CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     566           0 :                         return CS_FAIL;
     567             :                         break;
     568             :                 }
     569             :         } 
     570             : 
     571             :         return CS_SUCCEED;
     572             : }
     573             : 
     574             : static CS_RETCODE
     575         160 : _blk_rowxfer_in(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred)
     576             : {
     577             :         TDSSOCKET *tds;
     578             :         TDS_INT each_row;
     579             : 
     580         160 :         tdsdump_log(TDS_DBG_FUNC, "_blk_rowxfer_in(%p, %d, %p)\n", blkdesc, rows_to_xfer, rows_xferred);
     581             : 
     582         160 :         if (!blkdesc)
     583             :                 return CS_FAIL;
     584             : 
     585         160 :         tds = CONN(blkdesc)->tds_socket;
     586             : 
     587             :         /*
     588             :          * the first time blk_xfer called after blk_init()
     589             :          * do the query and get to the row data...
     590             :          */
     591             : 
     592         160 :         if (blkdesc->bcpinfo.xfer_init == 0) {
     593             : 
     594             :                 /*
     595             :                  * first call the start_copy function, which will
     596             :                  * retrieve details of the database table columns
     597             :                  */
     598             : 
     599          88 :                 if (TDS_FAILED(tds_bcp_start_copy_in(tds, &blkdesc->bcpinfo))) {
     600           0 :                         _ctclient_msg(CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     601           0 :                         return CS_FAIL;
     602             :                 }
     603             : 
     604          88 :                 blkdesc->bcpinfo.xfer_init = 1;
     605             :         } 
     606             : 
     607         160 :         for (each_row = 0; each_row < rows_to_xfer; each_row++ ) {
     608             : 
     609         160 :                 if (tds_bcp_send_record(tds, &blkdesc->bcpinfo, _blk_get_col_data, _blk_null_error, each_row) == TDS_SUCCESS) {
     610             :                         /* FIXME */
     611             :                 }
     612             :         }
     613             : 
     614             :         return CS_SUCCEED;
     615             : }
     616             : 
     617             : static void
     618           0 : _blk_null_error(TDSBCPINFO *bcpinfo, int index, int offset)
     619             : {
     620           0 :         CS_BLKDESC *blkdesc = (CS_BLKDESC *) bcpinfo;
     621             : 
     622           0 :         tdsdump_log(TDS_DBG_FUNC, "_blk_null_error(%p, %d, %d)\n", bcpinfo, index, offset);
     623             : 
     624           0 :         _ctclient_msg(CONN(blkdesc), "blk_rowxfer", 2, 7, 1, 142, "%d, %d",  index + 1, offset + 1);
     625           0 : }
     626             : 
     627             : static TDSRET
     628        2240 : _blk_get_col_data(TDSBCPINFO *bulk, TDSCOLUMN *bindcol, int offset)
     629             : {
     630        2240 :         int result = 0;
     631        2240 :         bool null_column = false;
     632        2240 :         unsigned char *src = NULL;
     633             : 
     634        2240 :         CS_INT      srctype = 0;
     635        2240 :         CS_INT      srclen  = 0;
     636        2240 :         CS_INT      destlen  = 0;
     637        2240 :         CS_SMALLINT *nullind = NULL;
     638        2240 :         CS_INT      *datalen = NULL;
     639        2240 :         CS_BLKDESC *blkdesc = (CS_BLKDESC *) bulk;
     640        2240 :         CS_CONTEXT *ctx = CONN(blkdesc)->ctx;
     641             : 
     642        2240 :         tdsdump_log(TDS_DBG_FUNC, "_blk_get_col_data(%p, %p, %d)\n", bulk, bindcol, offset);
     643             : 
     644             :         /*
     645             :          * Retrieve the initial bound column_varaddress
     646             :          * and increment it if offset specified
     647             :          */
     648             : 
     649        2240 :         src = (unsigned char *) bindcol->column_varaddr;
     650        2240 :         if (!src) {
     651           0 :                 tdsdump_log(TDS_DBG_ERROR, "error source field not addressable\n");
     652             :                 return TDS_FAIL;
     653             :         }
     654             : 
     655        2240 :         src += offset * bindcol->column_bindlen;
     656             :         
     657        2240 :         if (bindcol->column_nullbind) {
     658        2160 :                 nullind = bindcol->column_nullbind;
     659        2160 :                 nullind += offset;
     660             :         }
     661        2240 :         if (bindcol->column_lenbind) {
     662        2240 :                 datalen = bindcol->column_lenbind;
     663        2240 :                 datalen += offset;
     664             :         }
     665             : 
     666        2240 :         srctype = bindcol->column_bindtype;          /* passes to cs_convert */
     667             : 
     668        2240 :         tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data srctype = %d\n", srctype);
     669        2240 :         tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data datalen = %d\n", datalen ? *datalen : -1);
     670             : 
     671        2240 :         if (datalen) {
     672        2240 :                 if (*datalen == CS_UNUSED) {
     673           0 :                         switch (srctype) {
     674             :                         case CS_LONG_TYPE:          srclen = 8; break;
     675             :                         case CS_FLOAT_TYPE:         srclen = 8; break;
     676             :                         case CS_MONEY_TYPE:         srclen = 8; break;
     677             :                         case CS_DATETIME_TYPE:  srclen = 8; break;
     678           0 :                         case CS_INT_TYPE:           srclen = 4; break;
     679           0 :                         case CS_UINT_TYPE:          srclen = 4; break;
     680           0 :                         case CS_REAL_TYPE:          srclen = 4; break;
     681           0 :                         case CS_MONEY4_TYPE:    srclen = 4; break;
     682           0 :                         case CS_DATETIME4_TYPE: srclen = 4; break;
     683           0 :                         case CS_SMALLINT_TYPE:  srclen = 2; break;
     684           0 :                         case CS_USMALLINT_TYPE:  srclen = 2; break;
     685           0 :                         case CS_TINYINT_TYPE:   srclen = 1; break;
     686           0 :                         case CS_BIT_TYPE:   srclen = 1; break;
     687             :                         case CS_BIGINT_TYPE:        srclen = 8; break;
     688             :                         case CS_UBIGINT_TYPE:       srclen = 8; break;
     689           0 :                         case CS_UNIQUE_TYPE:        srclen = 16; break;
     690           0 :                         default:
     691           0 :                                 printf("error not fixed length type (%d) and datalen not specified\n",
     692           0 :                                         bindcol->column_bindtype);
     693           0 :                                 return CS_FAIL;
     694             :                         }
     695             : 
     696             :                 } else {
     697        2240 :                         srclen = *datalen;
     698             :                 }
     699             :         }
     700        2240 :         if (srclen == 0) {
     701        1040 :                 if (nullind && *nullind == -1)
     702             :                         null_column = true;
     703             :         }
     704             : 
     705             :         if (!null_column) {
     706             :                 CONV_RESULT convert_buffer;
     707             :                 CS_DATAFMT_COMMON srcfmt, destfmt;
     708             :                 CS_INT desttype;
     709             : 
     710        1200 :                 srcfmt.datatype = srctype;
     711        1200 :                 srcfmt.maxlength = srclen;
     712             : 
     713        1200 :                 desttype = _cs_convert_not_client(ctx, bindcol, &convert_buffer, &src);
     714        1200 :                 if (desttype == CS_ILLEGAL_TYPE)
     715        1200 :                         desttype = _ct_get_client_type(bindcol, false);
     716        1200 :                 if (desttype == CS_ILLEGAL_TYPE)
     717           0 :                         return CS_FAIL;
     718        1200 :                 destfmt.datatype  = desttype;
     719        1200 :                 destfmt.maxlength = bindcol->on_server.column_size;
     720        1200 :                 destfmt.precision = bindcol->column_prec;
     721        1200 :                 destfmt.scale     = bindcol->column_scale;
     722        1200 :                 destfmt.format    = CS_FMT_UNUSED;
     723             : 
     724             :                 /* if convert return FAIL mark error but process other columns */
     725        1200 :                 if ((result = _cs_convert(ctx, &srcfmt, (CS_VOID *) src,
     726        1200 :                                          &destfmt, (CS_VOID *) bindcol->bcp_column_data->data, &destlen)) != CS_SUCCEED) {
     727           0 :                         tdsdump_log(TDS_DBG_INFO1, "convert failed for %d \n", srctype);
     728             :                         return CS_FAIL;
     729             :                 }
     730             :         }
     731             : 
     732        2240 :         bindcol->bcp_column_data->datalen = destlen;
     733        2240 :         bindcol->bcp_column_data->is_null = null_column;
     734             : 
     735        2240 :         return TDS_SUCCESS;
     736             : }

Generated by: LCOV version 1.13