Re: Dreaded "Server SYBASE not found!" question

Frediano Ziglio <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <1260692593.5010.59.camel@freddy>
Il giorno sab, 12/12/2009 alle 12.42 -0500, James K. Lowden ha scritto:
> Nelson, Erik - 2 wrote:
> > There's an outstanding todo in login.c to open the log file prior to
> > tds_set_server() where "SYBASE" is being set in to
> > connection->server_name, but it's not at all clear why the server
> > name/IP aren't being set correctly since the server info is clearly
> > being found in freetds.conf.  
> ...
> > [Hiruko] found in "/modleng/usr/etc/odbc.ini"
> > found this section:
> >         [Hiruko]
> >         Driver  =       FreeTDS
> >         Description     =       DataDirect 5.1 SQL Server Wire Protocol
> >         Servername      =       Hiruko
> >         Server  =       Hiruko
> >         Port    =       1433
> 
> Server and Servername cannot be in the same section.  One overrides the
> other.  
> 
> This highlights a more general question, for which I'd like to hear
> suggestions (and/or see a patch!) from anyone who's interested.  
> 
> We have two mutually exclusive attributes in our configuration files.  In
> odbc.ini we have server/servername; in freetds.conf we have port/instance.
>  These inevitably trip up some people, probably a lot more than write to
> the list, who over-specify the sever.  What to do?  
> 
> One solution is to die noisily with err(3) when invalid combinations are
> found for the requested server.  (Also, perhaps warnings writting to
> stderr for any other configuration problems e.g. invalid property names). 
> 
> 
> A second way is to document the conflict clearly and have a careful
> override policy.  I started working on that, but I'm not satisfied.  It
> reminded me of something one of the Bell Labs guys said about writing
> early UNIX man pages: sometimes the documented behavior was so
> embarrassing that it motivated them to fix it.  
> 

I would suggest a proper error using correct way (that is no stderr).

> Another solution is to eliminate the "other" name.  
> 
> For odbc.ini, we could eliminate "servername".  Instead, "server" would
> first be looked up in freetds.conf, if it exists.  If nothing is found,
> then "server" would be treated as a DNS name.  This is consistent with how
> a servername is treated during a db-lib/ct-lib lookup.  

Although this breaks compatibility I'd agree. I see not that difference
between two terms.

> For freetds.conf, we could eliminate "instance" and always use "port".  If
> "port" is a number, it's a port; if "port" is a string, it's a named
> instance.  Or, always treat "port" as a potential named instance,
> interrogate the server, and revert to a number only if the server refuses
> to reply with a valid port.  (I'm tempted to keep "instance" and eliminate
> "port" instead, but I'm held back, perhaps wrongly, by tradition.  And I
> wonder whether you can name your instance "80"?) 
> 

And what about port is a port specified in /etc/services ?
Personally I would eliminate both and use "compressed" syntax like
"server:port" or "server\instance". This for two reason:
- is already supported by libTDS
- is compatible with ODBC and the way you specify this in DSN
configuration.

> I tend to favor "die early and often": if the configuration file is
> invalid, complain and stop.  But, particularly in web environments (and
> given the way TDSDUMP logging works), it can be hard to diagnose why the
> server connection failed.  
> 

If upper layer do not read correctly error is not my problem.

> I *also* think it's better to make mistakes less likely by eliminating
> opportunities.  
> 

I think first step is eliminate confusion refusing to even try to
connect if both specified (server/servername and/or port/instance).

> Suggestions?  
> 

As a start see attached patch

freddy77

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
vedi.diff (text/x-patch, 7.7 KB)
Index: include/tds.h
===================================================================
RCS file: /cvs/freetds/freetds/include/tds.h,v
retrieving revision 1.323
diff -U 10 -r1.323 tds.h
--- include/tds.h	26 Nov 2009 09:47:41 -0000	1.323
+++ include/tds.h	13 Dec 2009 08:13:56 -0000
@@ -280,21 +280,22 @@
  * TDSERRNO is emitted by libtds to the client library's error handler
  * (which may in turn call the client's error handler).
  * These match the db-lib msgno, because the same values have the same meaning
  * in db-lib and ODBC.  ct-lib maps them to ct-lib numbers (todo). 
  */
 typedef enum {	TDSEOK    = TDS_SUCCEED, 
 		TDSEICONVIU    = 2400, 
 		TDSEICONVAVAIL = 2401, 
 		TDSEICONVO     = 2402, 
 		TDSEICONVI     = 2403, 
-		TDSEICONV2BIG  = 2404, 
+		TDSEICONV2BIG  = 2404,
+		TDSEPORTINSTANCE	= 2500,
 		TDSESYNC = 20001, 
 		TDSEFCON = 20002, 
 		TDSETIME = 20003, 
 		TDSEREAD = 20004, 
 		TDSEWRIT = 20006, 
 		TDSESOCK = 20008, 
 		TDSECONN = 20009, 
 		TDSEMEM  = 20010,
 		TDSEINTF = 20012,	/* Server name not found in interface file */
 		TDSEUHST = 20013,	/* Unknown host machine name. */
Index: src/tds/config.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/config.c,v
retrieving revision 1.151
diff -U 10 -r1.151 config.c
--- src/tds/config.c	26 Nov 2009 09:47:41 -0000	1.151
+++ src/tds/config.c	13 Dec 2009 08:13:56 -0000
@@ -619,24 +619,22 @@
 	}
 	if (login->suppress_language) {
 		connection->suppress_language = 1;
 	}
 	if (login->bulk_copy) {
 		connection->bulk_copy = 1;
 	}
 	if (login->block_size) {
 		connection->block_size = login->block_size;
 	}
-	if (login->port) {
+	if (login->port)
 		connection->port = login->port;
-		tds_dstr_copy(&connection->instance_name, "");
-	}
 	if (login->connect_timeout)
 		connection->connect_timeout = login->connect_timeout;
 
 	if (login->query_timeout)
 		connection->query_timeout = login->query_timeout;
 
 	/* copy other info not present in configuration file */
 	memcpy(connection->capabilities, login->capabilities, TDS_MAX_CAPABILITY);
 }
 
@@ -1029,25 +1027,21 @@
 
 		/*
 		 * Make a guess about the port number
 		 */
 
 		if (connection->port == 0) {
 			/*
 			 * Not set in the [global] section of the
 			 * configure file, take a guess.
 			 */
-#ifdef TDS50
-			ip_port = 4000;
-#else
-			ip_port = 1433;
-#endif
+			ip_port = TDS_DEF_PORT;
 		} else {
 			/*
 			 * Preserve setting from the [global] section
 			 * of the configure file.
 			 */
 			ip_port = connection->port;
 		}
 		if ((env_port = getenv("TDSPORT")) != NULL) {
 			ip_port = tds_lookup_port(env_port);
 			tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %s from $TDSPORT.\n", env_port);
@@ -1080,28 +1074,26 @@
 	const char *pSep;
 	const char *server;
 
 	/* seek the ':' in login server_name */
 	server = tds_dstr_cstr(&login->server_name);
 	pSep = strrchr(server, ':');
 
 	if (pSep && pSep != server) {	/* yes, i found it! */
 		/* modify connection-> && login->server_name & ->port */
 		login->port = connection->port = atoi(pSep + 1);
-		tds_dstr_copy(&connection->instance_name, "");
 	} else {
 		/* handle instance name */
 		pSep = strrchr(server, '\\');
 		if (!pSep || pSep == server)
 			return 0;
 
-		login->port = connection->port = 0;
 		tds_dstr_copy(&connection->instance_name, pSep + 1);
 	}
 
 	tds_dstr_setlen(&login->server_name, pSep - server);
 	if (!tds_dstr_dup(&connection->server_name, &login->server_name))
 		return 0;
 
 	return 1;
 }
 
Index: src/tds/login.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/login.c,v
retrieving revision 1.191
diff -U 10 -r1.191 login.c
--- src/tds/login.c	2 Dec 2009 22:58:21 -0000	1.191
+++ src/tds/login.c	13 Dec 2009 08:13:56 -0000
@@ -420,20 +420,25 @@
 		tdserror(tds->tds_ctx, tds, TDSEUHST, 0 );
 		tdsdump_log(TDS_DBG_ERROR, "IP address pointer is empty\n");
 		if (!tds_dstr_isempty(&connection->server_name)) {
 			tdsdump_log(TDS_DBG_ERROR, "Server %s not found!\n", tds_dstr_cstr(&connection->server_name));
 		} else {
 			tdsdump_log(TDS_DBG_ERROR, "No server specified!\n");
 		}
 		return TDSECONN;
 	}
 
+	if (connection->port && !tds_dstr_isempty(&connection->instance_name)) {
+		tdserror(tds->tds_ctx, tds, TDSEPORTINSTANCE, 0);
+		return TDSECONN;
+	}
+		
 	if (!IS_TDS50(tds) && !tds_dstr_isempty(&connection->instance_name))
 		connection->port = tds7_get_instance_port(tds_dstr_cstr(&connection->ip_addr), tds_dstr_cstr(&connection->instance_name));
 
 	if (connection->port < 1) {
 		tdsdump_log(TDS_DBG_ERROR, "invalid port number\n");
 		return TDSECONN;
 	}
 
 	memcpy(tds->capabilities, connection->capabilities, TDS_MAX_CAPABILITY);
 
Index: src/tds/mem.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/mem.c,v
retrieving revision 1.193
diff -U 10 -r1.193 mem.c
--- src/tds/mem.c	26 Nov 2009 09:47:41 -0000	1.193
+++ src/tds/mem.c	13 Dec 2009 08:13:57 -0000
@@ -806,21 +806,20 @@
 	tds_dstr_init(&connection->ip_addr);
 	tds_dstr_init(&connection->database);
 	tds_dstr_init(&connection->dump_file);
 	tds_dstr_init(&connection->client_charset);
 	tds_dstr_init(&connection->instance_name);
 
 	/* fill in all hardcoded defaults */
 	if (!tds_dstr_copy(&connection->server_name, TDS_DEF_SERVER))
 		goto Cleanup;
 	connection->tds_version = TDS_DEFAULT_VERSION;
-	connection->port = TDS_DEF_PORT;
 	connection->block_size = 0;
 	/* TODO use system default ?? */
 	if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))
 		goto Cleanup;
 	if (locale) {
 		if (locale->language)
 			if (!tds_dstr_copy(&connection->language, locale->language))
 				goto Cleanup;
 		if (locale->server_charset)
 			if (!tds_dstr_copy(&connection->server_charset, locale->server_charset))
Index: src/tds/util.c
===================================================================
RCS file: /cvs/freetds/freetds/src/tds/util.c,v
retrieving revision 1.87
diff -U 10 -r1.87 util.c
--- src/tds/util.c	25 Aug 2009 14:25:35 -0000	1.87
+++ src/tds/util.c	13 Dec 2009 08:13:57 -0000
@@ -248,20 +248,21 @@
 
 static const TDS_ERROR_MESSAGE tds_error_messages[] = 
 	{ { TDSEICONVIU,     EXCONVERSION,	"Buffer exhausted converting characters from client into server's character set" }
 	, { TDSEICONVAVAIL,  EXCONVERSION,	"Character set conversion is not available between client character set '%.*s' and "
 						"server character set '%.*s'" }
 	, { TDSEICONVO,      EXCONVERSION,	"Error converting characters into server's character set. Some character(s) could "
 						"not be converted" }
 	, { TDSEICONVI,      EXCONVERSION,	"Some character(s) could not be converted into client's character set.  "
 						"Unconverted bytes were changed to question marks ('?')" }
 	, { TDSEICONV2BIG,   EXCONVERSION,	"Some character(s) could not be converted into client's character set" }
+	, { TDSEPORTINSTANCE,      EXCOMM,      "Both port and instance specified" }
 	, { TDSERPND,           EXPROGRAM,	"Attempt to initiate a new Adaptive Server operation with results pending" }
 	, { TDSEBTOK,              EXCOMM,	"Bad token from the server: Datastream processing out of sync" }
 	, { TDSECAP,               EXCOMM,	"DB-Library capabilities not accepted by the Server" }
 	, { TDSECAPTYP,            EXCOMM,	"Unexpected capability type in CAPABILITY datastream" }
 	, { TDSECLOS,              EXCOMM,	"Error in closing network connection" }
 	, { TDSECONN,              EXCOMM,	"Unable to connect: Adaptive Server is unavailable or does not exist" }
 	, { TDSEEUNR,              EXCOMM,	"Unsolicited event notification received" }
 	, { TDSEFCON,              EXCOMM,	"Adaptive Server connection failed" }
 	, { TDSENEG,               EXCOMM,	"Negotiated login attempt failed" }
 	, { TDSEOOB,               EXCOMM,	"Error in sending out-of-band data to the server" }
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.