📄 dblib.c
字号:
break; case BITBIND: return SYBBIT; break; case NUMERICBIND: return SYBNUMERIC; break; case DECIMALBIND: return SYBDECIMAL; break; default: return -1; break; }}/** * Conversion functions are handled in the TDS layer. * * The main reason for this is that ctlib and ODBC (and presumably DBI) need * to be able to do conversions between datatypes. This is possible because * the format of complex data (dates, money, numeric, decimal) is defined by * its representation on the wire; thus what we call DBMONEY is exactly its * format on the wire. CLIs that need a different representation (ODBC?) * need to convert from this format anyway, so the code would already be in * place. * * Each datatype is also defined by its Server-type so all CLIs should be * able to map native types to server types as well. * * tds_convert copies from src to dest and returns the output data length, * period. All padding and termination is the responsibility of the API library * and is done post-conversion. The peculiar rule in dbconvert() is that * a destlen of -1 and a desttype of SYBCHAR means the output buffer * should be null-terminated. */DBINT dbconvert(DBPROCESS *dbproc, int srctype, BYTE *src, DBINT srclen, int desttype, BYTE *dest, DBINT destlen){TDSSOCKET *tds = NULL;CONV_RESULT dres;DBINT ret;int i;int len;DBNUMERIC *num; tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() srctype = %d desttype = %d\n",srctype, desttype); if (dbproc) { tds = (TDSSOCKET *) dbproc->tds_socket; } if (src == NULL || srclen == 0) { /* FIX set appropriate NULL value for destination type */ memset(dest,'\0', destlen); return 0; } /* srclen of -1 means the source data is definitely NULL terminated */ if (srclen == -1) srclen = strlen((char *)src); if (dest == NULL) { /* FIX call error handler */ return -1; } /* oft times we are asked to convert a data type to itself */ if (srctype == desttype) { tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() srctype == desttype\n"); switch (desttype) { case SYBBINARY: case SYBIMAGE: if (srclen > destlen && destlen >= 0) { ret = -1; } else { memcpy(dest, src, srclen); if (srclen < destlen) memset(dest+srclen,0,destlen-srclen); ret = srclen; } break; case SYBCHAR: case SYBVARCHAR: case SYBTEXT: /* srclen of -1 means the source data is definitely NULL terminated */ if (srclen == -1) srclen = strlen((char *)src); if (destlen == 0 || destlen < -2) { ret = FAIL; } else if (destlen == -1) { /* rtrim and null terminate */ for (i = srclen-1; i>=0 && src[i] == ' '; --i) { srclen = i; } memcpy(dest,src,srclen); dest[srclen] = '\0'; ret = srclen; } else if (destlen == -2) { /* just null terminate */ memcpy(dest,src,srclen); dest[srclen] = '\0'; ret = srclen; } else { /* destlen is > 0 */ if (srclen > destlen) { /* fprintf(stderr,"%s: Line%d: Data-conversion resulted in overflow.\n", __FILE__, __LINE__); fprintf(stderr,"\tsrclen (%d)> destlen (%d).\n", srclen, destlen); */ ret = -1; } else { memcpy(dest, src, srclen); for (i = srclen; i < destlen; i++ ) dest[i] = ' '; ret = srclen; } } break; case SYBINT1: case SYBINT2: case SYBINT4: case SYBINT8: case SYBFLT8: case SYBREAL: case SYBBIT: case SYBBITN: case SYBMONEY: case SYBMONEY4: case SYBDATETIME: case SYBDATETIME4: case SYBUNIQUE: ret = get_size_by_type(desttype); memcpy(dest, src, ret); break; case SYBNUMERIC: case SYBDECIMAL: memcpy(dest, src, sizeof(DBNUMERIC)); ret = sizeof(DBNUMERIC); break; } return ret; } /* srctype == desttype */ /* FIXME what happen if client do not reset values ??? */ /* FIXME act differently for ms and sybase */ if (is_numeric_type(desttype)) { num = (DBNUMERIC *)dest; if ( num->precision == 0 ) dres.n.precision = 18; else dres.n.precision = num->precision; if ( num->scale == 0 ) dres.n.scale = 0; else dres.n.scale = num->scale; } tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() calling tds_convert\n"); len = tds_convert (g_dblib_ctx->tds_ctx, srctype, (TDS_CHAR *)src, srclen, desttype, &dres); if( len == TDS_FAIL ) return 0; switch (desttype) { case SYBBINARY: case SYBIMAGE: if (len > destlen && destlen >= 0) { fprintf(stderr,"%s: Line %d: Data-conversion resulted in overflow.\n", __FILE__, __LINE__); fprintf(stderr,"\tlen (%d) > destlen (%d).\n", len, destlen); ret = -1; } else { memcpy(dest, dres.ib, len); free(dres.ib); if (len < destlen) memset(dest+len,0,destlen-len); ret = len; } break; case SYBINT1: memcpy(dest,&(dres.ti),1); ret = 1; break; case SYBINT2: memcpy(dest,&(dres.si),2); ret = 2; break; case SYBINT4: memcpy(dest,&(dres.i),4); ret = 4; break; case SYBFLT8: memcpy(dest,&(dres.f),8); ret = 8; break; case SYBREAL: memcpy(dest,&(dres.r),4); ret = 4; break; case SYBBIT: case SYBBITN: memcpy(dest,&(dres.ti),1); ret = 1; break; case SYBMONEY: memcpy(dest,&(dres.m),sizeof(TDS_MONEY)); ret = sizeof(TDS_MONEY); break; case SYBMONEY4: memcpy(dest,&(dres.m4),sizeof(TDS_MONEY4)); ret = sizeof(TDS_MONEY4); break; case SYBDATETIME: memcpy(dest,&(dres.dt),sizeof(TDS_DATETIME)); ret = sizeof(TDS_DATETIME); break; case SYBDATETIME4: memcpy(dest,&(dres.dt4),sizeof(TDS_DATETIME4)); ret = sizeof(TDS_DATETIME4); break; case SYBNUMERIC: case SYBDECIMAL: memcpy(dest,&(dres.n), sizeof(TDS_NUMERIC)); ret = sizeof(TDS_NUMERIC); break; case SYBCHAR: case SYBVARCHAR: case SYBTEXT: tdsdump_log(TDS_DBG_INFO1, "%L inside dbconvert() outputting %d bytes character data destlen = %d \n", len, destlen); if (destlen == 0 || destlen < -2) { ret = FAIL; } else if (destlen == -1) { /* rtrim and null terminate */ for (i = len-1; i>=0 && dres.c[i] == ' '; --i) { len = i; } memcpy(dest, dres.c, len); dest[len] = '\0'; ret = len; } else if (destlen == -2) { /* just null terminate */ memcpy(dest,dres.c,len); dest[len] = 0; ret = len; } else { /* destlen is > 0 */ if (len > destlen) { /*fprintf(stderr,"%s: Line%d: Data-conversion resulted in overflow.\n", __FILE__, __LINE__); fprintf(stderr,"\tlen (%d)> destlen (%d).\n", len, destlen);*/ ret = -1; } else memcpy(dest, dres.c, len); for (i = len; i < destlen; i++ ) dest[i] = ' '; ret = len; } free(dres.c); break; } return(ret);}DBINT dbconvert_ps(DBPROCESS *dbproc, int srctype, BYTE *src, DBINT srclen, int desttype, BYTE *dest, DBINT destlen, DBTYPEINFO *typeinfo){DBNUMERIC *s;DBNUMERIC *d; if (is_numeric_type(desttype)) { if (typeinfo == (DBTYPEINFO *) NULL ) { if (is_numeric_type(srctype)) { s = (DBNUMERIC *)src; d = (DBNUMERIC *)dest; d->precision = s->precision; d->scale = s->scale; } else { d = (DBNUMERIC *)dest; d->precision = 18; d->scale = 0; } } else { d = (DBNUMERIC *)dest; d->precision = typeinfo->precision; d->scale = typeinfo->scale; } } return dbconvert(dbproc, srctype, src, srclen, desttype, dest, destlen);}RETCODE dbbind( DBPROCESS *dbproc, int column, int vartype, DBINT varlen, BYTE *varaddr){ TDSCOLINFO *colinfo = NULL; TDSRESULTINFO *resinfo = NULL; TDSSOCKET *tds = NULL; int srctype = -1; int desttype = -1; int okay = TRUE; /* so far, so good */ tdsdump_log(TDS_DBG_INFO1, "%L dbbind() column = %d %d %d\n",column, vartype, varlen); dbproc->avail_flag = FALSE; /* * Note on logic- I'm using a boolean variable 'okay' to tell me if * everything that has happened so far has gone okay. Basically if * something happened that wasn't okay we don't want to keep doing * things, but I also don't want to have a half dozen exit points from * this function. So basically I've wrapped each set of operation in a * "if (okay)" statement. Once okay becomes false we skip everything * else. */ okay = (dbproc!=NULL && dbproc->tds_socket!=NULL && varaddr!=NULL); if (okay) { tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; } okay = okay && ((column >= 1) && (column <= resinfo->num_cols)); if (okay) { colinfo = resinfo->columns[column-1]; srctype = tds_get_conversion_type(colinfo->column_type, colinfo->column_size); desttype = _db_get_server_type(vartype); tdsdump_log(TDS_DBG_INFO1, "%L dbbind() srctype = %d desttype = %d \n",srctype, desttype); okay = okay && dbwillconvert(srctype, _db_get_server_type(vartype)); } if (okay) { colinfo->varaddr = (char *)varaddr; colinfo->column_bindtype = vartype; colinfo->column_bindlen = varlen; } return okay ? SUCCEED : FAIL;} /* dbbind() */void dbsetifile(char *filename){ set_interfaces_file_loc(filename);}RETCODE dbnullbind(DBPROCESS *dbproc, int column, DBINT *indicator){TDSCOLINFO * colinfo;TDSRESULTINFO * resinfo;TDSSOCKET * tds; /* * XXX Need to check for possibly problems before assuming * everything is okay */ tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; colinfo = resinfo->columns[column-1]; colinfo->column_nullbind = (TDS_CHAR *) indicator; return SUCCEED;}DBINT dbcount(DBPROCESS *dbproc){TDSRESULTINFO * resinfo;TDSSOCKET * tds; tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; if (resinfo) return resinfo->row_count; else return tds->rows_affected;}void dbclrbuf(DBPROCESS *dbproc, DBINT n){ if (n <= 0) return; if (dbproc->row_buf.buffering_on) { if (n >= dbproc->row_buf.rows_in_buf) { buffer_delete_rows(&(dbproc->row_buf), dbproc->row_buf.rows_in_buf - 1); } else { buffer_delete_rows(&(dbproc->row_buf), n); } }}DBBOOL dbwillconvert(int srctype, int desttype){ return tds_willconvert (srctype, desttype);}int dbcoltype(DBPROCESS *dbproc,int column){TDSCOLINFO * colinfo;TDSRESULTINFO * resinfo;TDSSOCKET * tds; tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; colinfo = resinfo->columns[column-1]; switch (colinfo->column_type) { case SYBVARCHAR: return SYBCHAR; case SYBVARBINARY: return SYBBINARY; case SYBDATETIMN: if (colinfo->column_size==8) return SYBDATETIME; else if (colinfo->column_size==4) return SYBDATETIME4; case SYBMONEYN: /* needs to be based on column size (mlilback, 11/7/01) */ if (colinfo->column_size==4) return SYBMONEY4; else return SYBMONEY; case SYBFLTN: if (colinfo->column_size==8) return SYBFLT8; else if (colinfo->column_size==4) return SYBREAL; case SYBINTN: if (colinfo->column_size==4) return SYBINT4; else if (colinfo->column_size==2) return SYBINT2; else if (colinfo->column_size==1) return SYBINT1; else if (colinfo->column_size==8) return SYBINT8; default: return colinfo->column_type; }#ifndef NCBI_FTDS return 0; /* something went wrong */#endif}int dbcolutype(DBPROCESS *dbproc,int column){TDSCOLINFO * colinfo;TDSRESULTINFO * resinfo;TDSSOCKET * tds; tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; colinfo = resinfo->columns[column-1]; return colinfo->column_usertype;}DBTYPEINFO *dbcoltypeinfo(DBPROCESS *dbproc, int column){/* moved typeinfo from static into dbproc structure to make thread safe. (mlilback 11/7/01) */TDSCOLINFO * colinfo;TDSRESULTINFO * resinfo;TDSSOCKET * tds; tds = (TDSSOCKET *) dbproc->tds_socket; resinfo = tds->res_info; colinfo = resinfo->columns[column-1]; dbproc->typeinfo.precision = colinfo->column_prec; dbproc->typeinfo.scale = colinfo->column_scale; return &dbproc->typeinfo;}char *dbcolsource(DBPROCESS *dbproc,int colnum){TDSCOLINFO * colinfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -