Re: FreeTDS + (py)ODBC - global config section without servername parameter
Joe Sarre <[email protected]>
| Newsgroups | gmane.comp.db.tds.freetds |
|---|---|
| Message-ID | <[email protected]> |
Hi, I've got a patch which seems to work on my setup. Apologies if there is anything terribly wrong, as this is my first patch submission. Does this look like the right approach to you all? What shall I do next with this patch? Joe On 24 May 2010 21:23, Joe Sarre <[email protected]> wrote: > > Hi, > > 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 (ISO-8859-1) client_charset. > > 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 cases. > > 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. > > Best regards, > > Joe Sarre > _______________________________________________ FreeTDS mailing list [email protected] http://lists.ibiblio.org/mailman/listinfo/freetds
freetds-odbc-global.patch
(application/octet-stream, 1.5 KB)
diff -crB freetds-0.82/src/odbc/connectparams.c freetds-0.82-patched/src/odbc/connectparams.c
*** freetds-0.82/src/odbc/connectparams.c 2007-07-01 11:10:52.000000000 +0100
--- freetds-0.82-patched/src/odbc/connectparams.c 2010-05-25 16:10:29.000000000 +0100
***************
*** 246,251 ****
--- 246,252 ----
if (strcasecmp(option, "SERVER") == 0) {
/* ignore if servername or DSN specified */
if (!reparse) {
+ tds_read_conf_file(connection, NULL);
dest_s = &connection->server_name;
/* not that safe cast but works -- freddy77 */
if (!parse_server((char *) tds_dstr_cstr(&value), connection)) {
diff -crB freetds-0.82/src/tds/config.c freetds-0.82-patched/src/tds/config.c
*** freetds-0.82/src/tds/config.c 2007-12-23 21:12:02.000000000 +0000
--- freetds-0.82-patched/src/tds/config.c 2010-05-25 16:10:45.000000000 +0100
***************
*** 344,352 ****
static int
tds_read_conf_sections(FILE * in, const char *server, TDSCONNECTION * connection)
{
! tds_read_conf_section(in, "global", tds_parse_conf_section, connection);
! rewind(in);
! return tds_read_conf_section(in, server, tds_parse_conf_section, connection);
}
static int
--- 344,357 ----
static int
tds_read_conf_sections(FILE * in, const char *server, TDSCONNECTION * connection)
{
! int found = tds_read_conf_section(in, "global", tds_parse_conf_section, connection);
! if (server)
! {
! rewind(in);
! return tds_read_conf_section(in, server, tds_parse_conf_section, connection);
! }
! else
! return found;
}
static int