Skip to Content.
Sympa Menu

freetds - More on using FreeTDS on a server (was Re: [freetds] Server dumps core...)

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Steve Kirkendall <skirkendall AT dsl-only.net>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: More on using FreeTDS on a server (was Re: [freetds] Server dumps core...)
  • Date: Sat, 17 Apr 2004 18:38:01 -0700

Here's the latest on my efforts to use FreeTDS for server-side networking.

First the bad news: Microsoft's ODBC driver for SQL Server still refuses
to talk to my little server. All I get is a generic "Protocol error in
TDS stream". I suspect I'm failing to send some critical token in the
login response, but it's hard to be sure with an error message that vague.

Now a little the good news: I can now use the tsql program to submit
queries, and get tables back. The tables don't look quite right --
strings come across okay, but numbers are mangled. But I'm definitely
making progress.

And the real purpose of this message: Questions!

* Can anybody recommend an alternative ODBC/TDS driver for Windows? One
that, maybe, would give better error messages? Or it would also be okay
if it simply worked, I suppose.

* I have a log, produced by FreeTDS, of the network traffic in my failed
attempts to access my little SQL server via Microsoft's ODBC driver.
Does anybody out there have a similar dump of a *successful* login?
Nothing fancy, just a TDS4.2 login such as the "test connection"
button in the ODBC Microsoft SQL Server Setup dialog.

* What should I do about queries that don't result in tables? For example,
tsql sends a "set textsize 64512" request. My server currently just
sends token #253 (Result Set Done). Is that proper?

* Are there any common "gotchas" when sending numbers? It kind of looks
like tsql is printing the addresses of the numbers, instead of the
numbers themselves -- the values are all similar, but never identical.
I don't think it's an endian thing.

* Can anybody spot any obvious problems with my table-sending function,
below? The XXXX_t names are all types; their purpose should be pretty
obvious, except that rows are represented as an array of value_t values.
value_t is a union of all supported data types. For strings, it is a
(char *) and the actual text of the string is appended to each row's
value_t array; that way, when the row is freed so are all of its strings.
Column types, names, etc. are stored in the table->col array. By looking
at the log file, I have verified that my little SQL server is indeed
sending garbage for integers; this isn't a bug in tsql.

/* send a table to the client */
void tdsprinttable(table)
table_t table; /* the table to send */
{
TDSRESULTINFO *resinfo;/* FreeTDS library version of table */
int r, c; /* row & column counters */
int rowsize;/* maximum row memory needed */
int offset; /* offset of field within row */

/* allocate a FreeTDS table */
resinfo = tds_alloc_results(table->ncols);

/* fill in the column info for all columns */
rowsize = 0;
for (c = 0; c < table->ncols; c++)
{
/* fill in this column's info */
switch (table->col[c].type)
{
case OP_STRING:
resinfo->columns[c]->column_type = SYBCHAR;
resinfo->columns[c]->column_size =
table->col[c].width;
break;

case OP_INTEGER:
resinfo->columns[c]->column_type = SYBINT4;
resinfo->columns[c]->column_size = sizeof(long);
break;

case OP_NUMERIC:
resinfo->columns[c]->column_type = SYBFLT8;
resinfo->columns[c]->column_size = sizeof(double);
break;

case OP_BOOLEAN:
resinfo->columns[c]->column_type = SYBBIT;
resinfo->columns[c]->column_size = 1;
break;
}
strcpy(resinfo->columns[c]->column_name,
textnametext(table->col[c].name));
resinfo->columns[c]->column_namelen =
strlen(resinfo->columns[c]->column_name);

/* for non-string data, the data offsets don't change so
* we might as well set them here.
*/
resinfo->columns[c]->column_offset = c * sizeof(value_t);

/* add this column's row data size to rowmax */
rowsize += resinfo->columns[c]->column_size;
}

/* start the result, and send column info */
tds_send_result(tds, resinfo);
tds_send_174_token(tds, table->ncols);

/* for each row... */
for (r = 0; r < table->nrows; r++)
{
/* tell FreeTDS where the data is */
resinfo->current_row = (unsigned char *)&table->row[r];

/* convert the row */
for (c = 0; c < table->ncols; c++)
{
/* most fields' offsets don't change, but we do
* need to worry about strings.
*/
if (table->col[c].type == OP_STRING)
{
resinfo->columns[c]->column_offset =
(unsigned char
*)table->row[r][c].string
- resinfo->current_row;
}
}

/* send the row */
tds_send_row(tds, resinfo);
}
resinfo->current_row = NULL;

/* end the table */
tds_send_253_token(tds, 16, table->nrows);
tds_flush_packet(tds);

/* clean up */
tds_free_results(resinfo);
didresult = 1;
}

--
Steve Kirkendall |A:It is confusing, since people don't read that way
kirkenda AT cs.pdx.edu |Q:Why is top-posting bad?
|A:It is adding comments to the top of a message
|Q:What is top-posting?




Archive powered by MHonArc 2.6.24.

Top of Page