Documentation Source Text
Check-in [1bbb35f908]
Not logged in

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

Overview
SHA1 Hash:1bbb35f90846659105e9ad4e69b37448b4753dea
Date: 2012-10-30 18:15:20
User: drh
Comment:Import the download page changes from the 3.7.14 branch.
Tags And Properties
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to misc/althttpd.c

77
78
79
80
81
82
83

84
85
86
87
88
89
90
...
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
...
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
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
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
...
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
....
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
....
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
....
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <time.h>
#include <sys/times.h>
#include <netdb.h>
#include <errno.h>

#ifdef linux
#include <sys/sendfile.h>
#endif
#include <assert.h>

/*
** Configure the server by setting the following macros and recompiling.
................................................................................
  FILE *log;
  if( zTmpNam ){
    unlink(zTmpNam);
  }
  if( zLogFile && !omitLog ){
    time_t now;
    struct tm *pTm;
    struct tms sTms;
    double rScale;
    int i;

    char zDate[200];
    char *zRM = zRemoteUser ? zRemoteUser : "*";

    if( zScript==0 || zScript[0]==0 ) zScript = "*";
    if( zRemoteAddr==0 || zRemoteAddr[0]==0 ) zRemoteAddr = "*";
    if( zHttpHost==0 || zHttpHost[0]==0 ) zHttpHost = "*";
    if( zReferer==0 || zReferer[0]==0 ) zReferer = "*";
................................................................................
    for(i=0; zReferer[i]; i++){ 
      if( isspace(zReferer[i]) ){ zReferer = "*"; break; }
    }
    if( zAgent==0 || zAgent[0]==0 ) zAgent = "*";
    time(&now);
    pTm = localtime(&now);
    strftime(zDate, sizeof(zDate), "%Y-%m-%d %H:%M:%S", pTm);
    times(&sTms);
    rScale = 1.0/(double)sysconf(_SC_CLK_TCK);

    if( (log = fopen(zLogFile,"a"))!=0 ){
#ifdef COMBINED_LOG_FORMAT
      strftime(zDate, sizeof(zDate), "%d/%b/%Y:%H:%M:%S %z", pTm);
      fprintf(log, "%s - - [%s] \"%s %s %s\" %s %d \"%s\" \"%s\"\n",
              zRemoteAddr, zDate, zMethod, zScript, zProtocol,
              zReplyStatus, nOut, zReferer, zAgent);
#else
      strftime(zDate, sizeof(zDate), "%Y-%m-%d %H:%M:%S", pTm);
      fprintf(log, "%s %s %s://%s%s %s %s %d %d %g %g %g %g %d %d %s %s\n", 
          zDate, zRemoteAddr, zHttp, zHttpHost, zScript, zReferer,
          zReplyStatus, nIn, nOut,
          rScale*sTms.tms_utime,
          rScale*sTms.tms_stime,
          rScale*sTms.tms_cutime,
          rScale*sTms.tms_cstime,
          (int)(now - beginTime),
          nRequest, zAgent, zRM
      );
#endif
      fclose(log);
      nIn = nOut = 0;
    }
................................................................................
  exit(0);
}

/*
** This is called if we timeout.
*/
static void Timeout(int NotUsed){

  if( !debugFlag ){
    strcpy(zReplyStatus, "999");
    MakeLogEntry(0);
    exit(0);
  }
}

/*
** Tell the client that there is an error in the script.
*/
static void CgiScriptWritable(void){
  StartResponse("500 CGI Configuration Error");
  nOut += printf(
    "Content-type: text/html\r\n"
    "\r\n"
    "<head><title>CGI Configuration Error</title></head>\n"
    "<body><h1>CGI Configuration Error</h1>\n"
    "The CGI program %s is writable by users other than its owner.\n"
    "</body>\n", zRealScript);
  MakeLogEntry(0);
  exit(0);       
}

/*
** Tell the client that the server malfunctioned.
*/
static void Malfunction(int linenum, const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  StartResponse("500 Server Malfunction");
  nOut += printf(
    "Content-type: text/html\r\n"
    "\r\n"
    "<head><title>Server Malfunction</title></head>\n"
    "<body><h1>Server Malfunction</h1>\n"
    "<p>This web server has malfunctioned.\n\n"
    "(Error number: %d)</p>\n", linenum);
  if( zFormat ){
    nOut += printf("<p>");
    nOut += vprintf(zFormat, ap);
    nOut += printf("</p>\n\n");
  }
  nOut += printf("</body>\n");
  MakeLogEntry(0);
  exit(0);       
}

/*
** Do a server redirect to the document specified.  The document
** name not contain scheme or network location or the query string.
................................................................................
    { "gl",         2, "video/gl"                          },
    { "gtar",       4, "application/x-gtar"                },
    { "gz",         2, "application/x-gzip"                },
    { "hdf",        3, "application/x-hdf"                 },
    { "hh",         2, "text/plain"                        },
    { "hqx",        3, "application/mac-binhex40"          },
    { "h",          1, "text/plain"                        },
    { "htm",        3, "text/html"                         },
    { "html",       4, "text/html"                         },
    { "ice",        3, "x-conference/x-cooltalk"           },
    { "ief",        3, "image/ief"                         },
    { "iges",       4, "model/iges"                        },
    { "igs",        3, "model/iges"                        },
    { "ips",        3, "application/x-ipscript"            },
    { "ipx",        3, "application/x-ipix"                },
    { "jad",        3, "text/vnd.sun.j2me.app-descriptor"  },
................................................................................
    { "xyz",        3, "chemical/x-pdb"                    },
    { "zip",        3, "application/zip"                   },
  };

  for(i=nName-1; i>0 && zName[i]!='.'; i--){}
  z = &zName[i+1];
  len = nName - i;
  if( len<sizeof(zSuffix)-1 ){
    strcpy(zSuffix, z);
    for(i=0; zSuffix[i]; i++) zSuffix[i] = tolower(zSuffix[i]);
    first = 0;
    last = sizeof(aMime)/sizeof(aMime[0]);
    while( first<=last ){
      int c;
      i = (first+last)/2;
................................................................................
  nIn += strlen(zLine);
  zMethod = StrDup(GetFirstElement(zLine,&z));
  zRealScript = zScript = StrDup(GetFirstElement(z,&z));
  zProtocol = StrDup(GetFirstElement(z,&z));
  if( zProtocol==0 || strncmp(zProtocol,"HTTP/",5)!=0 || strlen(zProtocol)!=8 ){
    StartResponse("400 Bad Request");
    nOut += printf(
      "Content-type: text/html\r\n"
      "\r\n"
      "<title>Unknown Protocol On HTTP Request</title>\n"
      "<h1>Unknown Protocol</h1>\n"
      "This server does not understand the requested protocol\n"
    );
    MakeLogEntry(0);
    exit(0);
  }
  if( zScript[0]==0 ) NotFound(__LINE__);
  if( forceClose ){
................................................................................
  /* This very simple server only understands the GET, POST
  ** and HEAD methods
  */
  if( strcmp(zMethod,"GET")!=0 && strcmp(zMethod,"POST")!=0
       && strcmp(zMethod,"HEAD")!=0 ){
    StartResponse("501 Not Implemented");
    nOut += printf(
      "Content-type: text/html\r\n"
      "\r\n"
      "<head><title>Method not implemented</title></head>\n"
      "<body><h1>Method not implemented</h1>\n"
      "The %s method is not implemented on this server.\n" 
      "</body>\n",
      zMethod);
    MakeLogEntry(0);
    exit(0);
  }

  /* Get all the optional fields that follow the first line.
  */
................................................................................
    FILE *out;
    char *zBuf;
    int n;

    if( len>MAX_CONTENT_LENGTH ){
      StartResponse("500 Request too large");
      nOut += printf(
        "Content-type: text/html\r\n"
        "\r\n"
        "Too much POST data\n"
        "</body>\n"
      );
      MakeLogEntry(0);
      exit(0);
    }
    sprintf(zTmpNamBuf, "/tmp/-post-data-XXXXXX");
    zTmpNam = zTmpNamBuf;
    mkstemp(zTmpNam);
    out = fopen(zTmpNam,"w");
    if( out==0 ){
      StartResponse("500 Cannot create /tmp file");
      nOut += printf(
        "Content-type: text/html\r\n"
        "\r\n"
        "Could not open \"%s\" for writing\n"
        "</body>\n", zTmpNam
      );
      MakeLogEntry(0);
      exit(0);
    }
    zBuf = SafeMalloc( len );
    if( useTimeout ) alarm(15 + len/2000);
    n = fread(zBuf,1,len,stdin);
................................................................................
      char zBuf[1000];
      Malfunction(__LINE__, "cannot chdir to [%s] from [%s]", 
           zDir, getcwd(zBuf,999));
    }

    /* Setup the environment appropriately.
    */
    for(i=0; i<sizeof(cgienv)/sizeof(cgienv[0]); i++){
      if( *cgienv[i].pzEnvValue ){
        SetEnv(cgienv[i].zEnvName,*cgienv[i].pzEnvValue);
      }
    }
    if( useHttps ){
      putenv("HTTPS=on");
    }
................................................................................
  sHints.ai_protocol = 0;
  rc = getaddrinfo(localOnly ? "localhost": 0, zPort, &sHints, &pAddrs);
  if( rc ){
    fprintf(stderr, "could not get addr info: %s", 
            rc!=EAI_SYSTEM ? gai_strerror(rc) : strerror(errno));
    return 1;
  }
  for(n=0, p=pAddrs; n<sizeof(listener)/sizeof(listener[0]) && p!=0;
        p=p->ai_next){
    listener[n] = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if( listener[n]>=0 ){
      /* if we can't terminate nicely, at least allow the socket to be reused */
      setsockopt(listener[n], SOL_SOCKET, SO_REUSEADDR,&opt, sizeof(opt));
      
#if defined(IPV6_V6ONLY)







>







 







|
<

>







 







|
|
>








|


|
|
|
|







 







>













|

<
<
|
|












|

|
<
<
<

<

<

<







 







|
|







 







|







 







|

<
<







 







|

<
<
|
<







 







|


<











|

|
<







 







|







 







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
181
182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
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
...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
...
889
890
891
892
893
894
895
896
897


898
899
900
901
902
903
904
...
910
911
912
913
914
915
916
917
918


919

920
921
922
923
924
925
926
....
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036

1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
....
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
....
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <time.h>
#include <sys/times.h>
#include <netdb.h>
#include <errno.h>
#include <sys/resource.h>
#ifdef linux
#include <sys/sendfile.h>
#endif
#include <assert.h>

/*
** Configure the server by setting the following macros and recompiling.
................................................................................
  FILE *log;
  if( zTmpNam ){
    unlink(zTmpNam);
  }
  if( zLogFile && !omitLog ){
    time_t now;
    struct tm *pTm;
    struct rusage self, children;

    int i;
    int waitStatus;
    char zDate[200];
    char *zRM = zRemoteUser ? zRemoteUser : "*";

    if( zScript==0 || zScript[0]==0 ) zScript = "*";
    if( zRemoteAddr==0 || zRemoteAddr[0]==0 ) zRemoteAddr = "*";
    if( zHttpHost==0 || zHttpHost[0]==0 ) zHttpHost = "*";
    if( zReferer==0 || zReferer[0]==0 ) zReferer = "*";
................................................................................
    for(i=0; zReferer[i]; i++){ 
      if( isspace(zReferer[i]) ){ zReferer = "*"; break; }
    }
    if( zAgent==0 || zAgent[0]==0 ) zAgent = "*";
    time(&now);
    pTm = localtime(&now);
    strftime(zDate, sizeof(zDate), "%Y-%m-%d %H:%M:%S", pTm);
    waitpid(-1, &waitStatus, WNOHANG);
    getrusage(RUSAGE_SELF, &self);
    getrusage(RUSAGE_CHILDREN, &children);
    if( (log = fopen(zLogFile,"a"))!=0 ){
#ifdef COMBINED_LOG_FORMAT
      strftime(zDate, sizeof(zDate), "%d/%b/%Y:%H:%M:%S %z", pTm);
      fprintf(log, "%s - - [%s] \"%s %s %s\" %s %d \"%s\" \"%s\"\n",
              zRemoteAddr, zDate, zMethod, zScript, zProtocol,
              zReplyStatus, nOut, zReferer, zAgent);
#else
      strftime(zDate, sizeof(zDate), "%Y-%m-%d %H:%M:%S", pTm);
      fprintf(log, "%s %s %s://%s%s %s %s %d %d %d %d %d %d %d %d %s %s\n", 
          zDate, zRemoteAddr, zHttp, zHttpHost, zScript, zReferer,
          zReplyStatus, nIn, nOut,
          (int)(self.ru_utime.tv_sec*1000000 + self.ru_utime.tv_usec),
          (int)(self.ru_stime.tv_sec*1000000 + self.ru_stime.tv_usec),
          (int)(children.ru_utime.tv_sec*1000000 + children.ru_utime.tv_usec),
          (int)(children.ru_stime.tv_sec*1000000 + children.ru_stime.tv_usec),
          (int)(now - beginTime),
          nRequest, zAgent, zRM
      );
#endif
      fclose(log);
      nIn = nOut = 0;
    }
................................................................................
  exit(0);
}

/*
** This is called if we timeout.
*/
static void Timeout(int NotUsed){
  (void)NotUsed;
  if( !debugFlag ){
    strcpy(zReplyStatus, "999");
    MakeLogEntry(0);
    exit(0);
  }
}

/*
** Tell the client that there is an error in the script.
*/
static void CgiScriptWritable(void){
  StartResponse("500 CGI Configuration Error");
  nOut += printf(
    "Content-type: text/plain\r\n"
    "\r\n"


    "The CGI program %s is writable by users other than its owner.\n",
    zRealScript);
  MakeLogEntry(0);
  exit(0);       
}

/*
** Tell the client that the server malfunctioned.
*/
static void Malfunction(int linenum, const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  StartResponse("500 Server Malfunction");
  nOut += printf(
    "Content-type: text/plain\r\n"
    "\r\n"
    "Web server malfunctioned; error number %d\n\n", linenum);



  if( zFormat ){

    nOut += vprintf(zFormat, ap);

  }

  MakeLogEntry(0);
  exit(0);       
}

/*
** Do a server redirect to the document specified.  The document
** name not contain scheme or network location or the query string.
................................................................................
    { "gl",         2, "video/gl"                          },
    { "gtar",       4, "application/x-gtar"                },
    { "gz",         2, "application/x-gzip"                },
    { "hdf",        3, "application/x-hdf"                 },
    { "hh",         2, "text/plain"                        },
    { "hqx",        3, "application/mac-binhex40"          },
    { "h",          1, "text/plain"                        },
    { "htm",        3, "text/html; charset=utf-8"          },
    { "html",       4, "text/html; charset=utf-8"          },
    { "ice",        3, "x-conference/x-cooltalk"           },
    { "ief",        3, "image/ief"                         },
    { "iges",       4, "model/iges"                        },
    { "igs",        3, "model/iges"                        },
    { "ips",        3, "application/x-ipscript"            },
    { "ipx",        3, "application/x-ipix"                },
    { "jad",        3, "text/vnd.sun.j2me.app-descriptor"  },
................................................................................
    { "xyz",        3, "chemical/x-pdb"                    },
    { "zip",        3, "application/zip"                   },
  };

  for(i=nName-1; i>0 && zName[i]!='.'; i--){}
  z = &zName[i+1];
  len = nName - i;
  if( len<(int)sizeof(zSuffix)-1 ){
    strcpy(zSuffix, z);
    for(i=0; zSuffix[i]; i++) zSuffix[i] = tolower(zSuffix[i]);
    first = 0;
    last = sizeof(aMime)/sizeof(aMime[0]);
    while( first<=last ){
      int c;
      i = (first+last)/2;
................................................................................
  nIn += strlen(zLine);
  zMethod = StrDup(GetFirstElement(zLine,&z));
  zRealScript = zScript = StrDup(GetFirstElement(z,&z));
  zProtocol = StrDup(GetFirstElement(z,&z));
  if( zProtocol==0 || strncmp(zProtocol,"HTTP/",5)!=0 || strlen(zProtocol)!=8 ){
    StartResponse("400 Bad Request");
    nOut += printf(
      "Content-type: text/plain\r\n"
      "\r\n"


      "This server does not understand the requested protocol\n"
    );
    MakeLogEntry(0);
    exit(0);
  }
  if( zScript[0]==0 ) NotFound(__LINE__);
  if( forceClose ){
................................................................................
  /* This very simple server only understands the GET, POST
  ** and HEAD methods
  */
  if( strcmp(zMethod,"GET")!=0 && strcmp(zMethod,"POST")!=0
       && strcmp(zMethod,"HEAD")!=0 ){
    StartResponse("501 Not Implemented");
    nOut += printf(
      "Content-type: text/plain\r\n"
      "\r\n"


      "The %s method is not implemented on this server.\n",

      zMethod);
    MakeLogEntry(0);
    exit(0);
  }

  /* Get all the optional fields that follow the first line.
  */
................................................................................
    FILE *out;
    char *zBuf;
    int n;

    if( len>MAX_CONTENT_LENGTH ){
      StartResponse("500 Request too large");
      nOut += printf(
        "Content-type: text/plain\r\n"
        "\r\n"
        "Too much POST data\n"

      );
      MakeLogEntry(0);
      exit(0);
    }
    sprintf(zTmpNamBuf, "/tmp/-post-data-XXXXXX");
    zTmpNam = zTmpNamBuf;
    mkstemp(zTmpNam);
    out = fopen(zTmpNam,"w");
    if( out==0 ){
      StartResponse("500 Cannot create /tmp file");
      nOut += printf(
        "Content-type: text/plain\r\n"
        "\r\n"
        "Could not open \"%s\" for writing\n", zTmpNam

      );
      MakeLogEntry(0);
      exit(0);
    }
    zBuf = SafeMalloc( len );
    if( useTimeout ) alarm(15 + len/2000);
    n = fread(zBuf,1,len,stdin);
................................................................................
      char zBuf[1000];
      Malfunction(__LINE__, "cannot chdir to [%s] from [%s]", 
           zDir, getcwd(zBuf,999));
    }

    /* Setup the environment appropriately.
    */
    for(i=0; i<(int)(sizeof(cgienv)/sizeof(cgienv[0])); i++){
      if( *cgienv[i].pzEnvValue ){
        SetEnv(cgienv[i].zEnvName,*cgienv[i].pzEnvValue);
      }
    }
    if( useHttps ){
      putenv("HTTPS=on");
    }
................................................................................
  sHints.ai_protocol = 0;
  rc = getaddrinfo(localOnly ? "localhost": 0, zPort, &sHints, &pAddrs);
  if( rc ){
    fprintf(stderr, "could not get addr info: %s", 
            rc!=EAI_SYSTEM ? gai_strerror(rc) : strerror(errno));
    return 1;
  }
  for(n=0, p=pAddrs; n<(int)(sizeof(listener)/sizeof(listener[0])) && p!=0;
        p=p->ai_next){
    listener[n] = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    if( listener[n]>=0 ){
      /* if we can't terminate nicely, at least allow the socket to be reused */
      setsockopt(listener[n], SOL_SOCKET, SO_REUSEADDR,&opt, sizeof(opt));
      
#if defined(IPV6_V6ONLY)

Changes to pages/changes.in

37
38
39
40
41
42
43





























44
45
46
47
48
49
50
      <a href="http://www.sqlite.org/src/timeline">
      http://www.sqlite.org/src/timeline</a>.</p>
    }
    hd_close_aux
    hd_enable_main 1
  }
}






























chng {2012-10-04 (3.7.14.1)} {
<li>Fix a bug (ticket 
<a href="www.sqlite.org/src/tktview/d02e1406a58ea02d">&#91;d02e1406a58ea02d]&#93;</a>)
that causes a segfault on a LEFT JOIN that includes an OR in the ON clause.
<li>Work around a bug in the optimizer in the VisualStudio-2012 compiler that
causes invalid code to be generated when compiling SQLite on ARM.







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







37
38
39
40
41
42
43
44
45
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
76
77
78
79
      <a href="http://www.sqlite.org/src/timeline">
      http://www.sqlite.org/src/timeline</a>.</p>
    }
    hd_close_aux
    hd_enable_main 1
  }
}

chng {2012-12-12 (3.7.15)} {
<li>Added the [sqlite3_errstr()] interface.
<li>Avoid invoking the [sqlite3_trace()] callback multiple times when a
    statement is automatically reprepared due to [SQLITE_SCHEMA] errors.
<li>Enhance IN operator processing to make use of indices with numeric
    affinities.
<li>Do full-table scans using covering indices when possible, under the
    theory that an index will be smaller and hence can be scanned with
    less I/O.
<li>Enhancements the command-line shell:
    <ul>
    <li>Added the ".print" command
    <li>Negative numbers in the ".width" command cause right-alignment
    <li>Add the ".wheretrace" command when compiled with SQLITE_DEBUG
    </ul>
<li>Added the [busy_timeout pragma].
<li>Enhance the query optimizer so that ORDER BY clauses are more aggressively
    optimized, especially in joins where various terms of the ORDER BY clause
    come from separate tables of the join.
<li>Added the [SQLITE_FCNTL_BUSYHANDLER] file control, used to allow VFS
    implementations to get access to the busy handler callback.
<li>Work around an optimizer bug in the MSVC compiler when targeting ARM.
<li>Fix various concurrency problems in shared-cache mode.
<li>Bug fix: Avoid a deadlock or crash if the [backup API], [shared cache],
    and the SQLite Encryption Extension are all used at once.
<li>Bug fix: SQL functions created using the TCL interface honor the
    "nullvalue" setting.
}

chng {2012-10-04 (3.7.14.1)} {
<li>Fix a bug (ticket 
<a href="www.sqlite.org/src/tktview/d02e1406a58ea02d">&#91;d02e1406a58ea02d]&#93;</a>)
that causes a segfault on a LEFT JOIN that includes an OR in the ON clause.
<li>Work around a bug in the optimizer in the VisualStudio-2012 compiler that
causes invalid code to be generated when compiling SQLite on ARM.

Changes to pages/compile.in

321
322
323
324
325
326
327












328
329
330
331
332
333
334

</tcl>

<a name="enablefeatures"></a>
<h2>1.4 Options To Enable Features Normally Turned Off</h2>

<tcl>












COMPILE_OPTION {SQLITE_ENABLE_8_3_NAMES=<i>&lt;1 or 2&gt;</i>} {
  If this C-preprocessor macro is defined, then extra code is
  included that allows SQLite to function on a filesystem that
  only support 8+3 filenames.  If the value of this macro is 1,
  then the default behavior is to continue to use long filenames and
  to only use 8+3 filenames if the 
  database connection is opened using [URI filenames] with







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







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

</tcl>

<a name="enablefeatures"></a>
<h2>1.4 Options To Enable Features Normally Turned Off</h2>

<tcl>
COMPILE_OPTION {SQLITE_ALLOW_COVERING_INDEX_SCAN=<i>&lt;0 or 1&gt;</i>} {
  This C-preprocess macro determines the default setting of the
  [SQLITE_CONFIG_COVERING_INDEX_SCAN] configuration setting.  It defaults
  to 1 (on) which means that covering indices are used for full table
  scans where possible, in order to reduce I/O and improve performance.
  However, the use of a covering indice for a full scan will cause results
  to appear in a different order from legacy, which could cause some
  (incorrectly-coded) legacy applications to break.  Hence, the covering
  index scan option can be disabled at compile-time on systems that what
  to minimize their risk of exposing errors in legacy applications.
}

COMPILE_OPTION {SQLITE_ENABLE_8_3_NAMES=<i>&lt;1 or 2&gt;</i>} {
  If this C-preprocessor macro is defined, then extra code is
  included that allows SQLite to function on a filesystem that
  only support 8+3 filenames.  If the value of this macro is 1,
  then the default behavior is to continue to use long filenames and
  to only use 8+3 filenames if the 
  database connection is opened using [URI filenames] with

Changes to pages/download.in

34
35
36
37
38
39
40
41
42






43
44
45
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
...
128
129
130
131
132
133
134
135
136
137
138
139
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
...
191
192
193
194
195
196
197

















198
199
200
201
202
203
204
205
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
279
280
281
282
283
284
285

286
287
288
289
290
291
292
    if {$size>1024*1024} {
      set size [format %.2f [expr {$size/(1024.0*1024.0)}]]
      set units MiB
    } elseif {$size>1024} {
      set size [format %.2f [expr {$size/(1024.0)}]]
      set units KiB
    }
    global pending_heading
    if {$pending_heading!=""} {






      hd_puts "<tr><td colspan=\"4\"><b>$pending_heading</b></td></tr>"
      set pending_heading {}
    }
    hd_puts "<tr><td width=\"10\"></td>"
    hd_puts "<td valign=\"top\" align=\"right\">"
    if {$frag!=""} {
      eval hd_fragment $frag
      set frag {}
    }
    hd_puts "<a href=\"/$file\">$file</a><br>($size $units)</td>"
    hd_puts "<td width=\"5\"></td>"
    regsub -all VERSION $desc $version d2
    hd_puts "<td valign=\"top\">"
    hd_resolve [string trim $d2]
    hd_puts "<br>(sha1: $sha1sum)</td></tr>"
    incr ::nDownload
  }
  if {$frag!=""} {
    eval hd_keywords [lrange $frag 1 end]
  }
}
cd $::DEST

proc Heading {title} {
  set ::pending_heading $title

  # hd_puts "<tr><td colspan=4><big><b>$title</b></big></td></tr>"
}

Heading {Pre-release Source Code Snapshots}


Product {sqlite-amalgamation-DATE.zip} {
................................................................................
Product {sqlite-tea-VVV.tar.gz} {
  A tarball of the [amalgamation] together with a
  <a href="http://www.tcl.tk/doc/tea/">Tcl Extension
  Architecture (TEA)</a>
  compatible configure script and makefile.
} {teatarball {TEA tarball}}

Heading {Documentation}

Product {sqlite-doc-VVV.zip} {
  This ZIP archive contains most of the static HTML files that
  comprise this website, including all of the SQL Syntax and the
  C/C++ interface specs and other miscellaneous documentation.
}

Heading {Precompiled Binaries for Linux}

Product sqlite-shell-linux-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
}

Product sqlite-analyzer-linux-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}

Heading {Precompiled Binaries for Mac OS X (x86)}

Product sqlite-shell-osx-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
}

Product sqlite-analyzer-osx-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}

Heading {Precompiled Binaries for Windows}

set start $nDownload
Product sqlite-shell-win32-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
................................................................................
}

Product sqlite-analyzer-win32-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}


















Heading {Precompiled Binaries for Windows Runtime}

Product sqlite-dll-winrt-x86-VVV.zip {
  This ZIP archive contains a DLL for the SQLite library version VERSION for
  32-bit x86 processors using the WinRT API.
}

Product sqlite-dll-winrt-x64-VVV.zip {
................................................................................
  hd_puts "
    Visit the <a href=\"http://system.data.sqlite.org/\">System.Data.SQLite.org
    </a> website and especially the <a href=\"$url\">download page</a> for
    source code and binaries of SQLite for .NET.</td></tr>
  "
}

Heading {Legacy Source Code Distribution Formats (Not Recommended)}

Product {sqlite-src-VVV.zip} {
  A ZIP archive of the complete source tree for SQLite version VERSION
  as extracted from the version control system.  <i>The Makefile and
  configure script in this tarball are not supported</i>.  Their use
  is <u>not</u> recommended. The SQLite developers do not use them.  
  You should not use them either.  If you want a configure script and
................................................................................
increasing version number when viewed using "ls".  For version 3.X.Y the
filename encoding is 3XXYY00.  For branch version 3.X.Y.Z, the encoding is
3XXYYZZ.

<p>The <i>date</i> in template (4) is of the form: YYYYMMDDHHMM

<a name="cvs"></a>

<h3>Canonical Source Code</h3>

<p>
The canonical SQLite source code is maintained in three self-synchronizing
[http://www.fossil-scm.org/ | Fossil] repositories that are
available for anonymous read-only access.  Anyone can 
view the repository contents and download historical versions







|

>
>
>
>
>
>
|








|


|

|








|

>







 







|







|













|













|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







 







|







 







>







34
35
36
37
38
39
40
41
42
43
44
45
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
76
77
78
79
80
81
...
135
136
137
138
139
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
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    if {$size>1024*1024} {
      set size [format %.2f [expr {$size/(1024.0*1024.0)}]]
      set units MiB
    } elseif {$size>1024} {
      set size [format %.2f [expr {$size/(1024.0)}]]
      set units KiB
    }
    global pending_heading pending_tag
    if {$pending_heading!=""} {
      if {$pending_tag!=""} {
        set tg "<a name=\"$pending_tag\"></a>"
        set pending_tag {}
      } else {
        set tg ""
      }
      hd_puts "<tr><td colspan=\"4\">$tg<b>$pending_heading</b></td></tr>\n"
      set pending_heading {}
    }
    hd_puts "<tr><td width=\"10\"></td>"
    hd_puts "<td valign=\"top\" align=\"right\">"
    if {$frag!=""} {
      eval hd_fragment $frag
      set frag {}
    }
    hd_puts "<a href=\"/$file\">$file</a><br>($size $units)</td>\n"
    hd_puts "<td width=\"5\"></td>"
    regsub -all VERSION $desc $version d2
    hd_puts "\n<td valign=\"top\">"
    hd_resolve [string trim $d2]
    hd_puts "<br>(sha1: $sha1sum)</td></tr>\n"
    incr ::nDownload
  }
  if {$frag!=""} {
    eval hd_keywords [lrange $frag 1 end]
  }
}
cd $::DEST

proc Heading {title {tag {}}} {
  set ::pending_heading $title
  set ::pending_tag $tag
  # hd_puts "<tr><td colspan=4><big><b>$title</b></big></td></tr>"
}

Heading {Pre-release Source Code Snapshots}


Product {sqlite-amalgamation-DATE.zip} {
................................................................................
Product {sqlite-tea-VVV.tar.gz} {
  A tarball of the [amalgamation] together with a
  <a href="http://www.tcl.tk/doc/tea/">Tcl Extension
  Architecture (TEA)</a>
  compatible configure script and makefile.
} {teatarball {TEA tarball}}

Heading {Documentation} docco

Product {sqlite-doc-VVV.zip} {
  This ZIP archive contains most of the static HTML files that
  comprise this website, including all of the SQL Syntax and the
  C/C++ interface specs and other miscellaneous documentation.
}

Heading {Precompiled Binaries for Linux} linux

Product sqlite-shell-linux-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
}

Product sqlite-analyzer-linux-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}

Heading {Precompiled Binaries for Mac OS X (x86)} mac

Product sqlite-shell-osx-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
}

Product sqlite-analyzer-osx-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}

Heading {Precompiled Binaries for Windows} win32

set start $nDownload
Product sqlite-shell-win32-x86-VVV.zip {
  A [command-line shell]
  for accessing and modifying SQLite databases.
  This program is compatible with all versions of SQLite through VERSION
  and beyond.
................................................................................
}

Product sqlite-analyzer-win32-x86-VVV.zip {
  An analysis program for database files compatible with all SQLite 
  versions through VERSION and beyond.
}

Heading {Precompiled Binaries for Windows Phone 8} wp8


Product sqlite-wp80-winrt-VVV.vsix {
  A complete VSIX package with an extension SDK and all other components
  needed to use SQLite for application development with Visual Studio
  2012 targeting Windows Phone 8.0.
}

Product sqlite-wp80-winrt-DATE.vsix {
  A complete VSIX package with an extension SDK and all other components
  needed to use SQLite for application development with Visual Studio
  2012 targeting Windows Phone 8.0.
  This particular VSIX uses a snapshot of SQLite as of VERSION.
}


Heading {Precompiled Binaries for Windows Runtime} winrt

Product sqlite-dll-winrt-x86-VVV.zip {
  This ZIP archive contains a DLL for the SQLite library version VERSION for
  32-bit x86 processors using the WinRT API.
}

Product sqlite-dll-winrt-x64-VVV.zip {
................................................................................
  hd_puts "
    Visit the <a href=\"http://system.data.sqlite.org/\">System.Data.SQLite.org
    </a> website and especially the <a href=\"$url\">download page</a> for
    source code and binaries of SQLite for .NET.</td></tr>
  "
}

Heading {Legacy Source Code Distribution Formats (Not Recommended)} old

Product {sqlite-src-VVV.zip} {
  A ZIP archive of the complete source tree for SQLite version VERSION
  as extracted from the version control system.  <i>The Makefile and
  configure script in this tarball are not supported</i>.  Their use
  is <u>not</u> recommended. The SQLite developers do not use them.  
  You should not use them either.  If you want a configure script and
................................................................................
increasing version number when viewed using "ls".  For version 3.X.Y the
filename encoding is 3XXYY00.  For branch version 3.X.Y.Z, the encoding is
3XXYYZZ.

<p>The <i>date</i> in template (4) is of the form: YYYYMMDDHHMM

<a name="cvs"></a>
<a name="fossil"></a>
<h3>Canonical Source Code</h3>

<p>
The canonical SQLite source code is maintained in three self-synchronizing
[http://www.fossil-scm.org/ | Fossil] repositories that are
available for anonymous read-only access.  Anyone can 
view the repository contents and download historical versions

Changes to pages/index.in

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

</td>
<td width="20"></td><td bgcolor="#044a64" width="1"></td><td width="20"></td>
<td valign="top">
<h3>Current Status</h3>

<p><ul>
<li><a href="releaselog/3_7_14_1.html">Version 3.7.14.1</a>
of SQLite is recommended for all new development.
Upgrading from version 3.7.6.3, 3.7.7, 3.7.7.1, 3.7.8, 3.7.9, 3.7.11,
3.7.12, 3.7.12.1, or 3.7.13 is optional.
Upgrading from all other SQLite versions (including version 3.7.14)
is recommended.</li>
</ul></p>

<h3>Common Links</h3>

<p><ul>
<li> <a href="features.html">Features</a> </li>







|


|
|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

</td>
<td width="20"></td><td bgcolor="#044a64" width="1"></td><td width="20"></td>
<td valign="top">
<h3>Current Status</h3>

<p><ul>
<li><a href="releaselog/3_7_15.html">Version 3.7.15</a>
of SQLite is recommended for all new development.
Upgrading from version 3.7.6.3, 3.7.7, 3.7.7.1, 3.7.8, 3.7.9, 3.7.11,
3.7.12, 3.7.12.1, 3.7.13, 3.7.14.1 is optional.
Upgrading from all other SQLite versions
is recommended.</li>
</ul></p>

<h3>Common Links</h3>

<p><ul>
<li> <a href="features.html">Features</a> </li>

Changes to pages/lang.in

2711
2712
2713
2714
2715
2716
2717
2718

2719

2720
2721
2722

2723

2724
2725
2726
2727
2728
2729
2730
Section INSERT insert {INSERT *INSERTs}

BubbleDiagram insert-stmt 1
</tcl>

<p>The INSERT statement comes in three basic forms.  
<ul>
<li><p>^The first form (with the "VALUES" keyword) creates a single new row in

an existing table. ^If no column-list is specified then the number of

values must be the same as the number of columns in the table. ^In this case
the result of evaluating the left-most expression in the VALUES list is 
inserted into the left-most column of the new row, and so on. ^If a

column-list is specified, then the number of values must match the number of

specified columns. ^Each of the named columns of the new row is populated
with the results of evaluating the corresponding VALUES expression. ^Table
columns that do not appear in the column list are populated with the default
column value (specified as part of the CREATE TABLE statement), or with NULL if
no default value is specified.

<li><p>The second form of the INSERT statement contains a SELECT statement







|
>
|
>
|
|
|
>
|
>







2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
Section INSERT insert {INSERT *INSERTs}

BubbleDiagram insert-stmt 1
</tcl>

<p>The INSERT statement comes in three basic forms.  
<ul>
<li><p>^The first form (with the "VALUES" keyword) creates one or more
new rows in
an existing table. ^If no column-list is specified then the number
of values inserted into each row
must be the same as the number of columns in the table. ^In this case
the result of evaluating the left-most expression in each term of
the VALUES list is inserted into the left-most column of the each new row,
and forth for each subsequent expression. ^If a
column-list is specified, then the number of values in each term of the
VALUS list must match the number of
specified columns. ^Each of the named columns of the new row is populated
with the results of evaluating the corresponding VALUES expression. ^Table
columns that do not appear in the column list are populated with the default
column value (specified as part of the CREATE TABLE statement), or with NULL if
no default value is specified.

<li><p>The second form of the INSERT statement contains a SELECT statement

Changes to pages/pragma.in

179
180
181
182
183
184
185









186
187
188
189
190
191
192
...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    "incremental" back to "none" always requires running [VACUUM] even
    on an empty database.
    </p>

    <p>^When the auto_vacuum pragma is invoked with no arguments, it
    returns the current auto_vacuum mode.</p>
}










Pragma cache_size {
    <p>^(<b>PRAGMA cache_size;
       <br>PRAGMA cache_size = </b><i>pages</i><b>;
       <br>PRAGMA cache_size = -</b><i>kibibytes</i><b>;</b></p>
    <p>Query or change the suggested maximum number of database disk pages
    that SQLite will hold in memory at once per open database file.)^  Whether
................................................................................
    ^The new journal mode is returned.  ^If the journal mode
    could not be changed, the original journal mode is returned.</p>

    <p>^The DELETE journaling mode is the normal behavior.  ^In the DELETE
    mode, the rollback journal is deleted at the conclusion of each
    transaction.  Indeed, the delete operation is the action that causes
    the transaction to commit.
    (See the documented titled <a href="atomiccommit.html">
    Atomic Commit In SQLite</a> for additional detail.)</p>

    <p>^The TRUNCATE journaling mode commits transactions by truncating
    the rollback journal to zero-length instead of deleting it.  On many
    systems, truncating a file is much faster than deleting the file since
    the containing directory does not need to be changed.</p>








>
>
>
>
>
>
>
>
>







 







|







179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
    "incremental" back to "none" always requires running [VACUUM] even
    on an empty database.
    </p>

    <p>^When the auto_vacuum pragma is invoked with no arguments, it
    returns the current auto_vacuum mode.</p>
}

Pragma busy_timeout {
    <p>^(<b>PRAGMA busy_timeout;
         <br>PRAGMA busy_timeout = </b><i>milliseconds</i><b>;</b></p>
    <p>Query or change the setting of the [sqlite3_busy_timeout | busy timeout].
    This pragma is an alternative to the [sqlite3_busy_timeout()] C-language
    interface which is made available as a pragma for use with language
    bindings that do not provide direct access to [sqlite3_busy_timeout()].
}

Pragma cache_size {
    <p>^(<b>PRAGMA cache_size;
       <br>PRAGMA cache_size = </b><i>pages</i><b>;
       <br>PRAGMA cache_size = -</b><i>kibibytes</i><b>;</b></p>
    <p>Query or change the suggested maximum number of database disk pages
    that SQLite will hold in memory at once per open database file.)^  Whether
................................................................................
    ^The new journal mode is returned.  ^If the journal mode
    could not be changed, the original journal mode is returned.</p>

    <p>^The DELETE journaling mode is the normal behavior.  ^In the DELETE
    mode, the rollback journal is deleted at the conclusion of each
    transaction.  Indeed, the delete operation is the action that causes
    the transaction to commit.
    (See the document titled <a href="atomiccommit.html">
    Atomic Commit In SQLite</a> for additional detail.)</p>

    <p>^The TRUNCATE journaling mode commits transactions by truncating
    the rollback journal to zero-length instead of deleting it.  On many
    systems, truncating a file is much faster than deleting the file since
    the containing directory does not need to be changed.</p>

Changes to pages/vtab.in

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702

This method undoes the work of [xConnect].

<p>This method is a destructor for a connection to the virtual table.
Contrast this method with [xDestroy].  The xDestroy is a destructor
for the entire virtual table.

<p>The xDestroy method is required for every virtual table implementation,
though it is acceptable for the [xDisconnect] and xDestroy methods to be
the same function if that makes sense for the particular virtual table.

<tcl>########################################################## xDestroy
hd_fragment {sqlite3_module.xDestroy} {xDestroy}</tcl>
<h3>2.5 The xDestroy Method</h3>

<blockquote><pre>
................................................................................
the [xDisconnect] method, and it also destroys the underlying 
table implementation. This method undoes the work of [xCreate].

<p>The [xDisconnect] method is called whenever a database connection
that uses a virtual table is closed. The xDestroy method is only 
called when a [DROP TABLE] statement is executed against the virtual table.

<p>The xDisconnect method is required for every virtual table implementation,
though it is acceptable for the xDisconnect and [xDestroy] methods to be
the same function if that makes sense for the particular virtual table.

<tcl>########################################################## xOpen
hd_fragment xopen {sqlite3_module.xOpen}</tcl>
<h3>2.6 The xOpen Method</h3>

<blockquote><pre>







|
|







 







|
|







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702

This method undoes the work of [xConnect].

<p>This method is a destructor for a connection to the virtual table.
Contrast this method with [xDestroy].  The xDestroy is a destructor
for the entire virtual table.

<p>The xDisconnect method is required for every virtual table implementation,
though it is acceptable for the xDisconnect and [xDestroy] methods to be
the same function if that makes sense for the particular virtual table.

<tcl>########################################################## xDestroy
hd_fragment {sqlite3_module.xDestroy} {xDestroy}</tcl>
<h3>2.5 The xDestroy Method</h3>

<blockquote><pre>
................................................................................
the [xDisconnect] method, and it also destroys the underlying 
table implementation. This method undoes the work of [xCreate].

<p>The [xDisconnect] method is called whenever a database connection
that uses a virtual table is closed. The xDestroy method is only 
called when a [DROP TABLE] statement is executed against the virtual table.

<p>The xDestroy method is required for every virtual table implementation,
though it is acceptable for the [xDisconnect] and xDestroy methods to be
the same function if that makes sense for the particular virtual table.

<tcl>########################################################## xOpen
hd_fragment xopen {sqlite3_module.xOpen}</tcl>
<h3>2.6 The xOpen Method</h3>

<blockquote><pre>

Changes to pages/whentouse.in

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
</p>
</li>

<li><p><b>Command-line dataset analysis tool</b></p>

<p>
Experienced SQL users can employ
the command-line <b>sqlite</b> program to analyze miscellaneous
datasets. Raw data can be imported from CSV files, then that
data can be sliced and diced to generate a myriad of summary
reports.  Possible uses include website log analysis, sports
statistics analysis, compilation of programming metrics, and
analysis of experimental results.
</p>

................................................................................
</p>
</li>

<li><p><b>Database Pedagogy</b></p>

<p>
Because it is simple to setup and use (installation is trivial: just
copy the <b>sqlite</b> or <b>sqlite.exe</b> executable to the target machine
and run it) SQLite makes a good database engine for use in teaching SQL.
Students can easily create as many databases as they like and can
email databases to the instructor for comments or grading.  For more
advanced students who are interested in studying how an RDBMS is
implemented, the modular and well-commented and documented SQLite code
can serve as a good basis.  This is not to say that SQLite is an accurate
model of how other database engines are implemented, but rather a student who







|







 







|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
</p>
</li>

<li><p><b>Command-line dataset analysis tool</b></p>

<p>
Experienced SQL users can employ
the command-line <b>sqlite3</b> program to analyze miscellaneous
datasets. Raw data can be imported from CSV files, then that
data can be sliced and diced to generate a myriad of summary
reports.  Possible uses include website log analysis, sports
statistics analysis, compilation of programming metrics, and
analysis of experimental results.
</p>

................................................................................
</p>
</li>

<li><p><b>Database Pedagogy</b></p>

<p>
Because it is simple to setup and use (installation is trivial: just
copy the <b>sqlite3</b> or <b>sqlite3.exe</b> executable to the target machine
and run it) SQLite makes a good database engine for use in teaching SQL.
Students can easily create as many databases as they like and can
email databases to the instructor for comments or grading.  For more
advanced students who are interested in studying how an RDBMS is
implemented, the modular and well-commented and documented SQLite code
can serve as a good basis.  This is not to say that SQLite is an accurate
model of how other database engines are implemented, but rather a student who