Skip to Content.
Sympa Menu

freetds - [freetds] Comment on change

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: ZIGLIO Frediano <Frediano.Ziglio AT vodafoneomnitel.it>
  • To: "Freetds (E-mail)" <freetds AT lists.ibiblio.org>
  • Subject: [freetds] Comment on change
  • Date: Wed, 5 Mar 2003 15:56:26 +0100

As steted yesterday some comment about Bill patch (follow a commented diff)

@ diff -u -u -1 -0 -b -r1.119 -r1.121
@ --- src/dblib/dblib.c 13 Feb 2003 21:25:11 -0000 1.119
@ +++ src/dblib/dblib.c 5 Mar 2003 09:46:31 -0000 1.121
@ @@ -1934,20 +1931,35 @@
@ if (is_blob_type(colinfo->column_type)) {
@ return (BYTE*) ((TDSBLOBINFO *) (resinfo->current_row +
colinfo->column_offset))->textvalue;
@ }
@
@ return (BYTE*) &resinfo->current_row[colinfo->column_offset];
@ }
@
@ RETCODE
@ dbcancel(DBPROCESS * dbproc)
@ {
@ +int marker;
@ +TDSSOCKET *tds;
@ +
@ + tds = (TDSSOCKET *) dbproc->tds_socket;
@ +
@ + while (tds->state != TDS_COMPLETED ) {
@ +
@ + marker = tds_get_byte(tds);
@ +
@ + tdsdump_log(TDS_DBG_INFO1, "%L dbcancel() discarding
results. marker is %x\n", marker);
@ +
@ + if (tds_process_default_tokens(tds, marker) == TDS_FAIL)
@ + return TDS_FAIL;
@ + }
@ +
@ tds_send_cancel(dbproc->tds_socket);
@ tds_process_cancel(dbproc->tds_socket);
@ return SUCCEED;
@ }
@

?? skipping data instead to send a proper cancel is quite bad... if server
is returning huge amount of data cancel take ages.... IMHO libtds (token.c)
should be encharge for processing cancel, not dblib.


@ @@ -3996,43 +4010,72 @@
@ }
@
@ RETCODE
@ dbsqlsend(DBPROCESS * dbproc)
@ {
@ int result = FAIL;
@ TDSSOCKET *tds;
@ char *cmdstr;
@ int rc;
@ TDS_INT result_type;
@ +unsigned char marker;
@ +int done_flags;
@ +int pending_error = 0;
@
@ dbproc->avail_flag = FALSE;
@ dbproc->envchange_rcv = 0;
@ dbproc->dbresults_state = DBRESINIT;
@
@ tdsdump_log(TDS_DBG_FUNC, "%L in dbsqlsend()\n");
@ tds = (TDSSOCKET *) dbproc->tds_socket;
@ - if (tds->res_info && tds->res_info->more_results) {
@ - /*
@ - * XXX If I read the documentation correctly it gets a
@ - * bit more complicated than this.
@ - *
@ - * You see if the person did a query and retrieved all
@ - * the rows but didn't call dbresults() and if the query
@ - * didn't return multiple results then this routine should
@ - * just end the TDS_DONE_TOKEN packet and be done with it.
@ - *
@ - * Unfortunately the only way we can know that is by peeking

@ - * ahead to the next byte. Peeking could block and this is
supposed
@ - * to be a non-blocking call.
@ - *
@ - */
@
@ + if (tds->state == TDS_PENDING) {
@ + _dblib_client_msg(dbproc, 20019, 7, "Attempt to initiate a
new SQL Server operation with results pending.");
@ + return FAIL;
@ + }
@ +
@ + if (tds->state == TDS_LASTROW) {
@ +
@ + while(tds->state != TDS_COMPLETED && !pending_error) {
@ +
@ + marker = tds_get_byte(tds);
@ +
@ + tdsdump_log(TDS_DBG_INFO1, "%L dbsqlsend state =
lastrow marker is %x\n", marker);
@ + switch (marker) {
@ + case TDS_DONE_TOKEN:
@ + case TDS_DONEPROC_TOKEN:
@ + case TDS_DONEINPROC_TOKEN:
@ + tds_process_end(tds, marker,
&done_flags);
@ + break;
@ + case TDS_RETURNSTATUS_TOKEN:
@ + tds->has_status = 1;
@ + tds->ret_status = tds_get_int(tds);
@ + break;
@ + case TDS_PARAM_TOKEN:
@ + tds_unget_byte(tds);
@ +
tds_process_param_result_tokens(tds);
@ + break;
@ + case TDS5_PARAMFMT_TOKEN:
@ + tds_process_dyn_result(tds);
@ + break;
@ + case TDS5_PARAMS_TOKEN:
@ +
tds_process_params_result_token(tds);
@ + break;
@ + default:
@ + _dblib_client_msg(dbproc, 20019, 7,
"Attempt to initiate a new SQL Server operation with results pending.");
@ + pending_error = 1;
@ +
@ + }
@ + }
@ + }
@ +
@ + if (pending_error) {
@ dbproc->command_state = DBCMDSENT;
@ result = FAIL;
@ } else {

I don't understand the state TDS_LASTROW... Why old code didn't work?

@ diff -u -u -1 -0 -b -r1.110 -r1.114
@ --- src/tds/convert.c 26 Jan 2003 10:27:36 -0000 1.110
@ +++ src/tds/convert.c 5 Mar 2003 13:14:31 -0000 1.114
@ @@ -1928,25 +1945,29 @@
@
@ case STRING_GARBLED:
@
@ tdsdump_log(TDS_DBG_INFO1,"error_handler: Attempt to
convert data stopped by syntax error in source field \n");
@ return TDS_CONVERT_SYNTAX;
@ }
@
@ tok = strtok_r((char *)NULL, " ,", &lasts);
@ }
@
@ + if (t->tm_year == 0 && t->tm_mon == 0 && t->tm_mday == 0) {
@ + dt_days = 0;
@ + } else {
@ i = (t->tm_mon - 13) / 12;
@ dt_days = 1461 * ( t->tm_year + 300 + i ) / 4 +
@ (367 * ( t->tm_mon - 1 - 12*i ) ) / 12 -
@ (3 * ( ( t->tm_year + 400 + i ) / 100 ) ) / 4 +
@ t->tm_mday - 109544;
@ + }
@

year == month == day == 0 ???
This seem a NULL value. tds_convert should not handle null values (library
dependent).

@ diff -u -u -1 -0 -b -r1.69 -r1.72
@ --- src/tds/query.c 26 Jan 2003 10:27:36 -0000 1.69
@ +++ src/tds/query.c 5 Mar 2003 13:14:32 -0000 1.72
@ @@ -417,24 +426,107 @@
@ * @return TDS_FAIL on error or TDS_SUCCEED
@ */
@ static int
@ tds_put_data(TDSSOCKET * tds, TDSCOLINFO * curcol, unsigned char
*current_row, int i)
@ {
@ unsigned char *src;
@ TDS_NUMERIC *num;
@ TDSBLOBINFO *blob_info;
@ int colsize;
@ int is_null;
@ + const unsigned char CHARBIN_NULL[] = { 0xff, 0xff };
@ + const unsigned char GEN_NULL = 0x00;
@ +
@ +/* I don't think this is working as tds_set_null is not being called
prior to this...
@ + I can't figure out how where I should call tds_set_null() anyway....
@
@ is_null = tds_get_null(current_row, i);
@ +*/
@ colsize = curcol->column_cur_size;
@ + if (colsize == 0)
@ + is_null = 1;
@ + else
@ + is_null = 0;
@ +

Bad. Think at empty and not null string (supported in TDS7+).

@ + tdsdump_log(TDS_DBG_INFO1, "%L tds_put_data: is_null = %d, colsize =
%d\n", is_null, colsize);
@ +
@ +
@ + if (IS_TDS7_PLUS(tds)) {
@ + src = &(current_row[curcol->column_offset]);
@ + if (is_null) {
@ +
@ + tdsdump_log(TDS_DBG_INFO1, "%L tds_put_data: null
param\n");
@ + switch(curcol->column_type) {
@ + case XSYBCHAR:
@ + case XSYBVARCHAR:
@ + case XSYBBINARY:
@ + case XSYBVARBINARY:
@ + case XSYBNCHAR:
@ + case XSYBNVARCHAR:
@ + tdsdump_log(TDS_DBG_INFO1, "%L
tds_put_data: putting CHARBIN_NULL\n");
@ + tds_put_n(tds, CHARBIN_NULL, 2);
@ + break;
@ + default:
@ + tdsdump_log(TDS_DBG_INFO1, "%L
tds_put_data: putting GEN_NULL\n");
@ + tds_put_byte(tds, GEN_NULL);

This do not take into account length (think at null text or image...)

@ + break;
@
@ + }
@ + } else {
@ + tdsdump_log(TDS_DBG_INFO1, "%L tds_put_data: not
null param varint_size = %d\n", curcol->column_varint_size);
@ + switch (curcol->column_varint_size) {
@ + case 4: /* Its a BLOB... */
@ + blob_info = (TDSBLOBINFO *) &
(current_row[curcol->column_offset]);
@ + tds_put_byte(tds, 16);
@ + tds_put_n(tds, blob_info->textptr, 16);
@ + tds_put_n(tds, blob_info->timestamp, 8);
@ + tds_put_int(tds, colsize);
@ + break;
@ + case 2:
@ + tds_put_smallint(tds, colsize);
@ + break;
@ + case 1:
@ + if (is_numeric_type(curcol->column_type))
@ + colsize =
tds_numeric_bytes_per_prec[((TDS_NUMERIC *) src)->precision];
@ + tds_put_byte(tds, colsize);
@ + break;
@ + case 0:
@ + colsize =
tds_get_size_by_type(curcol->column_type);
@ + break;
@ + }
@ +
@ + /* put real data */
@ + if (is_numeric_type(curcol->column_type)) {
@ + TDS_NUMERIC buf;
@ + num = (TDS_NUMERIC *) src;
@ + memcpy(&buf, num, sizeof(buf));
@ + tdsdump_log(TDS_DBG_INFO1, "%L swapping
numeric data...\n");
@ +
tds_swap_datatype(tds_get_conversion_type(curcol->column_type, colsize),
(unsigned char *) &buf);
@ + num = &buf;
@ + tds_put_n(tds, num->array, colsize);
@ + } else if (is_blob_type(curcol->column_type)) {
@ + blob_info = (TDSBLOBINFO *) src;
@ + tds_put_n(tds, blob_info->textvalue,
colsize);
@ + } else {
@ +#ifdef WORDS_BIGENDIAN
@ + unsigned char buf[64];
@ + if (tds->emul_little_endian &&
!is_numeric_type(curcol->column_type) && colsize < 64) {
@ + tdsdump_log(TDS_DBG_INFO1, "%L
swapping coltype %d\n", tds_get_conversion_type(curcol->column_type,
colsize));
@ + memcpy(buf, src, colsize);
@ +
tds_swap_datatype(tds_get_conversion_type(curcol->column_type, colsize),
buf);
@ + src = buf;
@ + }
@ +#endif
@ + tds_put_n(tds, src, colsize);
@ + }
@ + }

Seem a bit replicated (see also complete code in query.c) ...

@ + } else {
@ /* put size of data */
@ src = &(current_row[curcol->column_offset]);
@ switch (curcol->column_varint_size) {
@ case 4: /* Its a BLOB... */
@ blob_info = (TDSBLOBINFO *) &
(current_row[curcol->column_offset]);
@ if (!is_null) {
@ tds_put_byte(tds, 16);
@ tds_put_n(tds, blob_info->textptr, 16);
@ tds_put_n(tds, blob_info->timestamp, 8);
@ tds_put_int(tds, colsize);

freddy77

=================================
"STRICTLY PERSONAL AND CONFIDENTIAL

This message may contain confidential and proprietary material for the sole
use of the intended recipient. Any review or distribution by others is
strictly prohibited. If you are not the intended recipient please contact
the sender and delete all copies.
The contents of this message that do not relate to the official business of
our company shall be understood as neither given nor endorsed by it."

=================================




Archive powered by MHonArc 2.6.24.

Top of Page