LCOV - code coverage report
Current view: top level - src/ctlib - blk.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 185 319 58.0 %
Date: 2024-03-23 08:24: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          32 : blk_alloc(CS_CONNECTION * connection, CS_INT version, CS_BLKDESC ** blk_pointer)
      53             : {
      54             :         CS_BLKDESC *blkdesc;
      55             : 
      56          32 :         tdsdump_log(TDS_DBG_FUNC, "blk_alloc(%p, %d, %p)\n", connection, version, blk_pointer);
      57             : 
      58          32 :         if (!connection || !connection->tds_socket)
      59             :                 return CS_FAIL;
      60             : 
      61          32 :         if (connection->tds_socket->conn->tds_version < 0x500)
      62             :                 return CS_FAIL;
      63             : 
      64          32 :         blkdesc = (CS_BLKDESC *) tds_alloc_bcpinfo();
      65          32 :         if (!blkdesc)
      66             :                 return CS_FAIL;
      67             : 
      68             :         /* so we know who we belong to */
      69          32 :         blkdesc->bcpinfo.parent = connection;
      70             : 
      71          32 :         *blk_pointer = blkdesc;
      72          32 :         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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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(NULL, 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          32 : blk_drop(CS_BLKDESC * blkdesc)
     300             : {
     301          32 :         tdsdump_log(TDS_DBG_FUNC, "blk_drop(%p)\n", blkdesc);
     302             : 
     303             :         /* this is possible as CS_BLKDESC contains just bcpinfo field */
     304          32 :         tds_free_bcpinfo(&blkdesc->bcpinfo);
     305             : 
     306          32 :         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         120 : blk_init(CS_BLKDESC * blkdesc, CS_INT direction, CS_CHAR * tablename, CS_INT tnamelen)
     330             : {
     331         120 :         tdsdump_log(TDS_DBG_FUNC, "blk_init(%p, %d, %p, %d)\n", blkdesc, direction, tablename, tnamelen);
     332             : 
     333         120 :         if (!blkdesc) {
     334             :                 return CS_FAIL;
     335             :         }
     336             : 
     337         120 :         if (direction != CS_BLK_IN && direction != CS_BLK_OUT ) {
     338           8 :                 _ctclient_msg(NULL, CONN(blkdesc), "blk_init", 1, 1, 1, 15, "");
     339           8 :                 return CS_FAIL;
     340             :         }
     341             : 
     342         112 :         if (!tablename) {
     343           8 :                 _ctclient_msg(NULL, CONN(blkdesc), "blk_init", 1, 1, 1, 6, "tblname");
     344           8 :                 return CS_FAIL;
     345             :         }
     346         104 :         tnamelen = _ct_get_string_length(tablename, tnamelen);
     347         104 :         if (tnamelen < 0) {
     348           8 :                 _ctclient_msg(NULL, CONN(blkdesc), "blk_init", 1, 1, 1, 4, "tblnamelen, %d", tnamelen);
     349           8 :                 return CS_FAIL;
     350             :         }
     351             : 
     352             :         /* free allocated storage in blkdesc & initialise flags, etc. */
     353          96 :         tds_deinit_bcpinfo(&blkdesc->bcpinfo);
     354             : 
     355             :         /* string can be no-nul terminated so copy with memcpy */
     356          96 :         if (!tds_dstr_copyn(&blkdesc->bcpinfo.tablename, tablename, tnamelen)) {
     357             :                 return CS_FAIL;
     358             :         }
     359             : 
     360          96 :         blkdesc->bcpinfo.direction = direction;
     361          96 :         blkdesc->bcpinfo.bind_count = CS_UNUSED;
     362          96 :         blkdesc->bcpinfo.xfer_init = 0;
     363             : 
     364          96 :         if (TDS_FAILED(tds_bcp_init(CONN(blkdesc)->tds_socket, &blkdesc->bcpinfo))) {
     365           0 :                 _ctclient_msg(NULL, CONN(blkdesc), "blk_init", 2, 5, 1, 140, "");
     366           0 :                 return CS_FAIL;
     367             :         }
     368          96 :         blkdesc->bcpinfo.bind_count = CS_UNUSED;
     369             : 
     370          96 :         return CS_SUCCEED;
     371             : }
     372             : 
     373             : CS_RETCODE
     374           0 : blk_props(CS_BLKDESC * blkdesc, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
     375             : {
     376             :         int retval, intval;
     377             : 
     378           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_props(%p, %d, %d, %p, %d, %p)\n", blkdesc, action, property, buffer, buflen, outlen);
     379             : 
     380           0 :         switch (property) {
     381           0 :         case BLK_IDENTITY: 
     382           0 :                 switch (action) {
     383           0 :                 case CS_SET: 
     384           0 :                         if (buffer) {
     385           0 :                                 memcpy(&intval, buffer, sizeof(intval));
     386           0 :                                 if (intval == CS_TRUE)
     387           0 :                                         blkdesc->bcpinfo.identity_insert_on = 1;
     388           0 :                                 if (intval == CS_FALSE)
     389           0 :                                         blkdesc->bcpinfo.identity_insert_on = 0;
     390             :                         }
     391             :                         return CS_SUCCEED;
     392             :                         break;
     393           0 :                 case CS_GET:
     394           0 :                         retval = blkdesc->bcpinfo.identity_insert_on == 1 ? CS_TRUE : CS_FALSE ;
     395           0 :                         if (buffer) {
     396           0 :                                 memcpy (buffer, &retval, sizeof(retval));
     397           0 :                                 if (outlen)
     398           0 :                                         *outlen = sizeof(retval);
     399             :                         }
     400             :                         return CS_SUCCEED;
     401             :                         break;
     402           0 :                 default:
     403           0 :                         _ctclient_msg(NULL, CONN(blkdesc), "blk_props", 2, 5, 1, 141, "%s, %d", "action", action);
     404             :                         break;
     405             :                 }
     406           0 :                 break;
     407             : 
     408           0 :         default:
     409           0 :                 _ctclient_msg(NULL, CONN(blkdesc), "blk_props", 2, 5, 1, 141, "%s, %d", "property", property);
     410           0 :                 break;
     411             :         }
     412             :         return CS_FAIL;
     413             : }
     414             : 
     415             : CS_RETCODE
     416           0 : blk_rowalloc(SRV_PROC * srvproc, CS_BLK_ROW ** row)
     417             : {
     418           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowalloc(%p, %p)\n", srvproc, row);
     419             : 
     420           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_rowalloc()\n");
     421           0 :         return CS_FAIL;
     422             : }
     423             : 
     424             : CS_RETCODE
     425           0 : blk_rowdrop(SRV_PROC * srvproc, CS_BLK_ROW * row)
     426             : {
     427           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowdrop(%p, %p)\n", srvproc, row);
     428             : 
     429           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_rowdrop()\n");
     430           0 :         return CS_FAIL;
     431             : }
     432             : 
     433             : CS_RETCODE
     434         160 : blk_rowxfer(CS_BLKDESC * blkdesc)
     435             : {
     436         160 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer(%p)\n", blkdesc);
     437             : 
     438         160 :         return blk_rowxfer_mult(blkdesc, NULL);
     439             : }
     440             : 
     441             : CS_RETCODE
     442         184 : blk_rowxfer_mult(CS_BLKDESC * blkdesc, CS_INT * row_count)
     443             : {
     444         184 :         CS_INT rows_to_xfer = 0;
     445         184 :         CS_INT rows_xferred = 0;
     446             :         CS_RETCODE ret;
     447             : 
     448         184 :         tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer_mult(%p, %p)\n", blkdesc, row_count);
     449             : 
     450         184 :         if (!row_count || *row_count == 0 )
     451         168 :                 rows_to_xfer = blkdesc->bcpinfo.bind_count;
     452             :         else
     453             :                 rows_to_xfer = *row_count;
     454             : 
     455         184 :         if (blkdesc->bcpinfo.direction == CS_BLK_IN) {
     456         160 :                 ret = _blk_rowxfer_in(blkdesc, rows_to_xfer, &rows_xferred);
     457             :         } else {
     458          24 :                 ret = _blk_rowxfer_out(blkdesc, rows_to_xfer, &rows_xferred);
     459             :         }
     460         184 :         if (row_count)
     461          24 :                 *row_count = rows_xferred;
     462         184 :         return ret;
     463             : 
     464             : }
     465             : 
     466             : CS_RETCODE
     467           0 : blk_sendrow(CS_BLKDESC * blkdesc, CS_BLK_ROW * row)
     468             : {
     469             : 
     470           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_sendrow(%p, %p)\n", blkdesc, row);
     471             : 
     472           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_sendrow()\n");
     473           0 :         return CS_FAIL;
     474             : }
     475             : 
     476             : CS_RETCODE
     477           0 : blk_sendtext(CS_BLKDESC * blkdesc, CS_BLK_ROW * row, CS_BYTE * buffer, CS_INT buflen)
     478             : {
     479           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_sendtext(%p, %p, %p, %d)\n", blkdesc, row, buffer, buflen);
     480             : 
     481           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_sendtext()\n");
     482           0 :         return CS_FAIL;
     483             : }
     484             : 
     485             : CS_RETCODE
     486           0 : blk_srvinit(SRV_PROC * srvproc, CS_BLKDESC * blkdescp)
     487             : {
     488           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_srvinit(%p, %p)\n", srvproc, blkdescp);
     489             : 
     490           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_srvinit()\n");
     491           0 :         return CS_FAIL;
     492             : }
     493             : 
     494             : CS_RETCODE
     495           0 : blk_textxfer(CS_BLKDESC * blkdesc, CS_BYTE * buffer, CS_INT buflen, CS_INT * outlen)
     496             : {
     497           0 :         tdsdump_log(TDS_DBG_FUNC, "blk_textxfer(%p, %p, %d, %p)\n", blkdesc, buffer, buflen, outlen);
     498             : 
     499           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED blk_textxfer()\n");
     500           0 :         return CS_FAIL;
     501             : }
     502             : 
     503             : static CS_RETCODE
     504          24 : _blk_rowxfer_out(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred)
     505             : {
     506             :         TDSSOCKET *tds;
     507             :         TDS_INT result_type;
     508             :         TDSRET ret;
     509             :         TDS_INT temp_count;
     510             : 
     511          24 :         tdsdump_log(TDS_DBG_FUNC, "_blk_rowxfer_out(%p, %d, %p)\n", blkdesc, rows_to_xfer, rows_xferred);
     512             : 
     513          24 :         if (!blkdesc || !CONN(blkdesc))
     514             :                 return CS_FAIL;
     515             : 
     516          24 :         tds = CONN(blkdesc)->tds_socket;
     517             : 
     518             :         /*
     519             :          * the first time blk_xfer called after blk_init()
     520             :          * do the query and get to the row data...
     521             :          */
     522             : 
     523          24 :         if (blkdesc->bcpinfo.xfer_init == 0) {
     524             : 
     525          16 :                 if (TDS_FAILED(tds_submit_queryf(tds, "select * from %s", tds_dstr_cstr(&blkdesc->bcpinfo.tablename)))) {
     526           0 :                         _ctclient_msg(NULL, CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     527           0 :                         return CS_FAIL;
     528             :                 }
     529             : 
     530          16 :                 while ((ret = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS)) == TDS_SUCCESS) {
     531          16 :                         if (result_type == TDS_ROW_RESULT)
     532             :                                 break;
     533             :                 }
     534             :         
     535           8 :                 if (ret != TDS_SUCCESS || result_type != TDS_ROW_RESULT) {
     536           0 :                         _ctclient_msg(NULL, CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     537           0 :                         return CS_FAIL;
     538             :                 }
     539             : 
     540           8 :                 blkdesc->bcpinfo.xfer_init = 1;
     541             :         }
     542             : 
     543          24 :         if (rows_xferred)
     544          24 :                 *rows_xferred = 0;
     545             : 
     546          40 :         for (temp_count = 0; temp_count < rows_to_xfer; temp_count++) {
     547             : 
     548          48 :                 ret = tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_STOPAT_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE);
     549             : 
     550          48 :                 tdsdump_log(TDS_DBG_FUNC, "blk_rowxfer_out() process_row_tokens returned %d\n", ret);
     551             : 
     552          48 :                 switch (ret) {
     553          48 :                 case TDS_SUCCESS:
     554          48 :                         if (result_type == TDS_ROW_RESULT || result_type == TDS_COMPUTE_RESULT) {
     555          40 :                                 if (result_type == TDS_ROW_RESULT) {
     556          40 :                                         if (_ct_bind_data( CONN(blkdesc)->ctx, tds->current_results, blkdesc->bcpinfo.bindinfo, temp_count))
     557             :                                                 return CS_ROW_FAIL;
     558          40 :                                         if (rows_xferred)
     559          40 :                                                 *rows_xferred = *rows_xferred + 1;
     560             :                                 }
     561             :                                 break;
     562             :                         }
     563             :                 case TDS_NO_MORE_RESULTS: 
     564             :                         return CS_END_DATA;
     565             :                         break;
     566             : 
     567           0 :                 default:
     568           0 :                         _ctclient_msg(NULL, CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     569           0 :                         return CS_FAIL;
     570             :                         break;
     571             :                 }
     572             :         } 
     573             : 
     574             :         return CS_SUCCEED;
     575             : }
     576             : 
     577             : static CS_RETCODE
     578         160 : _blk_rowxfer_in(CS_BLKDESC * blkdesc, CS_INT rows_to_xfer, CS_INT * rows_xferred)
     579             : {
     580             :         TDSSOCKET *tds;
     581             :         TDS_INT each_row;
     582             : 
     583         160 :         tdsdump_log(TDS_DBG_FUNC, "_blk_rowxfer_in(%p, %d, %p)\n", blkdesc, rows_to_xfer, rows_xferred);
     584             : 
     585         160 :         if (!blkdesc)
     586             :                 return CS_FAIL;
     587             : 
     588         160 :         tds = CONN(blkdesc)->tds_socket;
     589             : 
     590             :         /*
     591             :          * the first time blk_xfer called after blk_init()
     592             :          * do the query and get to the row data...
     593             :          */
     594             : 
     595         160 :         if (blkdesc->bcpinfo.xfer_init == 0) {
     596             : 
     597             :                 /*
     598             :                  * first call the start_copy function, which will
     599             :                  * retrieve details of the database table columns
     600             :                  */
     601             : 
     602          88 :                 if (TDS_FAILED(tds_bcp_start_copy_in(tds, &blkdesc->bcpinfo))) {
     603           0 :                         _ctclient_msg(NULL, CONN(blkdesc), "blk_rowxfer", 2, 5, 1, 140, "");
     604           0 :                         return CS_FAIL;
     605             :                 }
     606             : 
     607          88 :                 blkdesc->bcpinfo.xfer_init = 1;
     608             :         } 
     609             : 
     610         160 :         for (each_row = 0; each_row < rows_to_xfer; each_row++ ) {
     611             : 
     612         160 :                 if (tds_bcp_send_record(tds, &blkdesc->bcpinfo, _blk_get_col_data, _blk_null_error, each_row) == TDS_SUCCESS) {
     613             :                         /* FIXME */
     614             :                 }
     615             :         }
     616             : 
     617             :         return CS_SUCCEED;
     618             : }
     619             : 
     620             : static void
     621           0 : _blk_null_error(TDSBCPINFO *bcpinfo, int index, int offset)
     622             : {
     623           0 :         CS_BLKDESC *blkdesc = (CS_BLKDESC *) bcpinfo;
     624             : 
     625           0 :         tdsdump_log(TDS_DBG_FUNC, "_blk_null_error(%p, %d, %d)\n", bcpinfo, index, offset);
     626             : 
     627           0 :         _ctclient_msg(NULL, CONN(blkdesc), "blk_rowxfer", 2, 7, 1, 142, "%d, %d",  index + 1, offset + 1);
     628           0 : }
     629             : 
     630             : static TDSRET
     631        2240 : _blk_get_col_data(TDSBCPINFO *bulk, TDSCOLUMN *bindcol, int offset)
     632             : {
     633        2240 :         int result = 0;
     634        2240 :         bool null_column = false;
     635        2240 :         unsigned char *src = NULL;
     636             : 
     637        2240 :         CS_INT      srctype = 0;
     638        2240 :         CS_INT      srclen  = 0;
     639        2240 :         CS_INT      destlen  = 0;
     640        2240 :         CS_SMALLINT *nullind = NULL;
     641        2240 :         CS_INT      *datalen = NULL;
     642        2240 :         CS_BLKDESC *blkdesc = (CS_BLKDESC *) bulk;
     643        2240 :         CS_CONTEXT *ctx = CONN(blkdesc)->ctx;
     644             : 
     645        2240 :         tdsdump_log(TDS_DBG_FUNC, "_blk_get_col_data(%p, %p, %d)\n", bulk, bindcol, offset);
     646             : 
     647             :         /*
     648             :          * Retrieve the initial bound column_varaddress
     649             :          * and increment it if offset specified
     650             :          */
     651             : 
     652        2240 :         src = (unsigned char *) bindcol->column_varaddr;
     653        2240 :         if (!src) {
     654           0 :                 tdsdump_log(TDS_DBG_ERROR, "error source field not addressable\n");
     655             :                 return TDS_FAIL;
     656             :         }
     657             : 
     658        2240 :         src += offset * bindcol->column_bindlen;
     659             :         
     660        2240 :         if (bindcol->column_nullbind) {
     661        2160 :                 nullind = bindcol->column_nullbind;
     662        2160 :                 nullind += offset;
     663             :         }
     664        2240 :         if (bindcol->column_lenbind) {
     665        2240 :                 datalen = bindcol->column_lenbind;
     666        2240 :                 datalen += offset;
     667             :         }
     668             : 
     669        2240 :         srctype = bindcol->column_bindtype;          /* passes to cs_convert */
     670             : 
     671        2240 :         tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data srctype = %d\n", srctype);
     672        2240 :         tdsdump_log(TDS_DBG_INFO1, "blk_get_col_data datalen = %d\n", datalen ? *datalen : -1);
     673             : 
     674        2240 :         if (datalen) {
     675        2240 :                 if (*datalen == CS_UNUSED) {
     676           0 :                         switch (srctype) {
     677             :                         case CS_LONG_TYPE:          srclen = 8; break;
     678             :                         case CS_FLOAT_TYPE:         srclen = 8; break;
     679             :                         case CS_MONEY_TYPE:         srclen = 8; break;
     680             :                         case CS_DATETIME_TYPE:  srclen = 8; break;
     681           0 :                         case CS_INT_TYPE:           srclen = 4; break;
     682           0 :                         case CS_UINT_TYPE:          srclen = 4; break;
     683           0 :                         case CS_REAL_TYPE:          srclen = 4; break;
     684           0 :                         case CS_MONEY4_TYPE:    srclen = 4; break;
     685           0 :                         case CS_DATETIME4_TYPE: srclen = 4; break;
     686           0 :                         case CS_SMALLINT_TYPE:  srclen = 2; break;
     687           0 :                         case CS_USMALLINT_TYPE:  srclen = 2; break;
     688           0 :                         case CS_TINYINT_TYPE:   srclen = 1; break;
     689           0 :                         case CS_BIT_TYPE:   srclen = 1; break;
     690             :                         case CS_BIGINT_TYPE:        srclen = 8; break;
     691             :                         case CS_UBIGINT_TYPE:       srclen = 8; break;
     692           0 :                         case CS_UNIQUE_TYPE:        srclen = 16; break;
     693           0 :                         default:
     694           0 :                                 tdsdump_log(TDS_DBG_ERROR, "Not fixed length type (%d) and datalen not specified\n",
     695           0 :                                             bindcol->column_bindtype);
     696             :                                 return CS_FAIL;
     697             :                         }
     698             : 
     699             :                 } else {
     700        2240 :                         srclen = *datalen;
     701             :                 }
     702             :         }
     703        2240 :         if (srclen == 0) {
     704        1040 :                 if (nullind && *nullind == -1)
     705             :                         null_column = true;
     706             :         }
     707             : 
     708             :         if (!null_column) {
     709             :                 CONV_RESULT convert_buffer;
     710             :                 CS_DATAFMT_COMMON srcfmt, destfmt;
     711             :                 CS_INT desttype;
     712             : 
     713        1200 :                 srcfmt.datatype = srctype;
     714        1200 :                 srcfmt.maxlength = srclen;
     715             : 
     716        1200 :                 desttype = _cs_convert_not_client(ctx, bindcol, &convert_buffer, &src);
     717        1200 :                 if (desttype == CS_ILLEGAL_TYPE)
     718        1200 :                         desttype = _ct_get_client_type(bindcol, false);
     719        1200 :                 if (desttype == CS_ILLEGAL_TYPE)
     720           0 :                         return CS_FAIL;
     721        1200 :                 destfmt.datatype  = desttype;
     722        1200 :                 destfmt.maxlength = bindcol->on_server.column_size;
     723        1200 :                 destfmt.precision = bindcol->column_prec;
     724        1200 :                 destfmt.scale     = bindcol->column_scale;
     725        1200 :                 destfmt.format    = CS_FMT_UNUSED;
     726             : 
     727             :                 /* if convert return FAIL mark error but process other columns */
     728        1200 :                 if ((result = _cs_convert(ctx, &srcfmt, (CS_VOID *) src,
     729        1200 :                                          &destfmt, (CS_VOID *) bindcol->bcp_column_data->data, &destlen)) != CS_SUCCEED) {
     730           0 :                         tdsdump_log(TDS_DBG_INFO1, "convert failed for %d \n", srctype);
     731             :                         return CS_FAIL;
     732             :                 }
     733             :         }
     734             : 
     735        2240 :         bindcol->bcp_column_data->datalen = destlen;
     736        2240 :         bindcol->bcp_column_data->is_null = null_column;
     737             : 
     738        2240 :         return TDS_SUCCESS;
     739             : }

Generated by: LCOV version 1.13