[PATCH] consolidated locale/client charset update

"Craig A. Berry" <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
The attached patch completes the client charset handling changes we've  
had in progress for a couple weeks now.  It includes changes  
previously submitted but not yet applied as well some new changes.  It  
makes sense to look at it all together as one integral set of changes.

Here's what it does:

1.) Completely removes client charset handling from locales.conf  
processing, including removing the client_charset field from the  
TDSLOCALE structure.  This is obviously a binary incompatibility and  
should trigger relevant policies about when it can ship and so forth.

2.) Sets the client charset based on the current locale in  
tds_alloc_connection(), essentially moving logic to there from  
tds_alloc_locale().

3.)  In tds_iconv_info_init(), reports problems getting a canonical  
charset without using the nonexistent canonical name that it failed to  
look up.

4.)  Modifies tsql so that it does not hard-wire the client charset to  
whatever the current locale says it is.  It now lets the library  
default it to that, but it can be overridden by either freetds.conf or  
by the newly implemented -J command line option.  Of course the  
freetds.conf setting works for any application, not just tsql.

Affected files:

% lsdiff -s charset_update.patch
! include/tds.h
! src/apps/tsql.c
! src/tds/iconv.c
! src/tds/locale.c
! src/tds/mem.c

________________________________________
Craig A. Berry
mailto:[email protected]

"... getting out of a sonnet is much more
  difficult than getting in."
                  Brad Leithauser

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
charset_update.patch (application/octet-stream, 8 KB)
--- include/tds.h;-0	Sat Apr 10 09:29:36 2010
+++ include/tds.h	Thu May 27 09:43:38 2010
@@ -908,7 +908,6 @@ typedef struct tds_locale
 {
 	char *language;
 	char *server_charset;
-	char *client_charset;
 	char *date_fmt;
 } TDSLOCALE;
 
--- src/apps/tsql.c;-0	Thu Apr  8 03:19:16 2010
+++ src/apps/tsql.c	Thu May 27 15:40:38 2010
@@ -297,7 +297,8 @@ static void
 tsql_print_usage(const char *progname)
 {
 	fprintf(stderr,
-		"Usage:\t%s [-S <server> | -H <hostname> -p <port>] -U <username> [-P <password>] [-I <config file>] [-o <options>] [-t delim] [-r delim] [-D database]\n"
+		"Usage:\t%s [-S <server> | -H <hostname> -p <port>] -U <username> [-P <password>]\n"
+		"\t\t[-I <config file>] [-J <client charset>] [-o <options>] [-t delim] [-r delim] [-D database]\n"
 		"\t%s -C\n"
 		"Options:\n"
 		"\tf\tDo not print footer\n"
@@ -402,23 +403,10 @@ populate_login(TDSLOGIN * login, int arg
 	char *confile = NULL;
 	int port = 0;
 	int opt;
-	const char *locale = NULL;
 	const char *charset = NULL;
 	char *opt_flags_str = NULL;
 
-	setlocale(LC_ALL, "");
-	locale = setlocale(LC_ALL, NULL);
-
-#if HAVE_LOCALE_CHARSET
-	charset = locale_charset();
-#endif
-#if HAVE_NL_LANGINFO && defined(CODESET)
-	if (!charset)
-		charset = nl_langinfo(CODESET);
-#endif
-
-
-	while ((opt = getopt(argc, argv, "H:S:I:P:U:p:Co:t:r:D:Lv")) != -1) {
+	while ((opt = getopt(argc, argv, "H:S:I:J:P:U:p:Co:t:r:D:Lv")) != -1) {
 		switch (opt) {
 		case 't':
 			opt_col_term = strdup(optarg);
@@ -452,6 +440,9 @@ populate_login(TDSLOGIN * login, int arg
 			free(confile);
 			confile = strdup(optarg);
 			break;
+		case 'J':
+			charset = strdup(optarg);
+			break;
 		case 'p':
 			port = atoi(optarg);
 			break;
@@ -495,16 +486,6 @@ populate_login(TDSLOGIN * login, int arg
 		}
 	}
 
-
-	if (locale)
-		if (!QUIET) printf("locale is \"%s\"\n", locale);
-	if (charset) {
-		if (!QUIET) printf("locale charset is \"%s\"\n", charset);
-	} else {
-		charset = "ISO-8859-1";
-		if (!QUIET) printf("using default charset \"%s\"\n", charset);
-	}
-	
 	if ((global_opt_flags & OPT_INSTANCES) && hostname) {
 		static const char template[] = "%s.instances";
 		char ip[24] = {'\0'};
@@ -582,7 +563,7 @@ populate_login(TDSLOGIN * login, int arg
 		tds_set_app(login, "TSQL");
 		tds_set_library(login, "TDS-Library");
 		tds_set_server(login, servername);
-		tds_set_client_charset(login, charset);
+		if (charset) tds_set_client_charset(login, charset);
 		tds_set_language(login, "us_english");
 		tds_set_passwd(login, password);
 		if (confile) {
@@ -595,7 +576,7 @@ populate_login(TDSLOGIN * login, int arg
 		tds_set_library(login, "TDS-Library");
 		tds_set_server(login, hostname);
 		tds_set_port(login, port);
-		tds_set_client_charset(login, charset);
+		if (charset) tds_set_client_charset(login, charset);
 		tds_set_language(login, "us_english");
 		tds_set_passwd(login, password);
 	}
@@ -681,6 +662,8 @@ main(int argc, char **argv)
 	pid_t timer_pid = 0;
 	int pipes[2];
 #endif
+	const char *locale = NULL;
+	const char *charset = NULL;
 
 	istty = isatty(0);
 
@@ -710,6 +693,32 @@ main(int argc, char **argv)
 	tds_set_parent(tds, NULL);
 	connection = tds_read_config_info(tds, login, context->locale);
 
+	setlocale(LC_ALL, "");
+	locale = setlocale(LC_ALL, NULL);
+
+#if HAVE_LOCALE_CHARSET
+	charset = locale_charset();
+#endif
+#if HAVE_NL_LANGINFO && defined(CODESET)
+	if (!charset)
+		charset = nl_langinfo(CODESET);
+#endif
+
+	if (locale)
+		if (!QUIET) printf("locale is \"%s\"\n", locale);
+	if (charset) {
+		if (!QUIET) printf("locale charset is \"%s\"\n", charset);
+	}
+	
+	if (tds_dstr_isempty(&connection->client_charset)) {
+		if (!charset)
+			charset = "ISO-8859-1";
+
+		tds_set_client_charset(login, charset);
+		tds_dstr_dup(&connection->client_charset, &login->client_charset);
+	}
+	if (!QUIET) printf("using default charset \"%s\"\n", tds_dstr_cstr(&connection->client_charset));
+
 	if (opt_default_db) {
 		tds_dstr_copy(&connection->database, opt_default_db);
 		if (!QUIET) fprintf(stderr, "Default database being set to %s\n", opt_default_db);
--- src/tds/iconv.c;-0	Mon Feb  8 06:16:43 2010
+++ src/tds/iconv.c	Thu May 27 17:10:48 2010
@@ -440,12 +440,12 @@ tds_iconv_info_init(TDSICONV * char_conv
 	server_canonical = tds_canonical_charset(server_name);
 
 	if (client_canonical < 0) {
-		tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: client charset name \"%s\" unrecognized\n", client->name);
+		tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: client charset name \"%s\" unrecognized\n", client_name);
 		return 0;
 	}
 
 	if (server_canonical < 0) {
-		tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: server charset name \"%s\" unrecognized\n", client->name);
+		tdsdump_log(TDS_DBG_FUNC, "tds_iconv_info_init: server charset name \"%s\" unrecognized\n", server_name);
 		return 0;
 	}
 
--- src/tds/locale.c;-0	Tue Oct 16 10:12:22 2007
+++ src/tds/locale.c	Thu May 27 10:05:49 2010
@@ -22,6 +22,10 @@
 #include <config.h>
 #endif
 
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
 #include <stdarg.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -68,12 +72,16 @@ tds_get_locale(void)
 	if (in) {
 		tds_read_conf_section(in, "default", tds_parse_locale, locale);
 
+#if HAVE_LOCALE_H
+		setlocale(LC_ALL, "");
+		s = setlocale(LC_ALL, NULL);
+#else
 		s = getenv("LANG");
+#endif
 		if (s && s[0]) {
 			int found;
 			char buf[128];
 			const char *strip = "@._";
-			const char *charset = NULL;
 
 			/* do not change environment !!! */
 			tds_strlcpy(buf, s, sizeof(buf));
@@ -96,19 +104,13 @@ tds_get_locale(void)
 				if (!s)
 					continue;
 				*s = 0;
-				if (*strip == '.')
-					charset = s+1;
 				rewind(in);
 				found = tds_read_conf_section(in, buf, tds_parse_locale, locale);
 			}
 
-			/* charset specified in LANG ?? */
-			if (charset) {
-				free(locale->client_charset);
-				locale->client_charset = strdup(charset);
-			}
 		}
 
+
 		fclose(in);
 	}
 	return locale;
--- src/tds/mem.c;-0	Sun May  2 06:52:13 2010
+++ src/tds/mem.c	Thu May 27 13:46:22 2010
@@ -690,35 +690,9 @@ TDSLOCALE *
 tds_alloc_locale(void)
 {
 	TDSLOCALE *locale;
-#if !(HAVE_NL_LANGINFO && defined(CODESET))
-	char *lc_all;
-#endif
 
 	TEST_MALLOC(locale, TDSLOCALE);
 
-#if HAVE_NL_LANGINFO && defined(CODESET)
-	locale->client_charset = strdup(nl_langinfo(CODESET));
-#else
-	locale->client_charset = strdup("ISO-8859-1");
-	if (!locale->client_charset)
-		goto Cleanup;
-
-	if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
-		goto Cleanup;
-
-	if (strtok(lc_all, ".")) {
-		char *encoding = strtok(NULL, "@");
-		if (encoding) {
-			free(locale->client_charset);
-			locale->client_charset = strdup(encoding);
-		}
-	}
-	free(lc_all);
-#endif
-	if (!locale->client_charset)
-		goto Cleanup;
-	tdsdump_log(TDS_DBG_FUNC, "tds_alloc_locale(): initialized locale to \"%s\"\n", locale->client_charset? locale->client_charset : "NULL");
-
 	return locale;
 
       Cleanup:
@@ -832,6 +806,9 @@ tds_alloc_connection(TDSLOCALE * locale)
 {
 	TDSCONNECTION *connection;
 	char hostname[128];
+#if !(HAVE_NL_LANGINFO && defined(CODESET))
+	char *lc_all;
+#endif
 
 	TEST_MALLOC(connection, TDSCONNECTION);
 	tds_dstr_init(&connection->server_name);
@@ -854,9 +831,28 @@ tds_alloc_connection(TDSLOCALE * locale)
 		goto Cleanup;
 	connection->tds_version = TDS_DEFAULT_VERSION;
 	connection->block_size = 0;
-	/* TODO use system default ?? */
+
+	setlocale(LC_ALL, "");
+#if HAVE_NL_LANGINFO && defined(CODESET)
+	if (!tds_dstr_copy(&connection->client_charset, nl_langinfo(CODESET)))
+		goto Cleanup;;
+#else
 	if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
 		goto Cleanup;
+
+	if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
+		goto Cleanup;
+
+	if (strtok(lc_all, ".")) {
+		char *encoding = strtok(NULL, "@");
+		if (encoding) {
+			if (!tds_dstr_copy(&connection->client_charset, encoding))
+				goto Cleanup;
+		}
+	}
+	free(lc_all);
+#endif
+
 	if (locale) {
 		if (locale->language)
 			if (!tds_dstr_copy(&connection->language, locale->language))
@@ -1154,7 +1150,6 @@ tds_free_locale(TDSLOCALE * locale)
 	free(locale->language);
 	free(locale->server_charset);
 	free(locale->date_fmt);
-	free(locale->client_charset);
 	free(locale);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.