Skip to Content.
Sympa Menu

freetds - Re: Help Freetds 0.53 - removing messages printed to STDERR

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Michael Horowitz" <michael.horowitz AT storagenetworks.com>
  • To: freetds AT franklin.oit.unc.edu
  • Subject: Re: Help Freetds 0.53 - removing messages printed to STDERR
  • Date: Wed, 2 Jan 2002 21:01:09 -0500


Hello again,

I am not really familiar with the code, but I used some the hints you gave
me and took a quick look through the code. I think I have spotted the
problem.

In tds/token.c line 1139, you swap the bytes, but I think they are already
swapped.
Here is a section of the code:
/* message number */
/* swap bytes on bigendian systems (mlilback, 11/7/01) */
rc = tds_get_int(tds);
#ifdef WORDS_BIGENDIAN
tds_swap_bytes(&rc, 4);
#endif
tds->msg_info->msg_number = rc;

I looked at tds_get_int, and it already swaps the bytes:
/*
** Get an int32 from the server.
*/
TDS_INT tds_get_int(TDSSOCKET *tds)
{
unsigned char bytes[4];

tds_get_n(tds, bytes, 4);
#if WORDS_BIGENDIAN
if (tds->emul_little_endian) {
return TDS_BYTE_SWAP32(*(TDS_INT *)bytes);
}
#endif
return *(TDS_INT *)bytes;
}

And, "tds->msg_info->msg_number" is a TDS_SMALLINT:

typedef struct tds_msg_info {
TDS_SMALLINT priv_msg_type;
TDS_SMALLINT line_number;
TDS_SMALLINT msg_number;
TDS_SMALLINT msg_state;
TDS_SMALLINT msg_level;
TDS_CHAR *server;
TDS_CHAR *message;
TDS_CHAR *proc_name;
TDS_CHAR *sql_state;
} TDSMSGINFO;

And, a TDS_SMALLINT is a short, which is 2 bytes:
typedef short TDS_SMALLINT; /* 16 bit int */

So, if the bytes are double swapped for "rc" and the 2 least significant
bytes end up as 0, then when it is assigned to
"tds->msg_info->msg_number", "tds->msg_info->msg_number" ends up as zero.

I took a look in the "servermsg_cb()" like you suggested, and if the
message nubmer is false(zero), then it calls "warn" with just the text of
the message:
if(srvmsg->msgnumber) {
PerlIO_printf(DBILOGFP, "Server message: number=%ld
severity=%ld ",
srvmsg->msgnumber, srvmsg->severity);
PerlIO_printf(DBILOGFP, "state=%ld line=%ld ",
srvmsg->state, srvmsg->line);
if (srvmsg->svrnlen > 0) {
PerlIO_printf(DBILOGFP, "server=%s ", srvmsg->svrname);
}
if (srvmsg->proclen > 0) {
PerlIO_printf(DBILOGFP, "procedure=%s ", srvmsg->proc);
}
PerlIO_printf(DBILOGFP, "text=%s\n", srvmsg->text);
} else {
warn("%s\n", srvmsg->text);
}

I modified my perl program to have a warn handler, and that was exactly
it. The message is being printed as a warn message since it has no
message number.

So you seem to be correct. I am not familiar with the code, so maybe
there is a reason for the double swapping... Tell me if I am wrong.
I am going to remove the second swapping of bytes and see if it works.

--Mike

> Michael Horowitz writes:
> > Hello again,
> >
> > I added an insert statement that violated a primary key constraint, and
> > this is what I get:
>
> > Violation of PRIMARY KEY constraint 'PK_names'. Cannot insert duplicate
> > key in object 'names'.
> > The statement has been terminated.
>
> Right - this really looks like a bug in FreeTDS.
>
> If I run a similar script with the Sybase libraries I get:
>
> -> prepare for DBD::Sybase::db (DBI::db=HASH(0x81c5ac8)~0x81c5a68
> 'insert dups values(1, 'testing too')')
> New DBI::st (for DBD::Sybase::st, parent=DBI::db=HASH(0x81c5a68), id=)
> dbih_setup_handle(DBI::st=HASH(0x81c5ae0)=>DBI::st=HASH(0x80f8930),
> DBD::Sybase::st, 81c5af8, Null!)
> dbih_make_com(DBI::db=HASH(0x81c5a68), DBD::Sybase::st, 396)
> <- prepare= DBI::st=HASH(0x81c5ae0) at dups.pl line 8
> -> execute for DBD::Sybase::st (DBI::st=HASH(0x81c5ae0)~0x80f8930)
> syb_st_execute() -> ct_command() OK
> syb_st_execute() -> ct_send() OK
> st_next_result() -> ct_results(4048) == 1
> st_next_result() -> ct_results(4046) == 1
> ct_results() final retcode = -205
> st_next_result() -> lasterr = 2601, lastsev = 14
> st_next_result() -> restype is not data result, force failFlag
> syb_st_execute() -> got CS_CMD_DONE: resetting ACTIVE, moreResults,
> dyn_execed
> !! ERROR: 2601 'Server message number=2601 severity=14 state=3 line=1
> text=Attempt to insert duplicate key row in object 'dups' with unique index
> 'dups_i_16960090731'
> Server message number=3621 severity=10 state=0 line=1 text=Command has been
> aborted.
> '
> <- execute= undef at dups.pl line 9
> DBD::Sybase::st execute failed: Server message number=2601 severity=14
> state=3 line=1 text=Attempt to insert duplicate key row in object 'dups'
> with unique index 'dups_i_16960090731'
> Server message number=3621 severity=10 state=0 line=1 text=Command has been
> aborted.
> <> DESTROY ignored for outer handle DBI::st=HASH(0x81c5ae0) (inner
> DBI::st=HASH(0x80f8930))
> -> DESTROY for DBD::Sybase::st (DBI::st=HASH(0x80f8930)~INNER)
>
>
> In your case the servermsg_cb() function in dbdimp.c gets an error
> message structure that does not have the error number set, possibly
> because of the endian fiddling.
>
> I don't know how to get this fixed - I suspect that we'll have to wait
> for Brian to get back...
>
> Michael
> --
> Michael Peppler - Data Migrations Inc. - http://www.mbay.net/~mpeppler
> mpeppler AT peppler.org - mpeppler AT mbay.net
> International Sybase User Group - http://www.isug.com




Archive powered by MHonArc 2.6.24.

Top of Page