]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The documentation says that the built-in date-time functions give undefined
authordrh <drh@noemail.net>
Tue, 29 Nov 2016 20:39:48 +0000 (20:39 +0000)
committerdrh <drh@noemail.net>
Tue, 29 Nov 2016 20:39:48 +0000 (20:39 +0000)
results for dates before 0000-01-01 and after 9999-12-31.  Change the
actually implementation so that the answer given is really NULL.  This also
avoids unnecessary hand-wringing over an signed integer overflow that might
otherwise occur when processing out-of-bound dates.

FossilOrigin-Name: d410a839752153c6d8be08f758abfbc16475745a

manifest
manifest.uuid
src/date.c
test/date.test

index f7115da4be91f8d0928d9466954100acb61f537f..733c2d390f568b4bbac180e0348a97bf07c2405f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sbroken\shyperlinks\sto\sthe\ssqlite3_snapshot\sobjection\sdefinition\nin\sthe\sdocumentation.\s\sNo\schanges\sto\scode.
-D 2016-11-28T21:22:26.486
+C The\sdocumentation\ssays\sthat\sthe\sbuilt-in\sdate-time\sfunctions\sgive\sundefined\nresults\sfor\sdates\sbefore\s0000-01-01\sand\safter\s9999-12-31.\s\sChange\sthe\nactually\simplementation\sso\sthat\sthe\sanswer\sgiven\sis\sreally\sNULL.\s\sThis\salso\navoids\sunnecessary\shand-wringing\sover\san\ssigned\sinteger\soverflow\sthat\smight\notherwise\soccur\swhen\sprocessing\sout-of-bound\sdates.
+D 2016-11-29T20:39:48.413
 F Makefile.in 6b572807415d3f0a379cebc9461416d8df4a12c8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc bb4d970894abbbe0e88d00aac29bd52af8bc95f4
@@ -337,7 +337,7 @@ F src/build.c 178f16698cbcb43402c343a9413fe22c99ffee21
 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c a2a52d6e353f459d8ab0f07321f60fafa47d5421
-F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b
+F src/date.c 53a4019b90ae1c9cb990196eed0ed196d3f341e1
 F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
 F src/delete.c cac97d1117a3008934da3a6a587b3608e65e1495
 F src/expr.c 8c224aa28278a5c1eed55247b7a571ff388ad5c2
@@ -626,7 +626,7 @@ F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
 F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
 F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
 F test/cursorhint2.test fa41f0d997e67db921d08c31e73111b32811201a
-F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
+F test/date.test 47e7f7057c0efac0e5e26da2d7b6a9a128139de6
 F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
 F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
 F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
@@ -1535,7 +1535,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7cc2d60dce90b8d4dca35708e33002ae6387806e
-R de1f3e041fb172133322c08f2e17859a
+P 9021f6875f897d8b609ebcc04162dc6e0b529a4a
+R e95c6d806c4c5b465cfcf2c97462edc9
 U drh
-Z 0f2a9b7b29f5f440f84b18c2372070c3
+Z f7a67f418429ef937fb437b96080796e
index aaf092107693de2ecd54b7bf7f87032c5338164a..95eeb46ae61c430a6fc2377f6a72ffeb24013f2a 100644 (file)
@@ -1 +1 @@
-9021f6875f897d8b609ebcc04162dc6e0b529a4a
\ No newline at end of file
+d410a839752153c6d8be08f758abfbc16475745a
\ No newline at end of file
index 8b2f2fa71763cc5bfa05b61596b48e2d9890897a..a90b5318b8d3b5b4b026390e72eb3b6bf20c998a 100644 (file)
@@ -75,6 +75,7 @@ struct DateTime {
   char validJD;      /* True (1) if iJD is valid */
   char validTZ;      /* True (1) if tz is valid */
   char tzSet;        /* Timezone was set explicitly */
+  char isError;      /* An overflow has occurred */
 };
 
 
@@ -366,6 +367,15 @@ static int parseDateOrTime(
   return 1;
 }
 
+/*
+** Return TRUE if the given julian day number is within range.
+**
+** The input is the JulianDay times 86400000.
+*/
+static int validJulianDay(sqlite3_int64 iJD){
+  return iJD>=148699540800000 && iJD<=464269060799999;
+}
+
 /*
 ** Compute the Year, Month, and Day from the julian day number.
 */
@@ -376,6 +386,10 @@ static void computeYMD(DateTime *p){
     p->Y = 2000;
     p->M = 1;
     p->D = 1;
+  }else if( !validJulianDay(p->iJD) ){
+    memset(p, 0, sizeof(*p));
+    p->isError = 1;
+    return;
   }else{
     Z = (int)((p->iJD + 43200000)/86400000);
     A = (int)((Z - 1867216.25)/36524.25);
@@ -814,6 +828,7 @@ static int isDate(
     z = sqlite3_value_text(argv[i]);
     if( z==0 || parseModifier(context, (char*)z, p) ) return 1;
   }
+  if( p->isError || (p->validJD && !validJulianDay(p->iJD)) ) return 1;
   return 0;
 }
 
index 2f48b111e6f4e64f125008a5803511e6b56591f4..0286bcc3bca0c32e416e954addcaea4cfe534bac 100644 (file)
@@ -61,8 +61,8 @@ datetest 1.19 {julianday('2000-01-01 12:00:00.1')}   2451545.00000116
 datetest 1.20 {julianday('2000-01-01 12:00:00.01')}  2451545.00000012
 datetest 1.21 {julianday('2000-01-01 12:00:00.001')} 2451545.00000001
 datetest 1.22 {julianday('2000-01-01 12:00:00.')} NULL
-datetest 1.23 julianday(12345.6) 12345.6
-datetest 1.23b julianday('12345.6') 12345.6
+datetest 1.23 julianday(12345.6) NULL
+datetest 1.23b julianday(1721059.5) 1721059.5
 datetest 1.24 {julianday('2001-01-01 12:00:00 bogus')} NULL
 datetest 1.25 {julianday('2001-01-01 bogus')} NULL
 datetest 1.26 {julianday('2001-01-01 12:60:00')} NULL
@@ -418,16 +418,6 @@ datetest 8.19 {datetime('now','11.25 seconds')} {2003-10-22 12:34:11}
 datetest 8.90 {datetime('now','abcdefghijklmnopqrstuvwyxzABCDEFGHIJLMNOP')} NULL
 set sqlite_current_time 0
 
-# Negative years work.  Example:  '-4713-11-26' is JD 1.5.
-#
-datetest 9.1 {julianday('-4713-11-24 12:00:00')} {0.0}
-datetest 9.2 {julianday(datetime(5))} {5.0}
-datetest 9.3 {julianday(datetime(10))} {10.0}
-datetest 9.4 {julianday(datetime(100))} {100.0}
-datetest 9.5 {julianday(datetime(1000))} {1000.0}
-datetest 9.6 {julianday(datetime(10000))} {10000.0}
-datetest 9.7 {julianday(datetime(100000))} {100000.0}
-
 # datetime() with just an HH:MM:SS correctly inserts the date 2000-01-01.
 #
 datetest 10.1 {datetime('01:02:03')}  {2000-01-01 01:02:03}