Skip to Content.
Sympa Menu

freetds - Re: [freetds] dbbind failure on unknown bindtype

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: jklowden AT schemamania.org
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] dbbind failure on unknown bindtype
  • Date: Wed, 29 Dec 2010 13:23:50 -0500

On Tue, Dec 28, 2010 at 10:47:07PM -0800, Paul Thurston wrote:
> Here's the call sequence (on SQL Server 2008)
>
> int iColType = dbcoltype(dproc, iColumn + 1);
> // The value is returned as iColType = 56
>
> RETCODE errCode = dbbind(dbproc, iColumn + 1, iColType, iColType, iColSize,
> (BYTE*) csBuffer);
> //error message: Unknown bind type passed to DB-Library

Hi Paul,

The above code is wrong and the message correct!

The third parameter of dbbind() is

INT vartype "a description of the binding's data type"

It's one of the defined constants I referred you to in sybdb.h.

In your case, if csBuffer is a DBINT* (and thus iColSize == sizeof(DBINT))
then your vartype should be INTBIND, not SYBINT4.

I know, it's not very consistent.

dbbind() tells the library about the program's variables. db-lib learns
about the server's datatypes from the server before the dbbind() call, when
the metadata are sent in response to dbresults(). dbbind() tells the library
the type, size, and address of the program variable into which the each
columns's data are to be copied. The library then undertakes to place the
server's data into the client's variables in the format prescribed by the
value of the vartype parameter.

I think many people confuse client and server datatypes. We're used to
living in an Intel IEEE world, with its way of representing numbers. But
database servers (should) define their types in machine-independent ways.

http://msdn.microsoft.com/en-us/library/ms187745.aspx

SYBINT4 defines no bit pattern or size. It refers to a T-SQL datatype that
is defined by its *characteristics*, by what values it can hold. The server
is free to invent ways to store & transmit that integer as long as the type
continues to behave as advertised.

INTBIND denotes a C datatype. It serves the same purpose in dbbind() as a
format string of "%d" does in scanf(3). It's needed because C has no
typeof() operator and no function overloading, no built-in way to pass to a
function the type of a variable.

The vendors sometimes foment confusion by conflating the two. Examples:

1. The above link includes "storage" in its description of each type,
inviting the reader to think of the type in phyisical terms. (It also uses
the "-2^31 ... to 2^31-1" notation, which is neither mathematical, nor C, nor
SQL. But who really reads that page anyway?)

2. Both vendors provide a terrible table in the dbbind() documentation
implying that e.g. INTBIND "refers to" SYBINT4. It could also be used with
SYBCHAR, to name just one.

3. The type parameters of dbconvert() are taken from the datatype domain,
not the vartype domain, despite the fact that the destination at least must
refer to a C program variable, not an abstract SQL datatype.

Power being what it is, the weeds they sow sprout faster than I can root them
out!

(To its credit, btw, Microsoft's ODBC documentation does get it right:
SQL_C_SLONG denotes an integer and SQLINTEGER defines one. No mention of
server datatypes when discussing C datatypes. Cf.
http://msdn.microsoft.com/en-us/library/ms714556(v=vs.85).aspx.)

All said, I think you'll find bsqldb and the db-lib unit tests all work as
expected with your server. dbbind() is fine. I hope my little sojourn in
pedantry helps clarify the issue.

--jkl




Archive powered by MHonArc 2.6.24.

Top of Page