[PATCH] reorder charset handlling in tsql (Re: SQL Server version and TDS Version)

"Craig A. Berry" <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
On Apr 29, 2010, at 11:02 PM, Craig A. Berry wrote:

> I think the right fix is going to be to reorder things in tsql.c so  
> it only puts a charset in the login structure when the user  
> specifies one explicitly on the command line or, as a last chance,  
> puts the charset in the connection structure if it's empty after the  
> call to tds_read_config_info().


And that's what I've done in the attached patch.  Specifically,

1.)  Implement the -J command-line option (lifted directly from the  
Sybase documentation) to explicitly set the client charset.  This is  
now the only case where tsql will set the charset before reading  
configuration info, and we know from recent experience that this  
trumps what's in freetds.conf.

2.)  If and only if reading configuration info fails to set the client  
charset (which I think is unlikely since it apparently chooses its own  
default), tsql will set it to the charset read from locale_charset()  
or nl_langinfo().  If it wasn't able to get a charset from the locale,  
it will hardwire it to ISO-8859-1.

There is a new line of output showing the default charset actually  
being used, which is now somewhat less likely to be the locale  
charset.  This output could of course be suppressed in cases where  
they are the same:

% ./src/apps/tsql -Usomeuser -Smyserver
Password:
locale is "C"
locale charset is "US-ASCII"
using default charset "ISO-8859-1"
1>


My assumption throughout is that the TDS library already knows how to  
pick a charset and the application should defer to it unless there is  
good reason to explicitly override it, which we now have the ability  
to do.  Most likely the old logic using locale charset in tsql.c  
predates all of the advanced charset handling in src/tds/iconv.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
tsql_charset.patch (application/octet-stream, 4 KB)
Index: src/apps/tsql.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/apps/tsql.c,v
retrieving revision 1.133
diff -p -u -r1.133 tsql.c
--- src/apps/tsql.c	8 Apr 2010 08:19:16 -0000	1.133
+++ src/apps/tsql.c	30 Apr 2010 15:17:57 -0000
@@ -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);
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.