SQLite

Check-in [48d5cab3ac]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update sessions branch with latest trunk changes.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: 48d5cab3ac08b25ec94d6ecfd25779320558110f
User & Date: dan 2011-06-22 12:01:09.000
Context
2011-06-23
02:11
Pull the latest trunk changes into the sessions branch. (check-in: 5d95b42946 user: drh tags: sessions)
2011-06-22
12:01
Update sessions branch with latest trunk changes. (check-in: 48d5cab3ac user: dan tags: sessions)
10:56
Change a test case in types3.test slightly so that it works with the latest versions of Tcl. (check-in: 6e1f4df51a user: dan tags: trunk)
2011-06-21
01:29
Merge the latest trunk changes into the sessions branch. (check-in: f3d148e0d1 user: drh tags: sessions)
Changes
Unified Diff Ignore Whitespace Patch
Changes to Makefile.msc.
110
111
112
113
114
115
116

117
118
119
120
121
122
123

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IF "$(PLATFORM)"!=""
LTLINKOPTS = /MACHINE:$(PLATFORM)

!ENDIF

# nawk compatible awk.
NAWK = .\gawk.exe

# You should not have to change anything below this line
###############################################################################







>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IF "$(PLATFORM)"!=""
LTLINKOPTS = /MACHINE:$(PLATFORM)
LTLIBOPTS = /MACHINE:$(PLATFORM)
!ENDIF

# nawk compatible awk.
NAWK = .\gawk.exe

# You should not have to change anything below this line
###############################################################################
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	libsqlite3.lib sqlite3.exe libtclsqlite3.lib

libsqlite3.lib:	$(LIBOBJ)
	$(LTLIB) -OUT:$@ $(LIBOBJ) $(TLIBS)

libtclsqlite3.lib:	tclsqlite.lo libsqlite3.lib
	$(LTLIB) /LIBPATH:$(TCLLIBDIR) -OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)

sqlite3.exe:	$(TOP)\src\shell.c libsqlite3.lib sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		$(TOP)\src\shell.c \
		/link $(LTLINKOPTS) libsqlite3.lib $(LIBREADLINE) $(TLIBS)

# This target creates a directory named "tsrc" and fills it with







|


|







438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

# This is the default Makefile target.  The objects listed here
# are what get build when you type just "make" with no arguments.
#
all:	libsqlite3.lib sqlite3.exe libtclsqlite3.lib

libsqlite3.lib:	$(LIBOBJ)
	$(LTLIB) $(LTLIBOPTS) /OUT:$@ $(LIBOBJ) $(TLIBS)

libtclsqlite3.lib:	tclsqlite.lo libsqlite3.lib
	$(LTLIB) $(LTLIBOPTS) /LIBPATH:$(TCLLIBDIR) /OUT:$@ tclsqlite.lo libsqlite3.lib $(LIBTCL:tcl=tclstub) $(TLIBS)

sqlite3.exe:	$(TOP)\src\shell.c libsqlite3.lib sqlite3.h
	$(LTLINK) $(READLINE_FLAGS) \
		$(TOP)\src\shell.c \
		/link $(LTLINKOPTS) libsqlite3.lib $(LIBREADLINE) $(TLIBS)

# This target creates a directory named "tsrc" and fills it with
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
soaktest:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\all.test -soak=1

test:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\veryquick.test

spaceanal_tcl.h:	$(TOP)\tool\spaceanal.tcl
	$(NAWK) "/^[^#]/ { gsub(/\\/,\"\\\\\\\\\");gsub(/\\\"/,\"\\\\\\\"\");gsub(/^/,\"\\\"\");gsub(/$$/,\"\\n\\\"\");print }" \
		$(TOP)\tool\spaceanal.tcl >spaceanal_tcl.h

sqlite3_analyzer.exe:	$(TESTFIXTURE_SRC) spaceanal_tcl.h
	$(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \
		-DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE \
		-DBUILD_sqlite -I$(TCLINCDIR) \
		$(TESTFIXTURE_SRC) \







|







834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
soaktest:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\all.test -soak=1

test:	testfixture.exe sqlite3.exe
	.\testfixture.exe $(TOP)\test\veryquick.test

spaceanal_tcl.h:	$(TOP)\tool\spaceanal.tcl
	$(NAWK) -f $(TOP)/tool/tostr.awk \
		$(TOP)\tool\spaceanal.tcl >spaceanal_tcl.h

sqlite3_analyzer.exe:	$(TESTFIXTURE_SRC) spaceanal_tcl.h
	$(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \
		-DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE \
		-DBUILD_sqlite -I$(TCLINCDIR) \
		$(TESTFIXTURE_SRC) \
867
868
869
870
871
872
873
874
sqlite3.def: libsqlite3.lib
	echo EXPORTS >sqlite3.def
	dumpbin /all libsqlite3.lib \
		| $(NAWK) "/ 1 _sqlite3_/ { sub(/^.* _/,\"\");print }" \
		| sort >>sqlite3.def

sqlite3.dll: $(LIBOBJ) sqlite3.def
	link /DLL /OUT:$@ /DEF:sqlite3.def $(LIBOBJ)







|
868
869
870
871
872
873
874
875
sqlite3.def: libsqlite3.lib
	echo EXPORTS >sqlite3.def
	dumpbin /all libsqlite3.lib \
		| $(NAWK) "/ 1 _sqlite3_/ { sub(/^.* _/,\"\");print }" \
		| sort >>sqlite3.def

sqlite3.dll: $(LIBOBJ) sqlite3.def
	link $(LTLINKOPTS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ)
Changes to main.mk.
217
218
219
220
221
222
223

224
225
226
227
228
229
230
  parse.h \
  sqlite3.h


# Source code to the test files.
#
TESTSRC = \

  $(TOP)/ext/fts3/fts3_test.c \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
  $(TOP)/src/test3.c \
  $(TOP)/src/test4.c \
  $(TOP)/src/test5.c \
  $(TOP)/src/test6.c \







>







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  parse.h \
  sqlite3.h


# Source code to the test files.
#
TESTSRC = \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_test.c \
  $(TOP)/src/test1.c \
  $(TOP)/src/test2.c \
  $(TOP)/src/test3.c \
  $(TOP)/src/test4.c \
  $(TOP)/src/test5.c \
  $(TOP)/src/test6.c \
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/where.c \
  parse.c \
  $(TOP)/ext/fts3/fts3.c \
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/session/test_session.c

# Header files used by all library source files.







<







298
299
300
301
302
303
304

305
306
307
308
309
310
311
  $(TOP)/src/vdbe.c \
  $(TOP)/src/vdbemem.c \
  $(TOP)/src/where.c \
  parse.c \
  $(TOP)/ext/fts3/fts3.c \
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \

  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/session/test_session.c

# Header files used by all library source files.
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
		-o threadtest3$(EXE) $(THREADLIB)

threadtest: threadtest3$(EXE)
	./threadtest3$(EXE)

sqlite3_analyzer$(EXE):	$(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \
			$(TOP)/tool/spaceanal.tcl
	sed \
	  -e '/^#/d' \
	  -e 's,\\,\\\\,g' \
	  -e 's,",\\",g' \
	  -e 's,^,",' \
	  -e 's,$$,\\n",' \
	  $(TOP)/tool/spaceanal.tcl >spaceanal_tcl.h
	$(TCCX) $(TCL_FLAGS) -DTCLSH=2 $(TESTFIXTURE_FLAGS)                    \
		-DSQLITE_TEST=1 -DSQLITE_PRIVATE=""                            \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c                    \
		-o sqlite3_analyzer$(EXE)                                      \
		$(LIBTCL) $(THREADLIB)

TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO)







|
<
<
<
<
<
|







549
550
551
552
553
554
555
556





557
558
559
560
561
562
563
564
		-o threadtest3$(EXE) $(THREADLIB)

threadtest: threadtest3$(EXE)
	./threadtest3$(EXE)

sqlite3_analyzer$(EXE):	$(TOP)/src/tclsqlite.c sqlite3.c $(TESTSRC) \
			$(TOP)/tool/spaceanal.tcl
	$(NAWK) -f $(TOP)/tool/tostr.awk $(TOP)/tool/spaceanal.tcl \





		 >spaceanal_tcl.h
	$(TCCX) $(TCL_FLAGS) -DTCLSH=2 $(TESTFIXTURE_FLAGS)                    \
		-DSQLITE_TEST=1 -DSQLITE_PRIVATE=""                            \
		$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c                    \
		-o sqlite3_analyzer$(EXE)                                      \
		$(LIBTCL) $(THREADLIB)

TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO)
Changes to src/date.c.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#include <time.h>

#ifndef SQLITE_OMIT_DATETIME_FUNCS

/*
** On recent Windows platforms, the localtime_s() function is available
** as part of the "Secure CRT". It is essentially equivalent to 
** localtime_r() available under most POSIX platforms, except that the 
** order of the parameters is reversed.
**
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
**
** If the user has not indicated to use localtime_r() or localtime_s()
** already, check for an MSVC build environment that provides 
** localtime_s().
*/
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
#define HAVE_LOCALTIME_S 1
#endif

/*
** A structure for holding a single date and time.
*/
typedef struct DateTime DateTime;
struct DateTime {
  sqlite3_int64 iJD; /* The julian day number times 86400000 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







46
47
48
49
50
51
52
















53
54
55
56
57
58
59
#include "sqliteInt.h"
#include <stdlib.h>
#include <assert.h>
#include <time.h>

#ifndef SQLITE_OMIT_DATETIME_FUNCS


















/*
** A structure for holding a single date and time.
*/
typedef struct DateTime DateTime;
struct DateTime {
  sqlite3_int64 iJD; /* The julian day number times 86400000 */
406
407
408
409
410
411
412
413

















414
415







































416
417
418




419
420




421
422





423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480

481
482
483
484
485
486
487
** Clear the YMD and HMS and the TZ
*/
static void clearYMD_HMS_TZ(DateTime *p){
  p->validYMD = 0;
  p->validHMS = 0;
  p->validTZ = 0;
}


















#ifndef SQLITE_OMIT_LOCALTIME
/*







































** Compute the difference (in milliseconds)
** between localtime and UTC (a.k.a. GMT)
** for the time value p where p is in UTC.




*/
static sqlite3_int64 localtimeOffset(DateTime *p){




  DateTime x, y;
  time_t t;





  x = *p;
  computeYMD_HMS(&x);
  if( x.Y<1971 || x.Y>=2038 ){
    x.Y = 2000;
    x.M = 1;
    x.D = 1;
    x.h = 0;
    x.m = 0;
    x.s = 0.0;
  } else {
    int s = (int)(x.s + 0.5);
    x.s = s;
  }
  x.tz = 0;
  x.validJD = 0;
  computeJD(&x);
  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
#ifdef HAVE_LOCALTIME_R
  {
    struct tm sLocal;
    localtime_r(&t, &sLocal);
    y.Y = sLocal.tm_year + 1900;
    y.M = sLocal.tm_mon + 1;
    y.D = sLocal.tm_mday;
    y.h = sLocal.tm_hour;
    y.m = sLocal.tm_min;
    y.s = sLocal.tm_sec;
  }
#elif defined(HAVE_LOCALTIME_S) && HAVE_LOCALTIME_S
  {
    struct tm sLocal;
    localtime_s(&sLocal, &t);
    y.Y = sLocal.tm_year + 1900;
    y.M = sLocal.tm_mon + 1;
    y.D = sLocal.tm_mday;
    y.h = sLocal.tm_hour;
    y.m = sLocal.tm_min;
    y.s = sLocal.tm_sec;
  }
#else
  {
    struct tm *pTm;
    sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
    pTm = localtime(&t);
    y.Y = pTm->tm_year + 1900;
    y.M = pTm->tm_mon + 1;
    y.D = pTm->tm_mday;
    y.h = pTm->tm_hour;
    y.m = pTm->tm_min;
    y.s = pTm->tm_sec;
    sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  }
#endif
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);

  return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */

/*
** Process a modifier to a date-time stamp.  The modifiers are
** as follows:








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
>
>
>
>

|
>
>
>
>


>
>
>
>
>

















<
<
<
|
|
<
|
|
<
<

<
<
<
<
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491



492
493

494
495


496




497
498
499
500
501
502















503
504
505
506
507
508
509
510
511
512
513
514
515
** Clear the YMD and HMS and the TZ
*/
static void clearYMD_HMS_TZ(DateTime *p){
  p->validYMD = 0;
  p->validHMS = 0;
  p->validTZ = 0;
}

/*
** On recent Windows platforms, the localtime_s() function is available
** as part of the "Secure CRT". It is essentially equivalent to 
** localtime_r() available under most POSIX platforms, except that the 
** order of the parameters is reversed.
**
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
**
** If the user has not indicated to use localtime_r() or localtime_s()
** already, check for an MSVC build environment that provides 
** localtime_s().
*/
#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE_LOCALTIME_S) && \
     defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
#define HAVE_LOCALTIME_S 1
#endif

#ifndef SQLITE_OMIT_LOCALTIME
/*
** The following routine implements the rough equivalent of localtime_r()
** using whatever operating-system specific localtime facility that
** is available.  This routine returns 0 on success and
** non-zero on any kind of error.
**
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
** routine will always fail.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
  int rc;
#if (!defined(HAVE_LOCALTIME_R) || !HAVE_LOCALTIME_R) \
      && (!defined(HAVE_LOCALTIME_S) || !HAVE_LOCALTIME_S)
  struct tm *pX;
  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(mutex);
  pX = localtime(t);
#ifndef SQLITE_OMIT_BUILTIN_TEST
  if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
#endif
  if( pX ) *pTm = *pX;
  sqlite3_mutex_leave(mutex);
  rc = pX==0;
#else
#ifndef SQLITE_OMIT_BUILTIN_TEST
  if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
#endif
#if defined(HAVE_LOCALTIME_R) && HAVE_LOCALTIME_R
  rc = localtime_r(t, pTm)==0;
#else
  rc = localtime_s(pTm, t);
#endif /* HAVE_LOCALTIME_R */
#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
  return rc;
}
#endif /* SQLITE_OMIT_LOCALTIME */


#ifndef SQLITE_OMIT_LOCALTIME
/*
** Compute the difference (in milliseconds) between localtime and UTC

** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
** return this value and set *pRc to SQLITE_OK. 
**
** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
** is undefined in this case.
*/
static sqlite3_int64 localtimeOffset(
  DateTime *p,                    /* Date at which to calculate offset */
  sqlite3_context *pCtx,          /* Write error here if one occurs */
  int *pRc                        /* OUT: Error code. SQLITE_OK or ERROR */
){
  DateTime x, y;
  time_t t;
  struct tm sLocal;

  /* Initialize the contents of sLocal to avoid a compiler warning. */
  memset(&sLocal, 0, sizeof(sLocal));

  x = *p;
  computeYMD_HMS(&x);
  if( x.Y<1971 || x.Y>=2038 ){
    x.Y = 2000;
    x.M = 1;
    x.D = 1;
    x.h = 0;
    x.m = 0;
    x.s = 0.0;
  } else {
    int s = (int)(x.s + 0.5);
    x.s = s;
  }
  x.tz = 0;
  x.validJD = 0;
  computeJD(&x);
  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);



  if( osLocaltime(&t, &sLocal) ){
    sqlite3_result_error(pCtx, "local time unavailable", -1);

    *pRc = SQLITE_ERROR;
    return 0;


  }




  y.Y = sLocal.tm_year + 1900;
  y.M = sLocal.tm_mon + 1;
  y.D = sLocal.tm_mday;
  y.h = sLocal.tm_hour;
  y.m = sLocal.tm_min;
  y.s = sLocal.tm_sec;















  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);
  *pRc = SQLITE_OK;
  return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */

/*
** Process a modifier to a date-time stamp.  The modifiers are
** as follows:
497
498
499
500
501
502
503
504



505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549

550
551
552
553

554
555
556
557
558
559
560
**     start of week
**     start of day
**     weekday N
**     unixepoch
**     localtime
**     utc
**
** Return 0 on success and 1 if there is any kind of error.



*/
static int parseModifier(const char *zMod, DateTime *p){
  int rc = 1;
  int n;
  double r;
  char *z, zBuf[30];
  z = zBuf;
  for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
    z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
  }
  z[n] = 0;
  switch( z[0] ){
#ifndef SQLITE_OMIT_LOCALTIME
    case 'l': {
      /*    localtime
      **
      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
      ** show local time.
      */
      if( strcmp(z, "localtime")==0 ){
        computeJD(p);
        p->iJD += localtimeOffset(p);
        clearYMD_HMS_TZ(p);
        rc = 0;
      }
      break;
    }
#endif
    case 'u': {
      /*
      **    unixepoch
      **
      ** Treat the current value of p->iJD as the number of
      ** seconds since 1970.  Convert to a real julian day number.
      */
      if( strcmp(z, "unixepoch")==0 && p->validJD ){
        p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
        clearYMD_HMS_TZ(p);
        rc = 0;
      }
#ifndef SQLITE_OMIT_LOCALTIME
      else if( strcmp(z, "utc")==0 ){
        sqlite3_int64 c1;
        computeJD(p);
        c1 = localtimeOffset(p);

        p->iJD -= c1;
        clearYMD_HMS_TZ(p);
        p->iJD += c1 - localtimeOffset(p);
        rc = 0;

      }
#endif
      break;
    }
    case 'w': {
      /*
      **    weekday N







|
>
>
>

|



















|

<




















|
>
|
|
|
<
>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591
**     start of week
**     start of day
**     weekday N
**     unixepoch
**     localtime
**     utc
**
** Return 0 on success and 1 if there is any kind of error. If the error
** is in a system call (i.e. localtime()), then an error message is written
** to context pCtx. If the error is an unrecognized modifier, no error is
** written to pCtx.
*/
static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
  int rc = 1;
  int n;
  double r;
  char *z, zBuf[30];
  z = zBuf;
  for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
    z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
  }
  z[n] = 0;
  switch( z[0] ){
#ifndef SQLITE_OMIT_LOCALTIME
    case 'l': {
      /*    localtime
      **
      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
      ** show local time.
      */
      if( strcmp(z, "localtime")==0 ){
        computeJD(p);
        p->iJD += localtimeOffset(p, pCtx, &rc);
        clearYMD_HMS_TZ(p);

      }
      break;
    }
#endif
    case 'u': {
      /*
      **    unixepoch
      **
      ** Treat the current value of p->iJD as the number of
      ** seconds since 1970.  Convert to a real julian day number.
      */
      if( strcmp(z, "unixepoch")==0 && p->validJD ){
        p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
        clearYMD_HMS_TZ(p);
        rc = 0;
      }
#ifndef SQLITE_OMIT_LOCALTIME
      else if( strcmp(z, "utc")==0 ){
        sqlite3_int64 c1;
        computeJD(p);
        c1 = localtimeOffset(p, pCtx, &rc);
        if( rc==SQLITE_OK ){
          p->iJD -= c1;
          clearYMD_HMS_TZ(p);
          p->iJD += c1 - localtimeOffset(p, pCtx, &rc);

        }
      }
#endif
      break;
    }
    case 'w': {
      /*
      **    weekday N
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  }else{
    z = sqlite3_value_text(argv[0]);
    if( !z || parseDateOrTime(context, (char*)z, p) ){
      return 1;
    }
  }
  for(i=1; i<argc; i++){
    if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){
      return 1;
    }
  }
  return 0;
}


/*
** The following routines implement the various date and time functions







|
|
<







758
759
760
761
762
763
764
765
766

767
768
769
770
771
772
773
  }else{
    z = sqlite3_value_text(argv[0]);
    if( !z || parseDateOrTime(context, (char*)z, p) ){
      return 1;
    }
  }
  for(i=1; i<argc; i++){
    z = sqlite3_value_text(argv[i]);
    if( z==0 || parseModifier(context, (char*)z, p) ) return 1;

  }
  return 0;
}


/*
** The following routines implement the various date and time functions
Changes to src/global.c.
165
166
167
168
169
170
171

172
173
174
175
176
177
178
   0,                         /* isMutexInit */
   0,                         /* isMallocInit */
   0,                         /* isPCacheInit */
   0,                         /* pInitMutex */
   0,                         /* nRefInitMutex */
   0,                         /* xLog */
   0,                         /* pLogArg */

};


/*
** Hash table for global functions - functions common to all
** database connections.  After initialization, this table is
** read-only.







>







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
   0,                         /* isMutexInit */
   0,                         /* isMallocInit */
   0,                         /* isPCacheInit */
   0,                         /* pInitMutex */
   0,                         /* nRefInitMutex */
   0,                         /* xLog */
   0,                         /* pLogArg */
   0,                         /* bLocaltimeFault */
};


/*
** Hash table for global functions - functions common to all
** database connections.  After initialization, this table is
** read-only.
Changes to src/main.c.
2919
2920
2921
2922
2923
2924
2925











2926
2927
2928
2929
2930
2931
2932
      sz = va_arg(ap, int);
      ppNew = va_arg(ap, void**);
      pFree = va_arg(ap, void*);
      if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
      sqlite3ScratchFree(pFree);
      break;
    }












  }
  va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
  return rc;
}








>
>
>
>
>
>
>
>
>
>
>







2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
      sz = va_arg(ap, int);
      ppNew = va_arg(ap, void**);
      pFree = va_arg(ap, void*);
      if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
      sqlite3ScratchFree(pFree);
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
    **
    ** If parameter onoff is non-zero, configure the wrappers so that all
    ** subsequent calls to localtime() and variants fail. If onoff is zero,
    ** undo this setting.
    */
    case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
      sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
      break;
    }

  }
  va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
  return rc;
}

Changes to src/sqlite.h.in.
5569
5570
5571
5572
5573
5574
5575

5576
5577
5578
5579
5580
5581
5582
5583
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_PGHDRSZ                 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC           18

#define SQLITE_TESTCTRL_LAST                    18

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for







>
|







5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
#define SQLITE_TESTCTRL_ASSERT                  12
#define SQLITE_TESTCTRL_ALWAYS                  13
#define SQLITE_TESTCTRL_RESERVE                 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_PGHDRSZ                 17
#define SQLITE_TESTCTRL_SCRATCHMALLOC           18
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         19
#define SQLITE_TESTCTRL_LAST                    19

/*
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
Changes to src/sqliteInt.h.
2457
2458
2459
2460
2461
2462
2463

2464
2465
2466
2467
2468
2469
2470
  int isMutexInit;                  /* True after mutexes are initialized */
  int isMallocInit;                 /* True after malloc is initialized */
  int isPCacheInit;                 /* True after malloc is initialized */
  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
  int nRefInitMutex;                /* Number of users of pInitMutex */
  void (*xLog)(void*,int,const char*); /* Function for logging */
  void *pLogArg;                       /* First argument to xLog() */

};

/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */







>







2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
  int isMutexInit;                  /* True after mutexes are initialized */
  int isMallocInit;                 /* True after malloc is initialized */
  int isPCacheInit;                 /* True after malloc is initialized */
  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
  int nRefInitMutex;                /* Number of users of pInitMutex */
  void (*xLog)(void*,int,const char*); /* Function for logging */
  void *pLogArg;                       /* First argument to xLog() */
  int bLocaltimeFault;              /* True to fail localtime() calls */
};

/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
Changes to src/test1.c.
5517
5518
5519
5520
5521
5522
5523
















































5524
5525
5526
5527
5528
5529
5530
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  rc = printExplainQueryPlan(pStmt);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}
#endif /* SQLITE_OMIT_EXPLAIN */

















































/*
**      optimization_control DB OPT BOOLEAN
**
** Enable or disable query optimizations using the sqlite3_test_control()
** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
** OPT is the name of the optimization to be disabled.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  rc = printExplainQueryPlan(pStmt);
  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  return TCL_OK;
}
#endif /* SQLITE_OMIT_EXPLAIN */

/*
** sqlite3_test_control VERB ARGS...
*/
static int test_test_control(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  struct Verb {
    const char *zName;
    int i;
  } aVerb[] = {
    { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, 
  };
  int iVerb;
  int iFlag;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
    return TCL_ERROR;
  }

  rc = Tcl_GetIndexFromObjStruct(
      interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
  );
  if( rc!=TCL_OK ) return rc;

  iFlag = aVerb[iVerb].i;
  switch( iFlag ){
    case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
      int val;
      if( objc!=3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
        return TCL_ERROR;
      }
      if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
      sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
      break;
    }
  }

  Tcl_ResetResult(interp);
  return TCL_OK;
}


/*
**      optimization_control DB OPT BOOLEAN
**
** Enable or disable query optimizations using the sqlite3_test_control()
** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
** OPT is the name of the optimization to be disabled.
5781
5782
5783
5784
5785
5786
5787

5788
5789
5790
5791
5792
5793
5794
#endif
     { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
     { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
     { "test_sqlite3_log",         test_sqlite3_log, 0  },
#ifndef SQLITE_OMIT_EXPLAIN
     { "print_explain_query_plan", test_print_eqp, 0  },
#endif

  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;







>







5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
#endif
     { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  },
     { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  },
     { "test_sqlite3_log",         test_sqlite3_log, 0  },
#ifndef SQLITE_OMIT_EXPLAIN
     { "print_explain_query_plan", test_print_eqp, 0  },
#endif
     { "sqlite3_test_control", test_test_control },
  };
  static int bitmask_size = sizeof(Bitmask)*8;
  int i;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_like_count;
  extern int sqlite3_xferopt_count;
Changes to src/test_vfs.c.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
*/
struct Testvfs {
  char *zName;                    /* Name of this VFS */
  sqlite3_vfs *pParent;           /* The VFS to use for file IO */
  sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
  Tcl_Interp *interp;             /* Interpreter to run script in */
  Tcl_Obj *pScript;               /* Script to execute */
  int nScript;                    /* Number of elements in array apScript */
  Tcl_Obj **apScript;             /* Array version of pScript */
  TestvfsBuffer *pBuffer;         /* List of shared buffers */
  int isNoshm;

  int mask;                       /* Mask controlling [script] and [ioerr] */

  TestFaultInject ioerr_err;
  TestFaultInject full_err;







<
<







75
76
77
78
79
80
81


82
83
84
85
86
87
88
*/
struct Testvfs {
  char *zName;                    /* Name of this VFS */
  sqlite3_vfs *pParent;           /* The VFS to use for file IO */
  sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
  Tcl_Interp *interp;             /* Interpreter to run script in */
  Tcl_Obj *pScript;               /* Script to execute */


  TestvfsBuffer *pBuffer;         /* List of shared buffers */
  int isNoshm;

  int mask;                       /* Mask controlling [script] and [ioerr] */

  TestFaultInject ioerr_err;
  TestFaultInject full_err;
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299




300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  Testvfs *p, 
  const char *zMethod,
  Tcl_Obj *arg1,
  Tcl_Obj *arg2,
  Tcl_Obj *arg3
){
  int rc;                         /* Return code from Tcl_EvalObj() */
  int nArg;                       /* Elements in eval'd list */
  int nScript;
  Tcl_Obj ** ap;

  assert( p->pScript );

  if( !p->apScript ){
    int nByte;
    int i;
    if( TCL_OK!=Tcl_ListObjGetElements(p->interp, p->pScript, &nScript, &ap) ){
      Tcl_BackgroundError(p->interp);
      Tcl_ResetResult(p->interp);
      return;
    }
    p->nScript = nScript;
    nByte = (nScript+TESTVFS_MAX_ARGS)*sizeof(Tcl_Obj *);
    p->apScript = (Tcl_Obj **)ckalloc(nByte);
    memset(p->apScript, 0, nByte);
    for(i=0; i<nScript; i++){
      p->apScript[i] = ap[i];
    }
  }

  p->apScript[p->nScript] = Tcl_NewStringObj(zMethod, -1);
  p->apScript[p->nScript+1] = arg1;
  p->apScript[p->nScript+2] = arg2;
  p->apScript[p->nScript+3] = arg3;

  for(nArg=p->nScript; p->apScript[nArg]; nArg++){
    Tcl_IncrRefCount(p->apScript[nArg]);




  }

  rc = Tcl_EvalObjv(p->interp, nArg, p->apScript, TCL_EVAL_GLOBAL);
  if( rc!=TCL_OK ){
    Tcl_BackgroundError(p->interp);
    Tcl_ResetResult(p->interp);
  }

  for(nArg=p->nScript; p->apScript[nArg]; nArg++){
    Tcl_DecrRefCount(p->apScript[nArg]);
    p->apScript[nArg] = 0;
  }
}


/*
** Close an tvfs-file.
*/
static int tvfsClose(sqlite3_file *pFile){







<
<
|
<


<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
|
|

|
|
>
>
>
>
|
|
<




<
<
<
<
<







261
262
263
264
265
266
267


268

269
270






271









272


273
274
275
276
277
278
279
280
281
282
283

284
285
286
287





288
289
290
291
292
293
294
  Testvfs *p, 
  const char *zMethod,
  Tcl_Obj *arg1,
  Tcl_Obj *arg2,
  Tcl_Obj *arg3
){
  int rc;                         /* Return code from Tcl_EvalObj() */


  Tcl_Obj *pEval;

  assert( p->pScript );







  assert( zMethod );









  assert( p );


  assert( arg2==0 || arg1!=0 );
  assert( arg3==0 || arg2!=0 );

  pEval = Tcl_DuplicateObj(p->pScript);
  Tcl_IncrRefCount(p->pScript);
  Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1));
  if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1);
  if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2);
  if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3);

  rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);

  if( rc!=TCL_OK ){
    Tcl_BackgroundError(p->interp);
    Tcl_ResetResult(p->interp);
  }





}


/*
** Close an tvfs-file.
*/
static int tvfsClose(sqlite3_file *pFile){
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
      break;
    }

    case CMD_SCRIPT: {
      if( objc==3 ){
        int nByte;
        if( p->pScript ){

          Tcl_DecrRefCount(p->pScript);
          ckfree((char *)p->apScript);
          p->apScript = 0;
          p->nScript = 0;
          p->pScript = 0;
        }
        Tcl_GetStringFromObj(objv[2], &nByte);
        if( nByte>0 ){
          p->pScript = Tcl_DuplicateObj(objv[2]);
          Tcl_IncrRefCount(p->pScript);
        }







>

<
<
<







1066
1067
1068
1069
1070
1071
1072
1073
1074



1075
1076
1077
1078
1079
1080
1081
      break;
    }

    case CMD_SCRIPT: {
      if( objc==3 ){
        int nByte;
        if( p->pScript ){
          int i;
          Tcl_DecrRefCount(p->pScript);



          p->pScript = 0;
        }
        Tcl_GetStringFromObj(objv[2], &nByte);
        if( nByte>0 ){
          p->pScript = Tcl_DuplicateObj(objv[2]);
          Tcl_IncrRefCount(p->pScript);
        }
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
  }

  return TCL_OK;
}

static void testvfs_obj_del(ClientData cd){
  Testvfs *p = (Testvfs *)cd;

  if( p->pScript ) Tcl_DecrRefCount(p->pScript);
  sqlite3_vfs_unregister(p->pVfs);
  ckfree((char *)p->apScript);
  ckfree((char *)p->pVfs);
  ckfree((char *)p);
}

/*
** Usage:  testvfs VFSNAME ?SWITCHES?
**







>


<







1219
1220
1221
1222
1223
1224
1225
1226
1227
1228

1229
1230
1231
1232
1233
1234
1235
  }

  return TCL_OK;
}

static void testvfs_obj_del(ClientData cd){
  Testvfs *p = (Testvfs *)cd;
  int i;
  if( p->pScript ) Tcl_DecrRefCount(p->pScript);
  sqlite3_vfs_unregister(p->pVfs);

  ckfree((char *)p->pVfs);
  ckfree((char *)p);
}

/*
** Usage:  testvfs VFSNAME ?SWITCHES?
**
Changes to test/e_uri.test.
116
117
118
119
120
121
122




123
124
125
126
127
128
129
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
}





# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
# "localhost", an error is returned to the caller.
#
if {$tcl_platform(platform) == "unix"} {
  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
  foreach {tn uri error} "







>
>
>
>







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
    sqlite3_step $STMT
    sqlite3_finalize $STMT
    list [file exists file:test.db2] [file exists test.db2]
  } {0 1}
  sqlite3_close $DB
}

# ensure uri processing enabled for the rest of the tests
sqlite3_shutdown
sqlite3_config_uri 1

# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
# "localhost", an error is returned to the caller.
#
if {$tcl_platform(platform) == "unix"} {
  set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
  foreach {tn uri error} "
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    } $error
  }
}

# EVIDENCE-OF: R-45981-25528 The fragment component of a URI, if
# present, is ignored.
#
#   It is difficult to test that something is ignore correctly. So these tests
#   just show that adding a fragment does not interfere with the pathname or
#   parameters passed through to the VFS xOpen() methods.
#
if {$tcl_platform(platform) == "unix"} {
  foreach {tn uri parse} "
    1    {file:test.db#abc}     {[pwd]/test.db {}}
    2    {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
    3    {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
  " {
    do_test 3.$tn { parse_uri $uri } $parse
  }
}

# EVIDENCE-OF: R-62557-09390 SQLite uses the path component of the URI
# as the name of the disk file which contains the database.
#
# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
# then it is interpreted as an absolute path.
#
# EVIDENCE-OF: R-46234-61323 If the path does not begin with a '/'
# (meaning that the authority section is omitted from the URI) then the
# path is interpreted as a relative path.
#
if {$tcl_platform(platform) == "unix"} {
  foreach {tn uri parse} "
    1    {file:test.db}             {[pwd]/test.db {}}
    2    {file:/test.db}            {/test.db {}}
    3    {file:///test.db}          {/test.db {}}
    4    {file://localhost/test.db} {/test.db {}}
    5    {file:/a/b/c/test.db}      {/a/b/c/test.db {}}
  " {
    do_test 4.$tn { parse_uri $uri } $parse
  }
}

# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
# the name of a VFS object that provides the operating system interface
# that should be used to access the database file on disk.
#
#   The above is tested by cases 1.* below.







|



<
|
|
|
|
|
|
<












<
|
|
|
|
|
|
|
|
<







144
145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172

173
174
175
176
177
178
179
180

181
182
183
184
185
186
187
    } $error
  }
}

# EVIDENCE-OF: R-45981-25528 The fragment component of a URI, if
# present, is ignored.
#
#   It is difficult to test that something is ignored correctly. So these tests
#   just show that adding a fragment does not interfere with the pathname or
#   parameters passed through to the VFS xOpen() methods.
#

foreach {tn uri parse} "
  1    {file:test.db#abc}     {[pwd]/test.db {}}
  2    {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
  3    {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
" {
  do_filepath_test 3.$tn { parse_uri $uri } $parse

}

# EVIDENCE-OF: R-62557-09390 SQLite uses the path component of the URI
# as the name of the disk file which contains the database.
#
# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
# then it is interpreted as an absolute path.
#
# EVIDENCE-OF: R-46234-61323 If the path does not begin with a '/'
# (meaning that the authority section is omitted from the URI) then the
# path is interpreted as a relative path.
#

foreach {tn uri parse} "
  1    {file:test.db}             {[pwd]/test.db {}}
  2    {file:/test.db}            {/test.db {}}
  3    {file:///test.db}          {/test.db {}}
  4    {file://localhost/test.db} {/test.db {}}
  5    {file:/a/b/c/test.db}      {/a/b/c/test.db {}}
" {
  do_filepath_test 4.$tn { parse_uri $uri } $parse

}

# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
# the name of a VFS object that provides the operating system interface
# that should be used to access the database file on disk.
#
#   The above is tested by cases 1.* below.
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
# database is opened for read-write (but not create) access, as if
# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
#
# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
#
sqlite3_shutdown
sqlite3_config_uri 1
foreach {tn uri read write create} {
  1    {file:test.db?mode=ro}     1 0 0
  2    {file:test.db?mode=rw}     1 1 0
  3    {file:test.db?mode=rwc}    1 1 1
} {
  set RES(c,0) {1 {unable to open database file}}
  set RES(c,1) {0 {}}







<
<







266
267
268
269
270
271
272


273
274
275
276
277
278
279
# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
# database is opened for read-write (but not create) access, as if
# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
#
# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
#


foreach {tn uri read write create} {
  1    {file:test.db?mode=ro}     1 0 0
  2    {file:test.db?mode=rw}     1 1 0
  3    {file:test.db?mode=rwc}    1 1 1
} {
  set RES(c,0) {1 {unable to open database file}}
  set RES(c,1) {0 {}}
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  db close
}
sqlite3_enable_shared_cache $orig

# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
# query component of a URI is not an error.
#
do_test 12.1 {
  parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
} {/test.db {an unknown parameter is ok {}}}
do_test 12.2 {
  parse_uri file://localhost/test.db?an&unknown&parameter&is&ok
} {/test.db {an {} unknown {} parameter {} is {} ok {}}}

# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
# supported within the path and query components of a URI.
#
# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
# URI filename are interpreted, they are encoded using UTF-8 and all
# hexadecimal escape sequences replaced by a single byte containing the
# corresponding octet.
#
#   The second of the two statements above is tested by creating a
#   multi-byte utf-8 character using a sequence of %HH escapes.
#
foreach {tn uri parse} "
  1  {file:/test.%64%62}                             {/test.db {}}
  2  {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
  3  {file:/%C3%BF.db}                               {/\xFF.db {}}
" {
  do_test 13.$tn { parse_uri $uri } $parse
}

finish_test







|


|



















|



423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  db close
}
sqlite3_enable_shared_cache $orig

# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
# query component of a URI is not an error.
#
do_filepath_test 12.1 {
  parse_uri file://localhost/test.db?an=unknown&parameter=is&ok=
} {/test.db {an unknown parameter is ok {}}}
do_filepath_test 12.2 {
  parse_uri file://localhost/test.db?an&unknown&parameter&is&ok
} {/test.db {an {} unknown {} parameter {} is {} ok {}}}

# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
# supported within the path and query components of a URI.
#
# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
# URI filename are interpreted, they are encoded using UTF-8 and all
# hexadecimal escape sequences replaced by a single byte containing the
# corresponding octet.
#
#   The second of the two statements above is tested by creating a
#   multi-byte utf-8 character using a sequence of %HH escapes.
#
foreach {tn uri parse} "
  1  {file:/test.%64%62}                             {/test.db {}}
  2  {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
  3  {file:/%C3%BF.db}                               {/\xFF.db {}}
" {
  do_filepath_test 13.$tn { parse_uri $uri } $parse
}

finish_test
Changes to test/tester.tcl.
349
350
351
352
353
354
355















356
357
358
359
360
361
362
    puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
    fail_test $name
  } else {
    puts " Ok"
  }
  flush stdout
}
















proc realnum_normalize {r} {
  # different TCL versions display floating point values differently.
  string map {1.#INF inf Inf inf .0e e} [regsub -all {(e[+-])0+} $r {\1}]
}
proc do_realnum_test {name cmd expected} {
  uplevel [list do_test $name [







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
    puts "\nExpected: \[$expected\]\n     Got: \[$result\]"
    fail_test $name
  } else {
    puts " Ok"
  }
  flush stdout
}

proc filepath_normalize {p} {
  # test cases should be written to assume "unix"-like file paths
  if {$::tcl_platform(platform)!="unix"} {
    # lreverse*2 as a hack to remove any unneeded {} after the string map
    lreverse [lreverse [string map {\\ /} [regsub -nocase -all {[a-z]:[/\\]+} $p {/}]]]
  } {
    set p
  }
}
proc do_filepath_test {name cmd expected} {
  uplevel [list do_test $name [
    subst -nocommands { filepath_normalize [ $cmd ] }
  ] [filepath_normalize $expected]]
}

proc realnum_normalize {r} {
  # different TCL versions display floating point values differently.
  string map {1.#INF inf Inf inf .0e e} [regsub -all {(e[+-])0+} $r {\1}]
}
proc do_realnum_test {name cmd expected} {
  uplevel [list do_test $name [
Added test/tkt-bd484a090c.test.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 2011 June 21
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains tests for SQLite. Specifically, it tests that SQLite
# does not crash and an error is returned if localhost() fails. This 
# is the problem reported by ticket bd484a090c.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix tkt-bd484a090c


do_test 1.1 {
  lindex [catchsql { SELECT datetime('now', 'localtime') }] 0
} {0}
do_test 1.2 {
  lindex [catchsql { SELECT datetime('now', 'utc') }] 0
} {0}

sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 1

do_test 2.1 {
  catchsql { SELECT datetime('now', 'localtime') }
} {1 {local time unavailable}}
do_test 2.2 {
  catchsql { SELECT datetime('now', 'utc') }
} {1 {local time unavailable}}

sqlite3_test_control SQLITE_TESTCTRL_LOCALTIME_FAULT 0

finish_test
Changes to test/types3.test.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# A variable with only a string representation comes in as TEXT
do_test types3-1.1 {
  set V {}
  append V {}
  concat [tcl_variable_type V] [execsql {SELECT typeof(:V)}]
} {string text}

# A variable with an integer representation comes in as INTEGER
do_test types3-1.2 {
  set V [expr {int(1+2)}]
  concat [tcl_variable_type V] [execsql {SELECT typeof(:V)}]







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# A variable with only a string representation comes in as TEXT
do_test types3-1.1 {
  set V {}
  append V x
  concat [tcl_variable_type V] [execsql {SELECT typeof(:V)}]
} {string text}

# A variable with an integer representation comes in as INTEGER
do_test types3-1.2 {
  set V [expr {int(1+2)}]
  concat [tcl_variable_type V] [execsql {SELECT typeof(:V)}]
Added tool/tostr.awk.


















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
#!/usr/bin/awk
#
# Convert input text into a C string
#
{
  gsub(/\\/,"\\\\");
  gsub(/\"/,"\\\"");
  print "\"" $0 "\\n\"";
}