[freetds] FreeTDS + (py)ODBC - global config section without servername parameter
joe.sarre at gmail.com
Mon May 24 16:23:52 EDT 2010
I've found some behaviour of freetds which I didn't expect, and I'd like to
see if this is a bug or expected behaviour, and what the best alternative
way is to achieve what I'm trying to achieve.
I have a Fedora server running pyODBC, which connects to any of a number of
MSSQL database servers. The particular database server is configured by
hostname, and that's convenient because it allows me to use the same
connection string on my Windows desktop using MS ODBC. This setup all
worked correctly until recently, when I needed to obtain some data from the
database that was not encodable using ISO-8859-1.
I found that putting the line "client charset = UTF-8" in a section entitled
[databasename1] and replacing the SERVER=host.name1 with
SERVERNAME=databasename1 worked fine. I could see that the driver was
converting to the right charset ("iconv to convert client-side data to the
"UTF-8" character set") and the output was as expected. However, I would
rather use hostnames than database names for various reasons, and so I tried
putting "client charset = UTF-8" in the [global] section, and going back to
using SERVER=host.name1 in my connection string. The dump file now said
"iconv to convert client-side data to the "ISO-8859-1" character set" and my
Cyrillic characters had become ?s.
I spent some time digging around in the unixODBC and FreeTDS code trying to
get to the bottom of how the character set is chosen, and here is what I
found (please forgive this fairly naïve attempt to understand the code):
* odbc.c: SQLDriverConnect calls tds_alloc_connection
* mem.c: tds_alloc_connection assigns a default value of ISO-8859-1 to
the connection->client_charset attribute.
* There are various other functions which then have access to the
connection structure without modifying it:
- connectparams.c: odbc_parse_connect_string
- odbc.c: odbc_connect
- config.c: tds_fix_connection
- login.c: tds_connect
* finally, it ends up in iconv.c: tds_iconv_open with the default
For my purposes, I could recompile FreeTDS, changing the default from mem.c
to be UTF-8. Nevertheless, it seems to me that the client charset from the
[global] section should be respected. The place I think this should happen
is in connectparams.c: odbc_parse_connect_string. This function reads the
config file if the SERVERNAME parameter is set in the connection string, but
not if the SERVER parameter is set. I think it should read it in both
Does this sound reasonable? Is there some reason that it has been
implemented this way?
Tomorrow I will spend some time working on a patch along the lines described
above, and if I complete it, I'll forward it to the mailing list.
Thanks in advance for your help and advice.
More information about the FreeTDS