Skip to Content.
Sympa Menu

freetds - RE: Funny Dates

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Bob Kline <bkline AT rksystems.com>
  • To: TDS Development Group <freetds AT franklin.oit.unc.edu>
  • Subject: RE: Funny Dates
  • Date: Tue, 6 Feb 2001 08:53:38 -0500 (EST)

On Tue, 6 Feb 2001, Stefanos Karasavvidis wrote:

> I had the same problem some months ago, which got solved by applying
> a patch that was posted to this list some time ago. Although posted
> to this list, the patch was never applied to the snapshot builds (I
> don't know if it is applied now).

I can't tell from the information included with the rest of this thread
whether the problem reported here is the same as the date problems for
which I submitted a patch last August, but I just checked and discovered
that this patch has still not been applied.

Here is the text for my original report:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Date: Mon, 14 Aug 2000 09:06:40 -0400 (EDT)
From: Bob Kline <bkline AT rksystems.com>
Reply-To: TDS Development Group <freetds AT franklin.oit.unc.edu>
To: TDS Development Group <freetds AT franklin.oit.unc.edu>
Cc: Julien de Murcia <demurcia AT sablet.grenoble.hp.com>
Subject: [freetds] Patch to work around JVM optimization bug

The problem which was reported last week with randomly incorrect dates
being returned from queries turned out to have been caused by a bug in
the Java virtual machine's optimization (specifically version 1.2.2,
Java HotSpot Server VM 2.0fcs, mixed code, build E), which wasn't
handling complex mathematical expressions properly in all cases. The
attached file contains a patch which simplifies the calculations used
when parsing dates returned in the TDS buffer, breaking down the
formulas into smaller incremental steps using more temporary variables
to reduce the chances for the optimizer to get confused. It also does
some promotions to long int sooner to ensure that the code will work
with dates well into the future.

This has been run through the unittests suite, and has also been tested
by the list member posting the original problem, who reports that with
the patch the problem no longer occurs. Please fold this into the
latest snapshot. Please also fix unittests/Makefile so that t0006 uses
the same type of rule as all the other tests, and unittests/t0036 so
that it does not fail if the tables being dropped do not already exist.

Thanks.

--
Bob Kline
mailto:bkline AT rksystems.com
http://www.rksystems.com
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

I have attached the original patch as well.

Craig: Do you need me to generate a fresh patch against the current
sources? Was there a problem with the original patch which caused you
to decide not to apply it? If so, could you tell me what the problem
was so we can solve it? This patch corrects two problems with date
handling in the driver, and it would be good to have these resolved. I
don't really care whether you solve the problems with my patch, but I
would like to see them taken care of one way or another.

Thanks,
Bob
diff -Naur original/Tds.java modified/Tds.java
--- original/Tds.java Mon Jul 17 00:41:06 2000
+++ modified/Tds.java Fri Aug 11 15:41:50 2000
@@ -1848,6 +1848,10 @@
int type)
throws java.io.IOException, TdsException
{
+ // Some useful constants
+ final long SECONDS_PER_DAY = 24L * 60L * 60L;
+ final long DAYS_BETWEEN_1900_AND_1970 = 25567L;
+
int len;
Object result;

@@ -1877,14 +1881,19 @@
// It appears that a datetime is made of of 2 32bit ints
// The first one is the number of days since 1900
// The second integer is the number of seconds*300
- int days = comm.getTdsInt();
- int time = comm.getTdsInt();
- long seconds = (long)((days - 25567)*(24*60*60))
- + (long)(time/300);
- long micros = ((time % 300) * 1000000) / 300;
- long millis = (micros / 1000)
- + ((micros % 1000)>=500 ? 1 : 0)
- + seconds * 1000 - zoneOffset;
+ // The reason the calculations below are sliced up into
+ // such small baby steps is to avoid a bug in JDK1.2.2's
+ // runtime, which got confused by the original complexity.
+ long tdsDays = (long)comm.getTdsInt();
+ long tdsTime = (long)comm.getTdsInt();
+ long sqlDays = tdsDays - DAYS_BETWEEN_1900_AND_1970;
+ long seconds = sqlDays * SECONDS_PER_DAY + tdsTime / 300L;
+ long micros = ((tdsTime % 300L) * 1000000L) / 300L;
+ long millis = seconds * 1000L + micros / 1000L - zoneOffset;
+
+ // Round up if appropriate.
+ if (micros % 1000L >= 500L)
+ millis++;

result = new Timestamp(millis - getDstOffset(millis));
break;
@@ -1897,11 +1906,11 @@
// the second smallint is the number of minutes past
// midnight.

- int days = comm.getTdsShort();
- int minutes = comm.getTdsShort();
- long seconds = (long)((days - 25567)*(24*60*60))
- + (long)(minutes * 60);
- long millis = seconds * 1000 - zoneOffset;
+ long tdsDays = (long)comm.getTdsShort();
+ long minutes = (long)comm.getTdsShort();
+ long sqlDays = tdsDays - DAYS_BETWEEN_1900_AND_1970;
+ long seconds = sqlDays * SECONDS_PER_DAY + minutes * 60L;
+ long millis = seconds * 1000L - zoneOffset;

result = new Timestamp(millis - getDstOffset(millis));
break;



Archive powered by MHonArc 2.6.24.

Top of Page