📄 dblib.c
字号:
/* * =========================================================================== * PRODUCTION $Log: dblib.c,v $ * PRODUCTION Revision 1000.1 2003/11/17 22:20:19 gouriano * PRODUCTION PRODUCTION: UPGRADED [ORIGINAL] Dev-tree R1.7 * PRODUCTION * =========================================================================== *//* FreeTDS - Library of routines accessing Sybase and Microsoft databases * Copyright (C) 1998-1999 Brian Bruns * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <tds_config.h>#include "tdsutil.h"#include "tds.h"#include "sybfront.h"#include "sybdb.h"#include "dblib.h"#include "tdsconvert.h"#include <unistd.h>#include <stdlib.h>#include <assert.h>#include <time.h>#include <stdarg.h>static char software_version[] = "$Id: dblib.c,v 1000.1 2003/11/17 22:20:19 gouriano Exp $";static void *no_unused_var_warn[] = {software_version, no_unused_var_warn};#if !HAVE_VASPRINTFint vasprintf(char **ret, const char *fmt, va_list ap);#endifstatic int _db_get_server_type(int bindtype);static int _get_printable_size(TDSCOLINFO *colinfo);static void _set_null_value(DBPROCESS *dbproc, BYTE *varaddr, int datatype, int maxlen);/* info/err message handler functions (or rather pointers to them) */int (*g_dblib_msg_handler)() = NULL;int (*g_dblib_err_handler)() = NULL;typedef struct dblib_context { TDSCONTEXT *tds_ctx; TDSSOCKET *connection_list[TDS_MAX_CONN];} DBLIBCONTEXT;static DBLIBCONTEXT *g_dblib_ctx = NULL;#ifdef TDS42int g_dblib_version = DBVERSION_42;#endif#ifdef TDS50int g_dblib_version = DBVERSION_100;#endif#ifdef TDS46int g_dblib_version = DBVERSION_46;#endif/* I'm taking some liberties here, there is no such thing as DBVERSION_70 in ** the real world, so we make it up as we go along */#ifdef TDS70int g_dblib_version = DBVERSION_70;#endif#ifdef TDS80int g_dblib_version = DBVERSION_80;#endifstatic int dblib_add_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds){int i = 0; while (i<TDS_MAX_CONN && ctx->connection_list[i]) i++; if (i==TDS_MAX_CONN) { fprintf(stderr,"Max connections reached, increase value of TDS_MAX_CONN\n"); return 1; } else { ctx->connection_list[i] = tds; return 0; }}static void dblib_del_connection(DBLIBCONTEXT *ctx, TDSSOCKET *tds){int i=0; while (i<TDS_MAX_CONN && ctx->connection_list[i]!=tds) i++; if (i==TDS_MAX_CONN) { /* connection wasn't on the free list...now what */ } else { /* remove it */ ctx->connection_list[i] = NULL; }}static void buffer_init(DBPROC_ROWBUF *buf){ memset(buf, 0x0, sizeof(*buf));#ifndef NCBI_FTDS buf->buffering_on = 0; buf->first_in_buf = 0;#endif buf->newest = -1;#ifndef NCBI_FTDS buf->oldest = 0; buf->elcount = 0; buf->element_size = 0; buf->rows_in_buf = 0; buf->rows = NULL;#endif buf->next_row = 1;} /* buffer_init() */static void buffer_clear(DBPROC_ROWBUF *buf){ buf->next_row = 1; buf->first_in_buf = 0; buf->newest = -1;#ifdef NCBI_FTDS buf->rows_offset = 0;#endif buf->oldest = 0; buf->rows_in_buf = 0; if (buf->rows) { free(buf->rows); } buf->rows = NULL;} /* buffer_clear() */static void buffer_free(DBPROC_ROWBUF *buf){ if (buf->rows != NULL) { free(buf->rows); } buf->rows = NULL;} /* clear_buffer() */static void buffer_delete_rows( DBPROC_ROWBUF *buf, /* (U) buffer to clear */ int count) /* (I) number of elements to purge */{ assert(count <= buf->elcount); /* possibly a little to pedantic */ if (count > buf->rows_in_buf) { count = buf->rows_in_buf; } buf->oldest = (buf->oldest + count) % buf->elcount; buf->rows_in_buf -= count; buf->first_in_buf = count==buf->rows_in_buf ? buf->next_row-1 : buf->first_in_buf + count; assert(buf->first_in_buf >= 0);} /* buffer_delete_rows() */static int buffer_start_resultset( DBPROC_ROWBUF *buf, /* (U) buffer to clear */ int element_size) /* */{ int space_needed = -1; assert(element_size > 0); if (buf->rows != NULL) {#ifndef NCBI_FTDS memset(buf->rows, 0xad, buf->element_size*buf->rows_in_buf);#endif free(buf->rows); } buf->first_in_buf = 0; buf->next_row = 1; buf->newest = -1;#ifdef NCBI_FTDS buf->rows_offset = 0;#endif buf->oldest = 0; buf->elcount = buf->buffering_on ? buf->elcount : 1; buf->element_size = element_size; buf->rows_in_buf = 0; space_needed = element_size * buf->elcount; buf->rows = malloc(space_needed); return buf->rows==NULL ? FAIL : SUCCEED;} /* buffer_start_resultset() */static void buffer_delete_all_rows( DBPROC_ROWBUF *buf) /* (U) buffer to clear */{ buffer_delete_rows(buf, buf->rows_in_buf);} /* delete_all_buffer_rows() */static int buffer_index_of_resultset_row( DBPROC_ROWBUF *buf, /* (U) buffer to clear */ int row_number) /* (I) */{ int result = -1; if (row_number < buf->first_in_buf) { result = -1; } else if (row_number > ((buf->rows_in_buf + buf->first_in_buf) -1)) { result = -1; } else { result = ((row_number - buf->first_in_buf) + buf->oldest) % buf->elcount; } return result;} /* buffer_index_of_resultset_row() */static void *buffer_row_address( DBPROC_ROWBUF *buf, /* (U) buffer to clear */ int index) /* (I) raw index of row to return */{ void *result = NULL; assert(index >= 0); assert(index < buf->elcount); if (index>=buf->elcount || index<0) { result = NULL; } else { int offset = buf->element_size * (index % buf->elcount); result = (char *)buf->rows + offset; } return result;} /* buffer_row_address() */static void buffer_add_row( DBPROC_ROWBUF *buf, /* (U) buffer to add row into */ void *row, /* (I) pointer to the row data */ int row_size){ void *dest = NULL; assert(row_size > 0); assert(row_size == buf->element_size); assert(buf->elcount >= 1);#ifdef NCBI_FTDS if(++buf->newest >= buf->elcount){ buf->newest=0; } if(buf->newest==0){ buf->rows_offset=0; } else { buf->rows_offset += buf->element_size; } /***buf->newest = (buf->newest+1)%buf->elcount;**/ if (buf->rows_in_buf==0 && buf->first_in_buf==0) { buf->first_in_buf = 1; } buf->rows_in_buf++; /* * if we have wrapped around we need to adjust oldest * and rows_in_buf */ if (buf->rows_in_buf > buf->elcount) { buf->oldest = (buf->oldest + 1) % buf->elcount; buf->first_in_buf++; buf->rows_in_buf--; } assert(buf->elcount >= buf->rows_in_buf); assert( buf->rows_in_buf==0 || (((buf->oldest+buf->rows_in_buf) - 1)%buf->elcount)==buf->newest); assert(buf->rows_in_buf>0 || (buf->first_in_buf==buf->next_row-1)); assert(buf->rows_in_buf==0 || (buf->first_in_buf<=buf->next_row)); assert(buf->next_row-1 <= (buf->first_in_buf + buf->rows_in_buf));/* dest = buffer_row_address(buf, buf->newest); memcpy(dest, row, row_size);*/ memcpy((char*)buf->rows + buf->rows_offset,row,row_size);#else buf->newest = (buf->newest + 1) % buf->elcount; if (buf->rows_in_buf==0 && buf->first_in_buf==0) { buf->first_in_buf = 1; } buf->rows_in_buf++; /* * if we have wrapped around we need to adjust oldest * and rows_in_buf */ if (buf->rows_in_buf > buf->elcount) { buf->oldest = (buf->oldest + 1) % buf->elcount; buf->first_in_buf++; buf->rows_in_buf--; } assert(buf->elcount >= buf->rows_in_buf); assert( buf->rows_in_buf==0 || (((buf->oldest+buf->rows_in_buf) - 1)%buf->elcount)==buf->newest); assert(buf->rows_in_buf>0 || (buf->first_in_buf==buf->next_row-1)); assert(buf->rows_in_buf==0 || (buf->first_in_buf<=buf->next_row)); assert(buf->next_row-1 <= (buf->first_in_buf + buf->rows_in_buf)); dest = buffer_row_address(buf, buf->newest); memcpy(dest, row, row_size);#endif} /* buffer_add_row() */static int buffer_is_full(DBPROC_ROWBUF *buf){ return buf->rows_in_buf==buf->elcount;} /* buffer_is_full() */static void buffer_set_buffering( DBPROC_ROWBUF *buf, /* (U) */ int buf_size) /* (I) number of rows to buffer, 0 to turn off */{ /* XXX If the user calls this routine in the middle of * a result set and changes the size of the buffering * they are pretty much toast. * * We need to figure out what to do if the user shrinks the * size of the row buffer. What rows should be thrown out, * what should happen to the current row, etc? */ assert(buf_size >= 0); if (buf_size < 0) { /* XXX is it okay to ignore this? */ } else if (buf_size == 0) { buf->buffering_on = 0; buf->elcount = 1; buffer_delete_all_rows(buf); } else { buf->buffering_on = 1; buffer_clear(buf); buffer_free(buf); buf->elcount = buf_size; if (buf->element_size > 0) { buf->rows = malloc(buf->element_size * buf->elcount); } else { buf->rows = NULL; } }} /* buffer_set_buffering() */static void buffer_transfer_bound_data( DBPROC_ROWBUF *buf, /* (U) */ DBPROCESS *dbproc, /* (I) */ int row_num) /* (I) resultset row number */{int i;TDSCOLINFO *curcol;TDSRESULTINFO *resinfo;TDSSOCKET *tds;int srctype;BYTE *src;int desttype;int destlen;/* this should probably go somewhere else */ tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; for (i=0;i<resinfo->num_cols;i++) { curcol = resinfo->columns[i]; if (curcol->column_nullbind) { if (tds_get_null(resinfo->current_row,i)) { *((DBINT *)curcol->column_nullbind)=-1; } else { *((DBINT *)curcol->column_nullbind)=0; } } if (curcol->varaddr) { DBINT srclen = -1; int index = buffer_index_of_resultset_row(buf, row_num); assert (index >= 0); /* XXX now what? */ if (is_blob_type(curcol->column_type)) { srclen = curcol->column_textsize; src = (BYTE *)curcol->column_textvalue; } else { src = ((BYTE *)buffer_row_address(buf, index)) + curcol->column_offset; } desttype = _db_get_server_type(curcol->column_bindtype); srctype = tds_get_conversion_type(curcol->column_type, curcol->column_size); if (tds_get_null(resinfo->current_row,i)) { _set_null_value(dbproc, curcol->varaddr, desttype, curcol->column_bindlen); } else { if (curcol->column_bindtype == STRINGBIND) destlen = -2; else if (curcol->column_bindtype == NTBSTRINGBIND) destlen = -1; else destlen = curcol->column_bindlen; dbconvert(dbproc, srctype, /* srctype */ src, /* src */ srclen, /* srclen */ desttype, /* desttype */ (BYTE *)curcol->varaddr, /* dest */ destlen); /* destlen */ } /* else not null */ } }} /* buffer_transfer_bound_data() */RETCODE dbinit(){ /* DBLIBCONTEXT stores a list of current connections so they may be closed ** with dbexit() */ g_dblib_ctx = (DBLIBCONTEXT *) malloc(sizeof(DBLIBCONTEXT)); memset(g_dblib_ctx,'\0',sizeof(DBLIBCONTEXT)); g_dblib_ctx->tds_ctx = tds_alloc_context(); tds_ctx_set_parent(g_dblib_ctx->tds_ctx, g_dblib_ctx); /* set the functions in the TDS layer to point to the correct info/err * message handler functions */ g_dblib_ctx->tds_ctx->msg_handler = dblib_handle_info_message; g_dblib_ctx->tds_ctx->err_handler = dblib_handle_err_message; if( g_dblib_ctx->tds_ctx->locale && !g_dblib_ctx->tds_ctx->locale->date_fmt ) { /* set default in case there's no locale file */ g_dblib_ctx->tds_ctx->locale->date_fmt = strdup("%b %e %Y %l:%M:%S:%z%p"); } return SUCCEED;}LOGINREC *dblogin(){LOGINREC * loginrec; loginrec = (LOGINREC *) malloc(sizeof(LOGINREC)); loginrec->tds_login = (void *) tds_alloc_login(); /* set default values for loginrec */ tds_set_library(loginrec->tds_login,"DB-Library"); /* tds_set_charset(loginrec->tds_login,"iso_1"); */ /* tds_set_packet(loginrec->tds_login,TDS_DEF_BLKSZ); */ return loginrec;}void dbloginfree(LOGINREC *login){ if (login) { tds_free_login(login->tds_login); free(login); }}RETCODE dbsetlname(LOGINREC *login, char *value, int which){ switch (which) { case DBSETHOST: tds_set_host(login->tds_login, value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -