dblib.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:72k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: dblib.c,v $
  4.  * PRODUCTION Revision 1000.1  2003/11/17 22:20:19  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-1999  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #include "tdsutil.h"
  29. #include "tds.h"
  30. #include "sybfront.h"
  31. #include "sybdb.h"
  32. #include "dblib.h"
  33. #include "tdsconvert.h"
  34. #include <unistd.h>
  35. #include <stdlib.h>
  36. #include <assert.h>
  37. #include <time.h>
  38. #include <stdarg.h>
  39. static char  software_version[]   = "$Id: dblib.c,v 1000.1 2003/11/17 22:20:19 gouriano Exp $";
  40. static void *no_unused_var_warn[] = {software_version,
  41.                                      no_unused_var_warn};
  42. #if !HAVE_VASPRINTF
  43. int vasprintf(char **ret, const char *fmt, va_list ap);
  44. #endif
  45. static int _db_get_server_type(int bindtype);
  46. static int _get_printable_size(TDSCOLINFO *colinfo);
  47. static void _set_null_value(DBPROCESS *dbproc, BYTE *varaddr, int datatype, int maxlen);
  48. /* info/err message handler functions (or rather pointers to them) */
  49. int (*g_dblib_msg_handler)() = NULL;
  50. int (*g_dblib_err_handler)() = NULL;
  51. typedef struct dblib_context {
  52. TDSCONTEXT *tds_ctx;
  53. TDSSOCKET *connection_list[TDS_MAX_CONN];
  54. } DBLIBCONTEXT;
  55. static DBLIBCONTEXT *g_dblib_ctx = NULL;
  56. #ifdef TDS42
  57. int g_dblib_version = DBVERSION_42;
  58. #endif
  59. #ifdef TDS50
  60. int g_dblib_version = DBVERSION_100;
  61. #endif
  62. #ifdef TDS46
  63. int g_dblib_version = DBVERSION_46;
  64. #endif
  65. /* I'm taking some liberties here, there is no such thing as DBVERSION_70 in 
  66. ** the real world, so we make it up as we go along */
  67. #ifdef TDS70
  68. int g_dblib_version = DBVERSION_70;
  69. #endif
  70. #ifdef TDS80
  71. int g_dblib_version = DBVERSION_80;
  72. #endif
  73. static int dblib_add_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds)
  74. {
  75. int i = 0;
  76. while (i<TDS_MAX_CONN && ctx->connection_list[i]) i++;
  77. if (i==TDS_MAX_CONN) {
  78. fprintf(stderr,"Max connections reached, increase value of TDS_MAX_CONNn");
  79. return 1;
  80. } else {
  81. ctx->connection_list[i] = tds;
  82. return 0;
  83. }
  84. }
  85. static void dblib_del_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds)
  86. {
  87. int i=0;
  88. while (i<TDS_MAX_CONN && ctx->connection_list[i]!=tds) i++;
  89. if (i==TDS_MAX_CONN) {
  90. /* connection wasn't on the free list...now what */
  91. } else {
  92. /* remove it */
  93. ctx->connection_list[i] = NULL;
  94. }
  95. }
  96. static void buffer_init(DBPROC_ROWBUF *buf)
  97. {
  98.    memset(buf, 0x0, sizeof(*buf));
  99. #ifndef NCBI_FTDS
  100.    buf->buffering_on     = 0;
  101.    buf->first_in_buf     = 0;
  102. #endif
  103.    buf->newest           = -1;
  104. #ifndef NCBI_FTDS
  105.    buf->oldest           = 0;
  106.    buf->elcount          = 0;
  107.    buf->element_size     = 0;
  108.    buf->rows_in_buf      = 0;
  109.    buf->rows             = NULL;
  110. #endif
  111.    buf->next_row         = 1;
  112. } /* buffer_init()  */
  113. static void buffer_clear(DBPROC_ROWBUF *buf)
  114. {
  115.    buf->next_row         = 1;
  116.    buf->first_in_buf     = 0;
  117.    buf->newest           = -1;
  118. #ifdef NCBI_FTDS
  119.    buf->rows_offset      = 0;
  120. #endif
  121.    buf->oldest           = 0;
  122.    buf->rows_in_buf      = 0;
  123.    if (buf->rows) {
  124.       free(buf->rows);
  125.    }
  126.    buf->rows             = NULL;
  127. } /* buffer_clear()  */
  128. static void buffer_free(DBPROC_ROWBUF *buf)
  129. {
  130.    if (buf->rows != NULL)
  131.    {
  132.       free(buf->rows);
  133.    }
  134.    buf->rows = NULL;
  135. } /* clear_buffer()  */
  136. static void buffer_delete_rows(
  137.    DBPROC_ROWBUF *buf,    /* (U) buffer to clear             */
  138.    int            count)  /* (I) number of elements to purge */
  139. {
  140.    assert(count <= buf->elcount); /* possibly a little to pedantic */
  141.    if (count > buf->rows_in_buf)
  142.    {
  143.       count = buf->rows_in_buf;
  144.    }
  145.    
  146.    buf->oldest        = (buf->oldest + count) % buf->elcount;
  147.    buf->rows_in_buf  -= count;
  148.    buf->first_in_buf  = count==buf->rows_in_buf ? buf->next_row-1 : buf->first_in_buf + count;
  149.    
  150.    assert(buf->first_in_buf >= 0);
  151. } /* buffer_delete_rows() */
  152. static int buffer_start_resultset(
  153.    DBPROC_ROWBUF *buf,          /* (U) buffer to clear */
  154.    int            element_size) /*                     */
  155. {
  156.    int    space_needed = -1;
  157.    assert(element_size > 0);
  158.    if (buf->rows != NULL)
  159.    {
  160. #ifndef NCBI_FTDS
  161.       memset(buf->rows, 0xad, buf->element_size*buf->rows_in_buf);
  162. #endif
  163.       free(buf->rows);
  164.    }
  165.    buf->first_in_buf     = 0;
  166.    buf->next_row         = 1;
  167.    buf->newest           = -1;
  168. #ifdef NCBI_FTDS
  169.    buf->rows_offset     = 0;
  170. #endif
  171.    buf->oldest           = 0;
  172.    buf->elcount          = buf->buffering_on ? buf->elcount : 1;
  173.    buf->element_size     = element_size;
  174.    buf->rows_in_buf      = 0;
  175.    space_needed          = element_size * buf->elcount;   
  176.    buf->rows             = malloc(space_needed);
  177.    return buf->rows==NULL ? FAIL : SUCCEED;
  178. } /* buffer_start_resultset()  */
  179. static void buffer_delete_all_rows(
  180.    DBPROC_ROWBUF *buf)    /* (U) buffer to clear */
  181. {
  182.    buffer_delete_rows(buf, buf->rows_in_buf);
  183. } /* delete_all_buffer_rows() */
  184. static int buffer_index_of_resultset_row(
  185.    DBPROC_ROWBUF *buf,         /* (U) buffer to clear                 */
  186.    int            row_number)  /* (I)                                 */
  187. {
  188.    int   result = -1;
  189.    if (row_number < buf->first_in_buf)
  190.    {
  191.       result = -1;
  192.    }
  193.    else if (row_number > ((buf->rows_in_buf + buf->first_in_buf) -1))
  194.    {
  195.       result = -1;
  196.    }
  197.    else
  198.    {
  199.       result = ((row_number - buf->first_in_buf) 
  200.                 + buf->oldest) % buf->elcount;
  201.    }
  202.    return result;
  203. } /* buffer_index_of_resultset_row()  */
  204. static void *buffer_row_address(
  205.    DBPROC_ROWBUF *buf,    /* (U) buffer to clear                 */
  206.    int            index)  /* (I) raw index of row to return      */
  207. {
  208.    void   *result = NULL;
  209.    assert(index >= 0);
  210.    assert(index < buf->elcount);
  211.    if (index>=buf->elcount || index<0)
  212.    {
  213.       result = NULL;
  214.    }
  215.    else
  216.    {
  217.       int   offset = buf->element_size * (index % buf->elcount);
  218.       result = (char *)buf->rows + offset;
  219.    }
  220.    return result;
  221. } /* buffer_row_address()  */
  222. static void buffer_add_row(
  223.    DBPROC_ROWBUF *buf,       /* (U) buffer to add row into  */
  224.    void          *row,       /* (I) pointer to the row data */
  225.    int            row_size)
  226. {
  227.    void   *dest = NULL;
  228.    assert(row_size > 0);
  229.    assert(row_size == buf->element_size);
  230.    
  231.    assert(buf->elcount >= 1);
  232. #ifdef NCBI_FTDS
  233.    if(++buf->newest >= buf->elcount){
  234. buf->newest=0;
  235.    }
  236.    if(buf->newest==0){
  237. buf->rows_offset=0;
  238.    } else {
  239. buf->rows_offset += buf->element_size;
  240.    }
  241.    /***buf->newest = (buf->newest+1)%buf->elcount;**/
  242.    if (buf->rows_in_buf==0 && buf->first_in_buf==0)
  243.    {
  244.       buf->first_in_buf = 1;
  245.    }
  246.    buf->rows_in_buf++;
  247.    /* 
  248.     * if we have wrapped around we need to adjust oldest
  249.     * and rows_in_buf
  250.     */
  251.    if (buf->rows_in_buf > buf->elcount)
  252.    {
  253.       buf->oldest = (buf->oldest + 1) % buf->elcount;
  254.       buf->first_in_buf++;
  255.       buf->rows_in_buf--;
  256.    }
  257.    
  258.    assert(buf->elcount >= buf->rows_in_buf);
  259.    assert( buf->rows_in_buf==0
  260.            || (((buf->oldest+buf->rows_in_buf) - 1)%buf->elcount)==buf->newest);
  261.    assert(buf->rows_in_buf>0 || (buf->first_in_buf==buf->next_row-1));
  262.    assert(buf->rows_in_buf==0 || 
  263.           (buf->first_in_buf<=buf->next_row));
  264.    assert(buf->next_row-1 <= (buf->first_in_buf + buf->rows_in_buf));
  265. /*   dest = buffer_row_address(buf, buf->newest);
  266.    memcpy(dest, row, row_size);*/
  267.    memcpy((char*)buf->rows + buf->rows_offset,row,row_size);
  268. #else
  269.    
  270.    buf->newest = (buf->newest + 1) % buf->elcount;
  271.    if (buf->rows_in_buf==0 && buf->first_in_buf==0)
  272.    {
  273.       buf->first_in_buf = 1;
  274.    }
  275.    buf->rows_in_buf++;
  276.    /* 
  277.     * if we have wrapped around we need to adjust oldest
  278.     * and rows_in_buf
  279.     */
  280.    if (buf->rows_in_buf > buf->elcount)
  281.    {
  282.       buf->oldest = (buf->oldest + 1) % buf->elcount;
  283.       buf->first_in_buf++;
  284.       buf->rows_in_buf--;
  285.    }
  286.    
  287.    assert(buf->elcount >= buf->rows_in_buf);
  288.    assert( buf->rows_in_buf==0
  289.            || (((buf->oldest+buf->rows_in_buf) - 1)%buf->elcount)==buf->newest);
  290.    assert(buf->rows_in_buf>0 || (buf->first_in_buf==buf->next_row-1));
  291.    assert(buf->rows_in_buf==0 || 
  292.           (buf->first_in_buf<=buf->next_row));
  293.    assert(buf->next_row-1 <= (buf->first_in_buf + buf->rows_in_buf));
  294.    dest = buffer_row_address(buf, buf->newest);
  295.    memcpy(dest, row, row_size);
  296. #endif
  297. } /* buffer_add_row()  */
  298. static int buffer_is_full(DBPROC_ROWBUF *buf)
  299. {
  300.    return buf->rows_in_buf==buf->elcount;
  301. } /* buffer_is_full()  */
  302. static void buffer_set_buffering(
  303.    DBPROC_ROWBUF *buf,      /* (U)                                         */
  304.    int            buf_size) /* (I) number of rows to buffer, 0 to turn off */
  305. {
  306.    /* XXX If the user calls this routine in the middle of 
  307.     * a result set and changes the size of the buffering
  308.     * they are pretty much toast.
  309.     *
  310.     * We need to figure out what to do if the user shrinks the 
  311.     * size of the row buffer.  What rows should be thrown out, 
  312.     * what should happen to the current row, etc?
  313.     */
  314.    assert(buf_size >= 0);
  315.    if (buf_size < 0)
  316.    {
  317.       /* XXX is it okay to ignore this? */
  318.    }
  319.    else if (buf_size == 0)
  320.    {
  321.       buf->buffering_on = 0;
  322.       buf->elcount = 1;
  323.       buffer_delete_all_rows(buf);
  324.    }
  325.    else
  326.    {
  327.       buf->buffering_on = 1;
  328.       buffer_clear(buf);
  329.       buffer_free(buf);
  330.       buf->elcount = buf_size;
  331.       if (buf->element_size > 0)
  332.       {
  333.          buf->rows = malloc(buf->element_size * buf->elcount);
  334.       }
  335.       else
  336.       {
  337.          buf->rows = NULL;
  338.       }
  339.    }
  340. } /* buffer_set_buffering()  */
  341. static void buffer_transfer_bound_data(
  342.    DBPROC_ROWBUF *buf,      /* (U)                                         */
  343.    DBPROCESS     *dbproc,   /* (I)                                         */
  344.    int            row_num)  /* (I) resultset row number                    */
  345. {
  346. int            i;
  347. TDSCOLINFO    *curcol;
  348. TDSRESULTINFO *resinfo;
  349. TDSSOCKET     *tds;
  350. int            srctype;
  351. BYTE          *src;
  352. int            desttype;
  353. int            destlen;
  354. /* this should probably go somewhere else */
  355.    
  356. tds     = (TDSSOCKET *) dbproc->tds_socket;
  357. resinfo = tds->res_info;
  358.    
  359. for (i=0;i<resinfo->num_cols;i++) {
  360. curcol = resinfo->columns[i];
  361. if (curcol->column_nullbind) {
  362. if (tds_get_null(resinfo->current_row,i)) {
  363. *((DBINT *)curcol->column_nullbind)=-1;
  364. } else {
  365. *((DBINT *)curcol->column_nullbind)=0;
  366. }
  367. }
  368. if (curcol->varaddr) {
  369.   DBINT srclen = -1;
  370. int   index = buffer_index_of_resultset_row(buf, row_num);
  371.          
  372. assert (index >= 0);
  373. /* XXX now what? */
  374. if (is_blob_type(curcol->column_type)) {
  375. srclen =  curcol->column_textsize;
  376. src = (BYTE *)curcol->column_textvalue;
  377. } else {
  378. src = ((BYTE *)buffer_row_address(buf, index)) 
  379. + curcol->column_offset;
  380. }
  381. desttype = _db_get_server_type(curcol->column_bindtype);
  382. srctype = tds_get_conversion_type(curcol->column_type,
  383. curcol->column_size);
  384. if (tds_get_null(resinfo->current_row,i)) {
  385. _set_null_value(dbproc, curcol->varaddr, desttype, 
  386. curcol->column_bindlen);
  387.    } else {
  388.              if (curcol->column_bindtype == STRINGBIND)
  389.                destlen = -2;
  390.             else if (curcol->column_bindtype == NTBSTRINGBIND)
  391.                     destlen = -1;
  392.                  else
  393.                     destlen = curcol->column_bindlen;
  394.          dbconvert(dbproc,
  395.       srctype, /* srctype  */
  396.       src, /* src      */
  397.       srclen, /* srclen   */
  398.       desttype, /* desttype */
  399.       (BYTE *)curcol->varaddr, /* dest     */
  400.       destlen);        /* destlen  */
  401. } /* else not null */
  402. }
  403. }
  404. } /* buffer_transfer_bound_data()  */
  405. RETCODE dbinit()
  406. {
  407. /* DBLIBCONTEXT stores a list of current connections so they may be closed
  408. ** with dbexit() */
  409. g_dblib_ctx = (DBLIBCONTEXT *) malloc(sizeof(DBLIBCONTEXT));
  410. memset(g_dblib_ctx,'',sizeof(DBLIBCONTEXT));
  411. g_dblib_ctx->tds_ctx = tds_alloc_context();
  412. tds_ctx_set_parent(g_dblib_ctx->tds_ctx, g_dblib_ctx);
  413. /* set the functions in the TDS layer to point to the correct info/err
  414. * message handler functions */
  415. g_dblib_ctx->tds_ctx->msg_handler = dblib_handle_info_message;
  416. g_dblib_ctx->tds_ctx->err_handler = dblib_handle_err_message;
  417. if( g_dblib_ctx->tds_ctx->locale && !g_dblib_ctx->tds_ctx->locale->date_fmt ) {
  418. /* set default in case there's no locale file */
  419. g_dblib_ctx->tds_ctx->locale->date_fmt = strdup("%b %e %Y %l:%M:%S:%z%p"); 
  420. }
  421. return SUCCEED;
  422. }
  423. LOGINREC *dblogin()
  424. {
  425. LOGINREC * loginrec;
  426. loginrec = (LOGINREC *) malloc(sizeof(LOGINREC));
  427. loginrec->tds_login = (void *) tds_alloc_login();
  428. /* set default values for loginrec */
  429. tds_set_library(loginrec->tds_login,"DB-Library");
  430. /* tds_set_charset(loginrec->tds_login,"iso_1"); */
  431. /* tds_set_packet(loginrec->tds_login,TDS_DEF_BLKSZ); */
  432. return loginrec;
  433. }
  434. void dbloginfree(LOGINREC *login)
  435. {
  436. if (login) {
  437. tds_free_login(login->tds_login);
  438. free(login);
  439. }
  440. }
  441. RETCODE dbsetlname(LOGINREC *login, char *value, int which)
  442. {
  443. switch (which) {
  444. case DBSETHOST:
  445. tds_set_host(login->tds_login, value);
  446. return SUCCEED;
  447. break;
  448. case DBSETUSER:
  449. tds_set_user(login->tds_login, value);
  450. return SUCCEED;
  451. break;
  452. case DBSETPWD:
  453. tds_set_passwd(login->tds_login, value);
  454. return SUCCEED;
  455. break;
  456. case DBSETAPP:
  457. tds_set_app(login->tds_login, value);
  458. return SUCCEED;
  459. break;
  460. case DBSETCHARSET:
  461. tds_set_charset(login->tds_login, value);
  462. return SUCCEED;
  463. break;
  464. case DBSETNATLANG:
  465. tds_set_language(login->tds_login, value);
  466. return SUCCEED;
  467. break;
  468. case DBSETHID:
  469. default:
  470. tdsdump_log(TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetlname() which = %dn", which);
  471. return FAIL;
  472. break;
  473. }
  474. }
  475. RETCODE dbsetllong(LOGINREC *login, long value, int which)
  476. {
  477. switch (which) {
  478. case DBSETPACKET:
  479. tds_set_packet(login->tds_login, (short) value); /* XXX */
  480. return SUCCEED;
  481. break;
  482. default:
  483. tdsdump_log(TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetllong() which = %dn", which);
  484. return FAIL;
  485. break;
  486. }
  487. }
  488. RETCODE dbsetlshort(LOGINREC *login, int value, int which)
  489. {
  490. switch (which) {
  491. case DBSETHIER:
  492. default:
  493. tdsdump_log(TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetlshort() which = %dn", which);
  494. return FAIL;
  495. break;
  496. }
  497. }
  498. RETCODE dbsetlbool(LOGINREC *login, int value, int which)
  499. {
  500. switch (which) {
  501. case DBSETBCP:
  502. tds_set_bulk(login->tds_login, (TDS_TINYINT) value);
  503. return SUCCEED;
  504. break;
  505. case DBSETNOSHORT:
  506. case DBSETENCRYPT:
  507. case DBSETLABELED:
  508. default:
  509. tdsdump_log(TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetlbool() which = %dn", which);
  510. return FAIL;
  511. break;
  512. }
  513. }
  514. DBPROCESS *tdsdbopen(LOGINREC *login,char *server)
  515. {
  516. DBPROCESS *dbproc;
  517.    
  518. dbproc = (DBPROCESS *) malloc(sizeof(DBPROCESS));
  519. memset(dbproc,'',sizeof(DBPROCESS));
  520. dbproc->avail_flag = TRUE;
  521. tds_set_server(login->tds_login,server);
  522.    
  523.    dbproc->tds_socket = (void *) tds_connect(login->tds_login, g_dblib_ctx->tds_ctx, (void *)dbproc);
  524.    dbproc->dbbuf = NULL;
  525.    dbproc->dbbufsz = 0;
  526.    if(dbproc->tds_socket) {
  527.       /* tds_set_parent( dbproc->tds_socket, dbproc); */
  528.       dblib_add_connection(g_dblib_ctx, dbproc->tds_socket);
  529.    } else {
  530.       fprintf(stderr,"DB-Library: Login incorrect.n");
  531.       free(dbproc); /* memory leak fix (mlilback, 11/17/01) */
  532.       return NULL;
  533.    }
  534.    
  535.    buffer_init(&(dbproc->row_buf));
  536.    
  537.    return dbproc;
  538. }
  539. RETCODE dbfcmd(DBPROCESS *dbproc, char *fmt, ...)
  540. {
  541. va_list ap;
  542. char *s;
  543. int len;
  544. RETCODE ret;
  545. va_start(ap, fmt);
  546. len = vasprintf(&s, fmt, ap);
  547. va_end(ap);
  548. if (len < 0) return FAIL;
  549. ret = dbcmd(dbproc, s);
  550. free(s);
  551. return ret;
  552. }
  553. RETCODE dbcmd(DBPROCESS *dbproc, char *cmdstring)
  554. {
  555. int newsz;
  556. void *p;
  557. if(dbproc == NULL) {
  558. return FAIL;
  559. }
  560. dbproc->avail_flag = FALSE;
  561. if(dbproc->dbbufsz == 0) {
  562. dbproc->dbbuf = (unsigned char *) malloc(strlen(cmdstring)+1);
  563. if(dbproc->dbbuf == NULL) {
  564. return FAIL;
  565. }
  566. strcpy((char *)dbproc->dbbuf, cmdstring);
  567. dbproc->dbbufsz = strlen(cmdstring) + 1;
  568. } else {
  569. newsz = strlen(cmdstring) + dbproc->dbbufsz;
  570. if((p=realloc(dbproc->dbbuf,newsz)) == NULL) {
  571. return FAIL;
  572. }
  573. dbproc->dbbuf = (unsigned char *)p;
  574. strcat((char *)dbproc->dbbuf, cmdstring);
  575. dbproc->dbbufsz = newsz;
  576. }
  577. return SUCCEED;
  578. }
  579. RETCODE dbsqlexec(DBPROCESS *dbproc)
  580. {
  581. RETCODE   rc = FAIL;
  582. TDSSOCKET *tds;
  583.    if (dbproc == NULL) {
  584.       return FAIL;
  585.    }
  586.    tds = (TDSSOCKET *) dbproc->tds_socket;
  587.    if (!tds || !tds->s) return FAIL;
  588.    if (tds->res_info && tds->res_info->more_results) 
  589.    /* if (dbproc->more_results && tds_is_end_of_results(dbproc->tds_socket)) */
  590.    {
  591.       dbresults(dbproc);
  592.    }
  593.       
  594.    if (SUCCEED == (rc = dbsqlsend(dbproc)))
  595.    {
  596.       /* 
  597.        * XXX We need to observe the timeout value and abort 
  598.        * if this times out.
  599.        */
  600.       rc = dbsqlok(dbproc);
  601.    }
  602.    dbproc->empty_res_hack = 0;
  603.    return rc;
  604. }
  605. RETCODE
  606. dbuse(DBPROCESS *dbproc, char *dbname)
  607. {
  608.    /* FIXME quote dbname if needed */
  609.    if ((dbproc == NULL)
  610.        || (dbfcmd(dbproc, "use %s", dbname) == FAIL)
  611.        || (dbsqlexec(dbproc) == FAIL)
  612.        || (dbcanquery(dbproc) == FAIL))
  613.       return FAIL;
  614.    return SUCCEED;
  615. }
  616. void
  617. dbclose(DBPROCESS *dbproc)
  618. {
  619. TDSSOCKET *tds;
  620. int i;
  621. tds = (TDSSOCKET *) dbproc->tds_socket;
  622. if (tds) {
  623.                 buffer_free(&(dbproc->row_buf));
  624. tds_free_socket(tds);
  625. }
  626. if (dbproc->bcp_tablename)
  627. free(dbproc->bcp_tablename);
  628. if (dbproc->bcp_hostfile)
  629. free(dbproc->bcp_hostfile);
  630. if (dbproc->bcp_errorfile)
  631. free(dbproc->bcp_errorfile);
  632. if (dbproc->bcp_columns) {
  633. for (i=0;i<dbproc->bcp_colcount;i++) {
  634. #ifdef NCBI_FTDS
  635.           if(dbproc->bcp_hostfile)
  636. #endif
  637. if (dbproc->bcp_columns[i]->data)
  638. free(dbproc->bcp_columns[i]->data);
  639. free(dbproc->bcp_columns[i]);
  640. }
  641. free(dbproc->bcp_columns);
  642. }
  643. if (dbproc->host_columns) {
  644. for (i=0;i<dbproc->host_colcount;i++) {
  645. if (dbproc->host_columns[i]->terminator)
  646. free(dbproc->host_columns[i]->terminator);
  647. free(dbproc->host_columns[i]);
  648. }
  649. free(dbproc->host_columns);
  650. }
  651. #ifdef NCBI_FTDS
  652.    if(dbproc->bcp_hint)
  653.        free(dbproc->bcp_hint);
  654. #endif
  655.     dbfreebuf(dbproc);
  656.         dblib_del_connection(g_dblib_ctx, dbproc->tds_socket);
  657. free(dbproc);
  658.         return;
  659. }
  660. void
  661. dbexit()
  662. {
  663. TDSSOCKET *tds;
  664. DBPROCESS *dbproc;
  665. int i;
  666. /* FIX ME -- this breaks if ctlib/dblib used in same process */
  667. for (i=0;i<TDS_MAX_CONN;i++) {
  668. tds = g_dblib_ctx->connection_list[i];
  669. if (tds) {
  670. dbproc = (DBPROCESS *) tds->parent;
  671. dbclose(dbproc);
  672. }
  673. }
  674. tds_free_context(g_dblib_ctx->tds_ctx);
  675. }
  676. RETCODE dbresults_r(DBPROCESS *dbproc, int recursive)
  677. {
  678. RETCODE       retcode = FAIL;
  679. TDSSOCKET *tds;
  680.    
  681.    /* 
  682.     * For now let's assume we have only 5 possible classes of tokens 
  683.     * at the next byte in the TDS stream
  684.     *   1) The start of a result set, either TDS_RESULT_TOKEN (tds ver 5.0)
  685.     *      or TDS_COL_NAME_TOKEN (tds ver 4.2).
  686.     *   2) A row token (TDS_ROW_TOKEN)
  687.     *   3) An end token (either 0xFD or 0xFE)
  688.     *   4) A done in proc token (0xFF)
  689.     *   5) A message or error token
  690.     */
  691.    if (dbproc == NULL) return FAIL;
  692.    buffer_clear(&(dbproc->row_buf));
  693.    tds = dbproc->tds_socket;
  694.    if (!tds || !tds->s) return FAIL;
  695.    retcode = tds_process_result_tokens(tds);
  696.    if (retcode == TDS_NO_MORE_RESULTS) {
  697. if (tds->res_info && tds->res_info->rows_exist) {
  698. return NO_MORE_RESULTS;
  699. } else {
  700. if (!dbproc->empty_res_hack) {
  701. dbproc->empty_res_hack = 1;
  702. return SUCCEED;
  703. } else {
  704. dbproc->empty_res_hack = 0;
  705. return NO_MORE_RESULTS;
  706. }
  707. }
  708.    }
  709.    if (retcode == TDS_SUCCEED) {
  710.     retcode = buffer_start_resultset(&(dbproc->row_buf), 
  711.                                       tds->res_info->row_size);
  712.    }
  713.    return retcode;
  714. }
  715.    
  716. /* =============================== dbresults() ===============================
  717.  * 
  718.  * Def: 
  719.  * 
  720.  * Ret:  SUCCEED, FAIL, NO_MORE_RESULTS, or NO_MORE_RPC_RESULTS
  721.  * 
  722.  * ===========================================================================
  723.  */
  724. RETCODE dbresults(DBPROCESS *dbproc)
  725. {
  726. RETCODE rc;
  727.    tdsdump_log(TDS_DBG_FUNC, "%L inside dbresults()n");
  728.    if (dbproc == NULL) return FAIL;
  729.    rc = dbresults_r(dbproc, 0);
  730.    tdsdump_log(TDS_DBG_FUNC, "%L leaving dbresults() returning %dn",rc);
  731.    return rc;
  732. }
  733. int dbnumcols(DBPROCESS *dbproc)
  734. {
  735. TDSRESULTINFO *resinfo;
  736. TDSSOCKET *tds;
  737. tds = (TDSSOCKET *) dbproc->tds_socket;
  738. resinfo = tds->res_info;
  739. if (resinfo)
  740. return resinfo->num_cols;
  741. return 0;
  742. }
  743. char *dbcolname(DBPROCESS *dbproc, int column)
  744. {
  745. #ifdef NCBI_FTDS
  746.     TDSRESULTINFO *resinfo;
  747.     TDSSOCKET *tds;
  748.     
  749.     tds = (TDSSOCKET *) dbproc->tds_socket;
  750.     resinfo = tds->res_info;
  751.     if (column < 1 || column > resinfo->num_cols || !resinfo->columns[column-1]) return NULL;
  752.     return resinfo->columns[column-1]->column_name;
  753. #else    
  754. static char buf[255];
  755. TDSRESULTINFO *resinfo;
  756. TDSSOCKET *tds;
  757. tds = (TDSSOCKET *) dbproc->tds_socket;
  758. resinfo = tds->res_info;
  759. if (column < 1 || column > resinfo->num_cols) return NULL;
  760. strcpy (buf,resinfo->columns[column-1]->column_name);
  761. return buf;
  762. #endif
  763. }
  764. RETCODE dbgetrow(
  765.    DBPROCESS *dbproc, 
  766.    DBINT row)
  767. {
  768.    RETCODE   result = FAIL;
  769.    int       index = buffer_index_of_resultset_row(&(dbproc->row_buf), row);
  770.    if (-1 == index)
  771.    {
  772.       result = NO_MORE_ROWS;
  773.    }
  774.    else
  775.    {
  776.       dbproc->row_buf.next_row = row;
  777.       buffer_transfer_bound_data(&(dbproc->row_buf), dbproc, row);
  778.       dbproc->row_buf.next_row++;
  779.       result = REG_ROW;
  780.    }
  781.    return result;
  782. }
  783. RETCODE dbnextrow(DBPROCESS *dbproc)
  784. {
  785.    TDSRESULTINFO *resinfo;
  786.    TDSSOCKET     *tds;
  787.    int            rc;
  788.    RETCODE        result = FAIL;
  789.    
  790.    tdsdump_log(TDS_DBG_FUNC, "%L inside dbnextrow()n");
  791.    if (dbproc == NULL) return FAIL;
  792.    tds = (TDSSOCKET *) dbproc->tds_socket;
  793.    if (!tds || !tds->s) {
  794.       tdsdump_log(TDS_DBG_FUNC, "%L leaving dbnextrow() returning %dn",FAIL);
  795.       return FAIL;
  796.    }
  797.    resinfo = tds->res_info;
  798.    if (!resinfo) {
  799.       tdsdump_log(TDS_DBG_FUNC, "%L leaving dbnextrow() returning %dn",NO_MORE_ROWS);
  800.       return NO_MORE_ROWS;
  801.    }
  802.    if (dbproc->row_buf.buffering_on && buffer_is_full(&(dbproc->row_buf))
  803.        && (-1 == buffer_index_of_resultset_row(&(dbproc->row_buf), 
  804.                                                dbproc->row_buf.next_row)))
  805.    {
  806.       result = BUF_FULL;
  807.    }
  808.    else 
  809.    {
  810.       /*
  811.        * Now try to get the dbproc->row_buf.next_row item into the row
  812.        * buffer
  813.        */
  814.       if (-1 != buffer_index_of_resultset_row(&(dbproc->row_buf), 
  815.                                               dbproc->row_buf.next_row))
  816.       {
  817.          /*
  818.           * Cool, the item we want is already there
  819.           */
  820.          rc     = TDS_SUCCEED;
  821.          result = REG_ROW;
  822.       }
  823.       else
  824.       {
  825.             /* 
  826.              * XXX Note- we need to handle "compute" results as well.
  827.              * I don't believe the current src/tds/token.c handles those
  828.              * so we don't handle them yet either.
  829.              */
  830.             /* 
  831.              * Get the row from the TDS stream.
  832.              */
  833.             rc = tds_process_row_tokens(dbproc->tds_socket);
  834.             if (rc == TDS_SUCCEED)
  835.             {
  836.                /*
  837.                 * Add the row to the row buffer
  838.                 */
  839.                buffer_add_row(&(dbproc->row_buf), resinfo->current_row, 
  840.                               resinfo->row_size);
  841.                result = REG_ROW;
  842.             }
  843.             else if (rc == TDS_NO_MORE_ROWS)
  844.             {
  845.                result = NO_MORE_ROWS;
  846.             }
  847.             else 
  848.             {
  849.                result = FAIL;
  850.             }
  851.       }
  852.    
  853.       if (result == REG_ROW)
  854.       {
  855.          /*
  856.           * The data is in the row buffer, now transfer it to the 
  857.           * bound variables
  858.           */
  859.          buffer_transfer_bound_data(&(dbproc->row_buf), dbproc, 
  860.                                     dbproc->row_buf.next_row);
  861.          dbproc->row_buf.next_row++;
  862.       }
  863.    }
  864.    tdsdump_log(TDS_DBG_FUNC, "%L leaving dbnextrow() returning %dn",result);
  865.    return result;
  866. } /* dbnextrow()  */
  867. static int _db_get_server_type(int bindtype)
  868. {
  869. switch (bindtype) {
  870. case CHARBIND:
  871. case STRINGBIND:
  872. case NTBSTRINGBIND:
  873. return SYBCHAR;
  874. break;
  875. case FLT8BIND:
  876. return SYBFLT8;
  877. break;
  878. case REALBIND:
  879. return SYBREAL;
  880. break;
  881. case INTBIND:
  882. return SYBINT4;
  883. break;
  884. case SMALLBIND:
  885. return SYBINT2;
  886. break;
  887. case TINYBIND:
  888. return SYBINT1;
  889. break;
  890.           case DATETIMEBIND:
  891.                return SYBDATETIME;
  892.                break;
  893.           case SMALLDATETIMEBIND:
  894.                return SYBDATETIME4;
  895.                break;
  896.           case MONEYBIND:
  897.                return SYBMONEY;
  898.                break;
  899.           case SMALLMONEYBIND:
  900.                return SYBMONEY4;
  901.                break;
  902.           case BINARYBIND:
  903.                return SYBBINARY;
  904.                break;
  905.           case VARYCHARBIND:
  906.                return SYBVARCHAR;
  907.                break;
  908.           case BITBIND:
  909.                return SYBBIT;
  910.                break;
  911.           case NUMERICBIND:
  912.                return SYBNUMERIC;
  913.                break;
  914.           case DECIMALBIND:
  915.                return SYBDECIMAL;
  916.                break;
  917.           default:
  918.                return -1;
  919.                break;
  920. }
  921. }
  922. /**
  923.  * Conversion functions are handled in the TDS layer.
  924.  * 
  925.  * The main reason for this is that ctlib and ODBC (and presumably DBI) need
  926.  * to be able to do conversions between datatypes. This is possible because
  927.  * the format of complex data (dates, money, numeric, decimal) is defined by
  928.  * its representation on the wire; thus what we call DBMONEY is exactly its
  929.  * format on the wire. CLIs that need a different representation (ODBC?) 
  930.  * need to convert from this format anyway, so the code would already be in
  931.  * place.
  932.  * 
  933.  * Each datatype is also defined by its Server-type so all CLIs should be 
  934.  * able to map native types to server types as well.
  935.  *
  936.  * tds_convert copies from src to dest and returns the output data length,
  937.  * period.  All padding and termination is the responsibility of the API library
  938.  * and is done post-conversion.  The peculiar rule in dbconvert() is that
  939.  * a destlen of -1 and a desttype of SYBCHAR means the output buffer
  940.  * should be null-terminated.  
  941.  */
  942. DBINT dbconvert(DBPROCESS *dbproc,
  943. int srctype,
  944. BYTE *src,
  945. DBINT srclen,
  946. int desttype,
  947. BYTE *dest,
  948. DBINT destlen)
  949. {
  950. TDSSOCKET *tds = NULL;
  951. CONV_RESULT dres;
  952. DBINT       ret;
  953. int         i;
  954. int         len;
  955. DBNUMERIC   *num;
  956. tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() srctype = %d desttype = %dn",srctype, desttype);
  957. if (dbproc) {
  958. tds = (TDSSOCKET *) dbproc->tds_socket;
  959. }
  960.     if (src == NULL || srclen == 0) {
  961.        /* FIX set appropriate NULL value for destination type */
  962.        memset(dest,'', destlen);
  963.        return 0;
  964.     }
  965.     /* srclen of -1 means the source data is definitely NULL terminated */
  966.     if (srclen == -1) 
  967.        srclen = strlen((char *)src);
  968.     if (dest == NULL) {
  969.        /* FIX call error handler */
  970.        return -1;
  971.     }
  972.     
  973.     /* oft times we are asked to convert a data type to itself */
  974.     if (srctype == desttype) {
  975.    tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() srctype == desttypen");
  976.        switch (desttype) {
  977.           case SYBBINARY:
  978.           case SYBIMAGE:
  979.                if (srclen > destlen && destlen >= 0) {
  980.                   ret = -1;
  981.                }
  982.                else {
  983.                   memcpy(dest, src, srclen);
  984.   if (srclen < destlen)
  985.   memset(dest+srclen,0,destlen-srclen);
  986.                   ret = srclen;
  987.                }
  988.                break;
  989.           case SYBCHAR:
  990.           case SYBVARCHAR:
  991.           case SYBTEXT:
  992.                /* srclen of -1 means the source data is definitely NULL terminated */
  993.                if (srclen == -1) 
  994.                   srclen = strlen((char *)src);
  995.                if (destlen == 0 || destlen < -2) {
  996.                   ret = FAIL;
  997.                }
  998.                else if (destlen == -1) { /* rtrim and null terminate */
  999.                   for (i = srclen-1; i>=0 && src[i] == ' '; --i) {
  1000.       srclen = i;
  1001.   } 
  1002.                   memcpy(dest,src,srclen);
  1003.                   dest[srclen] = '';
  1004.                   ret = srclen;
  1005.                }
  1006.                else if (destlen == -2) { /* just null terminate */
  1007.                   memcpy(dest,src,srclen);
  1008.                   dest[srclen] = '';
  1009.                   ret = srclen;
  1010.                }
  1011.                else { /* destlen is > 0 */
  1012.                   if (srclen > destlen) {
  1013.                      /* fprintf(stderr,"%s: Line%d: Data-conversion resulted in overflow.n", __FILE__, __LINE__);
  1014.                      fprintf(stderr,"tsrclen (%d)> destlen (%d).n", srclen, destlen); */
  1015.                     ret = -1;
  1016.                   }
  1017.                   else {
  1018.                      memcpy(dest, src, srclen);
  1019.                      for (i = srclen; i < destlen; i++ )
  1020.                        dest[i] = ' ';
  1021.                      ret = srclen;
  1022.                   }
  1023.                }
  1024.                   
  1025.                break;
  1026.           case SYBINT1: 
  1027.           case SYBINT2:
  1028.           case SYBINT4:
  1029.           case SYBINT8:
  1030.           case SYBFLT8:
  1031.           case SYBREAL:
  1032.           case SYBBIT:
  1033.           case SYBBITN:
  1034.           case SYBMONEY:
  1035.           case SYBMONEY4:
  1036.           case SYBDATETIME:
  1037.           case SYBDATETIME4:
  1038.           case SYBUNIQUE:
  1039.                ret = get_size_by_type(desttype);
  1040.                memcpy(dest, src, ret);
  1041.                break;
  1042.           case SYBNUMERIC:
  1043.           case SYBDECIMAL:
  1044.                memcpy(dest, src, sizeof(DBNUMERIC));
  1045.                ret = sizeof(DBNUMERIC);
  1046.                break;
  1047.        }
  1048.        return ret;
  1049.     }          /* srctype == desttype */
  1050.      /* FIXME what happen if client do not reset values ??? */
  1051. /* FIXME act differently for ms and sybase */
  1052. if (is_numeric_type(desttype)) {
  1053. num = (DBNUMERIC *)dest;
  1054. if ( num->precision == 0 )
  1055. dres.n.precision = 18;
  1056. else
  1057. dres.n.precision = num->precision;
  1058. if ( num->scale == 0 )
  1059. dres.n.scale = 0;
  1060. else
  1061. dres.n.scale = num->scale;
  1062. }
  1063. tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() calling tds_convertn");
  1064. len = tds_convert (g_dblib_ctx->tds_ctx, srctype, (TDS_CHAR *)src, srclen, 
  1065.                        desttype, &dres);
  1066.    
  1067. if( len == TDS_FAIL )
  1068. return 0;
  1069.     switch (desttype) {
  1070.         case SYBBINARY:
  1071.         case SYBIMAGE:
  1072.              if (len > destlen && destlen >= 0) {
  1073.                 fprintf(stderr,"%s: Line %d: Data-conversion resulted in overflow.n", __FILE__, __LINE__);
  1074.                 fprintf(stderr,"tlen (%d) > destlen (%d).n", len, destlen);
  1075.                 ret = -1;
  1076.              } else {
  1077.                 memcpy(dest, dres.ib, len);
  1078.                 free(dres.ib);
  1079. if (len < destlen)
  1080. memset(dest+len,0,destlen-len);
  1081. ret = len;
  1082.              }
  1083.              break;
  1084.         case SYBINT1:
  1085.              memcpy(dest,&(dres.ti),1);
  1086.              ret = 1;
  1087.              break;
  1088.         case SYBINT2:
  1089.              memcpy(dest,&(dres.si),2);
  1090.              ret = 2;
  1091.              break;
  1092.         case SYBINT4:
  1093.              memcpy(dest,&(dres.i),4);
  1094.              ret = 4;
  1095.              break;
  1096.         case SYBFLT8:
  1097.              memcpy(dest,&(dres.f),8);
  1098.              ret = 8;
  1099.              break;
  1100.         case SYBREAL:
  1101.              memcpy(dest,&(dres.r),4);
  1102.              ret = 4;
  1103.              break;
  1104.         case SYBBIT:
  1105.         case SYBBITN:
  1106.              memcpy(dest,&(dres.ti),1);
  1107.              ret = 1;
  1108.              break;
  1109.         case SYBMONEY:
  1110.              memcpy(dest,&(dres.m),sizeof(TDS_MONEY));
  1111.              ret = sizeof(TDS_MONEY);
  1112.              break;
  1113.         case SYBMONEY4:
  1114.              memcpy(dest,&(dres.m4),sizeof(TDS_MONEY4));
  1115.              ret = sizeof(TDS_MONEY4);
  1116.              break;
  1117.         case SYBDATETIME:
  1118.              memcpy(dest,&(dres.dt),sizeof(TDS_DATETIME));
  1119.              ret = sizeof(TDS_DATETIME);
  1120.              break;
  1121.         case SYBDATETIME4:
  1122.              memcpy(dest,&(dres.dt4),sizeof(TDS_DATETIME4));
  1123.              ret = sizeof(TDS_DATETIME4);
  1124.              break;
  1125.         case SYBNUMERIC:
  1126.         case SYBDECIMAL:
  1127.              memcpy(dest,&(dres.n), sizeof(TDS_NUMERIC));
  1128.              ret = sizeof(TDS_NUMERIC);
  1129.              break;
  1130.         case SYBCHAR:
  1131.         case SYBVARCHAR:
  1132.         case SYBTEXT:
  1133.          tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() outputting %d bytes character data destlen = %d n", len, destlen);
  1134.              if (destlen == 0 || destlen < -2) {
  1135.                 ret = FAIL;
  1136.              }
  1137.              else if (destlen == -1) { /* rtrim and null terminate */
  1138.                 for (i = len-1; i>=0 && dres.c[i] == ' '; --i) {
  1139.     len = i;
  1140. }
  1141.                 memcpy(dest, dres.c, len);
  1142. dest[len] = '';
  1143.                 ret = len;
  1144.              }
  1145.              else if (destlen == -2) { /* just null terminate */
  1146.                 memcpy(dest,dres.c,len);
  1147. dest[len] = 0;
  1148.                 ret = len;
  1149.              }
  1150.              else { /* destlen is > 0 */
  1151.                 if (len > destlen) {
  1152.                  /*fprintf(stderr,"%s: Line%d: Data-conversion resulted in overflow.n", __FILE__, __LINE__);
  1153.                  fprintf(stderr,"tlen (%d)> destlen (%d).n", len, destlen);*/
  1154.                      ret = -1;
  1155.                 }
  1156.                 else
  1157.                    memcpy(dest, dres.c, len);
  1158.                    for (i = len; i < destlen; i++ )
  1159.                        dest[i] = ' ';
  1160.                    ret = len;
  1161.              }
  1162.                 
  1163.              free(dres.c);
  1164.              break;
  1165.      }
  1166.      return(ret);
  1167. }
  1168. DBINT dbconvert_ps(DBPROCESS *dbproc,
  1169. int srctype,
  1170. BYTE *src,
  1171. DBINT srclen,
  1172. int desttype,
  1173. BYTE *dest,
  1174. DBINT destlen,
  1175. DBTYPEINFO *typeinfo)
  1176. {
  1177. DBNUMERIC *s;
  1178. DBNUMERIC *d;
  1179. if (is_numeric_type(desttype)) {
  1180. if (typeinfo == (DBTYPEINFO *) NULL ) {
  1181. if (is_numeric_type(srctype)) {
  1182. s = (DBNUMERIC *)src;
  1183. d = (DBNUMERIC *)dest;
  1184. d->precision = s->precision;
  1185. d->scale     = s->scale;
  1186. } else {
  1187. d = (DBNUMERIC *)dest;
  1188. d->precision = 18;
  1189. d->scale     = 0;
  1190. }
  1191. } else {
  1192. d = (DBNUMERIC *)dest;
  1193. d->precision = typeinfo->precision;
  1194. d->scale     = typeinfo->scale;
  1195. }
  1196. }
  1197. return dbconvert(dbproc, srctype, src, srclen,
  1198. desttype, dest, destlen);
  1199. }
  1200. RETCODE dbbind(
  1201.    DBPROCESS *dbproc,
  1202.    int        column,
  1203.    int        vartype,
  1204.    DBINT      varlen,
  1205.    BYTE      *varaddr)
  1206. {
  1207.    TDSCOLINFO    *colinfo = NULL;
  1208.    TDSRESULTINFO *resinfo = NULL;
  1209.    TDSSOCKET     *tds     = NULL;
  1210.    int            srctype = -1;   
  1211.    int            desttype = -1;   
  1212.    int            okay    = TRUE; /* so far, so good */
  1213. tdsdump_log(TDS_DBG_INFO1, "%L dbbind() column = %d %d %dn",column, vartype, varlen);
  1214. dbproc->avail_flag = FALSE;
  1215.    /* 
  1216.     * Note on logic-  I'm using a boolean variable 'okay' to tell me if
  1217.     * everything that has happened so far has gone okay.  Basically if 
  1218.     * something happened that wasn't okay we don't want to keep doing 
  1219.     * things, but I also don't want to have a half dozen exit points from 
  1220.     * this function.  So basically I've wrapped each set of operation in a 
  1221.     * "if (okay)" statement.  Once okay becomes false we skip everything 
  1222.     * else.
  1223.     */
  1224. okay = (dbproc!=NULL && dbproc->tds_socket!=NULL && varaddr!=NULL);
  1225. if (okay) {
  1226. tds = (TDSSOCKET *) dbproc->tds_socket;
  1227. resinfo = tds->res_info;
  1228. }
  1229.    
  1230. okay = okay && ((column >= 1) && (column <= resinfo->num_cols));
  1231. if (okay) {
  1232. colinfo  = resinfo->columns[column-1];
  1233. srctype = tds_get_conversion_type(colinfo->column_type,
  1234. colinfo->column_size);
  1235. desttype = _db_get_server_type(vartype);
  1236. tdsdump_log(TDS_DBG_INFO1, "%L dbbind() srctype = %d desttype = %d n",srctype, desttype);
  1237. okay = okay && dbwillconvert(srctype, _db_get_server_type(vartype));
  1238. }
  1239. if (okay) {   
  1240. colinfo->varaddr         = (char *)varaddr;
  1241. colinfo->column_bindtype = vartype;
  1242. colinfo->column_bindlen  = varlen;
  1243. }
  1244. return okay ? SUCCEED : FAIL;
  1245. } /* dbbind()  */
  1246. void dbsetifile(char *filename)
  1247. {
  1248. set_interfaces_file_loc(filename);
  1249. }
  1250. RETCODE dbnullbind(DBPROCESS *dbproc, int column, DBINT *indicator)
  1251. {
  1252. TDSCOLINFO * colinfo;
  1253. TDSRESULTINFO * resinfo;
  1254. TDSSOCKET * tds;
  1255.         /*
  1256.          *  XXX Need to check for possibly problems before assuming
  1257.          *  everything is okay
  1258.          */
  1259. tds = (TDSSOCKET *) dbproc->tds_socket;
  1260. resinfo = tds->res_info;
  1261. colinfo = resinfo->columns[column-1];
  1262. colinfo->column_nullbind = (TDS_CHAR *) indicator;
  1263.         return SUCCEED;
  1264. }
  1265. DBINT dbcount(DBPROCESS *dbproc)
  1266. {
  1267. TDSRESULTINFO * resinfo;
  1268. TDSSOCKET * tds;
  1269. tds = (TDSSOCKET *) dbproc->tds_socket;
  1270. resinfo = tds->res_info;
  1271. if (resinfo) 
  1272. return resinfo->row_count;
  1273. else return tds->rows_affected;
  1274. }
  1275. void dbclrbuf(DBPROCESS *dbproc, DBINT n)
  1276. {
  1277.    if (n <= 0) return;
  1278.    if (dbproc->row_buf.buffering_on)
  1279.    {
  1280.       if (n >= dbproc->row_buf.rows_in_buf) {
  1281.        buffer_delete_rows(&(dbproc->row_buf), dbproc->row_buf.rows_in_buf - 1);
  1282.       } else {
  1283.        buffer_delete_rows(&(dbproc->row_buf), n);
  1284.       }
  1285.    }
  1286. }
  1287. DBBOOL dbwillconvert(int srctype, int desttype)
  1288. {
  1289.    return tds_willconvert (srctype, desttype);
  1290. }
  1291. int dbcoltype(DBPROCESS *dbproc,int column)
  1292. {
  1293. TDSCOLINFO * colinfo;
  1294. TDSRESULTINFO * resinfo;
  1295. TDSSOCKET * tds;
  1296. tds = (TDSSOCKET *) dbproc->tds_socket;
  1297. resinfo = tds->res_info;
  1298. colinfo = resinfo->columns[column-1];
  1299. switch (colinfo->column_type) {
  1300. case SYBVARCHAR:
  1301. return SYBCHAR; 
  1302. case SYBVARBINARY:
  1303. return SYBBINARY;
  1304. case SYBDATETIMN:
  1305. if (colinfo->column_size==8)
  1306. return SYBDATETIME;
  1307. else if (colinfo->column_size==4)
  1308. return SYBDATETIME4;
  1309. case SYBMONEYN:
  1310. /* needs to be based on column size (mlilback, 11/7/01) */
  1311. if (colinfo->column_size==4)
  1312. return SYBMONEY4;
  1313. else
  1314. return SYBMONEY;
  1315. case SYBFLTN:
  1316. if (colinfo->column_size==8)
  1317. return SYBFLT8;
  1318. else if (colinfo->column_size==4)
  1319. return SYBREAL;
  1320. case SYBINTN:
  1321. if (colinfo->column_size==4)
  1322. return SYBINT4;
  1323. else if (colinfo->column_size==2)
  1324. return SYBINT2; 
  1325. else if (colinfo->column_size==1)
  1326. return SYBINT1; 
  1327. else if (colinfo->column_size==8)
  1328.     return SYBINT8;
  1329. default:
  1330. return colinfo->column_type;
  1331. }
  1332. #ifndef NCBI_FTDS
  1333. return 0; /* something went wrong */
  1334. #endif
  1335. }
  1336. int dbcolutype(DBPROCESS *dbproc,int column)
  1337. {
  1338. TDSCOLINFO * colinfo;
  1339. TDSRESULTINFO * resinfo;
  1340. TDSSOCKET * tds;
  1341. tds = (TDSSOCKET *) dbproc->tds_socket;
  1342. resinfo = tds->res_info;
  1343. colinfo = resinfo->columns[column-1];
  1344.         return colinfo->column_usertype;
  1345. }
  1346. DBTYPEINFO *dbcoltypeinfo(DBPROCESS *dbproc, int column)
  1347. {
  1348. /* moved typeinfo from static into dbproc structure to make thread safe. 
  1349. (mlilback 11/7/01) */
  1350. TDSCOLINFO * colinfo;
  1351. TDSRESULTINFO * resinfo;
  1352. TDSSOCKET * tds;
  1353. tds = (TDSSOCKET *) dbproc->tds_socket;
  1354. resinfo = tds->res_info;
  1355. colinfo = resinfo->columns[column-1];
  1356. dbproc->typeinfo.precision = colinfo->column_prec;
  1357. dbproc->typeinfo.scale = colinfo->column_scale;
  1358. return &dbproc->typeinfo;
  1359. }
  1360. char *dbcolsource(DBPROCESS *dbproc,int colnum)
  1361. {
  1362. TDSCOLINFO * colinfo;
  1363. TDSRESULTINFO * resinfo;
  1364. TDSSOCKET * tds;
  1365. tds = (TDSSOCKET *) dbproc->tds_socket;
  1366. resinfo = tds->res_info;
  1367. colinfo = resinfo->columns[colnum-1];
  1368. #ifdef NCBI_FTDS
  1369.    return colinfo->full_column_name;
  1370. #else
  1371. return colinfo->column_name;
  1372. #endif
  1373. }
  1374. DBINT dbcollen(DBPROCESS *dbproc, int column)
  1375. {
  1376. TDSCOLINFO * colinfo;
  1377. TDSRESULTINFO * resinfo;
  1378. TDSSOCKET * tds;
  1379. tds = (TDSSOCKET *) dbproc->tds_socket;
  1380. resinfo = tds->res_info;
  1381. if (column<1 || column>resinfo->num_cols) return -1;
  1382. colinfo = resinfo->columns[column-1];
  1383. return colinfo->column_size;
  1384. }
  1385. /* dbvarylen(), pkleef@openlinksw.com 01/21/02 */
  1386. DBINT dbvarylen(DBPROCESS *dbproc, int column)
  1387. {
  1388. TDSCOLINFO * colinfo;
  1389. TDSRESULTINFO *resinfo;
  1390. TDSSOCKET *tds;
  1391. tds = (TDSSOCKET *) dbproc->tds_socket;
  1392. resinfo = tds->res_info;
  1393. if (column<1 || column>resinfo->num_cols) 
  1394. return FALSE;
  1395. colinfo = resinfo->columns[column-1];
  1396. if (tds_get_null (resinfo->current_row, column))
  1397. return TRUE;
  1398. switch (colinfo->column_type) {
  1399. /* variable length fields */
  1400. case SYBNVARCHAR:
  1401. case SYBVARBINARY:
  1402. case SYBVARCHAR:
  1403. return TRUE;
  1404. /* types that can be null */
  1405. case SYBBITN:
  1406. case SYBDATETIMN:
  1407. case SYBDECIMAL:
  1408. case SYBFLTN:
  1409. case SYBINTN:
  1410. case SYBMONEYN:
  1411. case SYBNUMERIC:
  1412. return TRUE;
  1413. /* blob types */
  1414. case SYBIMAGE:
  1415. case SYBNTEXT:
  1416. case SYBTEXT:
  1417. return TRUE;
  1418. }
  1419. return FALSE;
  1420. }
  1421. DBINT dbdatlen(DBPROCESS *dbproc, int column)
  1422. {
  1423. TDSCOLINFO * colinfo;
  1424. TDSRESULTINFO * resinfo;
  1425. TDSSOCKET * tds;
  1426. DBINT ret;
  1427. /* FIXME -- this is the columns info, need per row info */
  1428. /* Fixed by adding cur_row_size to colinfo, filled in by process_row
  1429. in token.c. (mlilback, 11/7/01) */
  1430. tds = (TDSSOCKET *) dbproc->tds_socket;
  1431. resinfo = tds->res_info;
  1432. if (column<1 || column>resinfo->num_cols) return -1;
  1433. colinfo = resinfo->columns[column-1];
  1434. tdsdump_log(TDS_DBG_INFO1, "%L dbdatlen() type = %dn",colinfo->column_type);
  1435. if (tds_get_null(resinfo->current_row,column-1))
  1436. ret = 0;
  1437. else
  1438. ret = colinfo->cur_row_size;
  1439. tdsdump_log(TDS_DBG_FUNC, "%L leaving dbdatlen() returning %dn",ret);
  1440. return ret;
  1441. }
  1442. BYTE *
  1443. dbdata(DBPROCESS *dbproc, int column)
  1444. {
  1445. TDSCOLINFO * colinfo;
  1446. TDSRESULTINFO * resinfo;
  1447. TDS_VARBINARY *varbin;
  1448.  register TDS_SMALLINT t;
  1449. resinfo = dbproc->tds_socket->res_info;
  1450. if (column<1 || column>resinfo->num_cols) return NULL;
  1451. if (tds_get_null(resinfo->current_row,column-1)) {
  1452. return NULL;
  1453. }
  1454. colinfo = resinfo->columns[column-1];
  1455. t= colinfo->column_type;
  1456. if (is_blob_type(t)) {
  1457. return (BYTE *)colinfo->column_textvalue;
  1458. if (t == SYBVARBINARY) {
  1459. varbin = (TDS_VARBINARY *)
  1460. &(resinfo->current_row[colinfo->column_offset]);
  1461. return (BYTE *)varbin->array;
  1462. }
  1463. /* else */
  1464. return &resinfo->current_row[colinfo->column_offset];
  1465. }
  1466. RETCODE dbcancel(DBPROCESS *dbproc)
  1467. {
  1468.    tds_send_cancel(dbproc->tds_socket);
  1469.    tds_process_cancel(dbproc->tds_socket);
  1470.    /* tds_process_default_tokens(dbproc->tds_socket,CANCEL); */
  1471.    return SUCCEED;
  1472. }
  1473. DBINT dbspr1rowlen(DBPROCESS *dbproc)
  1474. {
  1475. TDSCOLINFO * colinfo;
  1476. TDSRESULTINFO * resinfo;
  1477. TDSSOCKET * tds;
  1478. int col,len=0,collen,namlen;
  1479. tds = (TDSSOCKET *) dbproc->tds_socket;
  1480. resinfo = tds->res_info;
  1481. for (col=0;col<resinfo->num_cols;col++)
  1482. {
  1483. colinfo = resinfo->columns[col];
  1484. collen = _get_printable_size(colinfo);
  1485. namlen = strlen(colinfo->column_name);
  1486. len += collen > namlen ? collen : namlen;
  1487. }
  1488. /* the space between each column */
  1489. len += resinfo->num_cols - 1;
  1490. /* the newline */
  1491. len++;
  1492. return len;
  1493. }
  1494. RETCODE dbspr1row(DBPROCESS *dbproc, char *buffer, DBINT buf_len)
  1495. {
  1496. TDSCOLINFO * colinfo;
  1497. TDSRESULTINFO * resinfo;
  1498. TDSSOCKET * tds;
  1499. int i,col,collen,namlen,len;
  1500. char dest[256];
  1501. int desttype, srctype;
  1502. int buf_cur=0;
  1503. RETCODE ret;
  1504. tds = (TDSSOCKET *) dbproc->tds_socket;
  1505. resinfo = tds->res_info;
  1506. buffer[0]='';
  1507. if ((ret = dbnextrow(dbproc))!=REG_ROW) 
  1508. return ret;
  1509. for (col=0;col<resinfo->num_cols;col++)
  1510. {
  1511. colinfo = resinfo->columns[col];
  1512. if (tds_get_null(resinfo->current_row,col)) {
  1513. strcpy(dest,"NULL");
  1514. } else {
  1515. desttype = _db_get_server_type(STRINGBIND);
  1516. srctype = tds_get_conversion_type(colinfo->column_type,colinfo->column_size);
  1517. dbconvert(dbproc, srctype ,dbdata(dbproc,col+1), -1, desttype, (BYTE *)dest, 255);
  1518. }
  1519. collen = _get_printable_size(colinfo);
  1520. namlen = strlen(colinfo->column_name);
  1521. len = collen > namlen ? collen : namlen;
  1522. for (i=strlen(dest);i<len;i++)
  1523. strcat(dest," ");
  1524. if (strlen(dest) + buf_cur < buf_len) {
  1525. strcat(buffer,dest);
  1526. buf_cur+=strlen(dest);
  1527. }
  1528. if (strlen(buffer)<buf_len) {
  1529. strcat(buffer," ");
  1530. buf_cur++;
  1531. }
  1532. }
  1533. if (strlen(buffer)<buf_len) 
  1534. strcat(buffer,"n");
  1535. return ret;
  1536. }
  1537. RETCODE
  1538. dbprrow(DBPROCESS *dbproc)
  1539. {
  1540. TDSCOLINFO * colinfo;
  1541. TDSRESULTINFO * resinfo;
  1542. TDSSOCKET * tds;
  1543. int i,col,collen,namlen,len;
  1544. char dest[256];
  1545. int desttype, srctype;
  1546. tds = (TDSSOCKET *) dbproc->tds_socket;
  1547. resinfo = tds->res_info;
  1548. while(dbnextrow(dbproc)==REG_ROW) {
  1549. for (col=0;col<resinfo->num_cols;col++)
  1550. {
  1551. colinfo = resinfo->columns[col];
  1552. if (tds_get_null(resinfo->current_row,col)) {
  1553. strcpy(dest,"NULL");
  1554. } else {
  1555. desttype = _db_get_server_type(STRINGBIND);
  1556. srctype = tds_get_conversion_type(colinfo->column_type,colinfo->column_size);
  1557. dbconvert(dbproc, srctype ,dbdata(dbproc,col+1), -1, desttype, (BYTE *)dest, 255);
  1558. /* printf ("some datat"); */
  1559. }
  1560. printf("%s",dest);
  1561. collen = _get_printable_size(colinfo);
  1562. namlen = strlen(colinfo->column_name);
  1563. len = collen > namlen ? collen : namlen;
  1564. for (i=strlen(dest);i<len;i++)
  1565. printf(" ");
  1566. printf(" ");
  1567. }
  1568. printf ("n");
  1569. }
  1570. return SUCCEED;
  1571. }
  1572. static int _get_printable_size(TDSCOLINFO *colinfo)
  1573. {
  1574. switch (colinfo->column_type) {
  1575. case SYBINTN:
  1576. switch(colinfo->column_size) {
  1577. case 1: return 3;
  1578. case 2: return 6;
  1579. case 4: return 11;
  1580. }
  1581. case SYBINT1:
  1582. return 3;
  1583. case SYBINT2:
  1584. return 6;
  1585. case SYBINT4:
  1586.          return 11;
  1587. case SYBVARCHAR:
  1588. case SYBCHAR:
  1589. return colinfo->column_size;
  1590. case SYBFLT8:
  1591. return 11; /* FIX ME -- we do not track precision */
  1592. case SYBREAL:
  1593. return 11; /* FIX ME -- we do not track precision */
  1594. case SYBMONEY:
  1595.          return 12; /* FIX ME */
  1596. case SYBMONEY4:
  1597.          return 12; /* FIX ME */
  1598. case SYBDATETIME:
  1599.          return 26; /* FIX ME */
  1600. case SYBDATETIME4:
  1601.          return 26; /* FIX ME */
  1602. case SYBBIT:
  1603. case SYBBITN:
  1604. return 1;
  1605. /* FIX ME -- not all types present */
  1606. default:
  1607. return 0;
  1608. }
  1609. }
  1610. RETCODE dbsprline(DBPROCESS *dbproc,char *buffer, DBINT buf_len, DBCHAR line_char)
  1611. {
  1612. TDSCOLINFO * colinfo;
  1613. TDSRESULTINFO * resinfo;
  1614. TDSSOCKET * tds;
  1615. int i,col, len, collen, namlen;
  1616. char line_str[2],dest[256];
  1617. int buf_cur=0;
  1618. tds = (TDSSOCKET *) dbproc->tds_socket;
  1619. resinfo = tds->res_info;
  1620. buffer[0]='';
  1621. line_str[0]=line_char;
  1622. line_str[1]='';
  1623. for (col=0;col<resinfo->num_cols;col++)
  1624. {
  1625. dest[0]='';
  1626. colinfo = resinfo->columns[col];
  1627. collen = _get_printable_size(colinfo);
  1628. namlen = strlen(colinfo->column_name);
  1629. len = collen > namlen ? collen : namlen;
  1630. for (i=0;i<len;i++) 
  1631. strcat(dest,line_str);
  1632. if (strlen(dest)<buf_len-buf_cur) {
  1633. strcat(buffer,dest);
  1634. buf_cur += strlen(dest);
  1635. }
  1636. if (strlen(dest)<buf_len-buf_cur) {
  1637. strcat(buffer," ");
  1638. buf_cur++;
  1639. }
  1640. }
  1641. if (strlen(dest)<buf_len-buf_cur) 
  1642. strcat(buffer,"n");
  1643. return SUCCEED;
  1644. }
  1645. RETCODE dbsprhead(DBPROCESS *dbproc,char *buffer, DBINT buf_len)
  1646. {
  1647. TDSCOLINFO * colinfo;
  1648. TDSRESULTINFO * resinfo;
  1649. TDSSOCKET * tds;
  1650. int i,col, len, collen, namlen;
  1651. char dest[256];
  1652. int buf_cur=0;
  1653. tds = (TDSSOCKET *) dbproc->tds_socket;
  1654. resinfo = tds->res_info;
  1655. buffer[0]='';
  1656. for (col=0;col<resinfo->num_cols;col++)
  1657. {
  1658. colinfo = resinfo->columns[col];
  1659. collen = _get_printable_size(colinfo);
  1660. namlen = strlen(colinfo->column_name);
  1661. len = collen > namlen ? collen : namlen;
  1662. strcpy(dest,colinfo->column_name);
  1663. for (i=strlen(colinfo->column_name);i<len;i++)
  1664. strcat(dest," ");
  1665. if (strlen(dest) < buf_len-buf_cur) {
  1666. strcat(buffer,dest);
  1667. buf_cur += strlen(dest);
  1668. }
  1669. if (strlen(dest) < buf_len-buf_cur) {
  1670. strcat(buffer," ");
  1671. buf_cur++;
  1672. }
  1673. }
  1674. if (strlen(dest) < buf_len-buf_cur) 
  1675. strcat(buffer,"n");
  1676. return SUCCEED;
  1677. }
  1678. void dbprhead(DBPROCESS *dbproc)
  1679. {
  1680. TDSCOLINFO * colinfo;
  1681. TDSRESULTINFO * resinfo;
  1682. TDSSOCKET * tds;
  1683. int i,col, len, collen, namlen;
  1684. tds = (TDSSOCKET *) dbproc->tds_socket;
  1685. resinfo = tds->res_info;
  1686. for (col=0;col<resinfo->num_cols;col++)
  1687. {
  1688. colinfo = resinfo->columns[col];
  1689. collen = _get_printable_size(colinfo);
  1690. namlen = strlen(colinfo->column_name);
  1691. len = collen > namlen ? collen : namlen;
  1692. printf("%s",colinfo->column_name);
  1693. for (i=strlen(colinfo->column_name);i<len;i++)
  1694. printf(" ");
  1695. printf(" ");
  1696. }
  1697. printf ("n");
  1698. for (col=0;col<resinfo->num_cols;col++)
  1699. {
  1700. colinfo = resinfo->columns[col];
  1701. collen = _get_printable_size(colinfo);
  1702. namlen = strlen(colinfo->column_name);
  1703. len = collen > namlen ? collen : namlen;
  1704. for (i=0;i<len;i++)
  1705. printf("-");
  1706. printf(" ");
  1707. }
  1708. printf ("n");
  1709. }
  1710. RETCODE
  1711. dbrows(DBPROCESS *dbproc)
  1712. {
  1713. TDSRESULTINFO * resinfo;
  1714. TDSSOCKET * tds;
  1715. tds = (TDSSOCKET *) dbproc->tds_socket;
  1716. resinfo = tds->res_info;
  1717. if (resinfo && resinfo->rows_exist) return SUCCEED;
  1718. else return FAIL;
  1719. }
  1720. /* STUBS */
  1721. RETCODE dbsetdeflang(char *language)
  1722. {
  1723. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetdeflang()n");
  1724. return SUCCEED;
  1725. }
  1726. int dbgetpacket(DBPROCESS *dbproc)
  1727. {
  1728. TDSSOCKET *tds = dbproc->tds_socket;
  1729. if (!tds || !tds->env) {
  1730. return TDS_DEF_BLKSZ;
  1731. } else {
  1732. return tds->env->block_size;
  1733. }
  1734. }
  1735. RETCODE dbsetmaxprocs(int maxprocs)
  1736. {
  1737. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetmaxprocs()n");
  1738. return SUCCEED;
  1739. }
  1740. RETCODE dbsettime(int seconds)
  1741. {
  1742. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsettime()n");
  1743. return SUCCEED;
  1744. }
  1745. RETCODE dbsetlogintime(int seconds)
  1746. {
  1747. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetlogintime()n");
  1748. return SUCCEED;
  1749. }
  1750. DBBOOL dbhasretstat(DBPROCESS *dbproc)
  1751. {
  1752. TDSSOCKET *tds = (TDSSOCKET *) dbproc->tds_socket;
  1753. if (tds->has_status) {
  1754. return TRUE;
  1755. } else {
  1756. return FALSE;
  1757. }
  1758. }
  1759. DBINT dbretstatus(DBPROCESS *dbproc)
  1760. {
  1761. TDSSOCKET *tds = (TDSSOCKET *) dbproc->tds_socket;
  1762. return tds->ret_status;
  1763. }
  1764. RETCODE dbcmdrow(DBPROCESS *dbproc)
  1765. {
  1766.         TDSSOCKET *tds = (TDSSOCKET *) dbproc->tds_socket;
  1767.         if (tds->res_info)
  1768.                 return SUCCEED;
  1769.         return TDS_FAIL;
  1770. }
  1771. int dbaltcolid(DBPROCESS *dbproc, int computeid, int column)
  1772. {
  1773. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbaltcolid()n");
  1774. return -1;
  1775. }
  1776. DBINT 
  1777. dbadlen(DBPROCESS *dbproc,int computeid, int column)
  1778. {
  1779. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbaddlen()n");
  1780. return 0;
  1781. }
  1782. int dbalttype(DBPROCESS *dbproc, int computeid, int column)
  1783. {
  1784. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbalttype()n");
  1785. return 0;
  1786. }
  1787. BYTE *dbadata(DBPROCESS *dbproc, int computeid, int column)
  1788. {
  1789. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbadata()n");
  1790. return (BYTE*)"";
  1791. }
  1792. int dbaltop(DBPROCESS *dbproc, int computeid, int column)
  1793. {
  1794. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbaltop()n");
  1795. return -1;
  1796. }
  1797. RETCODE dbsetopt(DBPROCESS *dbproc, int option, char *char_param, int int_param)
  1798. {
  1799.    switch (option) {
  1800.       case DBBUFFER:
  1801.       {
  1802.          /* XXX should be more robust than just a atoi() */
  1803.          buffer_set_buffering(&(dbproc->row_buf), atoi(char_param));
  1804.          break;
  1805.       }
  1806.       default:
  1807.       {
  1808.          break;
  1809.       }
  1810.    }
  1811.    return SUCCEED;
  1812. }
  1813. void
  1814. dbsetinterrupt(DBPROCESS *dbproc, int (*ckintr)(),int (*hndlintr)())
  1815. {
  1816. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetinterrupt()n");
  1817. }
  1818. int dbnumrets(DBPROCESS *dbproc)
  1819. {
  1820. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbnumrets()n");
  1821. return 0;
  1822. }
  1823. char *dbretname(DBPROCESS *dbproc, int retnum)
  1824. {
  1825. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbretname()n");
  1826. return NULL;
  1827. }
  1828. BYTE *dbretdata(DBPROCESS *dbproc, int retnum)
  1829. {
  1830. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbretdata()n");
  1831. return NULL;
  1832. }
  1833. int dbretlen(DBPROCESS *dbproc, int retnum)
  1834. {
  1835. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbretlen()n");
  1836. return -1;
  1837. }
  1838. RETCODE dbsqlok(DBPROCESS *dbproc)
  1839. {
  1840. unsigned char   marker;
  1841. RETCODE rc = SUCCEED;
  1842. TDSSOCKET *tds;
  1843. tds = (TDSSOCKET *) dbproc->tds_socket;
  1844. if (dbproc->text_sent) {
  1845. tds_flush_packet(tds);
  1846. dbproc->text_sent = 0;
  1847. do {
  1848. marker = tds_get_byte(tds);
  1849. if(tds->s == 0) return FAIL;
  1850. tds_process_default_tokens(tds, marker);
  1851. } while (marker!=TDS_DONE_TOKEN);
  1852. return SUCCEED;
  1853. }
  1854.    /*
  1855.     * See what the next packet from the server is.  If it is an error
  1856.     * then we should return FAIL
  1857.     */
  1858. /* Calling dbsqlexec on an update only stored proc should read all tokens
  1859. while (is_msg_token(tds_peek(tds))) {
  1860. marker = tds_get_byte(tds);
  1861. if (tds_process_default_tokens(tds, marker)!=TDS_SUCCEED) {
  1862. rc=FAIL;
  1863. }
  1864. */
  1865. do {
  1866. marker = tds_peek(tds);
  1867. if (!is_result_token(marker)) {
  1868. marker = tds_get_byte(tds);
  1869. /* tds_process_default_tokens can return TDS_ERROR in which case
  1870. ** we still want to read til end, but TDS_FAIL is an unrecoverable
  1871. ** error */
  1872. if (tds_process_default_tokens(tds, marker)!=TDS_SUCCEED) {
  1873. rc=FAIL;
  1874. }
  1875. }
  1876. #ifdef NCBI_FTDS
  1877. if(tds->s == 0) return FAIL;
  1878. #endif
  1879. } while (!is_hard_end_token(marker) && !is_result_token(marker));
  1880. /* clean up */
  1881. if (rc==FAIL && !is_end_token(marker)) {
  1882. do {
  1883. marker = tds_get_byte(tds);
  1884. if (tds_process_default_tokens(tds, marker)!=TDS_SUCCEED) {
  1885. return FAIL;
  1886. }
  1887. #ifdef NCBI_FTDS
  1888. if(tds->s == 0) return FAIL;
  1889. #endif
  1890. } while (marker!=TDS_DONE_TOKEN);
  1891. }
  1892. return rc;
  1893. }
  1894. int dbnumalts(DBPROCESS *dbproc,int computeid)
  1895. {
  1896. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbnumalts()n");
  1897. return 0;
  1898. }
  1899. BYTE *
  1900. dbbylist(DBPROCESS *dbproc, int computeid, int *size)
  1901. {
  1902. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbbylist()n");
  1903. if (size) *size = 0;
  1904. return NULL;
  1905. }
  1906. DBBOOL dbdead(DBPROCESS *dbproc)
  1907. {
  1908. if(dbproc &&
  1909. dbproc->tds_socket &&
  1910. dbproc->tds_socket->s)
  1911. return FALSE;
  1912. else
  1913. return TRUE;
  1914. }
  1915. EHANDLEFUNC
  1916. dberrhandle(EHANDLEFUNC handler)
  1917. {
  1918.    EHANDLEFUNC retFun = g_dblib_err_handler;
  1919.    g_dblib_err_handler = handler;
  1920.    return retFun;
  1921. }
  1922. MHANDLEFUNC
  1923. dbmsghandle(MHANDLEFUNC handler)
  1924. {
  1925.    MHANDLEFUNC retFun = g_dblib_msg_handler;
  1926.    g_dblib_msg_handler = handler;
  1927.    return retFun;
  1928. }
  1929. RETCODE dbmnyadd(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2, DBMONEY *sum)
  1930. {
  1931.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyadd()n");
  1932. return SUCCEED;
  1933. }
  1934. RETCODE dbmnysub(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2, DBMONEY *diff)
  1935. {
  1936.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnysyb()n");
  1937. return SUCCEED;
  1938. }
  1939. RETCODE dbmnymul(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2, DBMONEY *prod)
  1940. {
  1941.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnymul()n");
  1942. return SUCCEED;
  1943. }
  1944. RETCODE dbmnydivide(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2, DBMONEY *quotient)
  1945. {
  1946.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnydivide()n");
  1947. return SUCCEED;
  1948. }
  1949. RETCODE dbmnycmp(DBPROCESS *dbproc, DBMONEY *m1, DBMONEY *m2)
  1950. {
  1951.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnycmp()n");
  1952. return SUCCEED;
  1953. }
  1954. RETCODE dbmnyscale(DBPROCESS *dbproc, DBMONEY *dest, int multiplier, int addend)
  1955. {
  1956.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyscale()n");
  1957. return SUCCEED;
  1958. }
  1959. RETCODE dbmnyzero(DBPROCESS *dbproc, DBMONEY *dest)
  1960. {
  1961.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyzero()n");
  1962. return SUCCEED;
  1963. }
  1964. RETCODE dbmnymaxpos(DBPROCESS *dbproc, DBMONEY *dest)
  1965. {
  1966.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnymaxpos()n");
  1967. return SUCCEED;
  1968. }
  1969. RETCODE dbmnymaxneg(DBPROCESS *dbproc, DBMONEY *dest)
  1970. {
  1971.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnymaxneg()n");
  1972. return SUCCEED;
  1973. }
  1974. RETCODE dbmnyndigit(DBPROCESS *dbproc, DBMONEY *mnyptr,DBCHAR *value, DBBOOL *zero)
  1975. {
  1976.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyndigit()n");
  1977. return SUCCEED;
  1978. }
  1979. RETCODE dbmnyinit(DBPROCESS *dbproc,DBMONEY *mnyptr, int trim, DBBOOL *negative)
  1980. {
  1981.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyinit()n");
  1982. return SUCCEED;
  1983. }
  1984. RETCODE dbmnydown(DBPROCESS *dbproc,DBMONEY *mnyptr, int divisor, int *remainder)
  1985. {
  1986.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnydown()n");
  1987. return SUCCEED;
  1988. }
  1989. RETCODE dbmnyinc(DBPROCESS *dbproc,DBMONEY *mnyptr)
  1990. {
  1991.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyinc()n");
  1992. return SUCCEED;
  1993. }
  1994. RETCODE dbmnydec(DBPROCESS *dbproc,DBMONEY *mnyptr)
  1995. {
  1996.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnydec()n");
  1997. return SUCCEED;
  1998. }
  1999. RETCODE dbmnyminus(DBPROCESS *dbproc,DBMONEY *src, DBMONEY *dest)
  2000. {
  2001.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnyminus()n");
  2002. return SUCCEED;
  2003. }
  2004. RETCODE dbmny4minus(DBPROCESS *dbproc, DBMONEY4 *src, DBMONEY4 *dest)
  2005. {
  2006.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4minus()n");
  2007. return SUCCEED;
  2008. }
  2009. RETCODE dbmny4zero(DBPROCESS *dbproc, DBMONEY4 *dest)
  2010. {
  2011.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4zero()n");
  2012. return SUCCEED;
  2013. }
  2014. RETCODE dbmny4add(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *sum)
  2015. {
  2016.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4add()n");
  2017. return SUCCEED;
  2018. }
  2019. RETCODE dbmny4sub(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *diff)
  2020. {
  2021.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4sub()n");
  2022. return SUCCEED;
  2023. }
  2024. RETCODE dbmny4mul(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *prod)
  2025. {
  2026.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4mul()n");
  2027. return SUCCEED;
  2028. }
  2029. RETCODE dbmny4divide(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2, DBMONEY4 *quotient)
  2030. {
  2031.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4divide()n");
  2032. return SUCCEED;
  2033. }
  2034. RETCODE dbmny4cmp(DBPROCESS *dbproc, DBMONEY4 *m1, DBMONEY4 *m2)
  2035. {
  2036.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmny4cmp()n");
  2037. return SUCCEED;
  2038. }
  2039. RETCODE dbdatecmp(DBPROCESS *dbproc, DBDATETIME *d1, DBDATETIME *d2)
  2040. {
  2041. if (d1->dtdays == d2->dtdays ) {
  2042. if ( d1->dttime == d2->dttime )
  2043. return 0;
  2044. else
  2045. return d1->dttime > d2->dttime ? 1 : -1 ;
  2046. }
  2047. /* date 1 is before 1900 */
  2048. if (d1->dtdays > 2958463) {
  2049. if (d2->dtdays > 2958463) /* date 2 is before 1900 */
  2050. return d1->dtdays > d2->dtdays ? 1 : -1 ;
  2051. else
  2052. return -1;
  2053. } else {
  2054. /* date 1 is after 1900 */
  2055. if (d2->dtdays < 2958463) /* date 2 is after 1900 */
  2056. return d1->dtdays > d2->dtdays ? 1 : -1 ;
  2057. else
  2058. return 1;
  2059. }
  2060. return SUCCEED;
  2061. }
  2062. RETCODE dbdatecrack(DBPROCESS *dbproc, DBDATEREC *di, DBDATETIME *dt)
  2063. {
  2064. TDSDATEREC dr;
  2065. tds_datecrack(SYBDATETIME, dt, &dr);
  2066. #ifndef MSDBLIB
  2067. di->dateyear    = dr.year;
  2068. di->datemonth   = dr.month;
  2069. di->datedmonth  = dr.day;
  2070. di->datedyear   = dr.dayofyear;
  2071. di->datedweek   = dr.weekday;
  2072. di->datehour    = dr.hour;
  2073. di->dateminute  = dr.minute;
  2074. di->datesecond  = dr.second;
  2075. di->datemsecond = dr.millisecond;
  2076. #else
  2077. di->year        = dr.year;
  2078. di->month       = dr.month + 1;
  2079. di->day         = dr.day;
  2080. di->dayofyear   = dr.dayofyear;
  2081. di->weekday     = dr.weekday + 1;
  2082. di->hour        = dr.hour;
  2083. di->minute      = dr.minute;
  2084. di->second      = dr.second;
  2085. di->millisecond = dr.millisecond;
  2086. #endif
  2087. return SUCCEED;
  2088. }
  2089. void dbrpwclr(LOGINREC *login)
  2090. {
  2091.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbrpwclr()n");
  2092. }
  2093. RETCODE dbrpwset(LOGINREC *login, char *srvname, char *password, int pwlen)
  2094. {
  2095.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbrpwset()n");
  2096. return SUCCEED;
  2097. }
  2098. int dbspid(DBPROCESS *dbproc)
  2099. {
  2100.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbspid()n");
  2101. return 0;
  2102. }
  2103. void
  2104. dbsetuserdata(DBPROCESS *dbproc, BYTE *ptr)
  2105. {
  2106. dbproc->user_data = ptr;
  2107. return;
  2108. }
  2109. BYTE *dbgetuserdata(DBPROCESS *dbproc)
  2110. {
  2111. return dbproc->user_data;
  2112. }
  2113. RETCODE dbsetversion(DBINT version)
  2114. {
  2115. g_dblib_version  = version;
  2116. return SUCCEED;
  2117. }
  2118. RETCODE dbmnycopy(DBPROCESS *dbproc, DBMONEY *src, DBMONEY *dest)
  2119. {
  2120. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmnycopy()n");
  2121. return SUCCEED;
  2122. }
  2123. RETCODE dbcanquery(DBPROCESS *dbproc)
  2124. {
  2125. TDSSOCKET *tds;
  2126. int rc;
  2127. if (dbproc == NULL)
  2128. return FAIL;
  2129. tds = (TDSSOCKET *) dbproc->tds_socket;
  2130. if (!tds || !tds->s) 
  2131. return FAIL;
  2132. /*
  2133.  *  Just throw away all pending rows from the last query
  2134.  */
  2135. do {
  2136. rc = tds_process_row_tokens(dbproc->tds_socket);
  2137. } while (rc == TDS_SUCCEED);
  2138. if (rc == TDS_FAIL)
  2139. return FAIL;
  2140. return SUCCEED;
  2141. }
  2142. void dbfreebuf(DBPROCESS *dbproc)
  2143. {
  2144. if(dbproc->dbbuf) {
  2145. free(dbproc->dbbuf);
  2146. dbproc->dbbuf = NULL;
  2147. }
  2148. dbproc->dbbufsz = 0;
  2149. } /* dbfreebuf()  */
  2150. RETCODE dbclropt(DBPROCESS *dbproc,int option, char *param)
  2151. {
  2152.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbcltopt()n");
  2153. return SUCCEED;
  2154. }
  2155. DBBOOL dbisopt(DBPROCESS *dbproc,int option, char *param)
  2156. {
  2157.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbisopt()n");
  2158. return TRUE;
  2159. }
  2160. DBINT dbcurrow(DBPROCESS *dbproc)
  2161. {
  2162.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbcurrow()n");
  2163. return 0;
  2164. }
  2165. STATUS dbrowtype(DBPROCESS *dbproc)
  2166. {
  2167. tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbrowtype()n");
  2168. return NO_MORE_ROWS;
  2169. }
  2170. int dbcurcmd(DBPROCESS *dbproc)
  2171. {
  2172.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbcurcmd()n");
  2173. return 0;
  2174. }
  2175. RETCODE dbmorecmds(DBPROCESS *dbproc)
  2176. {
  2177.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbmorecmds()n");
  2178. return SUCCEED;
  2179. }
  2180. int dbrettype(DBPROCESS *dbproc,int retnum)
  2181. {
  2182.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbrettype()n");
  2183. return 0;
  2184. }
  2185. int dbstrlen(DBPROCESS *dbproc)
  2186. {
  2187. return dbproc->dbbufsz;
  2188. }
  2189. char *dbgetchar(DBPROCESS *dbproc, int pos)
  2190. {
  2191.      if (dbproc->dbbufsz > 0) {
  2192.        if (pos >= 0 && pos < dbproc->dbbufsz )
  2193.             return (char*)&dbproc->dbbuf[pos];
  2194.        else
  2195.           return (char *)NULL;
  2196.      }
  2197.     else
  2198.         return (char *)NULL;
  2199. }
  2200. RETCODE dbstrcpy(DBPROCESS *dbproc, int start, int numbytes, char *dest)
  2201. {
  2202. dest[0] = 0; /* start with empty string being returned */
  2203. if (dbproc->dbbufsz>0) {
  2204. strncpy(dest, (char*)&dbproc->dbbuf[start], numbytes);
  2205. }
  2206. return SUCCEED;
  2207. }
  2208. RETCODE dbsafestr(DBPROCESS *dbproc,char *src, DBINT srclen, char *dest, DBINT destlen, int quotetype)
  2209. {
  2210. int i, j = 0;
  2211. int squote = FALSE, dquote = FALSE;
  2212. /* check parameters */
  2213. if (srclen<-1 || destlen<-1)
  2214. return FAIL;
  2215. if (srclen==-1) 
  2216. srclen = strlen(src);
  2217. if (quotetype == DBSINGLE || quotetype == DBBOTH)
  2218. squote = TRUE;
  2219. if (quotetype == DBDOUBLE || quotetype == DBBOTH)
  2220. dquote = TRUE;
  2221. /* return FAIL if invalid quotetype */
  2222. if (!dquote && !squote)
  2223. return FAIL;
  2224. for (i=0;i<srclen;i++) {
  2225. /* dbsafestr returns fail if the deststr is not big enough */
  2226. /* need one char + one for terminator */
  2227. if (destlen >= 0 && j>=destlen)
  2228. return FAIL;
  2229. if (squote && src[i]==''')
  2230. dest[j++] = ''';
  2231. else if (dquote && src[i]=='"')
  2232. dest[j++] = '"';
  2233. if (destlen >= 0 && j>=destlen)
  2234. return FAIL;
  2235. dest[j++] = src[i];
  2236. }
  2237. if (destlen >= 0 && j>=destlen)
  2238. return FAIL;
  2239. dest[j]='';
  2240. return SUCCEED;
  2241. }
  2242. char *dbprtype(int token)
  2243. {
  2244.    char  *result = NULL;
  2245. /* 
  2246.  * I added several types, but came up with my own result names
  2247.  * since I don't have an MS platform to compare to. --jkl
  2248.  */
  2249.    switch (token)
  2250.    {
  2251.       case SYBAOPAVG:       result = "avg";              break;
  2252.       case SYBAOPCNT:       result = "count";            break;
  2253.       case SYBAOPMAX:       result = "max";              break;
  2254.       case SYBAOPMIN:       result = "min";              break;
  2255.       case SYBAOPSUM:       result = "sum";              break;
  2256.  
  2257.       case SYBBINARY:       result = "binary";           break;
  2258.       case SYBBIT:          result = "bit";              break;
  2259.       case SYBBITN:         result = "bit-null";         break;
  2260.       case SYBCHAR:         result = "char";             break;
  2261.       case SYBDATETIME4:    result = "smalldatetime";    break;
  2262.       case SYBDATETIME:     result = "datetime";         break;
  2263.       case SYBDATETIMN:     result = "datetime-null";    break;
  2264.       case SYBDECIMAL:      result = "decimal";          break;
  2265.       case SYBFLT8:         result = "float";            break;
  2266.       case SYBFLTN:         result = "float-null";       break;
  2267.       case SYBIMAGE:        result = "image";            break;
  2268.       case SYBINT1:         result = "tinyint";          break;
  2269.       case SYBINT2:         result = "smallint";         break;
  2270.       case SYBINT4:         result = "int";              break;
  2271.       case SYBINT8:         result = "long long";        break;
  2272.       case SYBINTN:         result = "integer-null";     break;
  2273.       case SYBMONEY4:       result = "smallmoney";       break;
  2274.       case SYBMONEY:        result = "money";            break;
  2275.       case SYBMONEYN:       result = "money-null";       break;
  2276.       case SYBNTEXT:      result = "UCS-2 text";       break;
  2277.       case SYBNVARCHAR:     result = "UCS-2 varchar";   break;
  2278.       case SYBNUMERIC:      result = "numeric";          break;
  2279.       case SYBREAL:         result = "real";             break;
  2280.       case SYBTEXT:         result = "text";             break;
  2281.       case SYBUNIQUE:       result = "uniqueidentifier"; break;
  2282.       case SYBVARBINARY:    result = "varbinary";        break;
  2283.       case SYBVARCHAR:      result = "varchar";          break;
  2284.       case SYBVARIANT  :    result = "variant ";      break;
  2285.       case SYBVOID    :    result = "void";         break;
  2286.       case XSYBBINARY  :    result = "xbinary";      break;
  2287.       case XSYBCHAR    :    result = "xchar";      break;
  2288.       case XSYBNCHAR   :    result = "x UCS-2 char"; break;
  2289.       case XSYBNVARCHAR:    result = "x UCS-2 varchar"; break;
  2290.       case XSYBVARBINARY:   result = "xvarbinary";      break;
  2291.       case XSYBVARCHAR :    result = "xvarchar ";      break;
  2292.       default:              result = "";                 break;
  2293.    }
  2294.    return result;
  2295. DBBINARY *dbtxtimestamp(DBPROCESS *dbproc, int column)
  2296. {
  2297. TDSSOCKET *tds;
  2298. TDSRESULTINFO * resinfo;
  2299.    tds = (TDSSOCKET *) dbproc->tds_socket;
  2300.    if (!tds->res_info) return NULL;
  2301.    resinfo = tds->res_info;
  2302.    if (column < 1 || column > resinfo->num_cols) return NULL;
  2303.    /* else */
  2304.    return (DBBINARY *) resinfo->columns[column-1]->column_timestamp;
  2305. }
  2306. DBBINARY *dbtxptr(DBPROCESS *dbproc,int column)
  2307. {
  2308. TDSSOCKET *tds;
  2309. TDSRESULTINFO * resinfo;
  2310.    tds = (TDSSOCKET *) dbproc->tds_socket;
  2311.    if (!tds->res_info) return NULL;
  2312.    resinfo = tds->res_info;
  2313.    if (column < 1 || column > resinfo->num_cols) return NULL;
  2314.    /* else */
  2315.    return (DBBINARY *) &resinfo->columns[column-1]->column_textptr;
  2316. }
  2317. RETCODE
  2318. dbwritetext(DBPROCESS *dbproc, char *objname, DBBINARY *textptr, DBTINYINT textptrlen, DBBINARY *timestamp, DBBOOL log, DBINT size, BYTE *text)
  2319. {
  2320. char query[1024];
  2321. char textptr_string[35]; /* 16 * 2 + 2 (0x) + 1 */
  2322. char timestamp_string[19]; /* 8 * 2 + 2 (0x) + 1 */
  2323. int marker;
  2324. TDSSOCKET *tds = (TDSSOCKET *) dbproc->tds_socket;
  2325.     if (textptrlen > DBTXPLEN) return FAIL;
  2326.     dbconvert(dbproc, SYBBINARY, (TDS_CHAR *)textptr, textptrlen, SYBCHAR, textptr_string, -1);
  2327.     dbconvert(dbproc, SYBBINARY, (TDS_CHAR *)timestamp, 8, SYBCHAR, timestamp_string, -1);
  2328.     
  2329. sprintf(query, "writetext bulk %s 0x%s timestamp = 0x%s",
  2330. objname, textptr_string, timestamp_string); 
  2331. if (tds_submit_query(dbproc->tds_socket, query)!=TDS_SUCCEED) {
  2332. return FAIL;
  2333. }
  2334. #ifdef NCBI_FTDS
  2335.     if (!dbproc->tds_socket->s) return FAIL;
  2336. dbproc->tds_socket->out_flag=0x07;
  2337. tds_put_int(dbproc->tds_socket, size);
  2338. if (!text) {
  2339. dbproc->text_size = size;
  2340. dbproc->text_sent = 0;
  2341. return SUCCEED;
  2342. }
  2343. #endif
  2344. /* read the end token */
  2345. marker = tds_get_byte(dbproc->tds_socket);
  2346.     if (!dbproc->tds_socket->s) return FAIL;
  2347. tds_process_default_tokens(dbproc->tds_socket, marker);
  2348. if (marker != TDS_DONE_TOKEN) {
  2349. return FAIL;
  2350. }
  2351. #ifndef NCBI_FTDS
  2352. dbproc->tds_socket->out_flag=0x07;
  2353. tds_put_int(dbproc->tds_socket, size);
  2354. if (!text) {
  2355. dbproc->text_size = size;
  2356. dbproc->text_sent = 0;
  2357. return SUCCEED;
  2358. }
  2359. #endif
  2360. tds_put_bulk_data(dbproc->tds_socket, text, size);
  2361. tds_flush_packet(dbproc->tds_socket);
  2362. do {
  2363. marker = tds_get_byte(dbproc->tds_socket);
  2364. if(marker == 0 && dbproc->tds_socket->s == 0) return FAIL;
  2365. tds_process_default_tokens(dbproc->tds_socket, marker);
  2366. } while (marker!=TDS_DONE_TOKEN);
  2367. return SUCCEED;
  2368. }
  2369. STATUS dbreadtext(DBPROCESS *dbproc, void *buf, DBINT bufsize)
  2370. {
  2371. TDSSOCKET *tds;
  2372. TDSCOLINFO *curcol;
  2373. int cpbytes, bytes_avail, rc;
  2374. tds = dbproc->tds_socket;
  2375. if (!tds || !tds->res_info || !tds->res_info->columns[0])
  2376. return -1;
  2377. curcol = tds->res_info->columns[0];
  2378. /* if the current position is beyond the end of the text
  2379. ** set pos to 0 and return 0 to denote the end of the 
  2380. ** text */
  2381. if (curcol->column_textpos &&
  2382.    curcol->column_textpos>=curcol->column_textsize) {
  2383. curcol->column_textpos = 0;
  2384. return 0;
  2385. }
  2386. /* if pos is 0 (first time through or last call exhausted the text)
  2387. ** then read another row */ 
  2388. if (curcol->column_textpos==0) {
  2389.          rc = tds_process_row_tokens(dbproc->tds_socket);
  2390.          if (rc != TDS_SUCCEED) {
  2391. return NO_MORE_ROWS;
  2392. }
  2393. }
  2394. /* find the number of bytes to return */
  2395. bytes_avail = curcol->column_textsize - curcol->column_textpos;
  2396. cpbytes = bytes_avail > bufsize ? bufsize : bytes_avail;
  2397. memcpy(buf,&curcol->column_textvalue[curcol->column_textpos],cpbytes);
  2398. curcol->column_textpos += cpbytes;
  2399. return cpbytes;
  2400. }
  2401. RETCODE dbmoretext(DBPROCESS *dbproc, DBINT size, BYTE *text)
  2402. {
  2403. tds_put_bulk_data(dbproc->tds_socket, text, size);
  2404. dbproc->text_sent += size;
  2405. return SUCCEED;
  2406. }
  2407. void dbrecftos(char *filename)
  2408. {
  2409. }
  2410. char *dbversion()
  2411. {
  2412.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbversion()n");
  2413. return NULL;
  2414. }
  2415. RETCODE dbsetdefcharset(char *charset)
  2416. {
  2417.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbsetdefcharset()n");
  2418. return SUCCEED;
  2419. }
  2420. RETCODE dbreginit(
  2421.       DBPROCESS *dbproc,
  2422.       DBCHAR *procedure_name,
  2423.       DBSMALLINT namelen )
  2424. {
  2425.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbreginit()n");
  2426.         return SUCCEED;
  2427. }
  2428. RETCODE dbreglist(DBPROCESS *dbproc)
  2429. {
  2430.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbreglist()n");
  2431.         return SUCCEED;
  2432. }
  2433. RETCODE dbregparam(
  2434.       DBPROCESS    *dbproc,
  2435.       char         *param_name,
  2436.       int          type,
  2437.       DBINT        datalen,
  2438.       BYTE         *data )
  2439. {
  2440.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbregparam()n");
  2441.         return SUCCEED;
  2442. }
  2443. RETCODE dbregexec(
  2444.       DBPROCESS      *dbproc,
  2445.       DBUSMALLINT    options)
  2446. {
  2447.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbregexec()n");
  2448. return SUCCEED;
  2449. }
  2450. char      *dbmonthname(DBPROCESS *dbproc,char *language,int monthnum,DBBOOL shortform)
  2451. {
  2452. char *shortmon[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  2453. char *longmon[] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
  2454. if (shortform)
  2455. return shortmon[monthnum-1];
  2456. else
  2457. return longmon[monthnum-1];
  2458. }
  2459. char      *dbname(DBPROCESS *dbproc)
  2460. {
  2461. return NULL;
  2462. }
  2463. RETCODE dbsqlsend(DBPROCESS *dbproc)
  2464. {
  2465. int   result = FAIL;
  2466. TDSSOCKET *tds;
  2467. dbproc->avail_flag = FALSE;
  2468. tds = (TDSSOCKET *) dbproc->tds_socket;
  2469. if (tds->res_info && tds->res_info->more_results) {
  2470.       /* 
  2471.        * XXX If I read the documentation correctly it gets a
  2472.        * bit more complicated than this.
  2473.        *
  2474.        * You see if the person did a query and retrieved all 
  2475.        * the rows but didn't call dbresults() and if the query 
  2476.        * didn't return multiple results then this routine should
  2477.        * just end the TDS_DONE_TOKEN packet and be done with it.
  2478.        *
  2479.        * Unfortunately the only way we can know that is by peeking 
  2480.        * ahead to the next byte.  Peeking could block and this is supposed
  2481.        * to be a non-blocking call.  
  2482.        *
  2483.        */
  2484.  
  2485.       result = FAIL;
  2486.    }
  2487.    else
  2488.    {
  2489.       dbproc->more_results = TRUE;
  2490.       dbproc->empty_res_hack = 0;
  2491.       if (tds_submit_query(dbproc->tds_socket, (char *)dbproc->dbbuf)!=TDS_SUCCEED) {
  2492. return FAIL;
  2493.       }
  2494.       if (! dbproc->noautofree)
  2495.       {
  2496. dbfreebuf(dbproc);
  2497.       }
  2498.       result = SUCCEED;
  2499.    }
  2500.    return result;
  2501. }
  2502. RETCODE dbaltutype(DBPROCESS *dbproc, int computeid, int column)
  2503. {
  2504.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbaltutype()n");
  2505. return SUCCEED;
  2506. }
  2507. RETCODE dbaltlen(DBPROCESS *dbproc, int computeid, int column)
  2508. {
  2509.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbaltlen()n");
  2510. return SUCCEED;
  2511. }
  2512. RETCODE dbpoll(DBPROCESS *dbproc, long milliseconds, DBPROCESS **ready_dbproc, int *return_reason)
  2513. {
  2514.         tdsdump_log (TDS_DBG_FUNC, "%L UNIMPLEMENTED dbpoll()n");
  2515. return SUCCEED;
  2516. }
  2517. DBINT dblastrow(DBPROCESS *dbproc)
  2518. {
  2519. TDSRESULTINFO * resinfo;
  2520. TDSSOCKET * tds;
  2521. tds = (TDSSOCKET *) dbproc->tds_socket;
  2522. resinfo = tds->res_info;
  2523. return resinfo->row_count;
  2524. #if 0
  2525.   DBINT   result;
  2526.    if (dbproc->row_buf.rows_in_buf == 0)
  2527.    {
  2528.       result = 0;
  2529.    }
  2530.    else
  2531.    {
  2532.       /* rows returned from the row buffer start with 1 instead of 0
  2533.       ** newest is 0 based. */
  2534.       result = dbproc->row_buf.newest + 1;
  2535.    }
  2536.    return result;
  2537. #endif
  2538. }
  2539. DBINT dbfirstrow(DBPROCESS *dbproc)
  2540. {
  2541.    DBINT   result;
  2542.    if (dbproc->row_buf.rows_in_buf == 0)
  2543.    {
  2544.       result = 0;
  2545.    }
  2546.    else
  2547.    {
  2548.       result = dbproc->row_buf.oldest;
  2549.    }
  2550.    return result;
  2551. }
  2552. int dbiordesc(DBPROCESS *dbproc)
  2553. {
  2554.    return dbproc->tds_socket->s;
  2555. }
  2556. int dbiowdesc(DBPROCESS *dbproc)
  2557. {
  2558.    return dbproc->tds_socket->s;
  2559. }
  2560.  
  2561. static void _set_null_value(DBPROCESS *dbproc, BYTE *varaddr, int datatype, int maxlen)
  2562. {
  2563. switch (datatype) {
  2564. case SYBINT4:
  2565. memset(varaddr,'',4);
  2566. break;
  2567. case SYBINT2:
  2568. memset(varaddr,'',2);
  2569. break;
  2570. case SYBINT1:
  2571. memset(varaddr,'',1);
  2572. break;
  2573. case SYBFLT8:
  2574. memset(varaddr,'',8);
  2575. break;
  2576. case SYBREAL:
  2577. memset(varaddr,'',4);
  2578. break;
  2579. case SYBCHAR:
  2580. case SYBVARCHAR:
  2581. varaddr[0]='';
  2582. break;
  2583. }
  2584. }
  2585. DBBOOL dbisavail(DBPROCESS *dbproc)
  2586. {
  2587. return dbproc->avail_flag;
  2588. }
  2589. void dbsetavail(DBPROCESS *dbproc)
  2590. {
  2591. dbproc->avail_flag = TRUE;
  2592. }