Fossil

Check-in [f7fd7d0ac8]
Login

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

Overview
Comment:merge cleanX
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | cleanX-no-clean-glob
Files: files | file ages | folders
SHA1: f7fd7d0ac8f39f9de2ee94918acf7713ce50baf0
User & Date: jan.nijtmans 2014-04-24 09:59:01.000
Context
2014-04-29
08:11
merge cleanX check-in: 820b10f776 user: jan.nijtmans tags: cleanX-no-clean-glob
2014-04-24
09:59
merge cleanX check-in: f7fd7d0ac8 user: jan.nijtmans tags: cleanX-no-clean-glob
08:12
merge trunk check-in: 9d969db8a4 user: jan.nijtmans tags: cleanX
2014-03-23
17:15
merge cleanX check-in: 1d54c02400 user: jan.nijtmans tags: cleanX-no-clean-glob
Changes
Unified Diff Ignore Whitespace Patch
Changes to Makefile.Cygwin.in.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
TCLSH = tclsh

LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H -DFOSSIL_OMIT_LOAD_AVERAGE
INSTALLDIR =$(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@
FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@
FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@
FOSSIL_ENABLE_TCL_PRIVATE_STUBS = @FOSSIL_ENABLE_TCL_PRIVATE_STUBS@
SQLITE_CFLAGS += -DSQLITE_WIN32_NO_ANSI
SQLITE_CFLAGS += -DSQLITE_WIN32_MAX_PATH_BYTES=4096
SQLITE_CFLAGS += -DSQLITE_MAX_MMAP_SIZE=0x7fff0000

include $(SRCDIR)/main.mk

distclean: clean







|


<
<
<







34
35
36
37
38
39
40
41
42
43



44
45
46
47
48
49
50

#### Tcl shell for use in running the fossil testsuite.  If you do not
#    care about testing the end result, this can be blank.
#
TCLSH = tclsh

LIB = @LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC += @EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
INSTALLDIR =$(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@



SQLITE_CFLAGS += -DSQLITE_WIN32_NO_ANSI
SQLITE_CFLAGS += -DSQLITE_WIN32_MAX_PATH_BYTES=4096
SQLITE_CFLAGS += -DSQLITE_MAX_MMAP_SIZE=0x7fff0000

include $(SRCDIR)/main.mk

distclean: clean
Changes to Makefile.in.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#
TCLSH = tclsh

LIB =	@LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC +=	@EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
INSTALLDIR = $(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@
FOSSIL_ENABLE_TCL = @FOSSIL_ENABLE_TCL@
FOSSIL_ENABLE_TCL_STUBS = @FOSSIL_ENABLE_TCL_STUBS@
FOSSIL_ENABLE_TCL_PRIVATE_STUBS = @FOSSIL_ENABLE_TCL_PRIVATE_STUBS@

include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile







<
<
<





38
39
40
41
42
43
44



45
46
47
48
49
#
TCLSH = tclsh

LIB =	@LDFLAGS@ @EXTRA_LDFLAGS@ @LIBS@
TCC +=	@EXTRA_CFLAGS@ @CPPFLAGS@ @CFLAGS@ -DHAVE_AUTOCONFIG_H
INSTALLDIR = $(DESTDIR)@prefix@/bin
USE_SYSTEM_SQLITE = @USE_SYSTEM_SQLITE@




include $(SRCDIR)/main.mk

distclean: clean
	rm -f autoconfig.h config.log Makefile
Changes to VERSION.
1
1.28
|
1
1.29
Changes to auto.def.
246
247
248
249
250
251
252





253
254
255
256
257
258
259
if {![cc-check-function-in-lib socket {socket network}]} {
    # Last resort, may be Windows
    if {[string match *mingw* [get-define host]]} {
        define-append LIBS -lwsock32
    }
}
cc-check-function-in-lib iconv iconv






# Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars
if {![cc-check-functions getpassphrase]} {
    # Haiku needs this
    cc-check-function-in-lib getpass bsd
}
cc-check-function-in-lib dlopen dl







>
>
>
>
>







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
if {![cc-check-function-in-lib socket {socket network}]} {
    # Last resort, may be Windows
    if {[string match *mingw* [get-define host]]} {
        define-append LIBS -lwsock32
    }
}
cc-check-function-in-lib iconv iconv

# Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE
if {![cc-check-functions getloadavg]} {
  define FOSSIL_OMIT_LOAD_AVERAGE 1
}

# Check for getpassphrase() for Solaris 10 where getpass() truncates to 10 chars
if {![cc-check-functions getpassphrase]} {
    # Haiku needs this
    cc-check-function-in-lib getpass bsd
}
cc-check-function-in-lib dlopen dl
Changes to src/add.c.
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <assert.h>
#include <dirent.h>
#include "cygsup.h"

/*
** This routine returns the names of files in a working checkout that
** are created by Fossil itself, and hence should not be added, deleted,
** or merge, and should be omitted from "clean" and "extra" lists.
**
** Return the N-th name.  The first name has N==0.  When all names have
** been used, return 0.
*/
const char *fossil_reserved_name(int N, int omitRepo){
  /* Possible names of the local per-checkout database file and
  ** its associated journals







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <assert.h>
#include <dirent.h>
#include "cygsup.h"

/*
** This routine returns the names of files in a working checkout that
** are created by Fossil itself, and hence should not be added, deleted,
** or merge, and should be omitted from "clean" and "extras" lists.
**
** Return the N-th name.  The first name has N==0.  When all names have
** been used, return 0.
*/
const char *fossil_reserved_name(int N, int omitRepo){
  /* Possible names of the local per-checkout database file and
  ** its associated journals
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
**
** Usage: %fossil addremove ?OPTIONS?
**
** Do all necessary "add" and "rm" commands to synchronize the repository
** with the content of the working checkout:
**
**  *  All files in the checkout but not in the repository (that is,
**     all files displayed using the "extra" command) are added as
**     if by the "add" command.
**
**  *  All files in the repository but missing from the checkout (that is,
**     all files that show as MISSING with the "status" command) are
**     removed as if by the "rm" command.
**
** The command does not "commit".  You must run the "commit" separately







|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
**
** Usage: %fossil addremove ?OPTIONS?
**
** Do all necessary "add" and "rm" commands to synchronize the repository
** with the content of the working checkout:
**
**  *  All files in the checkout but not in the repository (that is,
**     all files displayed using the "extras" command) are added as
**     if by the "add" command.
**
**  *  All files in the repository but missing from the checkout (that is,
**     all files that show as MISSING with the "status" command) are
**     removed as if by the "rm" command.
**
** The command does not "commit".  You must run the "commit" separately
Changes to src/allrepo.c.
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  }
}


/*
** COMMAND: all
**
** Usage: %fossil all (changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync)
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories
** that can be useful before or after a period of disconnected operation.
**
** On Win32 systems, the file is named "_fossil" and is located in
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  }
}


/*
** COMMAND: all
**
** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync)
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories
** that can be useful before or after a period of disconnected operation.
**
** On Win32 systems, the file is named "_fossil" and is located in
** %LOCALAPPDATA%, %APPDATA% or %HOMEPATH%.
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
**               effects cannot be undone.  Use of the --dry-run option to
**               carefully review the local checkouts to be operated upon
**               and the --whatif option to carefully review the files to
**               be deleted beforehand is highly recommended.  The command
**               line options supported by the clean command itself, if any
**               are present, are passed along verbatim.
**
**    extra      Shows extra files from all local checkouts.  The command
**               line options supported by the extra command itself, if any
**               are present, are passed along verbatim.
**
**    ignore     Arguments are repositories that should be ignored by
**               subsequent clean, extra, list, pull, push, rebuild, and
**               sync operations.  The -c|--ckout option causes the listed
**               local checkouts to be ignored instead.
**
**    list | ls  Display the location of all repositories.  The -c|--ckout
**               option causes all local checkouts to be listed instead.
**
**    pull       Run a "pull" operation on all repositories.  Only the







|




|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
**               effects cannot be undone.  Use of the --dry-run option to
**               carefully review the local checkouts to be operated upon
**               and the --whatif option to carefully review the files to
**               be deleted beforehand is highly recommended.  The command
**               line options supported by the clean command itself, if any
**               are present, are passed along verbatim.
**
**    extras     Shows "extra" files from all local checkouts.  The command
**               line options supported by the extra command itself, if any
**               are present, are passed along verbatim.
**
**    ignore     Arguments are repositories that should be ignored by
**               subsequent clean, extras, list, pull, push, rebuild, and
**               sync operations.  The -c|--ckout option causes the listed
**               local checkouts to be ignored instead.
**
**    list | ls  Display the location of all repositories.  The -c|--ckout
**               option causes all local checkouts to be listed instead.
**
**    pull       Run a "pull" operation on all repositories.  Only the
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
**
** Repositories are automatically added to the set of known repositories
** when one of the following commands are run against the repository:
** clone, info, pull, push, or sync.  Even previously ignored repositories
** are added back to the list of repositories by these commands.
**
** Options:

**   --dontstop     Continue with other repositories even after an error.
**   --dry-run      If given, display instead of run actions.
*/
void all_cmd(void){
  int n;
  Stmt q;
  const char *zCmd;
  char *zSyscmd;
  char *zFossil;
  char *zQFilename;
  Blob extra;
  int useCheckouts = 0;
  int quiet = 0;
  int dryRunFlag = 0;

  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;
  int nToDel = 0;
  
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }

  if( g.argc<3 ){
    usage("changes|clean|extra|ignore|list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  blob_zero(&extra);
  zCmd = g.argv[2];
  if( !login_is_nobody() ) blob_appendf(&extra, " -U %s", g.zLogin);
  if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){







>














>










|







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
**
** Repositories are automatically added to the set of known repositories
** when one of the following commands are run against the repository:
** clone, info, pull, push, or sync.  Even previously ignored repositories
** are added back to the list of repositories by these commands.
**
** Options:
**   --showfile     Show the repository or checkout being operated upon.
**   --dontstop     Continue with other repositories even after an error.
**   --dry-run      If given, display instead of run actions.
*/
void all_cmd(void){
  int n;
  Stmt q;
  const char *zCmd;
  char *zSyscmd;
  char *zFossil;
  char *zQFilename;
  Blob extra;
  int useCheckouts = 0;
  int quiet = 0;
  int dryRunFlag = 0;
  int showFile = find_option("showfile",0,0)!=0;
  int stopOnError = find_option("dontstop",0,0)==0;
  int rc;
  int nToDel = 0;
  
  dryRunFlag = find_option("dry-run","n",0)!=0;
  if( !dryRunFlag ){
    dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
  }

  if( g.argc<3 ){
    usage("changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync");
  }
  n = strlen(g.argv[2]);
  db_open_config(1);
  blob_zero(&extra);
  zCmd = g.argv[2];
  if( !login_is_nobody() ) blob_appendf(&extra, " -U %s", g.zLogin);
  if( strncmp(zCmd, "list", n)==0 || strncmp(zCmd,"ls",n)==0 ){
183
184
185
186
187
188
189
190

191



192
193
194
195
196
197
198
    collect_argument(&extra, "force","f");
    collect_argument_value(&extra, "ignore");
    collect_argument_value(&extra, "keep");
    collect_argument(&extra, "temp",0);
    collect_argument(&extra, "verbose","v");
    collect_argument(&extra, "whatif",0);
    useCheckouts = 1;
  }else if( strncmp(zCmd, "extra", n)==0 ){

    zCmd = "extra --chdir";



    collect_argument(&extra, "abs-paths",0);
    collect_argument_value(&extra, "case-sensitive");
    collect_argument(&extra, "dotfiles",0);
    collect_argument_value(&extra, "ignore");
    collect_argument(&extra, "rel-paths",0);
    useCheckouts = 1;
    stopOnError = 0;







|
>
|
>
>
>







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
    collect_argument(&extra, "force","f");
    collect_argument_value(&extra, "ignore");
    collect_argument_value(&extra, "keep");
    collect_argument(&extra, "temp",0);
    collect_argument(&extra, "verbose","v");
    collect_argument(&extra, "whatif",0);
    useCheckouts = 1;
  }else if( strncmp(zCmd, "extras", n)==0 ){
    if( showFile ){
      zCmd = "extras --chdir";
    }else{
      zCmd = "extras --header --chdir";
    }
    collect_argument(&extra, "abs-paths",0);
    collect_argument_value(&extra, "case-sensitive");
    collect_argument(&extra, "dotfiles",0);
    collect_argument_value(&extra, "ignore");
    collect_argument(&extra, "rel-paths",0);
    useCheckouts = 1;
    stopOnError = 0;
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
      }
      fossil_free(zSql);
    }
    db_end_transaction(0);
    return;
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "changes clean extra ignore list ls push pull rebuild sync");
  }
  verify_all_options();
  zFossil = quoteFilename(g.nameOfExe);
  if( useCheckouts ){
    db_prepare(&q,
       "SELECT DISTINCT substr(name, 7), name COLLATE nocase"
       "  FROM global_config"







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
      }
      fossil_free(zSql);
    }
    db_end_transaction(0);
    return;
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
                 "changes clean extras ignore list ls push pull rebuild sync");
  }
  verify_all_options();
  zFossil = quoteFilename(g.nameOfExe);
  if( useCheckouts ){
    db_prepare(&q,
       "SELECT DISTINCT substr(name, 7), name COLLATE nocase"
       "  FROM global_config"
285
286
287
288
289
290
291



292
293
294
295
296
297
298
      db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;



    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s%s",
                      zFossil, zCmd, zQFilename, blob_str(&extra));
    if( !quiet || dryRunFlag ){
      fossil_print("%s\n", zSyscmd);
      fflush(stdout);







>
>
>







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
      db_multi_exec("INSERT INTO todel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }else if( showFile ){
      fossil_print("%s: %s\n", useCheckouts ? "checkout" : "repository",
                   zFilename);
    }
    zQFilename = quoteFilename(zFilename);
    zSyscmd = mprintf("%s %s %s%s",
                      zFossil, zCmd, zQFilename, blob_str(&extra));
    if( !quiet || dryRunFlag ){
      fossil_print("%s\n", zSyscmd);
      fflush(stdout);
Changes to src/attach.c.
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
    if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
      zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag" 
                        " WHERE tagname GLOB 'tkt-%q*'", zTkt);
      if( zTkt==0 ) fossil_redirect_home();
    }
    zTarget = zTkt;
    zTargetType = mprintf("Ticket <a href=\"%s/tktview/%S\">%S</a>",
                          g.zTop, zTkt, zTkt);
  }
  if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
  if( P("cancel") ){
    cgi_redirect(zFrom);
  }
  if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct()) ){







|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    if( g.perm.ApndTkt==0 || g.perm.Attach==0 ) login_needed();
    if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
      zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag" 
                        " WHERE tagname GLOB 'tkt-%q*'", zTkt);
      if( zTkt==0 ) fossil_redirect_home();
    }
    zTarget = zTkt;
    zTargetType = mprintf("Ticket <a href=\"%s/tktview/%s\">%S</a>",
                          g.zTop, zTkt, zTkt);
  }
  if( zFrom==0 ) zFrom = mprintf("%s/home", g.zTop);
  if( P("cancel") ){
    cgi_redirect(zFrom);
  }
  if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct()) ){
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
      return;
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Attachment Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid);

  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){
    @ (%d(rid))







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
      return;
    }
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Attachment Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);

  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){
    @ (%d(rid))
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
      output_text_with_line_numbers(z, zLn);
    }else{
      @ <pre>
      @ %h(z)
      @ </pre>
    }
  }else if( strncmp(zMime, "image/", 6)==0 ){
    @ <img src="%R/raw/%S(zSrc)?m=%s(zMime)"></img>
    style_submenu_element("Image", "Image", "%R/raw/%S?m=%s", zSrc, zMime);
  }else{
    int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
    @ <i>(file is %d(sz) bytes of binary data)</i>
  }
  @ </blockquote>
  manifest_destroy(pAttach);
  blob_reset(&attach);







|
|







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
      output_text_with_line_numbers(z, zLn);
    }else{
      @ <pre>
      @ %h(z)
      @ </pre>
    }
  }else if( strncmp(zMime, "image/", 6)==0 ){
    @ <img src="%R/raw/%s(zSrc)?m=%s(zMime)"></img>
    style_submenu_element("Image", "Image", "%R/raw/%s?m=%s", zSrc, zMime);
  }else{
    int sz = db_int(0, "SELECT size FROM blob WHERE rid=%d", ridSrc);
    @ <i>(file is %d(sz) bytes of binary data)</i>
  }
  @ </blockquote>
  manifest_destroy(pAttach);
  blob_reset(&attach);
Changes to src/browse.c.
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  int i, j;
  char *zSep = "";

  for(i=0; zPath[i]; i=j){
    for(j=i; zPath[j] && zPath[j]!='/'; j++){}
    if( zPath[j] && g.perm.Hyperlink ){
      if( zCI ){
        char *zLink = href("%R/%s?ci=%S&name=%#T%s", zURI, zCI, j, zPath,zREx);
        blob_appendf(pOut, "%s%z%#h</a>",
                     zSep, zLink, j-i, &zPath[i]);
      }else{
        char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
        blob_appendf(pOut, "%s%z%#h</a>",
                     zSep, zLink, j-i, &zPath[i]);
      }







|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  int i, j;
  char *zSep = "";

  for(i=0; zPath[i]; i=j){
    for(j=i; zPath[j] && zPath[j]!='/'; j++){}
    if( zPath[j] && g.perm.Hyperlink ){
      if( zCI ){
        char *zLink = href("%R/%s?name=%#T%s&ci=%s", zURI, j, zPath, zREx, zCI);
        blob_appendf(pOut, "%s%z%#h</a>",
                     zSep, zLink, j-i, &zPath[i]);
      }else{
        char *zLink = href("%R/%s?name=%#T%s", zURI, j, zPath, zREx);
        blob_appendf(pOut, "%s%z%#h</a>",
                     zSep, zLink, j-i, &zPath[i]);
      }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( zCI ){
    char zShort[20];
    memcpy(zShort, zUuid, 10);
    zShort[10] = 0;
    @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
    if( nD==0 ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S",
                            zUuid);
    }
  }else{
    @ <h2>The union of all files from all check-ins
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
  }







<
<
<
|

|

|







177
178
179
180
181
182
183



184
185
186
187
188
189
190
191
192
193
194
195
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
  if( linkTip ){
    style_submenu_element("Tip", "Tip", "%s",
                          url_render(&sURI, "ci", "tip", 0, 0));
  }
  if( zCI ){



    @ <h2>Files of check-in [%z(href("vinfo?name=%s",zUuid))%.10s(zUuid)</a>]
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?ci=%s&name=%T", zUuid, zPrefix);
    if( nD==0 ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
                            zUuid);
    }
  }else{
    @ <h2>The union of all files from all check-ins
    @ %s(blob_str(&dirname))</h2>
    zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
  }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
      blob_appendf(&dirname, "matching \"%s\"", zRE);
    }
  }
  if( zCI ){
    style_submenu_element("All", "All", "%s",
                          url_render(&sURI, "ci", 0, 0, 0));
    if( nD==0 && !showDirOnly ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%S",
                            zUuid);
    }
  }
  if( linkTrunk ){
    style_submenu_element("Trunk", "Trunk", "%s",
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }







|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
      blob_appendf(&dirname, "matching \"%s\"", zRE);
    }
  }
  if( zCI ){
    style_submenu_element("All", "All", "%s",
                          url_render(&sURI, "ci", 0, 0, 0));
    if( nD==0 && !showDirOnly ){
      style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s",
                            zUuid);
    }
  }
  if( linkTrunk ){
    style_submenu_element("Trunk", "Trunk", "%s",
                          url_render(&sURI, "ci", "trunk", 0, 0));
  }
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  }

  if( zCI ){
    @ <h2>%d(nFile) %s(zObjType) of check-in
    if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
      @ "%h(zCI)"
    }
    @ [%z(href("vinfo?name=%T",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2>
  }else{
    int n = db_int(0, "SELECT count(*) FROM plink");
    @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins
    @ %s(blob_str(&dirname))</h2>
  }









|







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  }

  if( zCI ){
    @ <h2>%d(nFile) %s(zObjType) of check-in
    if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){
      @ "%h(zCI)"
    }
    @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2>
  }else{
    int n = db_int(0, "SELECT count(*) FROM plink");
    @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins
    @ %s(blob_str(&dirname))</h2>
  }


615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
        @ <ul id="dir%d(nDir)" class="collapsed">
      }
      nDir++;
    }else if( !showDirOnly ){
      const char *zFileClass = fileext_class(p->zName);
      char *zLink;
      if( zCI ){
        zLink = href("%R/artifact/%S",p->zUuid);
      }else{
        zLink = href("%R/finfo?name=%T",p->zFullName);
      }
      @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a>
    }
    if( p->isLast ){
      int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);







|







612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
        @ <ul id="dir%d(nDir)" class="collapsed">
      }
      nDir++;
    }else if( !showDirOnly ){
      const char *zFileClass = fileext_class(p->zName);
      char *zLink;
      if( zCI ){
        zLink = href("%R/artifact/%s",p->zUuid);
      }else{
        zLink = href("%R/finfo?name=%T",p->zFullName);
      }
      @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a>
    }
    if( p->isLast ){
      int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0);
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
      }
    }else{
      zAge[0] = 0;
    }
    @ <tr>
    @ <td>%s(zAge)
    @ <td width="25">
    @ <td>%z(href("%R/artifact/%S?ln", zFUuid))%h(db_column_text(&q, 3))</a>
    @ </tr>
    @
  }
  @ <tr><td colspan=3><hr></tr>
  @ </table>
  db_finalize(&q);
  style_footer();
}







|








870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
      }
    }else{
      zAge[0] = 0;
    }
    @ <tr>
    @ <td>%s(zAge)
    @ <td width="25">
    @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a>
    @ </tr>
    @
  }
  @ <tr><td colspan=3><hr></tr>
  @ </table>
  db_finalize(&q);
  style_footer();
}
Changes to src/checkin.c.
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**    --header          Identify the repository if there are changes
**    -v|--verbose      Say "(none)" if there are no changes
**
** See also: extra, ls, status
*/
void changes_cmd(void){
  Blob report;
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verboseFlag = find_option("verbose","v",0)!=0;







|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**    --header          Identify the repository if there are changes
**    -v|--verbose      Say "(none)" if there are no changes
**
** See also: extras, ls, status
*/
void changes_cmd(void){
  Blob report;
  int vid;
  int useSha1sum = find_option("sha1sum", 0, 0)!=0;
  int showHdr = find_option("header",0,0)!=0;
  int verboseFlag = find_option("verbose","v",0)!=0;
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
**
**    --abs-paths       Display absolute pathnames.
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**
** See also: changes, extra, ls
*/
void status_cmd(void){
  int vid;
  db_must_be_within_tree();
       /* 012345678901234 */
  fossil_print("repository:   %s\n", db_repository_filename());
  fossil_print("local-root:   %s\n", g.zLocalRoot);







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
**
**    --abs-paths       Display absolute pathnames.
**    --rel-paths       Display pathnames relative to the current working
**                      directory.
**    --sha1sum         Verify file status using SHA1 hashing rather
**                      than relying on file mtimes.
**
** See also: changes, extras, ls
*/
void status_cmd(void){
  int vid;
  db_must_be_within_tree();
       /* 012345678901234 */
  fossil_print("repository:   %s\n", db_repository_filename());
  fossil_print("local-root:   %s\n", g.zLocalRoot);
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
** extra information about each file.  If FILENAMES are included, only
** the files listed (or their children if they are directories) are shown.
**
** Options:
**   --age           Show when each file was committed
**   -v|--verbose    Provide extra information about each file.
**
** See also: changes, extra, status
*/
void ls_cmd(void){
  int vid;
  Stmt q;
  int verboseFlag;
  int showAge;
  char *zOrderBy = "pathname";







|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
** extra information about each file.  If FILENAMES are included, only
** the files listed (or their children if they are directories) are shown.
**
** Options:
**   --age           Show when each file was committed
**   -v|--verbose    Provide extra information about each file.
**
** See also: changes, extras, status
*/
void ls_cmd(void){
  int vid;
  Stmt q;
  int verboseFlag;
  int showAge;
  char *zOrderBy = "pathname";
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446

447
448
449
450
451
452
453
** Pathnames are displayed according to the "relative-paths" setting,
** unless overridden by the --abs-paths or --rel-paths options.
**
** Options:
**    --abs-paths      Display absolute pathnames.
**    --case-sensitive <BOOL> override case-sensitive setting
**    --dotfiles       include files beginning with a dot (".")

**    --ignore <CSG>   ignore files matching patterns from the argument
**    --rel-paths      Display pathnames relative to the current working
**                     directory.
**
** See also: changes, clean, status
*/
void extra_cmd(void){
  Stmt q;
  const char *zIgnoreFlag = find_option("ignore",0,1);
  unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;

  int cwdRelative = 0;
  Glob *pIgnore;
  Blob rewrittenPathname;
  const char *zPathname, *zDisplayName;

  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
  capture_case_sensitive_option();







>






|



>







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
** Pathnames are displayed according to the "relative-paths" setting,
** unless overridden by the --abs-paths or --rel-paths options.
**
** Options:
**    --abs-paths      Display absolute pathnames.
**    --case-sensitive <BOOL> override case-sensitive setting
**    --dotfiles       include files beginning with a dot (".")
**    --header         Identify the repository if there are extras
**    --ignore <CSG>   ignore files matching patterns from the argument
**    --rel-paths      Display pathnames relative to the current working
**                     directory.
**
** See also: changes, clean, status
*/
void extras_cmd(void){
  Stmt q;
  const char *zIgnoreFlag = find_option("ignore",0,1);
  unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
  int showHdr = find_option("header",0,0)!=0;
  int cwdRelative = 0;
  Glob *pIgnore;
  Blob rewrittenPathname;
  const char *zPathname, *zDisplayName;

  if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP;
  capture_case_sensitive_option();
474
475
476
477
478
479
480





481
482
483
484
485
486
487
      file_relative_name(zFullName, &rewrittenPathname, 0);
      free(zFullName);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }





    fossil_print("%s\n", zDisplayName);
  }
  blob_reset(&rewrittenPathname);
  db_finalize(&q);
}

/*







>
>
>
>
>







476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
      file_relative_name(zFullName, &rewrittenPathname, 0);
      free(zFullName);
      zDisplayName = blob_str(&rewrittenPathname);
      if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
        zDisplayName += 2;  /* no unnecessary ./ prefix */
      }
    }
    if( showHdr ){
      showHdr = 0;
      fossil_print("Extras for %s at %s:\n", db_get("project-name","???"),
                   g.zLocalRoot);
    }
    fossil_print("%s\n", zDisplayName);
  }
  blob_reset(&rewrittenPathname);
  db_finalize(&q);
}

/*
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
**                     comma separated list of glob patterns.
**    --keep <CSG>     Keep files matching this comma separated
**                     list of glob patterns.
**    -n|--dry-run     If given, display instead of run actions.
**    --temp           Remove only Fossil-generated temporary files.
**    -v|--verbose     Show all files as they are removed.
**    -x|--extreme     Remove all files not part of the current
**                     checkout, without taking into consideration
**                     the "ignore-glob" setting and the --ignore
**                     command line option.
**                     Compatibile with "git clean -x".
**
** See also: addremove, extra, status
*/
void clean_cmd(void){
  int allFileFlag, allDirFlag, dryRunFlag, verboseFlag, extremeFlag;
  int emptyDirsFlag, dirsOnlyFlag;
  unsigned scanFlags = 0;
  const char *zIgnoreFlag, *zKeepFlag;
  Glob *pIgnore, *pKeep;







|
|
|


|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
**                     comma separated list of glob patterns.
**    --keep <CSG>     Keep files matching this comma separated
**                     list of glob patterns.
**    -n|--dry-run     If given, display instead of run actions.
**    --temp           Remove only Fossil-generated temporary files.
**    -v|--verbose     Show all files as they are removed.
**    -x|--extreme     Remove all files not part of the current
**                     checkout, except the ones matching --keep.
**                     Files not matching any of --clean/--ignore/-keep,
**                     will be prompted for.
**                     Compatibile with "git clean -x".
**
** See also: addremove, extras, status
*/
void clean_cmd(void){
  int allFileFlag, allDirFlag, dryRunFlag, verboseFlag, extremeFlag;
  int emptyDirsFlag, dirsOnlyFlag;
  unsigned scanFlags = 0;
  const char *zIgnoreFlag, *zKeepFlag;
  Glob *pIgnore, *pKeep;
617
618
619
620
621
622
623

624


625
626
627
628
629
630
631
    if( file_tree_name(g.zRepositoryName, &repo, 0) ){
      db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
    }
    db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      if( glob_match(pKeep, zName+nRoot) ){

        fossil_print("WARNING: KEPT file \"%s\" not removed\n", zName+nRoot);


        continue;
      }
      if( !allFileFlag && !dryRunFlag && (!extremeFlag || !glob_match(pIgnore, zName+nRoot)) ){
        Blob ans;
        char cReply;
        int matchIgnore = extremeFlag && glob_match(pIgnore, zName+nRoot);
        char *prompt = mprintf("%sRemove %s file \"%s\" (a=all/y/N)? ",







>
|
>
>







624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
    if( file_tree_name(g.zRepositoryName, &repo, 0) ){
      db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
    }
    db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)");
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      if( glob_match(pKeep, zName+nRoot) ){
        if( verboseFlag ){
          fossil_print("KEPT file \"%s\" not removed (due to --keep"
                       " or \"keep-glob\")\n", zName+nRoot);
        }
        continue;
      }
      if( !allFileFlag && !dryRunFlag && (!extremeFlag || !glob_match(pIgnore, zName+nRoot)) ){
        Blob ans;
        char cReply;
        int matchIgnore = extremeFlag && glob_match(pIgnore, zName+nRoot);
        char *prompt = mprintf("%sRemove %s file \"%s\" (a=all/y/N)? ",
666
667
668
669
670
671
672

673


674
675
676
677
678
679
680
        " WHERE x NOT IN (%s) AND y = 0"
        " ORDER BY 1 DESC",
        g.zLocalRoot, fossil_all_reserved_names(0)
    );
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      if( glob_match(pKeep, zName+nRoot) ){

        fossil_print("WARNING: KEPT directory \"%s\" not removed\n", zName+nRoot);


        continue;
      }
      if( !allDirFlag && !dryRunFlag && (!extremeFlag || !glob_match(pIgnore, zName+nRoot)) ){
        Blob ans;
        char cReply;
        int matchIgnore = extremeFlag && glob_match(pIgnore, zName+nRoot);
        int matchEmpty = extremeFlag && glob_match(pEmptyDirs, zName+nRoot);







>
|
>
>







676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
        " WHERE x NOT IN (%s) AND y = 0"
        " ORDER BY 1 DESC",
        g.zLocalRoot, fossil_all_reserved_names(0)
    );
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      if( glob_match(pKeep, zName+nRoot) ){
        if( verboseFlag ){
          fossil_print("KEPT directory \"%s\" not removed (due to --keep"
                       " or \"keep-glob\")\n", zName+nRoot);
        }
        continue;
      }
      if( !allDirFlag && !dryRunFlag && (!extremeFlag || !glob_match(pIgnore, zName+nRoot)) ){
        Blob ans;
        char cReply;
        int matchIgnore = extremeFlag && glob_match(pIgnore, zName+nRoot);
        int matchEmpty = extremeFlag && glob_match(pEmptyDirs, zName+nRoot);
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
    blob_append(&prompt, zInit, -1);
  }
#else
  blob_init(&prompt, zInit, -1);
#endif
  blob_append(&prompt,
    "\n"
    "# Enter commit message for this check-in. Lines beginning with # are ignored.\n"
    "#\n", -1
  );
  blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : login_name());
  if( p->zBranch && p->zBranch[0] ){
    blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
  }else{
    char *zTags = info_tags_of_checkin(parent_rid, 1);







|







849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
    blob_append(&prompt, zInit, -1);
  }
#else
  blob_init(&prompt, zInit, -1);
#endif
  blob_append(&prompt,
    "\n"
    "# Enter a commit message for this check-in. Lines beginning with # are ignored.\n"
    "#\n", -1
  );
  blob_appendf(&prompt, "# user: %s\n", p->zUserOvrd ? p->zUserOvrd : login_name());
  if( p->zBranch && p->zBranch[0] ){
    blob_appendf(&prompt, "# tags: %s\n#\n", p->zBranch);
  }else{
    char *zTags = info_tags_of_checkin(parent_rid, 1);
1339
1340
1341
1342
1343
1344
1345



1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
      allOk = 1;
    }else if( *zConvert && (cReply=='c' || cReply=='C') ){
      char *zOrig = file_newname(zFilename, "original", 1);
      FILE *f;
      blob_write_to_file(p, zOrig);
      fossil_free(zOrig);
      f = fossil_fopen(zFilename, "wb");



      if( fUnicode ) {
        int bomSize;
        const unsigned char *bom = get_utf8_bom(&bomSize);
        fwrite(bom, 1, bomSize, f);
        blob_to_utf8_no_bom(p, 0);
      }
      if( fHasAnyCr ){
        blob_to_lf_only(p);
      }
      fwrite(blob_buffer(p), 1, blob_size(p), f);
      fclose(f);

      return 1;
    }else if( cReply!='y' && cReply!='Y' ){
      fossil_fatal("Abandoning commit due to %s in %s",
                   zWarning, blob_str(&fname));
    }
    blob_reset(&ans);
    blob_reset(&fname);







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







1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
      allOk = 1;
    }else if( *zConvert && (cReply=='c' || cReply=='C') ){
      char *zOrig = file_newname(zFilename, "original", 1);
      FILE *f;
      blob_write_to_file(p, zOrig);
      fossil_free(zOrig);
      f = fossil_fopen(zFilename, "wb");
      if( f==0 ){
        fossil_warning("cannot open %s for writing", zFilename);
      }else{
        if( fUnicode ) {
          int bomSize;
          const unsigned char *bom = get_utf8_bom(&bomSize);
          fwrite(bom, 1, bomSize, f);
          blob_to_utf8_no_bom(p, 0);
        }
        if( fHasAnyCr ){
          blob_to_lf_only(p);
        }
        fwrite(blob_buffer(p), 1, blob_size(p), f);
        fclose(f);
      }
      return 1;
    }else if( cReply!='y' && cReply!='Y' ){
      fossil_fatal("Abandoning commit due to %s in %s",
                   zWarning, blob_str(&fname));
    }
    blob_reset(&ans);
    blob_reset(&fname);
1415
1416
1417
1418
1419
1420
1421




1422
1423
1424
1425
1426
1427
1428
** check-in process may be aborted if a file contains content that
** appears to be binary, Unicode text, or text with CR/NL line endings
** unless the interactive user chooses to proceed.  If there is no
** interactive user or these warnings should be skipped for some other
** reason, the --no-warnings option may be used.  A check-in is not
** allowed against a closed leaf.
**




** The --private option creates a private check-in that is never synced.
** Children of private check-ins are automatically private.
**
** The --tag option applies the symbolic tag name to the check-in.
**
** The --sha1sum option detects edited files by computing each file's
** SHA1 hash rather than just checking for changes to its size or mtime.







>
>
>
>







1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
** check-in process may be aborted if a file contains content that
** appears to be binary, Unicode text, or text with CR/NL line endings
** unless the interactive user chooses to proceed.  If there is no
** interactive user or these warnings should be skipped for some other
** reason, the --no-warnings option may be used.  A check-in is not
** allowed against a closed leaf.
**
** If a commit message is blank, you will be prompted:
** ("continue (y/N)?") to confirm you really want to commit with a
** blank commit message.  The default value is "N", do not commit.
**
** The --private option creates a private check-in that is never synced.
** Children of private check-ins are automatically private.
**
** The --tag option applies the symbolic tag name to the check-in.
**
** The --sha1sum option detects edited files by computing each file's
** SHA1 hash rather than just checking for changes to its size or mtime.
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
**    --no-warnings              omit all warnings about file contents
**    --nosign                   do not attempt to sign this commit with gpg
**    --private                  do not sync changes and their descendants
**    --sha1sum                  verify file status using SHA1 hashing rather
**                               than relying on file mtimes
**    --tag TAG-NAME             assign given tag TAG-NAME to the checkin
**
** See also: branch, changes, checkout, extra, sync
*/
void commit_cmd(void){
  int hasChanges;        /* True if unsaved changes exist */
  int vid;               /* blob-id of parent version */
  int nrid;              /* blob-id of a modified file */
  int nvid;              /* Blob-id of the new check-in */
  Blob comment;          /* Check-in comment */







|







1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
**    --no-warnings              omit all warnings about file contents
**    --nosign                   do not attempt to sign this commit with gpg
**    --private                  do not sync changes and their descendants
**    --sha1sum                  verify file status using SHA1 hashing rather
**                               than relying on file mtimes
**    --tag TAG-NAME             assign given tag TAG-NAME to the checkin
**
** See also: branch, changes, checkout, extras, sync
*/
void commit_cmd(void){
  int hasChanges;        /* True if unsaved changes exist */
  int vid;               /* blob-id of parent version */
  int nrid;              /* blob-id of a modified file */
  int nvid;              /* Blob-id of the new check-in */
  Blob comment;          /* Check-in comment */
Changes to src/clone.c.
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_fatal("file already exists: %s", g.argv[3]);
  }

  url_parse(g.argv[2], urlFlags);
  if( zDefaultUser==0 && g.urlUser!=0 ) zDefaultUser = g.urlUser;
  if( g.urlIsFile ){
    file_copy(g.urlName, g.argv[3]);
    db_close(1);
    db_open_repository(g.argv[3]);
    db_record_repository_filename(g.argv[3]);
    url_remember();
    if( !bPrivate ) delete_private_content();
    shun_artifacts();
    db_create_default_users(1, zDefaultUser);







|
|
|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_fatal("file already exists: %s", g.argv[3]);
  }

  url_parse(g.argv[2], urlFlags);
  if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user;
  if( g.url.isFile ){
    file_copy(g.url.name, g.argv[3]);
    db_close(1);
    db_open_repository(g.argv[3]);
    db_record_repository_filename(g.argv[3]);
    url_remember();
    if( !bPrivate ) delete_private_content();
    shun_artifacts();
    db_create_default_users(1, zDefaultUser);
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
** decision. Set the global preference if the URL is not being changed.
*/
void remember_or_get_http_auth(
  const char *zHttpAuth,  /* Credentials in the form "user:password" */
  int fRemember,          /* True to remember credentials for later reuse */
  const char *zUrl        /* URL for which these credentials apply */
){
  char *zKey = mprintf("http-auth:%s", g.urlCanonical);
  if( zHttpAuth && zHttpAuth[0] ){
    g.zHttpAuth = mprintf("%s", zHttpAuth);
  }
  if( fRemember ){
    if( g.zHttpAuth && g.zHttpAuth[0] ){
      set_httpauth(g.zHttpAuth);
    }else if( zUrl && zUrl[0] ){







|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
** decision. Set the global preference if the URL is not being changed.
*/
void remember_or_get_http_auth(
  const char *zHttpAuth,  /* Credentials in the form "user:password" */
  int fRemember,          /* True to remember credentials for later reuse */
  const char *zUrl        /* URL for which these credentials apply */
){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
  if( zHttpAuth && zHttpAuth[0] ){
    g.zHttpAuth = mprintf("%s", zHttpAuth);
  }
  if( fRemember ){
    if( g.zHttpAuth && g.zHttpAuth[0] ){
      set_httpauth(g.zHttpAuth);
    }else if( zUrl && zUrl[0] ){
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  free(zKey);
}

/*
** Get the HTTP Authorization preference from db.
*/
char *get_httpauth(void){
  char *zKey = mprintf("http-auth:%s", g.urlCanonical);
  return unobscure(db_get(zKey, 0));
  free(zKey);
}

/*
** Set the HTTP Authorization preference in db.
*/
void set_httpauth(const char *zHttpAuth){
  char *zKey = mprintf("http-auth:%s", g.urlCanonical);
  db_set(zKey, obscure(zHttpAuth), 0);
  free(zKey);
}

/*
** Look for SSH clone command line options and setup in globals.
*/







|








|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  free(zKey);
}

/*
** Get the HTTP Authorization preference from db.
*/
char *get_httpauth(void){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
  return unobscure(db_get(zKey, 0));
  free(zKey);
}

/*
** Set the HTTP Authorization preference in db.
*/
void set_httpauth(const char *zHttpAuth){
  char *zKey = mprintf("http-auth:%s", g.url.canonical);
  db_set(zKey, obscure(zHttpAuth), 0);
  free(zKey);
}

/*
** Look for SSH clone command line options and setup in globals.
*/
Changes to src/configure.c.
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
      usage(mprintf("%s AREA ?URL?", zMethod));
    }
    mask = configure_name_to_mask(g.argv[3], 1);
    if( g.argc==5 ){
      zServer = g.argv[4];
    }
    url_parse(zServer, URL_PROMPT_PW);
    if( g.urlProtocol==0 ) fossil_fatal("no server URL specified");
    user_select();
    url_enable_proxy("via proxy: ");
    if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
    if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
    if( strncmp(zMethod, "push", n)==0 ){
      client_sync(0,0,(unsigned)mask);
    }else if( strncmp(zMethod, "pull", n)==0 ){







|







922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
      usage(mprintf("%s AREA ?URL?", zMethod));
    }
    mask = configure_name_to_mask(g.argv[3], 1);
    if( g.argc==5 ){
      zServer = g.argv[4];
    }
    url_parse(zServer, URL_PROMPT_PW);
    if( g.url.protocol==0 ) fossil_fatal("no server URL specified");
    user_select();
    url_enable_proxy("via proxy: ");
    if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
    if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
    if( strncmp(zMethod, "push", n)==0 ){
      client_sync(0,0,(unsigned)mask);
    }else if( strncmp(zMethod, "pull", n)==0 ){
Changes to src/db.c.
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
       g.zVfsName
  );
  if( rc!=SQLITE_OK ){
    db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
  }
  sqlite3_busy_timeout(db, 5000);
  sqlite3_wal_autocheckpoint(db, 1);  /* Set to checkpoint frequently */
  sqlite3_create_function(db, "now", 0, SQLITE_ANY, 0, db_now_function, 0, 0);
  sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_ANY, 0,
                          db_checkin_mtime_function, 0, 0);
  sqlite3_create_function(db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
  sqlite3_create_function(db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
  sqlite3_create_function(
    db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
  );
  sqlite3_create_function(
    db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
  );







|
|

|
|
|







727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
       g.zVfsName
  );
  if( rc!=SQLITE_OK ){
    db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
  }
  sqlite3_busy_timeout(db, 5000);
  sqlite3_wal_autocheckpoint(db, 1);  /* Set to checkpoint frequently */
  sqlite3_create_function(db, "now", 0, SQLITE_UTF8, 0, db_now_function, 0, 0);
  sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
                          db_checkin_mtime_function, 0, 0);
  sqlite3_create_function(db, "user", 0, SQLITE_UTF8, 0, db_sql_user, 0, 0);
  sqlite3_create_function(db, "cgi", 1, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(db, "cgi", 2, SQLITE_UTF8, 0, db_sql_cgi, 0, 0);
  sqlite3_create_function(db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
  sqlite3_create_function(
    db, "is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
  );
  sqlite3_create_function(
    db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
  );
Changes to src/delta.c.
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
    *(zDelta++) = ':';
    memcpy(zDelta, &zOut[base], lenOut-base);
    zDelta += lenOut-base;
  }
  /* Output the final checksum record. */
  putInt(checksum(zOut, lenOut), &zDelta);
  *(zDelta++) = ';';
  free(collide);
  return zDelta - zOrigDelta; 
}

/*
** Return the size (in bytes) of the output from applying
** a delta. 
**







|







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
    *(zDelta++) = ':';
    memcpy(zDelta, &zOut[base], lenOut-base);
    zDelta += lenOut-base;
  }
  /* Output the final checksum record. */
  putInt(checksum(zOut, lenOut), &zDelta);
  *(zDelta++) = ';';
  fossil_free(collide);
  return zDelta - zOrigDelta; 
}

/*
** Return the size (in bytes) of the output from applying
** a delta. 
**
Changes to src/descendants.c.
327
328
329
330
331
332
333
334
335
336
337


338
339
340
341
342
343
344
345
346
347

348
349
350
351








352
353
354
355
356
357
358
** The -a|--all flag causes all leaves (closed and open) to be shown.
** The -c|--closed flag shows only closed leaves.
**
** The --recompute flag causes the content of the "leaf" table in the
** repository database to be recomputed.
**
** Options:
**   -a|--all     show ALL leaves
**   -c|--closed  show only closed leaves
**   --bybranch   order output by branch name
**   --recompute  recompute the "leaf" table in the repository DB


**
** See also: descendants, finfo, info, branch
*/
void leaves_cmd(void){
  Stmt q;
  Blob sql;
  int showAll = find_option("all", "a", 0)!=0;
  int showClosed = find_option("closed", "c", 0)!=0;
  int recomputeFlag = find_option("recompute",0,0)!=0;
  int byBranch = find_option("bybranch",0,0)!=0;

  char *zLastBr = 0;
  int n;
  char zLineNo[10];









  db_find_and_open_repository(0,0);
  if( recomputeFlag ) leaf_rebuild();
  blob_zero(&sql);
  blob_append(&sql, timeline_query_for_tty(), -1);
  blob_appendf(&sql, " AND blob.rid IN leaf");
  if( showClosed ){
    blob_appendf(&sql," AND %z", leaf_is_closed_sql("blob.rid"));







|
|
|
|
>
>










>

|


>
>
>
>
>
>
>
>







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
** The -a|--all flag causes all leaves (closed and open) to be shown.
** The -c|--closed flag shows only closed leaves.
**
** The --recompute flag causes the content of the "leaf" table in the
** repository database to be recomputed.
**
** Options:
**   -a|--all         show ALL leaves
**   -c|--closed      show only closed leaves
**   --bybranch       order output by branch name
**   --recompute      recompute the "leaf" table in the repository DB
**   -W|--width <num> With of lines (default 79). Must be >39 or 0
**                    (= no limit, resulting in a single line per entry).
**
** See also: descendants, finfo, info, branch
*/
void leaves_cmd(void){
  Stmt q;
  Blob sql;
  int showAll = find_option("all", "a", 0)!=0;
  int showClosed = find_option("closed", "c", 0)!=0;
  int recomputeFlag = find_option("recompute",0,0)!=0;
  int byBranch = find_option("bybranch",0,0)!=0;
  const char *zWidth = find_option("width","W",1);
  char *zLastBr = 0;
  int n, width;
  char zLineNo[10];

  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=39) ){
      fossil_fatal("-W|--width value must be >39 or 0");
    }
  }else{
    width = 79;
  }
  db_find_and_open_repository(0,0);
  if( recomputeFlag ) leaf_rebuild();
  blob_zero(&sql);
  blob_append(&sql, timeline_query_for_tty(), -1);
  blob_appendf(&sql, " AND blob.rid IN leaf");
  if( showClosed ){
    blob_appendf(&sql," AND %z", leaf_is_closed_sql("blob.rid"));
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
      fossil_free(zLastBr);
      zLastBr = fossil_strdup(zBr);
    }
    n++;
    sqlite3_snprintf(sizeof(zLineNo), zLineNo, "(%d)", n);
    fossil_print("%6s ", zLineNo);
    z = mprintf("%s [%.10s] %s", zDate, zId, zCom);
    comment_print(z, 7, 79);
    fossil_free(z);
  }
  fossil_free(zLastBr);
  db_finalize(&q);
}

/*







|







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
      fossil_free(zLastBr);
      zLastBr = fossil_strdup(zBr);
    }
    n++;
    sqlite3_snprintf(sizeof(zLineNo), zLineNo, "(%d)", n);
    fossil_print("%6s ", zLineNo);
    z = mprintf("%s [%.10s] %s", zDate, zId, zCom);
    comment_print(z, 7, width);
    fossil_free(z);
  }
  fossil_free(zLastBr);
  db_finalize(&q);
}

/*
Changes to src/diff.c.
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  int a = pA->indent, b = pB->indent;
  if( pA->h==pB->h ){
    while( a<pA->n && b<pB->n ){
      if( pA->z[a++] != pB->z[b++] ) return 0;
      while( a<pA->n && fossil_isspace(pA->z[a])) ++a;
      while( b<pB->n && fossil_isspace(pB->z[b])) ++b;
    }
    return pA->n-a == b<pB->n-b;
  }
  return 0;
}

/*
** Return true if the regular expression *pRe matches any of the
** N dlines







|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  int a = pA->indent, b = pB->indent;
  if( pA->h==pB->h ){
    while( a<pA->n && b<pB->n ){
      if( pA->z[a++] != pB->z[b++] ) return 0;
      while( a<pA->n && fossil_isspace(pA->z[a])) ++a;
      while( b<pB->n && fossil_isspace(pB->z[b])) ++b;
    }
    return pA->n-a == pB->n-b;
  }
  return 0;
}

/*
** Return true if the regular expression *pRe matches any of the
** N dlines
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  int nLeftDiff;       /* nLeft - nPrefix - nSuffix */
  int nRightDiff;      /* nRight - nPrefix - nSuffix */
  int aLCS[4];         /* Bounds of common middle segment */
  static const char zClassRm[]   = "<span class=\"diffrm\">";
  static const char zClassAdd[]  = "<span class=\"diffadd\">";
  static const char zClassChng[] = "<span class=\"diffchng\">";

  nLeft = pLeft->h & LENGTH_MASK;
  zLeft = pLeft->z;
  nRight = pRight->h & LENGTH_MASK;
  zRight = pRight->z;
  nShort = nLeft<nRight ? nLeft : nRight;

  nPrefix = 0;
  while( nPrefix<nShort && zLeft[nPrefix]==zRight[nPrefix] ){
    nPrefix++;
  }







|

|







764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  int nLeftDiff;       /* nLeft - nPrefix - nSuffix */
  int nRightDiff;      /* nRight - nPrefix - nSuffix */
  int aLCS[4];         /* Bounds of common middle segment */
  static const char zClassRm[]   = "<span class=\"diffrm\">";
  static const char zClassAdd[]  = "<span class=\"diffadd\">";
  static const char zClassChng[] = "<span class=\"diffchng\">";

  nLeft = pLeft->n;
  zLeft = pLeft->z;
  nRight = pRight->n;
  zRight = pRight->z;
  nShort = nLeft<nRight ? nLeft : nRight;

  nPrefix = 0;
  while( nPrefix<nShort && zLeft[nPrefix]==zRight[nPrefix] ){
    nPrefix++;
  }
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  int score;                 /* Final score.  0..100 */
  unsigned char c;           /* Character being examined */
  unsigned char aFirst[256]; /* aFirst[X] = index in zB[] of first char X */
  unsigned char aNext[252];  /* aNext[i] = index in zB[] of next zB[i] char */

  zA = pA->z;
  zB = pB->z;
  nA = pA->h & LENGTH_MASK;
  nB = pB->h & LENGTH_MASK;
  while( nA>0 && fossil_isspace(zA[0]) ){ nA--; zA++; }
  while( nA>0 && fossil_isspace(zA[nA-1]) ){ nA--; }
  while( nB>0 && fossil_isspace(zB[0]) ){ nB--; zB++; }
  while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
  if( nA>250 ) nA = 250;
  if( nB>250 ) nB = 250;
  avg = (nA+nB)/2;







|
|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  int score;                 /* Final score.  0..100 */
  unsigned char c;           /* Character being examined */
  unsigned char aFirst[256]; /* aFirst[X] = index in zB[] of first char X */
  unsigned char aNext[252];  /* aNext[i] = index in zB[] of next zB[i] char */

  zA = pA->z;
  zB = pB->z;
  nA = pA->n;
  nB = pB->n;
  while( nA>0 && fossil_isspace(zA[0]) ){ nA--; zA++; }
  while( nA>0 && fossil_isspace(zA[nA-1]) ){ nA--; }
  while( nB>0 && fossil_isspace(zB[0]) ){ nB--; zB++; }
  while( nB>0 && fossil_isspace(zB[nB-1]) ){ nB--; }
  if( nA>250 ) nA = 250;
  if( nB>250 ) nB = 250;
  avg = (nA+nB)/2;
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
  }
  for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
    clr = gradient_color(clr1, clr2, ann.nVers-1, i);
    ann.aVers[i].zBgColor = mprintf("#%06x", clr);
  }

  if( showLog ){
    char *zLink = href("%R/finfo?name=%t&ci=%S",zFilename,zCI);
    @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
    @ <ol>
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
      @ check-in %z(href("%R/info/%S",p->zMUuid))%.10s(p->zMUuid)</a>
      @ artifact %z(href("%R/artifact/%S",p->zFUuid))%.10s(p->zFUuid)</a>
      @ </span>
#if 0
      if( i>0 ){
        char *zLink = xhref("target='infowindow'",
                            "%R/fdiff?v1=%S&v2=%S&sbs=1",
                            p->zFUuid,ann.aVers[0].zFUuid);
        @ %z(zLink)[diff-to-top]</a>







|




|
|







2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
  }
  for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
    clr = gradient_color(clr1, clr2, ann.nVers-1, i);
    ann.aVers[i].zBgColor = mprintf("#%06x", clr);
  }

  if( showLog ){
    char *zLink = href("%R/finfo?name=%t&ci=%s",zFilename,zCI);
    @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
    @ <ol>
    for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
      @ <li><span style='background-color:%s(p->zBgColor);'>%s(p->zDate)
      @ check-in %z(href("%R/info/%s",p->zMUuid))%.10s(p->zMUuid)</a>
      @ artifact %z(href("%R/artifact/%s",p->zFUuid))%.10s(p->zFUuid)</a>
      @ </span>
#if 0
      if( i>0 ){
        char *zLink = xhref("target='infowindow'",
                            "%R/fdiff?v1=%S&v2=%S&sbs=1",
                            p->zFUuid,ann.aVers[0].zFUuid);
        @ %z(zLink)[diff-to-top]</a>
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
#endif
    }
    @ </ol>
    @ <hr>
  }
  if( !ann.bLimit ){
    @ <h2>Origin for each line in
    @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename)</a>
    @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
    iLimit = ann.nVers+10;
  }else{
    @ <h2>Lines added by the %d(iLimit) most recent ancestors of
    @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename)</a>
    @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
  }
  @ <pre>
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;
    char zPrefix[300];
    z[n] = 0;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;

    if( bBlame ){
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %13.13s:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
      }
    }else{
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %4d:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1);







|
|



|
|













|











|







2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
#endif
    }
    @ </ol>
    @ <hr>
  }
  if( !ann.bLimit ){
    @ <h2>Origin for each line in
    @ %z(href("%R/finfo?name=%h&ci=%s", zFilename, zCI))%h(zFilename)</a>
    @ from check-in %z(href("%R/info/%s",zCI))%S(zCI)</a>:</h2>
    iLimit = ann.nVers+10;
  }else{
    @ <h2>Lines added by the %d(iLimit) most recent ancestors of
    @ %z(href("%R/finfo?name=%h&ci=%s", zFilename, zCI))%h(zFilename)</a>
    @ from check-in %z(href("%R/info/%s",zCI))%S(zCI)</a>:</h2>
  }
  @ <pre>
  for(i=0; i<ann.nOrig; i++){
    int iVers = ann.aOrig[i].iVers;
    char *z = (char*)ann.aOrig[i].z;
    int n = ann.aOrig[i].n;
    char zPrefix[300];
    z[n] = 0;
    if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;

    if( bBlame ){
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%s", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %13.13s:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
      }
    }else{
      if( iVers>=0 ){
        struct AnnVers *p = ann.aVers+iVers;
        char *zLink = xhref("target='infowindow'", "%R/info/%s", p->zMUuid);
        sqlite3_snprintf(sizeof(zPrefix), zPrefix,
             "<span style='background-color:%s'>"
             "%s%.10s</a> %s</span> %4d:",
             p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
        fossil_free(zLink);
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1);
Changes to src/diffcmd.c.
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944
945
946
947

























948

949
950
951
952
953
954
955
956
957
@   tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
@   exit
@ }
@ update idletasks
@
@ proc saveDiff {} {
@   set fn [tk_getSaveFile]

@   set out [open $fn wb]
@   puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
@   puts $out "# to see the graphical diff.\n#"
@   puts $out "set fossilcmd {}"
@   puts $out "set prog [list $::prog]"
@   puts $out "set difftxt \173"
@   foreach e $::difftxt {puts $out [list $e]}
@   puts $out "\175"
@   puts $out "eval \$prog"
@   close $out
@ }

























@ ::ttk::button .bb.quit -text {Quit} -command exit

@ ::ttk::button .bb.save -text {Save As...} -command saveDiff
@ pack .bb.quit -side left
@ if {$fossilcmd!=""} {pack .bb.save -side left}
@ pack .bb.files -side left
@ grid rowconfigure . 1 -weight 1
@ grid columnconfigure . 1 -weight 1
@ grid columnconfigure . 4 -weight 1
@ grid .bb -row 0 -columnspan 6
@ eval grid [cols] -row 1 -sticky nsew







>











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

>

|







930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
@   tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
@   exit
@ }
@ update idletasks
@
@ proc saveDiff {} {
@   set fn [tk_getSaveFile]
@   if {$fn==""} return
@   set out [open $fn wb]
@   puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
@   puts $out "# to see the graphical diff.\n#"
@   puts $out "set fossilcmd {}"
@   puts $out "set prog [list $::prog]"
@   puts $out "set difftxt \173"
@   foreach e $::difftxt {puts $out [list $e]}
@   puts $out "\175"
@   puts $out "eval \$prog"
@   close $out
@ }
@ proc invertDiff {} {
@   global CFG
@   array set x [grid info .txtA]
@   if {$x(-column)==1} {
@     grid config .lnB -column 0
@     grid config .txtB -column 1
@     .txtB tag config add -background $CFG(RM_BG)
@     grid config .lnA -column 3
@     grid config .txtA -column 4
@     .txtA tag config rm -background $CFG(ADD_BG)
@   } else {
@     grid config .lnA -column 0
@     grid config .txtA -column 1
@     .txtA tag config rm -background $CFG(RM_BG)
@     grid config .lnB -column 3
@     grid config .txtB -column 4
@     .txtB tag config add -background $CFG(ADD_BG)
@   }
@   .mkr config -state normal
@   set clt [.mkr search -all < 1.0 end]
@   set cgt [.mkr search -all > 1.0 end]
@   foreach c $clt {.mkr replace $c "$c +1 chars" >}
@   foreach c $cgt {.mkr replace $c "$c +1 chars" <}
@   .mkr config -state disabled
@ }
@ ::ttk::button .bb.quit -text {Quit} -command exit
@ ::ttk::button .bb.invert -text {Invert} -command invertDiff
@ ::ttk::button .bb.save -text {Save As...} -command saveDiff
@ pack .bb.quit .bb.invert -side left
@ if {$fossilcmd!=""} {pack .bb.save -side left}
@ pack .bb.files -side left
@ grid rowconfigure . 1 -weight 1
@ grid columnconfigure . 1 -weight 1
@ grid columnconfigure . 4 -weight 1
@ grid .bb -row 0 -columnspan 6
@ eval grid [cols] -row 1 -sticky nsew
996
997
998
999
1000
1001
1002




1003
1004

1005
1006
1007
1008
1009
1010
1011
      ** for testing and debugging. */
      if( strglob("*-script",z) && i<g.argc-1 ){
        i++;
        zTempFile = g.argv[i];
        continue;
      }
    }




    blob_append(&script, " ", 1);
    shell_escape(&script, z);

  }
  blob_appendf(&script, "}\n%s", zDiffScript);
  if( zTempFile ){
    blob_write_to_file(&script, zTempFile);
    fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
  }else{
#if defined(FOSSIL_ENABLE_TCL)







>
>
>
>
|
|
>







1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
      ** for testing and debugging. */
      if( strglob("*-script",z) && i<g.argc-1 ){
        i++;
        zTempFile = g.argv[i];
        continue;
      }
    }
    if( sqlite3_strglob("*}*",z) ){
      blob_appendf(&script, " {%/}", z);
    }else{
      int j;
      blob_append(&script, " ", 1);
      for(j=0; z[j]; j++) blob_appendf(&script, "\\%03o", (unsigned char)z[j]);
    }
  }
  blob_appendf(&script, "}\n%s", zDiffScript);
  if( zTempFile ){
    blob_write_to_file(&script, zTempFile);
    fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
  }else{
#if defined(FOSSIL_ENABLE_TCL)
Changes to src/file.c.
975
976
977
978
979
980
981


982
983
984
985
986
987
988
      }else{
        blob_set(pOut, "..");
        for(j=i+1; zPwd[j]; j++){
          if( zPwd[j]=='/' ){
            blob_append(pOut, "/..", 3);
          }
        }


      }
      if( slash && i>0 && zPath[strlen(zPath)-1]=='/'){
        blob_append(pOut, "/", 1);
      }
      blob_reset(&tmp);
      return;
    }







>
>







975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
      }else{
        blob_set(pOut, "..");
        for(j=i+1; zPwd[j]; j++){
          if( zPwd[j]=='/' ){
            blob_append(pOut, "/..", 3);
          }
        }
        while( i>0 && (zPwd[i]!='/')) --i;
        blob_append(pOut, zPath+i, j-i);
      }
      if( slash && i>0 && zPath[strlen(zPath)-1]=='/'){
        blob_append(pOut, "/", 1);
      }
      blob_reset(&tmp);
      return;
    }
1042
1043
1044
1045
1046
1047
1048


1049

1050
1051
1052
1053
1054
1055
1056
  char *zLocalRoot;
  Blob full;
  int nFull;
  char *zFull;
  int (*xCmp)(const char*,const char*,int);

  blob_zero(pOut);


  db_must_be_within_tree();

  file_canonical_name(g.zLocalRoot, &localRoot, 1);
  nLocalRoot = blob_size(&localRoot);
  zLocalRoot = blob_buffer(&localRoot);
  assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
  file_canonical_name(zOrigName, &full, 0);
  nFull = blob_size(&full);
  zFull = blob_buffer(&full);







>
>
|
>







1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  char *zLocalRoot;
  Blob full;
  int nFull;
  char *zFull;
  int (*xCmp)(const char*,const char*,int);

  blob_zero(pOut);
  if( !g.localOpen ){
    blob_appendf(pOut, "%s", zOrigName);
    return 1;
  }
  file_canonical_name(g.zLocalRoot, &localRoot, 1);
  nLocalRoot = blob_size(&localRoot);
  zLocalRoot = blob_buffer(&localRoot);
  assert( nLocalRoot>0 && zLocalRoot[nLocalRoot-1]=='/' );
  file_canonical_name(zOrigName, &full, 0);
  nFull = blob_size(&full);
  zFull = blob_buffer(&full);
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
** Options:
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is
**                        a boolean: "yes", "no", "true", "false", etc.
*/
void cmd_test_tree_name(void){
  int i;
  Blob x;

  blob_zero(&x);
  capture_case_sensitive_option();
  for(i=2; i<g.argc; i++){
    if( file_tree_name(g.argv[i], &x, 1) ){
      fossil_print("%s\n", blob_buffer(&x));
      blob_reset(&x);
    }







>







1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
** Options:
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is
**                        a boolean: "yes", "no", "true", "false", etc.
*/
void cmd_test_tree_name(void){
  int i;
  Blob x;
  db_find_and_open_repository(0,0);
  blob_zero(&x);
  capture_case_sensitive_option();
  for(i=2; i<g.argc; i++){
    if( file_tree_name(g.argv[i], &x, 1) ){
      fossil_print("%s\n", blob_buffer(&x));
      blob_reset(&x);
    }
Changes to src/finfo.c.
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    zWidth = find_option("width","W",1);
    iLimit = zLimit ? atoi(zLimit) : -1;
    iWidth = zWidth ? atoi(zWidth) : 79;
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( (iWidth!=0) && (iWidth<=22) ){
      fossil_fatal("--width|-W value must be >22 or 0");
    }
    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());







|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    zWidth = find_option("width","W",1);
    iLimit = zLimit ? atoi(zLimit) : -1;
    iWidth = zWidth ? atoi(zWidth) : 79;
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( (iWidth!=0) && (iWidth<=22) ){
      fossil_fatal("-W|--width value must be >22 or 0");
    }
    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  if( P("showsql")!=0 ){
    @ <p>SQL: %h(blob_str(&sql))</p>
  }
  blob_reset(&sql);
  blob_zero(&title);
  if( baseCheckin ){
    char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
    char *zLink = href("%R/info/%S", zUuid);
    blob_appendf(&title, "Ancestors of file ");
    hyperlinked_path(zFilename, &title, zUuid, "tree", "");
    blob_appendf(&title, " from check-in %z%.10s</a>", zLink, zUuid);
    fossil_free(zUuid);
  }else{
    blob_appendf(&title, "History of files named ");
    hyperlinked_path(zFilename, &title, 0, "tree", "");







|







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  if( P("showsql")!=0 ){
    @ <p>SQL: %h(blob_str(&sql))</p>
  }
  blob_reset(&sql);
  blob_zero(&title);
  if( baseCheckin ){
    char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
    char *zLink = href("%R/info/%s", zUuid);
    blob_appendf(&title, "Ancestors of file ");
    hyperlinked_path(zFilename, &title, zUuid, "tree", "");
    blob_appendf(&title, " from check-in %z%.10s</a>", zLink, zUuid);
    fossil_free(zUuid);
  }else{
    blob_appendf(&title, "History of files named ");
    hyperlinked_path(zFilename, &title, 0, "tree", "");
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    const char *zCkin = db_column_text(&q,7);
    const char *zBgClr = db_column_text(&q, 8);
    const char *zBr = db_column_text(&q, 9);
    int fmid = db_column_int(&q, 10);
    int pfnid = db_column_int(&q, 11);
    int gidx;
    char zTime[10];
    char zShort[20];
    char zShortCkin[20];
    if( zBr==0 ) zBr = "trunk";
    if( uBg ){
      zBgClr = hash_color(zUser);
    }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
      zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
    }
    gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,







<
<







402
403
404
405
406
407
408


409
410
411
412
413
414
415
    const char *zCkin = db_column_text(&q,7);
    const char *zBgClr = db_column_text(&q, 8);
    const char *zBr = db_column_text(&q, 9);
    int fmid = db_column_int(&q, 10);
    int pfnid = db_column_int(&q, 11);
    int gidx;
    char zTime[10];


    if( zBr==0 ) zBr = "trunk";
    if( uBg ){
      zBgClr = hash_color(zUser);
    }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
      zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
    }
    gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
    @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
    }else{
      @ <td class="timelineTableCell">
    }
    sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
    sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
    if( zUuid ){
      if( fpid==0 ){
        @ <b>Added</b>
      }else if( pfnid ){
        char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
                                  pfnid);
        @ <b>Renamed</b> from







<
<







426
427
428
429
430
431
432


433
434
435
436
437
438
439
    @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
    @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
    if( zBgClr && zBgClr[0] ){
      @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
    }else{
      @ <td class="timelineTableCell">
    }


    if( zUuid ){
      if( fpid==0 ){
        @ <b>Added</b>
      }else if( pfnid ){
        char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
                                  pfnid);
        @ <b>Renamed</b> from
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
        @ <b>Renamed</b> to
        @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
        fossil_free(zNewName);
      }else{
        @ <b>Deleted</b> by check-in
      }
    }
    hyperlink_to_uuid(zShortCkin);
    @ %w(zCom) (user:
    hyperlink_to_user(zUser, zDate, "");
    @ branch: %h(zBr))
    if( g.perm.Hyperlink && zUuid ){
      const char *z = zFilename;
      @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
      @ [annotate]</a>
      @ %z(href("%R/blame?checkin=%S&filename=%h",zCkin,z))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=200&uf=%S",zUuid))[checkins&nbsp;using]</a>
      if( fpid ){
        @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zPUuid,zUuid))[diff]</a>
      }
    }
    if( fDebug & FINFO_DEBUG_MLINK ){
      int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
      int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
      @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
      if( srcid ){







|





|

|

|

|







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
        @ <b>Renamed</b> to
        @ %z(href("%R/finfo?name=%t",zNewName))%h(zNewName)</a> by check-in
        fossil_free(zNewName);
      }else{
        @ <b>Deleted</b> by check-in
      }
    }
    hyperlink_to_uuid(zCkin);
    @ %w(zCom) (user:
    hyperlink_to_user(zUser, zDate, "");
    @ branch: %h(zBr))
    if( g.perm.Hyperlink && zUuid ){
      const char *z = zFilename;
      @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
      @ [blame]</a>
      @ %z(href("%R/timeline?n=200&uf=%s",zUuid))[checkins&nbsp;using]</a>
      if( fpid ){
        @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
      }
    }
    if( fDebug & FINFO_DEBUG_MLINK ){
      int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
      int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
      @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
      if( srcid ){
Changes to src/http.c.
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
82
83
84
85
86
87
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  blob_zero(pLogin);
  if( g.urlUser==0 || fossil_strcmp(g.urlUser, "anonymous")==0 ){
     return;  /* If no login card for users "nobody" and "anonymous" */
  }
  if( g.urlIsSsh ){
     return;  /* If no login card for SSH: */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.urlUser;
  if( g.urlPasswd ){
    zPw = g.urlPasswd;
  }else if( g.cgiOutput ){
    /* Password failure while doing a sync from the web interface */
    cgi_printf("*** incorrect or missing password for user %h\n", zLogin);
    zPw = 0;
  }else{
    /* Password failure while doing a sync from the command-line interface */
    url_prompt_for_password();
    zPw = g.urlPasswd;
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash it it isn't already a SHA1 hash.
  */
  /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
  if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);







|


|






|
|
|







|







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
82
83
84
85
86
87
  Blob nonce;          /* The nonce */
  const char *zLogin;  /* The user login name */
  const char *zPw;     /* The user password */
  Blob pw;             /* The nonce with user password appended */
  Blob sig;            /* The signature field */

  blob_zero(pLogin);
  if( g.url.user==0 || fossil_strcmp(g.url.user, "anonymous")==0 ){
     return;  /* If no login card for users "nobody" and "anonymous" */
  }
  if( g.url.isSsh ){
     return;  /* If no login card for SSH: */
  }
  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pPayload, &nonce);
  blob_copy(&pw, &nonce);
  zLogin = g.url.user;
  if( g.url.passwd ){
    zPw = g.url.passwd;
  }else if( g.cgiOutput ){
    /* Password failure while doing a sync from the web interface */
    cgi_printf("*** incorrect or missing password for user %h\n", zLogin);
    zPw = 0;
  }else{
    /* Password failure while doing a sync from the command-line interface */
    url_prompt_for_password();
    zPw = g.url.passwd;
  }

  /* The login card wants the SHA1 hash of the password, so convert the
  ** password to its SHA1 hash it it isn't already a SHA1 hash.
  */
  /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
  if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;

  blob_zero(pHdr);
  i = strlen(g.urlPath);
  if( i>0 && g.urlPath[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep);
  if( g.urlProxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.urlProxyAuth);
  }
  if( g.zHttpAuth && g.zHttpAuth[0] ){
    const char *zCredentials = g.zHttpAuth;
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
  if( g.urlIsSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
  if( g.fHttpTrace ){
    blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
  }else{
    blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
  }
  blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}







|
|




|
|
|







|

|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
** the complete payload (including the login card) already compressed.
*/
static void http_build_header(Blob *pPayload, Blob *pHdr){
  int i;
  const char *zSep;

  blob_zero(pHdr);
  i = strlen(g.url.path);
  if( i>0 && g.url.path[i-1]=='/' ){
    zSep = "";
  }else{
    zSep = "/";
  }
  blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.url.path, zSep);
  if( g.url.proxyAuth ){
    blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
  }
  if( g.zHttpAuth && g.zHttpAuth[0] ){
    const char *zCredentials = g.zHttpAuth;
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
  blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
  if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
  if( g.fHttpTrace ){
    blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
  }else{
    blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
  }
  blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}
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

/*
** Prompt to save HTTP Basic Authorization information
*/
static int save_httpauth_prompt(void){
  Blob x;
  char c;
  if( (g.urlFlags & URL_REMEMBER)==0 ) return 0;
  prompt_user("Remember Basic Authorization credentials (Y/n)? ", &x);
  c = blob_str(&x)[0];
  blob_reset(&x);
  return ( c!='n' && c!='N' );
}

/*
** Get the HTTP Basic Authorization credentials from the user 
** when 401 is received.
*/
char *prompt_for_httpauth_creds(void){
  Blob x;
  char *zUser;
  char *zPw;
  char *zPrompt;
  char *zHttpAuth = 0;
  if( !isatty(fileno(stdin)) ) return 0;
  zPrompt = mprintf("\n%s authorization required by\n%s\n",
    g.urlIsHttps==1 ? "Encrypted HTTPS" : "Unencrypted HTTP", g.urlCanonical);
  fossil_print(zPrompt);
  free(zPrompt);
  if ( g.urlUser && g.urlPasswd && use_fossil_creds_for_httpauth_prompt() ){
    zHttpAuth = mprintf("%s:%s", g.urlUser, g.urlPasswd);
  }else{
    prompt_user("Basic Authorization user: ", &x);
    zUser = mprintf("%b", &x);
    zPrompt = mprintf("HTTP password for %b: ", &x);
    blob_reset(&x);
    prompt_for_password(zPrompt, &x, 1);
    zPw = mprintf("%b", &x);







|


















|


|
|







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

/*
** Prompt to save HTTP Basic Authorization information
*/
static int save_httpauth_prompt(void){
  Blob x;
  char c;
  if( (g.url.flags & URL_REMEMBER)==0 ) return 0;
  prompt_user("Remember Basic Authorization credentials (Y/n)? ", &x);
  c = blob_str(&x)[0];
  blob_reset(&x);
  return ( c!='n' && c!='N' );
}

/*
** Get the HTTP Basic Authorization credentials from the user 
** when 401 is received.
*/
char *prompt_for_httpauth_creds(void){
  Blob x;
  char *zUser;
  char *zPw;
  char *zPrompt;
  char *zHttpAuth = 0;
  if( !isatty(fileno(stdin)) ) return 0;
  zPrompt = mprintf("\n%s authorization required by\n%s\n",
    g.url.isHttps==1 ? "Encrypted HTTPS" : "Unencrypted HTTP", g.url.canonical);
  fossil_print(zPrompt);
  free(zPrompt);
  if ( g.url.user && g.url.passwd && use_fossil_creds_for_httpauth_prompt() ){
    zHttpAuth = mprintf("%s:%s", g.url.user, g.url.passwd);
  }else{
    prompt_user("Basic Authorization user: ", &x);
    zUser = mprintf("%b", &x);
    zPrompt = mprintf("HTTP password for %b: ", &x);
    blob_reset(&x);
    prompt_for_password(zPrompt, &x, 1);
    zPw = mprintf("%b", &x);
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  int rc = 0;           /* Result code */
  int iHttpVersion;     /* Which version of HTTP protocol server uses */
  char *zLine;          /* A single line of the reply header */
  int i;                /* Loop counter */
  int isError = 0;      /* True if the reply is an error message */
  int isCompressed = 1; /* True if the reply is compressed */

  if( transport_open(GLOBAL_URL()) ){
    fossil_warning(transport_errmsg(GLOBAL_URL()));
    return 1;
  }

  /* Construct the login card and prepare the complete payload */
  blob_zero(&login);
  if( useLogin ) http_build_login_card(pSend, &login);
  if( g.fHttpTrace ){







|
|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  int rc = 0;           /* Result code */
  int iHttpVersion;     /* Which version of HTTP protocol server uses */
  char *zLine;          /* A single line of the reply header */
  int i;                /* Loop counter */
  int isError = 0;      /* True if the reply is an error message */
  int isCompressed = 1; /* True if the reply is compressed */

  if( transport_open(&g.url) ){
    fossil_warning(transport_errmsg(&g.url));
    return 1;
  }

  /* Construct the login card and prepare the complete payload */
  blob_zero(&login);
  if( useLogin ) http_build_login_card(pSend, &login);
  if( g.fHttpTrace ){
258
259
260
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
    transport_log(out);
    free(zOutFile);
  }

  /*
  ** Send the request to the server.
  */
  transport_send(GLOBAL_URL(), &hdr);
  transport_send(GLOBAL_URL(), &payload);
  blob_reset(&hdr);
  blob_reset(&payload);
  transport_flip(GLOBAL_URL());
  
  /*
  ** Read and interpret the server reply
  */
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line(GLOBAL_URL()))!=0 && zLine[0]!=0 ){
    /* printf("[%s]\n", zLine); fflush(stdout); */
    if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc==401 ){
        if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){
          if( g.zHttpAuth ){
            if( g.zHttpAuth ) free(g.zHttpAuth);
          }
          g.zHttpAuth = prompt_for_httpauth_creds();
          transport_close(GLOBAL_URL());
          return http_exchange(pSend, pReply, useLogin, maxRedirect);
        }
      }
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_warning("server says: %s", &zLine[ii]);
        goto write_err;
      }
      if( iHttpVersion==0 ){
        closeConnection = 1;
      }else{
        closeConnection = 0;
      }
    }else if( g.urlIsSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
      if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_warning("server says: %s", &zLine[ii]);
        goto write_err;







|
|


|






|









|















|







258
259
260
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
    transport_log(out);
    free(zOutFile);
  }

  /*
  ** Send the request to the server.
  */
  transport_send(&g.url, &hdr);
  transport_send(&g.url, &payload);
  blob_reset(&hdr);
  blob_reset(&payload);
  transport_flip(&g.url);
  
  /*
  ** Read and interpret the server reply
  */
  closeConnection = 1;
  iLength = -1;
  while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
    /* printf("[%s]\n", zLine); fflush(stdout); */
    if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
      if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
      if( rc==401 ){
        if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){
          if( g.zHttpAuth ){
            if( g.zHttpAuth ) free(g.zHttpAuth);
          }
          g.zHttpAuth = prompt_for_httpauth_creds();
          transport_close(&g.url);
          return http_exchange(pSend, pReply, useLogin, maxRedirect);
        }
      }
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_warning("server says: %s", &zLine[ii]);
        goto write_err;
      }
      if( iHttpVersion==0 ){
        closeConnection = 1;
      }else{
        closeConnection = 0;
      }
    }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){
      if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err;
      if( rc!=200 && rc!=302 ){
        int ii;
        for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
        while( zLine[ii]==' ' ) ii++;
        fossil_warning("server says: %s", &zLine[ii]);
        goto write_err;
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
         zLine[j] = 0;
      }
      fossil_print("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i], 0);
      fSeenHttpAuth = 0;
      if( g.zHttpAuth ) free(g.zHttpAuth);
      g.zHttpAuth = get_httpauth();
      transport_close(GLOBAL_URL());
      return http_exchange(pSend, pReply, useLogin, maxRedirect);
    }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
      if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
        isCompressed = 0;
      }else if( fossil_strnicmp(&zLine[14], 
                          "application/x-fossil-uncompressed", -1)==0 ){
        isCompressed = 0;







|







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
         zLine[j] = 0;
      }
      fossil_print("redirect to %s\n", &zLine[i]);
      url_parse(&zLine[i], 0);
      fSeenHttpAuth = 0;
      if( g.zHttpAuth ) free(g.zHttpAuth);
      g.zHttpAuth = get_httpauth();
      transport_close(&g.url);
      return http_exchange(pSend, pReply, useLogin, maxRedirect);
    }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
      if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
        isCompressed = 0;
      }else if( fossil_strnicmp(&zLine[14], 
                          "application/x-fossil-uncompressed", -1)==0 ){
        isCompressed = 0;
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  }

  /*
  ** Extract the reply payload that follows the header
  */
  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(GLOBAL_URL(), blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);
  if( isError ){
    char *z;
    int i, j;
    z = blob_str(pReply);
    for(i=j=0; z[i]; i++, j++){
      if( z[i]=='<' ){







|







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  }

  /*
  ** Extract the reply payload that follows the header
  */
  blob_zero(pReply);
  blob_resize(pReply, iLength);
  iLength = transport_receive(&g.url, blob_buffer(pReply), iLength);
  blob_resize(pReply, iLength);
  if( isError ){
    char *z;
    int i, j;
    z = blob_str(pReply);
    for(i=j=0; z[i]; i++, j++){
      if( z[i]=='<' ){
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  **
  ** FIXME:  There is some bug in the lower layers that prevents the
  ** connection from remaining open.  The easiest fix for now is to
  ** simply close and restart the connection for each round-trip.
  **
  ** For SSH we will leave the connection open.
  */
  if( ! g.urlIsSsh ) closeConnection = 1; /* FIX ME */
  if( closeConnection ){
    transport_close(GLOBAL_URL());
  }else{
    transport_rewind(GLOBAL_URL());
  }
  return 0;

  /* 
  ** Jump to here if an error is seen.
  */
write_err:
  transport_close(GLOBAL_URL());
  return 1;  
}







|

|

|







|


389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
  **
  ** FIXME:  There is some bug in the lower layers that prevents the
  ** connection from remaining open.  The easiest fix for now is to
  ** simply close and restart the connection for each round-trip.
  **
  ** For SSH we will leave the connection open.
  */
  if( ! g.url.isSsh ) closeConnection = 1; /* FIX ME */
  if( closeConnection ){
    transport_close(&g.url);
  }else{
    transport_rewind(&g.url);
  }
  return 0;

  /* 
  ** Jump to here if an error is seen.
  */
write_err:
  transport_close(&g.url);
  return 1;  
}
Changes to src/http_socket.c.
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#endif
    iSocket = -1;
  }
}

/*
** Open a socket connection.  The identify of the server is determined
** by global variables that are set using url_parse():
**
**    g.urlName       Name of the server.  Ex: www.fossil-scm.org
**    g.urlPort       TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int socket_open(UrlData *pUrlData){
  static struct sockaddr_in addr;  /* The server address */
  static int addrIsInit = 0;       /* True once addr is initialized */








|

|
|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#endif
    iSocket = -1;
  }
}

/*
** Open a socket connection.  The identify of the server is determined
** by pUrlData
**
**    pUrlDAta->name       Name of the server.  Ex: www.fossil-scm.org
**    pUrlDAta->port       TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int socket_open(UrlData *pUrlData){
  static struct sockaddr_in addr;  /* The server address */
  static int addrIsInit = 0;       /* True once addr is initialized */

210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
    N -= (size_t)got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}

/*
** Attempt to resolve g.urlName to IP and setup g.zIpAddr so rcvfrom gets
** populated. For hostnames with more than one IP (or if overridden in
** ~/.ssh/config) the rcvfrom may not match the host to which we connect.

*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
  struct hostent *pHost;        /* Used to make best effort for rcvfrom */
  struct sockaddr_in addr;

  memset(&addr, 0, sizeof(addr));
  pHost = gethostbyname(pUrlData->name);
  if( pHost!=0 ){
    memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
  }
}







|
|
|
>












210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    N -= (size_t)got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}

/*
** Attempt to resolve pUrlData->name to an IP address and setup g.zIpAddr
** so rcvfrom gets populated. For hostnames with more than one IP (or
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
** to which we connect.
*/
void socket_ssh_resolve_addr(UrlData *pUrlData){
  struct hostent *pHost;        /* Used to make best effort for rcvfrom */
  struct sockaddr_in addr;

  memset(&addr, 0, sizeof(addr));
  pHost = gethostbyname(pUrlData->name);
  if( pHost!=0 ){
    memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
  }
}
Changes to src/http_ssl.c.
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
  blob_reset(&reply);
  return rc;
}

/*
** Open an SSL connection.  The identify of the server is determined
** by variables that are set using url_parse():
**
**    pUrlData->name  Name of the server.  Ex: www.fossil-scm.org
**    pUrlData->port  TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int ssl_open(UrlData *pUrlData){
  X509 *cert;
  int hasSavedCertificate = 0;







|

|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
  blob_reset(&reply);
  return rc;
}

/*
** Open an SSL connection.  The identify of the server is determined
** as follows:
**
**    g.url.name      Name of the server.  Ex: www.fossil-scm.org
**    pUrlData->port  TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int ssl_open(UrlData *pUrlData){
  X509 *cert;
  int hasSavedCertificate = 0;
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    hasSavedCertificate = 1;
  }

  if( pUrlData->useProxy ){
    int rc;
    BIO *sBio;
    char *connStr;
    connStr = mprintf("%s:%d", g.urlName, pUrlData->port);
    sBio = BIO_new_connect(connStr);
    free(connStr);
    if( BIO_do_connect(sBio)<=0 ){
      ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
            pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
      ssl_close();
      return 1;







|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    hasSavedCertificate = 1;
  }

  if( pUrlData->useProxy ){
    int rc;
    BIO *sBio;
    char *connStr;
    connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
    sBio = BIO_new_connect(connStr);
    free(connStr);
    if( BIO_do_connect(sBio)<=0 ){
      ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
            pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
      ssl_close();
      return 1;
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
  zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set_int(zHost, trusted, 1);
  free(zHost);
  BIO_free(mem);  
}

/*
** Get certificate for g.urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
  char *zHost, *zCert;
  BIO *mem;
  X509 *cert;

  zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);

  zCert = db_get(zHost, NULL);
  free(zHost);
  if ( zCert==NULL )
    return NULL;

  if ( pTrusted!=0 ){
    zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);

    *pTrusted = db_get_int(zHost, 0);
    free(zHost);
  }

  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);







|







|
>






|
>







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
  zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
  db_set_int(zHost, trusted, 1);
  free(zHost);
  BIO_free(mem);  
}

/*
** Get certificate for pUrlData->urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
  char *zHost, *zCert;
  BIO *mem;
  X509 *cert;

  zHost = mprintf("cert:%s",
      pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
  zCert = db_get(zHost, NULL);
  free(zHost);
  if ( zCert==NULL )
    return NULL;

  if ( pTrusted!=0 ){
    zHost = mprintf("trusted:%s",
             pUrlData->useProxy ? pUrlData->hostname : pUrlData->name);
    *pTrusted = db_get_int(zHost, 0);
    free(zHost);
  }

  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
Changes to src/http_transport.c.
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  }
  blob_reset(&zCmd);
  return sshPid==0;
}

/*
** Open a connection to the server.  The server is defined by the following
** global variables:
**
**   g.urlName        Name of the server.  Ex: www.fossil-scm.org
**   g.urlPort        TCP/IP port.  Ex: 80
**   g.urlIsHttps     Use TLS for the connection
**
** Return the number of errors.
*/
int transport_open(UrlData *pUrlData){
  int rc = 0;
  if( transport.isOpen==0 ){
    if( pUrlData->isSsh ){







|

|
|
|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  }
  blob_reset(&zCmd);
  return sshPid==0;
}

/*
** Open a connection to the server.  The server is defined by the following
** variables:
**
**   pUrlData->name        Name of the server.  Ex: www.fossil-scm.org
**   pUrlData->port        TCP/IP port.  Ex: 80
**   pUrlData->isHttps     Use TLS for the connection
**
** Return the number of errors.
*/
int transport_open(UrlData *pUrlData){
  int rc = 0;
  if( transport.isOpen==0 ){
    if( pUrlData->isSsh ){
Changes to src/info.c.
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
      @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
    }
    if( diffFlags ){
      append_diff(zOld, zNew, diffFlags, pRe);
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a>
    }
  }
}

/*
** Generate javascript to enhance HTML diffs.
*/







|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
      @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
      @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
    }
    if( diffFlags ){
      append_diff(zOld, zNew, diffFlags, pRe);
    }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
      @ &nbsp;&nbsp;
      @ %z(href("%R/fdiff?v1=%s&v2=%s&sbs=1",zOld,zNew))[diff]</a>
    }
  }
}

/*
** Generate javascript to enhance HTML diffs.
*/
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
      zPJ = blob_str(&projName);
      for(jj=0; zPJ[jj]; jj++){
        if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
          zPJ[jj] = '_';
        }
      }
      @ <tr><th>Timelines:</th><td>
      @   %z(href("%R/timeline?f=%S&unhide",zUuid))family</a>
      if( zParent ){
        @ | %z(href("%R/timeline?p=%S&unhide",zUuid))ancestors</a>
      }
      if( !isLeaf ){
        @ | %z(href("%R/timeline?d=%S&unhide",zUuid))descendants</a>
      }
      if( zParent && !isLeaf ){
        @ | %z(href("%R/timeline?dp=%S&unhide",zUuid))both</a>
      }
      db_prepare(&q2,"SELECT substr(tag.tagname,5) FROM tagxref, tag "
                     " WHERE rid=%d AND tagtype>0 "
                     "   AND tag.tagid=tagxref.tagid "
                     "   AND +tag.tagname GLOB 'sym-*'", rid);
      while( db_step(&q2)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q2, 0);







|

|


|


|







610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
      zPJ = blob_str(&projName);
      for(jj=0; zPJ[jj]; jj++){
        if( (zPJ[jj]>0 && zPJ[jj]<' ') || strchr("\"*/:<>?\\|", zPJ[jj]) ){
          zPJ[jj] = '_';
        }
      }
      @ <tr><th>Timelines:</th><td>
      @   %z(href("%R/timeline?f=%s&unhide",zUuid))family</a>
      if( zParent ){
        @ | %z(href("%R/timeline?p=%s&unhide",zUuid))ancestors</a>
      }
      if( !isLeaf ){
        @ | %z(href("%R/timeline?d=%s&unhide",zUuid))descendants</a>
      }
      if( zParent && !isLeaf ){
        @ | %z(href("%R/timeline?dp=%s&unhide",zUuid))both</a>
      }
      db_prepare(&q2,"SELECT substr(tag.tagname,5) FROM tagxref, tag "
                     " WHERE rid=%d AND tagtype>0 "
                     "   AND tag.tagid=tagxref.tagid "
                     "   AND +tag.tagname GLOB 'sym-*'", rid);
      while( db_step(&q2)==SQLITE_ROW ){
        const char *zTagName = db_column_text(&q2, 0);
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
        @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
        @         ZIP archive</a>
        fossil_free(zUrl);
      }
      @ </td></tr>
      @ <tr><th>Other&nbsp;Links:</th>
      @   <td>
      @     %z(href("%R/tree?ci=%S",zUuid))files</a>
      @   | %z(href("%R/fileage?name=%S",zUuid))file ages</a>
      @   | %z(href("%R/tree?ci=%S&nofiles",zUuid))folders</a>
      @   | %z(href("%R/artifact/%S",zUuid))manifest</a>
      if( g.perm.Write ){
        @   | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
      }
      @   </td>
      @ </tr>
      blob_reset(&projName);
    }
    @ </table>
  }else{







|
|
|
|

|







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
        @ | %z(href("%R/zip/%t-%S.zip?uuid=%s",zPJ,zUuid,zUuid))
        @         ZIP archive</a>
        fossil_free(zUrl);
      }
      @ </td></tr>
      @ <tr><th>Other&nbsp;Links:</th>
      @   <td>
      @     %z(href("%R/tree?ci=%s",zUuid))files</a>
      @   | %z(href("%R/fileage?name=%s",zUuid))file ages</a>
      @   | %z(href("%R/tree?ci=%s&nofiles",zUuid))folders</a>
      @   | %z(href("%R/artifact/%s",zUuid))manifest</a>
      if( g.perm.Write ){
        @   | %z(href("%R/ci_edit?r=%s",zUuid))edit</a>
      }
      @   </td>
      @ </tr>
      blob_reset(&projName);
    }
    @ </table>
  }else{
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  }else{
    @ %z(xhref("class='button'","%R/%s/%T?sbs=0",zPage,zName))
    @ Show&nbsp;Unified&nbsp;Diffs</a>
    @ %z(xhref("class='button'","%R/%s/%T?sbs=1",zPage,zName))
    @ Show&nbsp;Side-by-Side&nbsp;Diffs</a>
  }
  if( zParent ){
    @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
    @ Patch</a>
  }
  @</div>
  if( pRe ){
    @ <p><b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b></p>
  }







|







697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  }else{
    @ %z(xhref("class='button'","%R/%s/%T?sbs=0",zPage,zName))
    @ Show&nbsp;Unified&nbsp;Diffs</a>
    @ %z(xhref("class='button'","%R/%s/%T?sbs=1",zPage,zName))
    @ Show&nbsp;Side-by-Side&nbsp;Diffs</a>
  }
  if( zParent ){
    @ %z(xhref("class='button'","%R/vpatch?from=%s&to=%s",zParent,zUuid))
    @ Patch</a>
  }
  @</div>
  if( pRe ){
    @ <p><b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b></p>
  }
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Update of \"%h\"", pWiki->zWikiTitle);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
  style_submenu_element("Raw", "Raw", "artifact/%S", zUuid);
  style_submenu_element("History", "History", "whistory?name=%t",
                        pWiki->zWikiTitle);
  style_submenu_element("Page", "Page", "wiki?name=%t",
                        pWiki->zWikiTitle);
  login_anonymous_available();
  @ <div class="section">Overview</div>
  @ <p><table class="label-value">







|







768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
    if( strcmp(zModAction,"approve")==0 ){
      moderation_approve(rid);
    }
  }
  style_header("Update of \"%h\"", pWiki->zWikiTitle);
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zDate = db_text(0, "SELECT datetime(%.17g)", pWiki->rDate);
  style_submenu_element("Raw", "Raw", "artifact/%s", zUuid);
  style_submenu_element("History", "History", "whistory?name=%t",
                        pWiki->zWikiTitle);
  style_submenu_element("Page", "Page", "wiki?name=%t",
                        pWiki->zWikiTitle);
  login_anonymous_available();
  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
  @ <tr><th>Original&nbsp;User:</th><td>
  hyperlink_to_user(pWiki->zUser, zDate, "</td></tr>");
  if( pWiki->nParent>0 ){
    int i;
    @ <tr><th>Parent%s(pWiki->nParent==1?"":"s"):</th><td>
    for(i=0; i<pWiki->nParent; i++){
      char *zParent = pWiki->azParent[i];
      @ %z(href("info/%S",zParent))%s(zParent)</a>
    }
    @ </td></tr>
  }
  @ </table>

  if( g.perm.ModWiki && modPending ){
    @ <div class="section">Moderation</div>







|







796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
  @ <tr><th>Original&nbsp;User:</th><td>
  hyperlink_to_user(pWiki->zUser, zDate, "</td></tr>");
  if( pWiki->nParent>0 ){
    int i;
    @ <tr><th>Parent%s(pWiki->nParent==1?"":"s"):</th><td>
    for(i=0; i<pWiki->nParent; i++){
      char *zParent = pWiki->azParent[i];
      @ %z(href("info/%s",zParent))%s(zParent)</a>
    }
    @ </td></tr>
  }
  @ </table>

  if( g.perm.ModWiki && modPending ){
    @ <div class="section">Moderation</div>
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
    hyperlink_to_uuid(zVers);
    if( zBr && zBr[0] ){
      @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
    }
    @ - %!w(zCom) (user:
    hyperlink_to_user(zUser,zDate,")");
    if( g.perm.Hyperlink ){
      @ %z(href("%R/finfo?name=%T&ci=%S",zName,zVers))[ancestry]</a>
      @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName))
      @ [annotate]</a>
      @ %z(href("%R/blame?checkin=%S&filename=%T",zVers,zName))
      @ [blame]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }







|
|

|







1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
    hyperlink_to_uuid(zVers);
    if( zBr && zBr[0] ){
      @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
    }
    @ - %!w(zCom) (user:
    hyperlink_to_user(zUser,zDate,")");
    if( g.perm.Hyperlink ){
      @ %z(href("%R/finfo?name=%T&ci=%s",zName,zVers))[ancestry]</a>
      @ %z(href("%R/annotate?filename=%T&checkin=%s",zName,zVers))
      @ [annotate]</a>
      @ %z(href("%R/blame?filename=%T&checkin=%s",zName,zVers))
      @ [blame]</a>
    }
    cnt++;
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_append(pDownloadName, zName, -1);
    }
  }
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    objType |= OBJTYPE_ATTACHMENT;
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      if( g.perm.Hyperlink && g.perm.RdTkt ){
        @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
      }else{
        @ ticket [%S(zTarget)]
      }
    }else{
      if( g.perm.Hyperlink && g.perm.RdWiki ){
        @ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
      }else{







|







1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    objType |= OBJTYPE_ATTACHMENT;
    if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      if( g.perm.Hyperlink && g.perm.RdTkt ){
        @ ticket [%z(href("%R/tktview?name=%s",zTarget))%S(zTarget)</a>]
      }else{
        @ ticket [%S(zTarget)]
      }
    }else{
      if( g.perm.Hyperlink && g.perm.RdWiki ){
        @ wiki page [%z(href("%R/wiki?name=%t",zTarget))%h(zTarget)</a>]
      }else{
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }
  }else if( linkToView && g.perm.Hyperlink ){
    @ %z(href("%R/artifact/%S",zUuid))[view]</a>
  }
  return objType;
}


/*
** WEBPAGE: fdiff







|







1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  db_finalize(&q);
  if( cnt==0 ){
    @ Control artifact.
    if( pDownloadName && blob_size(pDownloadName)==0 ){
      blob_appendf(pDownloadName, "%.10s.txt", zUuid);
    }
  }else if( linkToView && g.perm.Hyperlink ){
    @ %z(href("%R/artifact/%s",zUuid))[view]</a>
  }
  return objType;
}


/*
** WEBPAGE: fdiff
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
    style_submenu_element("Unified Diff", "udiff",
                          "%s/fdiff?v1=%T&v2=%T&sbs=0%s",
                          g.zTop, P("v1"), P("v2"), zW);
  }

  if( P("smhdr")!=0 ){
    @ <h2>Differences From Artifact
    @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
    @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2>
  }else{
    @ <h2>Differences From
    @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);
    @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);
  }
  if( pRe ){
    @ <b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b>
  }
  @ <hr />







|
|


|

|







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
    style_submenu_element("Unified Diff", "udiff",
                          "%s/fdiff?v1=%T&v2=%T&sbs=0%s",
                          g.zTop, P("v1"), P("v2"), zW);
  }

  if( P("smhdr")!=0 ){
    @ <h2>Differences From Artifact
    @ %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a> To
    @ %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>.</h2>
  }else{
    @ <h2>Differences From
    @ Artifact %z(href("%R/artifact/%s",zV1))[%S(zV1)]</a>:</h2>
    object_description(v1, 0, 0);
    @ <h2>To Artifact %z(href("%R/artifact/%s",zV2))[%S(zV2)]</a>:</h2>
    object_description(v2, 0, 0);
  }
  if( pRe ){
    @ <b>Only differences that match regular expression "%h(zRe)"
    @ are shown.</b>
  }
  @ <hr />
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
        output_text_with_line_numbers(z, zLn);
      }else{
        @ <pre>
        @ %h(z)
        @ </pre>
      }
    }else if( strncmp(zMime, "image/", 6)==0 ){
      @ <img src="%R/raw/%S(zUuid)?m=%s(zMime)" />
      style_submenu_element("Image", "Image",
                            "%R/raw/%S?m=%s", zUuid, zMime);
    }else{
      @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
    }
    @ </blockquote>
  }
  style_footer();
}







|

|







1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
        output_text_with_line_numbers(z, zLn);
      }else{
        @ <pre>
        @ %h(z)
        @ </pre>
      }
    }else if( strncmp(zMime, "image/", 6)==0 ){
      @ <img src="%R/raw/%s(zUuid)?m=%s(zMime)" />
      style_submenu_element("Image", "Image",
                            "%R/raw/%s?m=%s", zUuid, zMime);
    }else{
      @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
    }
    @ </blockquote>
  }
  style_footer();
}
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
      moderation_approve(rid);
    }
  }
  zTktTitle = db_table_has_column( "ticket", "title" )
      ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
      : 0;
  style_header("Ticket Change Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid);
  style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
  style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName);
  style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName);
  if( P("plaintext") ){
    style_submenu_element("Formatted", "Formatted", "%R/info/%S", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/info/%S?plaintext", zUuid);
  }

  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){







|




|


|







1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
      moderation_approve(rid);
    }
  }
  zTktTitle = db_table_has_column( "ticket", "title" )
      ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
      : 0;
  style_header("Ticket Change Details");
  style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid);
  style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
  style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName);
  style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName);
  if( P("plaintext") ){
    style_submenu_element("Formatted", "Formatted", "%R/info/%s", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/info/%s?plaintext", zUuid);
  }

  @ <div class="section">Overview</div>
  @ <p><table class="label-value">
  @ <tr><th>Artifact&nbsp;ID:</th>
  @ <td>%z(href("%R/artifact/%s",zUuid))%s(zUuid)</a>
  if( g.perm.Setup ){
1888
1889
1890
1891
1892
1893
1894

1895
1896
1897









1898
1899
1900
1901
1902
1903

1904
1905
1906
1907
1908
1909
1910
1911
1912




1913
1914
1915
1916
1917
1918
1919
** Figure out what the artifact ID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid;
  int rc;


  zName = P("name");
  if( zName==0 ) fossil_redirect_home();









  if( validate16(zName, strlen(zName)) ){
    if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
      tktview_page();
      return;
    }
    if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){

      event_page();
      return;
    }
  }
  blob_set(&uuid, zName);
  rc = name_to_uuid(&uuid, -1, "*");
  if( rc==1 ){
    style_header("No Such Object");
    @ <p>No such object: %h(zName)</p>




    style_footer();
    return;
  }else if( rc==2 ){
    cgi_set_parameter("src","info");
    ambiguous_page();
    return;
  }







>



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


>
>
>
>







1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918



1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
** Figure out what the artifact ID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid;
  int rc;
  int nLen;

  zName = P("name");
  if( zName==0 ) fossil_redirect_home();
  nLen = strlen(zName);
  blob_set(&uuid, zName);
  if( name_collisions(zName) ){
    cgi_set_parameter("src","info");
    ambiguous_page();
    return;
  }
  rc = name_to_uuid(&uuid, -1, "*");
  if( rc==1 ){
    if( validate16(zName, nLen) ){
      if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%q*'", zName) ){
        tktview_page();
        return;
      }
      if( db_exists("SELECT 1 FROM tag"
                    " WHERE tagname GLOB 'event-%q*'", zName) ){
        event_page();
        return;
      }
    }



    style_header("No Such Object");
    @ <p>No such object: %h(zName)</p>
    if( nLen<4 ){
      @ <p>Object name should be no less than 4 characters.  Ten or more
      @ characters are recommended.</p>
    }
    style_footer();
    return;
  }else if( rc==2 ){
    cgi_set_parameter("src","info");
    ambiguous_page();
    return;
  }
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
    @ <hr />
    blob_reset(&suffix);
  }
  @ <p>Make changes to attributes of check-in
  @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
  form_begin(0, "%R/ci_edit");
  login_insert_csrf_secret();
  @ <div><input type="hidden" name="r" value="%S(zUuid)" />
  @ <table border="0" cellspacing="10">

  @ <tr><th align="right" valign="top">User:</th>
  @ <td valign="top">
  @   <input type="text" name="u" size="20" value="%h(zNewUser)" />
  @ </td></tr>








|







2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
    @ <hr />
    blob_reset(&suffix);
  }
  @ <p>Make changes to attributes of check-in
  @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
  form_begin(0, "%R/ci_edit");
  login_insert_csrf_secret();
  @ <div><input type="hidden" name="r" value="%s(zUuid)" />
  @ <table border="0" cellspacing="10">

  @ <tr><th align="right" valign="top">User:</th>
  @ <td valign="top">
  @   <input type="text" name="u" size="20" value="%h(zNewUser)" />
  @ </td></tr>

Changes to src/json.c.
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  INT(g, xferPanic);
  INT(g, fullHttpReply);
  INT(g, xlinkClusterOnly);
  INT(g, fTimeFormat);
  INT(g, markPrivate);
  INT(g, clockSkewSeen);
  INT(g, isHTTP);
  INT(g, urlIsFile);
  INT(g, urlIsHttps);
  INT(g, urlIsSsh);
  INT(g, urlPort);
  INT(g, urlDfltPort);
  INT(g, useLocalauth);
  INT(g, noPswd);
  INT(g, userUid);
  INT(g, rcvid);
  INT(g, okCsrf);
  INT(g, thTrace);
  INT(g, isHome);
  INT(g, nAux);
  INT(g, allowSymlinks);

  CSTR(g, zMainDbType);
  CSTR(g, zConfigDbType);
  CSTR(g, zLocalRoot);
  CSTR(g, zPath);
  CSTR(g, zExtra);
  CSTR(g, zBaseURL);
  CSTR(g, zTop);
  CSTR(g, zContentType);
  CSTR(g, zErrMsg);
  CSTR(g, urlName);
  CSTR(g, urlHostname);
  CSTR(g, urlProtocol);
  CSTR(g, urlPath);
  CSTR(g, urlUser);
  CSTR(g, urlPasswd);
  CSTR(g, urlCanonical);
  CSTR(g, urlProxyAuth);
  CSTR(g, urlFossil);
  CSTR(g, zLogin);
  CSTR(g, zSSLIdentity);
  CSTR(g, zIpAddr);
  CSTR(g, zNonce);
  CSTR(g, zCsrfToken);

  o = cson_new_object();







|
|
|
|
|



















|
|
|
|
|
|
|
|
|







1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  INT(g, xferPanic);
  INT(g, fullHttpReply);
  INT(g, xlinkClusterOnly);
  INT(g, fTimeFormat);
  INT(g, markPrivate);
  INT(g, clockSkewSeen);
  INT(g, isHTTP);
  INT(g.url, isFile);
  INT(g.url, isHttps);
  INT(g.url, isSsh);
  INT(g.url, port);
  INT(g.url, dfltPort);
  INT(g, useLocalauth);
  INT(g, noPswd);
  INT(g, userUid);
  INT(g, rcvid);
  INT(g, okCsrf);
  INT(g, thTrace);
  INT(g, isHome);
  INT(g, nAux);
  INT(g, allowSymlinks);

  CSTR(g, zMainDbType);
  CSTR(g, zConfigDbType);
  CSTR(g, zLocalRoot);
  CSTR(g, zPath);
  CSTR(g, zExtra);
  CSTR(g, zBaseURL);
  CSTR(g, zTop);
  CSTR(g, zContentType);
  CSTR(g, zErrMsg);
  CSTR(g.url, name);
  CSTR(g.url, hostname);
  CSTR(g.url, protocol);
  CSTR(g.url, path);
  CSTR(g.url, user);
  CSTR(g.url, passwd);
  CSTR(g.url, canonical);
  CSTR(g.url, proxyAuth);
  CSTR(g.url, fossil);
  CSTR(g, zLogin);
  CSTR(g, zSSLIdentity);
  CSTR(g, zIpAddr);
  CSTR(g, zNonce);
  CSTR(g, zCsrfToken);

  o = cson_new_object();
Changes to src/login.c.
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

  rc = sqlite3_open_v2(
       zOtherRepo, &pOther,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       g.zVfsName
  );
  if( rc==SQLITE_OK ){
    sqlite3_create_function(pOther,"now",0,SQLITE_ANY,0,db_now_function,0,0);
    sqlite3_create_function(pOther, "constant_time_cmp", 2, SQLITE_UTF8, 0,
                  constant_time_cmp_function, 0, 0);
    sqlite3_busy_timeout(pOther, 5000);
    zSQL = mprintf(
      "SELECT cexpire FROM user"
      " WHERE login=%Q"
      "   AND ipaddr=%Q"







|







704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

  rc = sqlite3_open_v2(
       zOtherRepo, &pOther,
       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
       g.zVfsName
  );
  if( rc==SQLITE_OK ){
    sqlite3_create_function(pOther,"now",0,SQLITE_UTF8,0,db_now_function,0,0);
    sqlite3_create_function(pOther, "constant_time_cmp", 2, SQLITE_UTF8, 0,
                  constant_time_cmp_function, 0, 0);
    sqlite3_busy_timeout(pOther, 5000);
    zSQL = mprintf(
      "SELECT cexpire FROM user"
      " WHERE login=%Q"
      "   AND ipaddr=%Q"
735
736
737
738
739
740
741











742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_close(pOther);
  fossil_free(zOtherRepo);
  return nXfer;
}












/*
** Lookup the uid for a non-built-in user with zLogin and zCookie and
** zRemoteAddr.  Return 0 if not found.
**
** Note that this only searches for logged-in entries with matching
** zCookie (db: user.cookie) and zRemoteAddr (db: user.ipaddr)
** entries.
*/
static int login_find_user(
  const char *zLogin,            /* User name */
  const char *zCookie,           /* Login cookie value */
  const char *zRemoteAddr        /* Abbreviated IP address for valid login */
){
  int uid;
  if( fossil_strcmp(zLogin, "anonymous")==0 ) return 0;
  if( fossil_strcmp(zLogin, "nobody")==0 ) return 0;
  if( fossil_strcmp(zLogin, "developer")==0 ) return 0;
  if( fossil_strcmp(zLogin, "reader")==0 ) return 0;
  uid = db_int(0,
    "SELECT uid FROM user"
    " WHERE login=%Q"
    "   AND ipaddr=%Q"
    "   AND cexpire>julianday('now')"
    "   AND length(cap)>0"
    "   AND length(pw)>0"







>
>
>
>
>
>
>
>
>
>
>















|
<
<
<







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768



769
770
771
772
773
774
775
    }
    sqlite3_finalize(pStmt);
  }
  sqlite3_close(pOther);
  fossil_free(zOtherRepo);
  return nXfer;
}

/*
** Return TRUE if zLogin is one of the special usernames
*/
int login_is_special(const char *zLogin){
  if( fossil_strcmp(zLogin, "anonymous")==0 ) return 1;
  if( fossil_strcmp(zLogin, "nobody")==0 ) return 1;
  if( fossil_strcmp(zLogin, "developer")==0 ) return 1;
  if( fossil_strcmp(zLogin, "reader")==0 ) return 1;
  return 0;
}

/*
** Lookup the uid for a non-built-in user with zLogin and zCookie and
** zRemoteAddr.  Return 0 if not found.
**
** Note that this only searches for logged-in entries with matching
** zCookie (db: user.cookie) and zRemoteAddr (db: user.ipaddr)
** entries.
*/
static int login_find_user(
  const char *zLogin,            /* User name */
  const char *zCookie,           /* Login cookie value */
  const char *zRemoteAddr        /* Abbreviated IP address for valid login */
){
  int uid;
  if( login_is_special(zLogin) ) return 0;



  uid = db_int(0,
    "SELECT uid FROM user"
    " WHERE login=%Q"
    "   AND ipaddr=%Q"
    "   AND cexpire>julianday('now')"
    "   AND length(cap)>0"
    "   AND length(pw)>0"
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
                   sqlite3_errmsg(pPeer), zSuffix);
      nErr++;
      sqlite3_close(pPeer);
      continue;
    }
    sqlite3_create_function(pPeer, "shared_secret", 3, SQLITE_UTF8,
                            0, sha1_shared_secret_sql_function, 0, 0);
    sqlite3_create_function(pPeer, "now", 0,SQLITE_ANY,0,db_now_function,0,0);
    sqlite3_busy_timeout(pPeer, 5000);
    zErr = 0;
    rc = sqlite3_exec(pPeer, zSql, 0, 0, &zErr);
    if( zErr ){
      blob_appendf(&err, "%s%s: %s%s", zPrefix, zRepoName, zErr, zSuffix);
      sqlite3_free(zErr);
      nErr++;







|







1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
                   sqlite3_errmsg(pPeer), zSuffix);
      nErr++;
      sqlite3_close(pPeer);
      continue;
    }
    sqlite3_create_function(pPeer, "shared_secret", 3, SQLITE_UTF8,
                            0, sha1_shared_secret_sql_function, 0, 0);
    sqlite3_create_function(pPeer, "now", 0,SQLITE_UTF8,0,db_now_function,0,0);
    sqlite3_busy_timeout(pPeer, 5000);
    zErr = 0;
    rc = sqlite3_exec(pPeer, zSql, 0, 0, &zErr);
    if( zErr ){
      blob_appendf(&err, "%s%s: %s%s", zPrefix, zRepoName, zErr, zSuffix);
      sqlite3_free(zErr);
      nErr++;
Changes to src/main.c.
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  void *xPreEval;        /* Optional, called before Tcl_Eval*(). */
  void *pPreContext;     /* Optional, provided to xPreEval(). */
  void *xPostEval;       /* Optional, called after Tcl_Eval*(). */
  void *pPostContext;    /* Optional, provided to xPostEval(). */
};
#endif

/*
** All global variables are in this structure.
*/
#define GLOBAL_URL()      ((UrlData *)(&g.urlIsFile))

struct Global {
  int argc; char **argv;  /* Command-line arguments to the program */
  char *nameOfExe;        /* Full path of executable. */
  const char *zErrlog;    /* Log errors to this file, if not NULL */
  int isConst;            /* True if the output is unchanging & cacheable */
  const char *zVfsName;   /* The VFS to use for database connections */
  sqlite3 *db;            /* The connection to the databases */







<
<
<
<
<







110
111
112
113
114
115
116





117
118
119
120
121
122
123
  void *xPreEval;        /* Optional, called before Tcl_Eval*(). */
  void *pPreContext;     /* Optional, provided to xPreEval(). */
  void *xPostEval;       /* Optional, called after Tcl_Eval*(). */
  void *pPostContext;    /* Optional, provided to xPostEval(). */
};
#endif






struct Global {
  int argc; char **argv;  /* Command-line arguments to the program */
  char *nameOfExe;        /* Full path of executable. */
  const char *zErrlog;    /* Log errors to this file, if not NULL */
  int isConst;            /* True if the output is unchanging & cacheable */
  const char *zVfsName;   /* The VFS to use for database connections */
  sqlite3 *db;            /* The connection to the databases */
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int wikiFlags;          /* Wiki conversion flags applied to %w and %W */
  char isHTTP;            /* True if server/CGI modes, else assume CLI. */
  char javascriptHyperlink; /* If true, set href= using script, not HTML */
  Blob httpHeader;        /* Complete text of the HTTP request header */


  /*
  ** NOTE: These members MUST be kept in sync with those in the "UrlData"
  **       structure defined in "url.c".
  */
  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */







|
>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  int *aCommitFile;       /* Array of files to be committed */
  int markPrivate;        /* All new artifacts are private if true */
  int clockSkewSeen;      /* True if clocks on client and server out of sync */
  int wikiFlags;          /* Wiki conversion flags applied to %w and %W */
  char isHTTP;            /* True if server/CGI modes, else assume CLI. */
  char javascriptHyperlink; /* If true, set href= using script, not HTML */
  Blob httpHeader;        /* Complete text of the HTTP request header */
  UrlData url;            /* Information about current URL */
#if 0
  /*
  ** NOTE: These members MUST be kept in sync with those in the "UrlData"
  **       structure defined in "url.c".
  */
  int urlIsFile;          /* True if a "file:" url */
  int urlIsHttps;         /* True if a "https:" url */
  int urlIsSsh;           /* True if an "ssh:" url */
192
193
194
195
196
197
198


199
200
201
202
203
204
205
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  char *urlFossil;        /* The fossil query parameter on ssh: */
  unsigned urlFlags;      /* Boolean flags controlling URL processing */
  int useProxy;           /* Used to remember that a proxy is in use */
  char *proxyUrlPath;
  int proxyOrigPort;      /* Tunneled port number for https through proxy */


  const char *zLogin;     /* Login name.  NULL or "" if not logged in. */
  const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
                             ** SSL client identity */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */
  int isHuman;            /* True if access by a human, not a spider or bot */







>
>







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  char *urlFossil;        /* The fossil query parameter on ssh: */
  unsigned urlFlags;      /* Boolean flags controlling URL processing */
  int useProxy;           /* Used to remember that a proxy is in use */
  char *proxyUrlPath;
  int proxyOrigPort;      /* Tunneled port number for https through proxy */
#endif

  const char *zLogin;     /* Login name.  NULL or "" if not logged in. */
  const char *zSSLIdentity;  /* Value of --ssl-identity option, filename of
                             ** SSL client identity */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */
  int isHuman;            /* True if access by a human, not a spider or bot */
1842
1843
1844
1845
1846
1847
1848

1849
1850
1851
1852
1853
1854
1855
  process_one_web_page(zNotFound, glob_create(zFileGlob));
}

/*
** Process all requests in a single SSH connection if possible.
*/
void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){

  do{
    cgi_handle_ssh_http_request(zIpAddr);
    process_one_web_page(0, FileGlob);
    blob_reset(&g.cgiIn);
  } while ( g.fSshClient & CGI_SSH_FOSSIL ||
          g.fSshClient & CGI_SSH_COMPAT );
}







>







1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
  process_one_web_page(zNotFound, glob_create(zFileGlob));
}

/*
** Process all requests in a single SSH connection if possible.
*/
void ssh_request_loop(const char *zIpAddr, Glob *FileGlob){
  blob_zero(&g.cgiIn);
  do{
    cgi_handle_ssh_http_request(zIpAddr);
    process_one_web_page(0, FileGlob);
    blob_reset(&g.cgiIn);
  } while ( g.fSshClient & CGI_SSH_FOSSIL ||
          g.fSshClient & CGI_SSH_COMPAT );
}
Changes to src/main.mk.
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_TCL variable may be undefined, set to 0, or set to 1.
# If it is set to 1, then we need to build the Tcl integration code and
# link to the Tcl library.
TCL_OBJ.0 = 
TCL_OBJ.1 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(TCL_OBJ.$(FOSSIL_ENABLE_TCL))  $(OBJDIR)/cson_amalgamation.o

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#







<
<
<
<
<
<
<
|







398
399
400
401
402
403
404







405
406
407
408
409
410
411
412
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)








EXTRAOBJ =  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE))  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
#
Changes to src/makemake.tcl.
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
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)

# The FOSSIL_ENABLE_TCL variable may be undefined, set to 0, or set to 1.
# If it is set to 1, then we need to build the Tcl integration code and
# link to the Tcl library.
TCL_OBJ.0 = 
TCL_OBJ.1 = $(OBJDIR)/th_tcl.o
TCL_OBJ. = $(TCL_OBJ.0)

EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(TCL_OBJ.$(FOSSIL_ENABLE_TCL)) \
  $(OBJDIR)/cson_amalgamation.o

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"







<
<
<
<
<
<
<





|







266
267
268
269
270
271
272







273
274
275
276
277
278
279
280
281
282
283
284
285
# to 1. If it is set to 1, then there is no need to build or link
# the sqlite3.o object. Instead, the system sqlite will be linked
# using -lsqlite3.
SQLITE3_OBJ.1 = 
SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o
SQLITE3_OBJ.  = $(SQLITE3_OBJ.0)








EXTRAOBJ = \
  $(SQLITE3_OBJ.$(USE_SYSTEM_SQLITE)) \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/th_tcl.o \
  $(OBJDIR)/cson_amalgamation.o

$(APPNAME):	$(OBJDIR)/headers $(OBJ) $(EXTRAOBJ)
	$(TCC) -o $(APPNAME) $(OBJ) $(EXTRAOBJ) $(LIB)

# This rule prevents make from using its default rules to try build
# an executable named "manifest" out of the file named "manifest.c"
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1f/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1f

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







|
|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
722
723
724
725
726
727
728

729
730
731
732
733
734
735
736
737
738
739
740
741
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ = \
  $(OBJDIR)/sqlite3.o \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \

  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

openssl:	zlib







>


<
<
<
<







715
716
717
718
719
720
721
722
723
724




725
726
727
728
729
730
731
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ = \
  $(OBJDIR)/sqlite3.o \
  $(OBJDIR)/shell.o \
  $(OBJDIR)/th.o \
  $(OBJDIR)/th_lang.o \
  $(OBJDIR)/th_tcl.o \
  $(OBJDIR)/cson_amalgamation.o





zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

openssl:	zlib
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"

writeln {ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif}

close $output_file
#
# End of the win/Makefile.mingw output
##############################################################################
##############################################################################
##############################################################################







<
|
|
<







812
813
814
815
816
817
818

819
820

821
822
823
824
825
826
827

writeln "\$(OBJDIR)/th.o:\t\$(SRCDIR)/th.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th.c -o \$(OBJDIR)/th.o\n"

writeln "\$(OBJDIR)/th_lang.o:\t\$(SRCDIR)/th_lang.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_lang.c -o \$(OBJDIR)/th_lang.o\n"


writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"


close $output_file
#
# End of the win/Makefile.mingw output
##############################################################################
##############################################################################
##############################################################################
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1f\include
SSLLIBDIR = $(B)\compat\openssl-1.0.1f\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic







|
|







1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1g\include
SSLLIBDIR = $(B)\compat\openssl-1.0.1g\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "${s}_.c"; incr i
}
writeln "\n"
set AdditionalObj [list shell sqlite3 th th_lang cson_amalgamation]
writeln -nonewline "OBJ   = "
set i 0
foreach s [lsort [concat $src $AdditionalObj]] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "\$(OX)\\$s\$O"; incr i
}
writeln " \\"
writeln -nonewline "        \$(OX)\\fossil.res\n\n"
writeln "!ifdef FOSSIL_ENABLE_TCL"
writeln "OBJ   = \$(OBJ) \$(OX)\\th_tcl\$O"
writeln "!endif"
writeln {
APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)

all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd

$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
	cd $(OX) 
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc}
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
  writeln "\techo \$(OX)\\$s.obj $redir \$@"
  set redir {>>}
}
writeln "!ifdef FOSSIL_ENABLE_TCL"
writeln "\techo \$(OX)\\th_tcl.obj $redir \$@"
set redir {>>}
writeln "!endif"
writeln "\techo \$(LIBS) $redir \$@"
writeln {
$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**







|











<
<
<




















<
<

<







1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111



1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131


1132

1133
1134
1135
1136
1137
1138
1139
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "${s}_.c"; incr i
}
writeln "\n"
set AdditionalObj [list shell sqlite3 th th_lang th_tcl cson_amalgamation]
writeln -nonewline "OBJ   = "
set i 0
foreach s [lsort [concat $src $AdditionalObj]] {
  if {$i > 0} {
    writeln " \\"
    writeln -nonewline "        "
  }
  writeln -nonewline "\$(OX)\\$s\$O"; incr i
}
writeln " \\"
writeln -nonewline "        \$(OX)\\fossil.res\n\n"



writeln {
APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)

all: $(OX) $(APPNAME)

zlib:
	@echo Building zlib from "$(ZLIBDIR)"...
	@pushd "$(ZLIBDIR)" && nmake /f win32\Makefile.msc $(ZLIB) && popd

$(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts zlib
	cd $(OX) 
	link $(LDFLAGS) /OUT:$@ $(LIBDIR) Wsetargv.obj fossil.res @linkopts

$(OX)\linkopts: $B\win\Makefile.msc}
set redir {>}
foreach s [lsort [concat $src $AdditionalObj]] {
  writeln "\techo \$(OX)\\$s.obj $redir \$@"
  set redir {>>}
}


set redir {>>}

writeln "\techo \$(LIBS) $redir \$@"
writeln {
$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190

$(OX)\th$O : $(SRCDIR)\th.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

!ifdef FOSSIL_ENABLE_TCL
$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**
!endif

VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 







<


<







1155
1156
1157
1158
1159
1160
1161

1162
1163

1164
1165
1166
1167
1168
1169
1170

$(OX)\th$O : $(SRCDIR)\th.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**


$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**


VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 
Changes to src/manifest.c.
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

/*
** Clear the memory allocated in a manifest object
*/
void manifest_destroy(Manifest *p){
  if( p ){
    blob_reset(&p->content);
    free(p->aFile);
    free(p->azParent);
    free(p->azCChild);
    free(p->aTag);
    free(p->aField);
    free(p->aCherrypick);
    if( p->pBaseline ) manifest_destroy(p->pBaseline);
    memset(p, 0, sizeof(*p));
    fossil_free(p);
  }
}

/*







|
|
|
|
|
|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

/*
** Clear the memory allocated in a manifest object
*/
void manifest_destroy(Manifest *p){
  if( p ){
    blob_reset(&p->content);
    fossil_free(p->aFile);
    fossil_free(p->azParent);
    fossil_free(p->azCChild);
    fossil_free(p->aTag);
    fossil_free(p->aField);
    fossil_free(p->aCherrypick);
    if( p->pBaseline ) manifest_destroy(p->pBaseline);
    memset(p, 0, sizeof(*p));
    fossil_free(p);
  }
}

/*
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
  if( !isNew ){
    for(i=0; i<pManifest->nField; i++){
      if( fossil_strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){
        zNewStatus = pManifest->aField[i].zValue;
      }
    }
    if( zNewStatus ){
      blob_appendf(&comment, "%h ticket [%.10s]: <i>%h</i>",
         zNewStatus, pManifest->zTicketUuid, zTitle
      );
      if( pManifest->nField>1 ){
        blob_appendf(&comment, " plus %d other change%s",
          pManifest->nField-1, pManifest->nField==2 ? "" : "s");
      }
      blob_appendf(&brief, "%h ticket [%.10s].",
                   zNewStatus, pManifest->zTicketUuid);
    }else{
      zNewStatus = db_text("unknown",
         "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
         zStatusColumn, pManifest->zTicketUuid
      );
      blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with "
           "%d other change%s",
           pManifest->zTicketUuid, zTitle, zNewStatus, pManifest->nField,
           pManifest->nField==1 ? "" : "s"
      );
      free(zNewStatus);
      blob_appendf(&brief, "Ticket [%.10s]: %d change%s",
           pManifest->zTicketUuid, pManifest->nField,
           pManifest->nField==1 ? "" : "s"
      );
    }
  }else{
    blob_appendf(&comment, "New ticket [%.10s] <i>%h</i>.",
      pManifest->zTicketUuid, zTitle
    );
    blob_appendf(&brief, "New ticket [%.10s].", pManifest->zTicketUuid);

  }
  free(zTitle);
  db_multi_exec(
    "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
    "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
    tktTagId, pManifest->rDate, rid, pManifest->zUser,
    blob_str(&comment), blob_str(&brief)
  );
  blob_reset(&comment);







|
|





|
|





|

|
|

|
|
|




|
|

|
>

|







1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
  if( !isNew ){
    for(i=0; i<pManifest->nField; i++){
      if( fossil_strcmp(pManifest->aField[i].zName, zStatusColumn)==0 ){
        zNewStatus = pManifest->aField[i].zValue;
      }
    }
    if( zNewStatus ){
      blob_appendf(&comment, "%h ticket [%s|%.10s]: <i>%h</i>",
         zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
      );
      if( pManifest->nField>1 ){
        blob_appendf(&comment, " plus %d other change%s",
          pManifest->nField-1, pManifest->nField==2 ? "" : "s");
      }
      blob_appendf(&brief, "%h ticket [%s|%.10s].",
                   zNewStatus, pManifest->zTicketUuid, pManifest->zTicketUuid);
    }else{
      zNewStatus = db_text("unknown",
         "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
         zStatusColumn, pManifest->zTicketUuid
      );
      blob_appendf(&comment, "Ticket [%s|%.10s] <i>%h</i> status still %h with "
           "%d other change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle, zNewStatus,
           pManifest->nField, pManifest->nField==1 ? "" : "s"
      );
      fossil_free(zNewStatus);
      blob_appendf(&brief, "Ticket [%s|%.10s]: %d change%s",
           pManifest->zTicketUuid, pManifest->zTicketUuid, pManifest->nField,
           pManifest->nField==1 ? "" : "s"
      );
    }
  }else{
    blob_appendf(&comment, "New ticket [%s|%.10s] <i>%h</i>.",
      pManifest->zTicketUuid, pManifest->zTicketUuid, zTitle
    );
    blob_appendf(&brief, "New ticket [%s|%.10s].", pManifest->zTicketUuid,
        pManifest->zTicketUuid);
  }
  fossil_free(zTitle);
  db_multi_exec(
    "REPLACE INTO event(type,tagid,mtime,objid,user,comment,brief)"
    "VALUES('t',%d,%.17g,%d,%Q,%Q,%Q)",
    tktTagId, pManifest->rDate, rid, pManifest->zUser,
    blob_str(&comment), blob_str(&brief)
  );
  blob_reset(&comment);
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
        TAG_BGCOLOR, rid,
        TAG_USER, rid,
        TAG_COMMENT, rid, p->rDate
      );
      zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event"
                        " WHERE rowid=last_insert_rowid()");
      wiki_extract_links(zCom, rid, 0, p->rDate, 1, WIKI_INLINE);
      free(zCom);

      /* If this is a delta-manifest, record the fact that this repository
      ** contains delta manifests, to free the "commit" logic to generate
      ** new delta manifests.
      */
      if( p->zBaseline!=0 ){
        static int once = 1;







|







1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
        TAG_BGCOLOR, rid,
        TAG_USER, rid,
        TAG_COMMENT, rid, p->rDate
      );
      zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event"
                        " WHERE rowid=last_insert_rowid()");
      wiki_extract_links(zCom, rid, 0, p->rDate, 1, WIKI_INLINE);
      fossil_free(zCom);

      /* If this is a delta-manifest, record the fact that this repository
      ** contains delta manifests, to free the "commit" logic to generate
      ** new delta manifests.
      */
      if( p->zBaseline!=0 ){
        static int once = 1;
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
    char *zComment;
    int nWiki;
    char zLength[40];
    while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
    nWiki = strlen(p->zWiki);
    sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
    tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
    free(zTag);
    prior = db_int(0,
      "SELECT rid FROM tagxref"
      " WHERE tagid=%d AND mtime<%.17g"
      " ORDER BY mtime DESC",
      tagid, p->rDate
    );
    if( prior ){







|







1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
    char *zComment;
    int nWiki;
    char zLength[40];
    while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
    nWiki = strlen(p->zWiki);
    sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
    tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
    fossil_free(zTag);
    prior = db_int(0,
      "SELECT rid FROM tagxref"
      " WHERE tagid=%d AND mtime<%.17g"
      " ORDER BY mtime DESC",
      tagid, p->rDate
    );
    if( prior ){
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
      "  (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
      p->rDate, rid, p->zUser, zComment,
      TAG_BGCOLOR, rid,
      TAG_BGCOLOR, rid,
      TAG_USER, rid,
      TAG_COMMENT, rid
    );
    free(zComment);
  }
  if( p->type==CFTYPE_EVENT ){
    char *zTag = mprintf("event-%s", p->zEventId);
    int tagid = tag_findid(zTag, 1);
    int prior, subsequent;
    int nWiki;
    char zLength[40];
    while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
    nWiki = strlen(p->zWiki);
    sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
    tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
    free(zTag);
    prior = db_int(0,
      "SELECT rid FROM tagxref"
      " WHERE tagid=%d AND mtime<%.17g AND rid!=%d"
      " ORDER BY mtime DESC",
      tagid, p->rDate, rid
    );
    subsequent = db_int(0,







|











|







1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
      "  (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
      p->rDate, rid, p->zUser, zComment,
      TAG_BGCOLOR, rid,
      TAG_BGCOLOR, rid,
      TAG_USER, rid,
      TAG_COMMENT, rid
    );
    fossil_free(zComment);
  }
  if( p->type==CFTYPE_EVENT ){
    char *zTag = mprintf("event-%s", p->zEventId);
    int tagid = tag_findid(zTag, 1);
    int prior, subsequent;
    int nWiki;
    char zLength[40];
    while( fossil_isspace(p->zWiki[0]) ) p->zWiki++;
    nWiki = strlen(p->zWiki);
    sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki);
    tag_insert(zTag, 1, zLength, rid, p->rDate, rid);
    fossil_free(zTag);
    prior = db_int(0,
      "SELECT rid FROM tagxref"
      " WHERE tagid=%d AND mtime<%.17g AND rid!=%d"
      " ORDER BY mtime DESC",
      tagid, p->rDate, rid
    );
    subsequent = db_int(0,
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913





1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956

1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
        p->rEventDate, rid, tagid, p->zUser, p->zComment,
        TAG_BGCOLOR, rid
      );
    }
  }
  if( p->type==CFTYPE_TICKET ){
    char *zTag;

    assert( manifest_crosslink_busy==1 );
    zTag = mprintf("tkt-%s", p->zTicketUuid);
    tag_insert(zTag, 1, 0, rid, p->rDate, rid);
    free(zTag);
    db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
                  p->zTicketUuid);
  }
  if( p->type==CFTYPE_ATTACHMENT ){





    db_multi_exec(
       "INSERT INTO attachment(attachid, mtime, src, target,"
                                        "filename, comment, user)"
       "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
       rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
       (p->zComment ? p->zComment : ""), p->zUser
    );
    db_multi_exec(
       "UPDATE attachment SET isLatest = (mtime=="
          "(SELECT max(mtime) FROM attachment"
          "  WHERE target=%Q AND filename=%Q))"
       " WHERE target=%Q AND filename=%Q",
       p->zAttachTarget, p->zAttachName,
       p->zAttachTarget, p->zAttachName
    );
    if( strlen(p->zAttachTarget)!=UUID_SIZE
     || !validate16(p->zAttachTarget, UUID_SIZE)
    ){
      char *zComment;
      if( p->zAttachSrc && p->zAttachSrc[0] ){
        zComment = mprintf(
             "Add attachment [/artifact/%S|%h] to wiki page [%h]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
             p->zAttachName, p->zAttachTarget);
      }
      db_multi_exec(
        "REPLACE INTO event(type,mtime,objid,user,comment)"
        "VALUES('w',%.17g,%d,%Q,%Q)",
        p->rDate, rid, p->zUser, zComment
      );
      free(zComment);
    }else{
      char *zComment;
      if( p->zAttachSrc && p->zAttachSrc[0] ){
        zComment = mprintf(
             "Add attachment [/artifact/%S|%h] to ticket [%S]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from ticket [%.10s]",
             p->zAttachName, p->zAttachTarget);
      }

      db_multi_exec(
        "REPLACE INTO event(type,mtime,objid,user,comment)"
        "VALUES('t',%.17g,%d,%Q,%Q)",
        p->rDate, rid, p->zUser, zComment
      );
      free(zComment);
    }
  }
  if( p->type==CFTYPE_CONTROL ){
    Blob comment;
    int i;
    const char *zName;
    const char *zValue;
    const char *zTagUuid;
    int branchMove = 0;
    blob_zero(&comment);
    if( p->zComment ){
      blob_appendf(&comment, " %s.", p->zComment);
    }
    /* Next loop expects tags to be sorted on UUID, so sort it. */
    qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
    for(i=0; i<p->nTag; i++){
      zTagUuid = p->aTag[i].zUuid;
      if( !zTagUuid ) continue;
      if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
        blob_appendf(&comment,
           " Edit [%S]:",
           zTagUuid);
        branchMove = 0;
        if( permitHooks && db_exists("SELECT 1 FROM event, blob"
            " WHERE event.type='ci' AND event.objid=blob.rid"
            " AND blob.uuid='%s'", zTagUuid) ){
          zScript = xfer_commit_code();
          zUuid = zTagUuid;
        }
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
           " Move to branch [/timeline?r=%h&nd&dp=%S&unhide | %h].",
           zValue, zTagUuid, zValue);
        branchMove = 1;
        continue;
      }else if( strcmp(zName, "*bgcolor")==0 ){
        blob_appendf(&comment,
           " Change branch background color to \"%h\".", zValue);
        continue;







<



|




>
>
>
>
>


|












|
<
|
<
<

|





<
<
<
<
<
<

<
|

|
|

|
|

>
|

|
|
|
|
<



















|
|












|







1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934

1935


1936
1937
1938
1939
1940
1941
1942






1943

1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
        p->rEventDate, rid, tagid, p->zUser, p->zComment,
        TAG_BGCOLOR, rid
      );
    }
  }
  if( p->type==CFTYPE_TICKET ){
    char *zTag;

    assert( manifest_crosslink_busy==1 );
    zTag = mprintf("tkt-%s", p->zTicketUuid);
    tag_insert(zTag, 1, 0, rid, p->rDate, rid);
    fossil_free(zTag);
    db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
                  p->zTicketUuid);
  }
  if( p->type==CFTYPE_ATTACHMENT ){
    char *zComment = 0;
    char const isAdd = (p->zAttachSrc && p->zAttachSrc[0]) ? 1 : 0;
    char const attachToType = fossil_is_uuid(p->zAttachTarget)
      ? 't' /* attach to ticket */
      : 'w' /* attach to wiki page */;
    db_multi_exec(
       "INSERT INTO attachment(attachid, mtime, src, target,"
                              "filename, comment, user)"
       "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
       rid, p->rDate, p->zAttachSrc, p->zAttachTarget, p->zAttachName,
       (p->zComment ? p->zComment : ""), p->zUser
    );
    db_multi_exec(
       "UPDATE attachment SET isLatest = (mtime=="
          "(SELECT max(mtime) FROM attachment"
          "  WHERE target=%Q AND filename=%Q))"
       " WHERE target=%Q AND filename=%Q",
       p->zAttachTarget, p->zAttachName,
       p->zAttachTarget, p->zAttachName
    );
    if( 'w' == attachToType ){

      if( isAdd ){


        zComment = mprintf(
             "Add attachment [/artifact/%s|%h] to wiki page [%h]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from wiki page [%h]",
             p->zAttachName, p->zAttachTarget);
      }






    }else{

      if( isAdd ){
        zComment = mprintf(
             "Add attachment [/artifact/%s|%h] to ticket [%s|%.10s]",
             p->zAttachSrc, p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }else{
        zComment = mprintf("Delete attachment \"%h\" from ticket [%s|%.10s]",
             p->zAttachName, p->zAttachTarget, p->zAttachTarget);
      }
    }
    db_multi_exec(
        "REPLACE INTO event(type,mtime,objid,user,comment)"
        "VALUES('%c',%.17g,%d,%Q,%Q)",
        attachToType, p->rDate, rid, p->zUser, zComment
    );
    fossil_free(zComment);

  }
  if( p->type==CFTYPE_CONTROL ){
    Blob comment;
    int i;
    const char *zName;
    const char *zValue;
    const char *zTagUuid;
    int branchMove = 0;
    blob_zero(&comment);
    if( p->zComment ){
      blob_appendf(&comment, " %s.", p->zComment);
    }
    /* Next loop expects tags to be sorted on UUID, so sort it. */
    qsort(p->aTag, p->nTag, sizeof(p->aTag[0]), tag_compare);
    for(i=0; i<p->nTag; i++){
      zTagUuid = p->aTag[i].zUuid;
      if( !zTagUuid ) continue;
      if( i==0 || fossil_strcmp(zTagUuid, p->aTag[i-1].zUuid)!=0 ){
        blob_appendf(&comment,
           " Edit [%s|%.10s]:",
           zTagUuid, zTagUuid);
        branchMove = 0;
        if( permitHooks && db_exists("SELECT 1 FROM event, blob"
            " WHERE event.type='ci' AND event.objid=blob.rid"
            " AND blob.uuid='%s'", zTagUuid) ){
          zScript = xfer_commit_code();
          zUuid = zTagUuid;
        }
      }
      zName = p->aTag[i].zName;
      zValue = p->aTag[i].zValue;
      if( strcmp(zName, "*branch")==0 ){
        blob_appendf(&comment,
           " Move to branch [/timeline?r=%h&nd&dp=%s&unhide | %h].",
           zValue, zTagUuid, zValue);
        branchMove = 1;
        continue;
      }else if( strcmp(zName, "*bgcolor")==0 ){
        blob_appendf(&comment,
           " Change branch background color to \"%h\".", zValue);
        continue;
Changes to src/name.c.
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
          "   AND event.type GLOB '%q'", zTag, zType);
      }
    }
  }
  return rid;
}


/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.  If multiple tags match, pick the latest.







<







264
265
266
267
268
269
270

271
272
273
274
275
276
277
          "   AND event.type GLOB '%q'", zTag, zType);
      }
    }
  }
  return rid;
}


/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.  If multiple tags match, pick the latest.
317
318
319
320
321
322
323





























324
325
326
327
328
329
330
  if((rid>0) && pUuid){
    *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }
  return rid;
}
































/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){







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







316
317
318
319
320
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
347
348
349
350
351
352
353
354
355
356
357
358
  if((rid>0) && pUuid){
    *pUuid = db_text(NULL, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }
  return rid;
}


/*
** name_collisions searches through events, blobs, and tickets for
** collisions of a given UUID based on its length on UUIDs no shorter
** than 4 characters in length.
*/
int name_collisions(const char *zName){
  Stmt q;
  int c = 0;         /* count of collisions for zName */
  int nLen;          /* length of zName */
  nLen = strlen(zName);
  if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){
    db_prepare(&q,
      "SELECT count(uuid) FROM"
      "  (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket"
      "   UNION ALL SELECT * FROM"
      "     (SELECT substr(tagname, 7, %d) FROM"
      "       tag WHERE tagname GLOB 'event-*')"
      "   UNION ALL SELECT * FROM"
      "     (SELECT substr(uuid, 1, %d) FROM blob))"
      "  WHERE uuid GLOB '%q*'"
      "  GROUP BY uuid HAVING count(uuid) > 1;",
      nLen, nLen, nLen, zName);
    if( db_step(&q)==SQLITE_ROW ){
      c = db_column_int(&q, 0);
    }
    db_finalize(&q);
  }
  return c;
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){
400
401
402
403
404
405
406
407
408
409







































410
411
412

413
414
415
416
417
418
419
  @ <ol>
  z = mprintf("%s", zName);
  canonical16(z, strlen(z));
  db_prepare(&q, "SELECT uuid, rid FROM blob WHERE uuid GLOB '%q*'", z);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%S(zUuid)">
    @ %S(zUuid)</a> -
    object_description(rid, 0, 0);







































    @ </p></li>
  }
  @ </ol>

  style_footer();
}

/*
** Convert the name in CGI parameter zParamName into a rid and return that
** rid.  If the CGI parameter is missing or is not a valid artifact tag,
** return 0.  If the CGI parameter is ambiguous, redirect to a page that







|
|

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



>







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
  @ <ol>
  z = mprintf("%s", zName);
  canonical16(z, strlen(z));
  db_prepare(&q, "SELECT uuid, rid FROM blob WHERE uuid GLOB '%q*'", z);
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    object_description(rid, 0, 0);
    @ </p></li>
  }
  db_finalize(&q);
  db_prepare(&q,
    "   SELECT tkt_rid, tkt_uuid, title"
    "     FROM ticket, ticketchng"
    "    WHERE ticket.tkt_id = ticketchng.tkt_id"
    "      AND tkt_uuid GLOB '%q*'"
    " GROUP BY tkt_uuid"
    " ORDER BY tkt_ctime DESC", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0); 
    const char *zUuid = db_column_text(&q, 1);
    const char *zTitle = db_column_text(&q, 2);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul></ul>
    @ Ticket
    hyperlink_to_uuid(zUuid);
    @ - %s(zTitle).
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>
  }
  db_finalize(&q);
  db_prepare(&q,
    "SELECT rid, uuid FROM"
    "  (SELECT tagxref.rid AS rid, substr(tagname, 7) AS uuid"
    "     FROM tagxref, tag WHERE tagxref.tagid = tag.tagid"
    "      AND tagname GLOB 'event-%q*') GROUP BY uuid", z);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0); 
    const char* zUuid = db_column_text(&q, 1);
    @ <li><p><a href="%s(g.zTop)/%T(zSrc)/%s(zUuid)">
    @ %s(zUuid)</a> -
    @ <ul><li>
    object_description(rid, 0, 0);
    @ </li></ul>
    @ </p></li>
  }
  @ </ol>
  db_finalize(&q);
  style_footer();
}

/*
** Convert the name in CGI parameter zParamName into a rid and return that
** rid.  If the CGI parameter is missing or is not a valid artifact tag,
** return 0.  If the CGI parameter is ambiguous, redirect to a page that
628
629
630
631
632
633
634

















































  db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
  while( db_step(&q)==SQLITE_ROW ){
    if( cnt++ ) fossil_print("%.79c\n", '-');
    whatis_rid(db_column_int(&q,0), 1);
  }
  db_finalize(&q);
}
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  db_prepare(&q, "SELECT rid FROM blob ORDER BY rid");
  while( db_step(&q)==SQLITE_ROW ){
    if( cnt++ ) fossil_print("%.79c\n", '-');
    whatis_rid(db_column_int(&q,0), 1);
  }
  db_finalize(&q);
}


/*
** COMMAND: test-ambiguous
** Usage: %fossil test-ambiguous [--minsize N]
**
** Show a list of ambiguous SHA1-hash abbreviations of N characters or
** more where N defaults to 4.  Change N to a different value using
** the "--minsize N" command-line option.
*/
void test_ambiguous_cmd(void){
  Stmt q, ins;
  int i;
  int minSize = 4;
  const char *zMinsize;
  char zPrev[100];
  db_find_and_open_repository(0,0);
  zMinsize = find_option("minsize",0,1);
  if( zMinsize && atoi(zMinsize)>0 ) minSize = atoi(zMinsize);
  db_multi_exec("CREATE TEMP TABLE dups(uuid, cnt)");
  db_prepare(&ins,"INSERT INTO dups(uuid) VALUES(substr(:uuid,1,:cnt))");
  db_prepare(&q,
    "SELECT uuid FROM blob "
    "UNION "
    "SELECT substr(tagname,7) FROM tag WHERE tagname GLOB 'event-*' "
    "UNION "
    "SELECT tkt_uuid FROM ticket "
    "ORDER BY 1"
  );
  zPrev[0] = 0;
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    for(i=0; zUuid[i]==zPrev[i] && zUuid[i]!=0; i++){}
    if( i>=minSize ){
      db_bind_int(&ins, ":cnt", i);
      db_bind_text(&ins, ":uuid", zUuid);
      db_step(&ins);
      db_reset(&ins);
    }
    sqlite3_snprintf(sizeof(zPrev), zPrev, "%s", zUuid);
  }
  db_finalize(&ins);
  db_finalize(&q);
  db_prepare(&q, "SELECT uuid FROM dups ORDER BY length(uuid) DESC, uuid");
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("%s\n", db_column_text(&q, 0));
  }
  db_finalize(&q);
}
Changes to src/report.c.
300
301
302
303
304
305
306

307
308
309
310
311
312
313
  rn = atoi(PD("rn","0"));
  db_prepare(&q, "SELECT title, sqlcode, owner, cols "
                   "FROM reportfmt WHERE rn=%d",rn);
  style_header("SQL For Report Format Number %d", rn);
  if( db_step(&q)!=SQLITE_ROW ){
    @ <p>Unknown report number: %d(rn)</p>
    style_footer();

    return;
  }
  zTitle = db_column_text(&q, 0);
  zSQL = db_column_text(&q, 1);
  zOwner = db_column_text(&q, 2);
  zClrKey = db_column_text(&q, 3);
  @ <table cellpadding=0 cellspacing=0 border=0>







>







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  rn = atoi(PD("rn","0"));
  db_prepare(&q, "SELECT title, sqlcode, owner, cols "
                   "FROM reportfmt WHERE rn=%d",rn);
  style_header("SQL For Report Format Number %d", rn);
  if( db_step(&q)!=SQLITE_ROW ){
    @ <p>Unknown report number: %d(rn)</p>
    style_footer();
    db_finalize(&q);
    return;
  }
  zTitle = db_column_text(&q, 0);
  zSQL = db_column_text(&q, 1);
  zOwner = db_column_text(&q, 2);
  zClrKey = db_column_text(&q, 3);
  @ <table cellpadding=0 cellspacing=0 border=0>
321
322
323
324
325
326
327

328
329
330
331
332
333
334
  @ </pre></td>
  @ <td width=15></td><td valign="top">
  output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3");
  @ </td>
  @ </tr></table>
  report_format_hints();
  style_footer();

}

/*
** WEBPAGE: /rptnew
** WEBPAGE: /rptedit
*/
void view_edit(void){







>







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  @ </pre></td>
  @ <td width=15></td><td valign="top">
  output_color_key(zClrKey, 0, "border=0 cellspacing=0 cellpadding=3");
  @ </td>
  @ </tr></table>
  report_format_hints();
  style_footer();
  db_finalize(&q);
}

/*
** WEBPAGE: /rptnew
** WEBPAGE: /rptedit
*/
void view_edit(void){
1024
1025
1026
1027
1028
1029
1030

1031
1032
1033
1034
1035
1036
1037
  }
  tabs = P("tablist")!=0;
  /* view_add_functions(tabs); */
  db_prepare(&q,
    "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE rn=%d", rn);
  if( db_step(&q)!=SQLITE_ROW ){
    cgi_redirect("reportlist");

    return;
  }
  zTitle = db_column_malloc(&q, 0);
  zSql = db_column_malloc(&q, 1);
  zOwner = db_column_malloc(&q, 2);
  zClrKey = db_column_malloc(&q, 3);
  db_finalize(&q);







>







1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  }
  tabs = P("tablist")!=0;
  /* view_add_functions(tabs); */
  db_prepare(&q,
    "SELECT title, sqlcode, owner, cols FROM reportfmt WHERE rn=%d", rn);
  if( db_step(&q)!=SQLITE_ROW ){
    cgi_redirect("reportlist");
    db_finalize(&q);
    return;
  }
  zTitle = db_column_malloc(&q, 0);
  zSql = db_column_malloc(&q, 1);
  zOwner = db_column_malloc(&q, 2);
  zClrKey = db_column_malloc(&q, 3);
  db_finalize(&q);
Changes to src/search.c.
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  const char *zWidth = find_option("width","W",1);
  int nLimit = zLimit ? atoi(zLimit) : -1000;   /* Max number of matching
                                                   lines/entries to list */
  int width;
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("--width|-W value must be >20 or 0");
    }
  }else{
    width = 79;
  }

  db_must_be_within_tree();
  if( g.argc<2 ) return;







|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  const char *zWidth = find_option("width","W",1);
  int nLimit = zLimit ? atoi(zLimit) : -1000;   /* Max number of matching
                                                   lines/entries to list */
  int width;
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = 79;
  }

  db_must_be_within_tree();
  if( g.argc<2 ) return;
Changes to src/setup.c.
275
276
277
278
279
280
281

282
283
284
285
286
287
288
  @ <span class="usertype">anonymous</span>, and
  @ <span class="usertype">nobody</span>.
  @ </p></li>
  @
  @ </ol>
  @ </td></tr></table>
  style_footer();

}

/*
** Return true if zPw is a valid password string.  A valid
** password string is:
**
**  (1)  A zero-length string, or







>







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  @ <span class="usertype">anonymous</span>, and
  @ <span class="usertype">nobody</span>.
  @ </p></li>
  @
  @ </ol>
  @ </td></tr></table>
  style_footer();
  db_finalize(&s);
}

/*
** Return true if zPw is a valid password string.  A valid
** password string is:
**
**  (1)  A zero-length string, or
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  if( zId && !g.perm.Setup && uid>0 ){
    char *zOldCaps;
    zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
    higherUser = zOldCaps && strchr(zOldCaps,'s');
  }

  if( P("can") ){
    cgi_redirect("setup_ulist");
    return;
  }

  /* If we have all the necessary information, write the new or
  ** modified user record.  After writing the user record, redirect
  ** to the page that displays a list of users.
  */







|







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  if( zId && !g.perm.Setup && uid>0 ){
    char *zOldCaps;
    zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
    higherUser = zOldCaps && strchr(zOldCaps,'s');
  }

  if( P("can") ){
    cgi_redirect("setup_ulist");  /* User pressed the Cancel button */
    return;
  }

  /* If we have all the necessary information, write the new or
  ** modified user record.  After writing the user record, redirect
  ** to the page that displays a list of users.
  */
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
    }
    if( isValidPwString(zPw) ){
      zPw = sha1_shared_secret(zPw, zLogin, 0);
    }else{
      zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
    }
    zOldLogin = db_text(0, "SELECT login FROM user WHERE uid=%d", uid);
    if( uid>0 &&
        db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
    ){
      style_header("User Creation Error");
      @ <span class="loginError">Login "%h(zLogin)" is already used by
      @ a different user.</span>
      @
      @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
      style_footer();
      return;







<
|
<







361
362
363
364
365
366
367

368

369
370
371
372
373
374
375
    }
    if( isValidPwString(zPw) ){
      zPw = sha1_shared_secret(zPw, zLogin, 0);
    }else{
      zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
    }
    zOldLogin = db_text(0, "SELECT login FROM user WHERE uid=%d", uid);

    if( db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid) ){

      style_header("User Creation Error");
      @ <span class="loginError">Login "%h(zLogin)" is already used by
      @ a different user.</span>
      @
      @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
      style_footer();
      return;
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
    style_header(mprintf("Edit User %h", zLogin));
  }else{
    style_header("Add A New User");
  }
  @ <div class="ueditCapBox">
  @ <form action="%s(g.zPath)" method="post"><div>
  login_insert_csrf_secret();





  @ <table>
  @ <tr>
  @   <td class="usetupEditLabel">User ID:</td>
  if( uid ){
    @   <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
  }else{
    @   <td>(new user)<input type="hidden" name="id" value="0" /></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Login:</td>



  @   <td><input type="text" name="login" value="%h(zLogin)" /></td>
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Contact&nbsp;Info:</td>
  @   <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td>

  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]
  @ <table border=0><tr><td valign="top">
  if( g.perm.Setup ){







>
>
>
>
>











>
>
>
|
|
|
|
|
>







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
516
517
518
519
520
    style_header(mprintf("Edit User %h", zLogin));
  }else{
    style_header("Add A New User");
  }
  @ <div class="ueditCapBox">
  @ <form action="%s(g.zPath)" method="post"><div>
  login_insert_csrf_secret();
  if( login_is_special(zLogin) ){
    @ <input type="hidden" name="login" value="%s(zLogin)">
    @ <input type="hidden" name="info" value="">
    @ <input type="hidden" name="pw" value="*">
  }
  @ <table>
  @ <tr>
  @   <td class="usetupEditLabel">User ID:</td>
  if( uid ){
    @   <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
  }else{
    @   <td>(new user)<input type="hidden" name="id" value="0" /></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Login:</td>
  if( login_is_special(zLogin) ){
    @    <td><b>%h(zLogin)</b></td>
  }else{
    @   <td><input type="text" name="login" value="%h(zLogin)" /></td>
    @ </tr>
    @ <tr>
    @   <td class="usetupEditLabel">Contact&nbsp;Info:</td>
    @   <td><textarea name="info" cols="40" rows="2">%h(zInfo)</textarea></td>
  }
  @ </tr>
  @ <tr>
  @   <td class="usetupEditLabel">Capabilities:</td>
  @   <td>
#define B(x) inherit[x]
  @ <table border=0><tr><td valign="top">
  if( g.perm.Setup ){
562
563
564
565
566
567
568

569
570
571
572
573
574
575
576
577
578

579
580
581
582
583
584
585
  @  <label><input type="checkbox" name="ax"%s(oa['x']) />%s(B('x'))Private
  @  </label><br />
  @  <label><input type="checkbox" name="az"%s(oa['z']) />%s(B('z'))Download
  @  Zip </label>
  @ </td></tr></table>
  @   </td>
  @ </tr>

  @ <tr>
  @   <td align="right">Password:</td>
  if( zPw[0] ){
    /* Obscure the password for all users */
    @   <td><input type="password" name="pw" value="**********" /></td>
  }else{
    /* Show an empty password as an empty input field */
    @   <td><input type="password" name="pw" value="" /></td>
  }
  @ </tr>

  zGroup = login_group_name();
  if( zGroup ){
    @ <tr>
    @ <td valign="top" align="right">Scope:</td>
    @ <td valign="top">
    @ <input type="radio" name="all" checked value="0">
    @ Apply changes to this repository only.<br />







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







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
  @  <label><input type="checkbox" name="ax"%s(oa['x']) />%s(B('x'))Private
  @  </label><br />
  @  <label><input type="checkbox" name="az"%s(oa['z']) />%s(B('z'))Download
  @  Zip </label>
  @ </td></tr></table>
  @   </td>
  @ </tr>
  if( !login_is_special(zLogin) ){
    @ <tr>
    @   <td align="right">Password:</td>
    if( zPw[0] ){
      /* Obscure the password for all users */
      @   <td><input type="password" name="pw" value="**********" /></td>
    }else{
      /* Show an empty password as an empty input field */
      @   <td><input type="password" name="pw" value="" /></td>
    }
    @ </tr>
  }
  zGroup = login_group_name();
  if( zGroup ){
    @ <tr>
    @ <td valign="top" align="right">Scope:</td>
    @ <td valign="top">
    @ <input type="radio" name="all" checked value="0">
    @ Apply changes to this repository only.<br />
Changes to src/shell.c.
2126
2127
2128
2129
2130
2131
2132

2133
2134
2135
2136

2137
2138
2139
2140
2141
2142
2143
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
  if( rc ){
    fprintf(stderr, "Cannot create output database: %s\n",
            sqlite3_errmsg(newDb));
  }else{

    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
    tryToCloneSchema(p, newDb, "type!='table'", 0);
    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);

  }
  sqlite3_close(newDb);
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.







>




>







2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
    return;
  }
  rc = sqlite3_open(zNewDb, &newDb);
  if( rc ){
    fprintf(stderr, "Cannot create output database: %s\n",
            sqlite3_errmsg(newDb));
  }else{
    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
    tryToCloneSchema(p, newDb, "type!='table'", 0);
    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
  }
  sqlite3_close(newDb);
}

/*
** If an input line begins with "." then invoke this routine to
** process that line.
3021
3022
3023
3024
3025
3026
3027

3028
3029
3030
3031
3032
3033
3034
      { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
      { "assert",                SQLITE_TESTCTRL_ASSERT                 },
      { "always",                SQLITE_TESTCTRL_ALWAYS                 },
      { "reserve",               SQLITE_TESTCTRL_RESERVE                },
      { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
      { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
      { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },

    };
    int testctrl = -1;
    int rc = 0;
    int i, n;
    open_db(p, 0);

    /* convert testctrl text option to value. allow any unique prefix







>







3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
      { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
      { "assert",                SQLITE_TESTCTRL_ASSERT                 },
      { "always",                SQLITE_TESTCTRL_ALWAYS                 },
      { "reserve",               SQLITE_TESTCTRL_RESERVE                },
      { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
      { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
      { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
      { "byteorder",             SQLITE_TESTCTRL_BYTEORDER              },
    };
    int testctrl = -1;
    int rc = 0;
    int i, n;
    open_db(p, 0);

    /* convert testctrl text option to value. allow any unique prefix
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077
          } else {
            fprintf(stderr,"Error: testctrl %s takes a single int option\n",
                    azArg[1]);
          }
          break;

        /* sqlite3_test_control(int) */
        case SQLITE_TESTCTRL_PRNG_SAVE:           
        case SQLITE_TESTCTRL_PRNG_RESTORE:        
        case SQLITE_TESTCTRL_PRNG_RESET:

          if( nArg==2 ){
            rc = sqlite3_test_control(testctrl);
            fprintf(p->out, "%d (0x%08x)\n", rc, rc);
          } else {
            fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
          }
          break;







|
|

>







3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
          } else {
            fprintf(stderr,"Error: testctrl %s takes a single int option\n",
                    azArg[1]);
          }
          break;

        /* sqlite3_test_control(int) */
        case SQLITE_TESTCTRL_PRNG_SAVE:
        case SQLITE_TESTCTRL_PRNG_RESTORE:
        case SQLITE_TESTCTRL_PRNG_RESET:
        case SQLITE_TESTCTRL_BYTEORDER:
          if( nArg==2 ){
            rc = sqlite3_test_control(testctrl);
            fprintf(p->out, "%d (0x%08x)\n", rc, rc);
          } else {
            fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
          }
          break;
Changes to src/sqlcmd.c.
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
  sqlite3 *db,
  const char **pzErrMsg,
  const void *notUsed
){
  sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0,
                          sqlcmd_content, 0, 0);
  sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0,
                          sqlcmd_compress, 0, 0);
  sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0,
                          sqlcmd_decompress, 0, 0);
  re_add_sql_func(db);
  g.repositoryOpen = 1;
  g.db = db;
  return SQLITE_OK;
}








|

|

|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
** database connection to be more useful to the human operator.
*/
static int sqlcmd_autoinit(
  sqlite3 *db,
  const char **pzErrMsg,
  const void *notUsed
){
  sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
                          sqlcmd_content, 0, 0);
  sqlite3_create_function(db, "compress", 1, SQLITE_UTF8, 0,
                          sqlcmd_compress, 0, 0);
  sqlite3_create_function(db, "decompress", 1, SQLITE_UTF8, 0,
                          sqlcmd_decompress, 0, 0);
  re_add_sql_func(db);
  g.repositoryOpen = 1;
  g.db = db;
  return SQLITE_OK;
}

Changes to src/sqlite3.c.
1
2
3
4
5
6
7
8
9
10
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.8.4.1.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other


|







1
2
3
4
5
6
7
8
9
10
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 3.8.5.  By combining all the individual C code files into this 
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.4.1"
#define SQLITE_VERSION_NUMBER 3008004
#define SQLITE_SOURCE_ID      "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|
|
|







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.5"
#define SQLITE_VERSION_NUMBER 3008005
#define SQLITE_SOURCE_ID      "2014-04-18 22:20:31 9a5d38c79d2482a23bcfbc3ff35ca4fa269c768d"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
6234
6235
6236
6237
6238
6239
6240

6241
6242
6243
6244
6245
6246
6247
6248
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21

#define SQLITE_TESTCTRL_LAST                    21

/*
** 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







>
|







6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_LAST                    22

/*
** 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
8435
8436
8437
8438
8439
8440
8441





8442
8443
8444
8445
8446
8447
8448
8449
8450



8451
8452
8453
8454









8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
**
**    0.5 -> -10           0.1 -> -33        0.0625 -> -40
*/
typedef INT16_TYPE LogEst;

/*
** Macros to determine whether the machine is big or little endian,





** evaluated at runtime.
*/
#ifdef SQLITE_AMALGAMATION
SQLITE_PRIVATE const int sqlite3one = 1;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
                             || defined(__x86_64) || defined(__x86_64__)



# define SQLITE_BIGENDIAN    0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE  SQLITE_UTF16LE
#else









# define SQLITE_BIGENDIAN    (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif

/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/







>
>
>
>
>
|






|
|
>
>
>



|
>
>
>
>
>
>
>
>
>


|







8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
**
**    0.5 -> -10           0.1 -> -33        0.0625 -> -40
*/
typedef INT16_TYPE LogEst;

/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros.  If that is unsuccessful, or if
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
** at run-time.
*/
#ifdef SQLITE_AMALGAMATION
SQLITE_PRIVATE const int sqlite3one = 1;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
#if (defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
     defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER    1234
# define SQLITE_BIGENDIAN    0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE  SQLITE_UTF16LE
#endif
#if (defined(sparc)    || defined(__ppc__))  \
    && !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER    4321
# define SQLITE_BIGENDIAN    1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE  SQLITE_UTF16BE
#endif
#if !defined(SQLITE_BYTEORDER)
# define SQLITE_BYTEORDER    0     /* 0 means "unknown at compile-time" */
# define SQLITE_BIGENDIAN    (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE  (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif

/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
8765
8766
8767
8768
8769
8770
8771

8772

8773
8774
8775
8776
8777
8778
8779
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);

SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);

SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);







>
|
>







8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
#define BTREE_OMIT_JOURNAL  1  /* Do not create or use a rollback journal */
#define BTREE_MEMORY        2  /* This is an in-memory DB */
#define BTREE_SINGLE        4  /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED     8  /* Use of a hash implementation is OK */

SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
#if SQLITE_MAX_MMAP_SIZE>0
SQLITE_PRIVATE   int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
#endif
SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
8815
8816
8817
8818
8819
8820
8821

8822
8823
8824
8825
8826
8827
8828
** indices.)
*/
#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
#define BTREE_BLOBKEY    2    /* Table has keys only - no data */

SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);

SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);

SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);

SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);








>







8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
** indices.)
*/
#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
#define BTREE_BLOBKEY    2    /* Table has keys only - no data */

SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);

SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);

SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);

8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);

SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);

SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);

#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif







|







8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);

SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);

SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);

#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
#define OP_NextIfOpen      7
#define OP_Prev            8
#define OP_Next            9
#define OP_AggStep        10 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_Checkpoint     11
#define OP_JournalMode    12
#define OP_Vacuum         13
#define OP_VFilter        14 /* synopsis: iPlan=r[P3] zPlan='P4'           */
#define OP_VUpdate        15 /* synopsis: data=r[P3@P2]                    */
#define OP_Goto           16
#define OP_Gosub          17
#define OP_Return         18
#define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
#define OP_InitCoroutine  20
#define OP_EndCoroutine   21







|







9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
#define OP_NextIfOpen      7
#define OP_Prev            8
#define OP_Next            9
#define OP_AggStep        10 /* synopsis: accum=r[P3] step(r[P2@P5])       */
#define OP_Checkpoint     11
#define OP_JournalMode    12
#define OP_Vacuum         13
#define OP_VFilter        14 /* synopsis: iplan=r[P3] zplan='P4'           */
#define OP_VUpdate        15 /* synopsis: data=r[P3@P2]                    */
#define OP_Goto           16
#define OP_Gosub          17
#define OP_Return         18
#define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
#define OP_InitCoroutine  20
#define OP_EndCoroutine   21
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
#define OP_SCopy          34 /* synopsis: r[P2]=r[P1]                      */
#define OP_ResultRow      35 /* synopsis: output=r[P1@P2]                  */
#define OP_CollSeq        36
#define OP_AddImm         37 /* synopsis: r[P1]=r[P1]+P2                   */
#define OP_MustBeInt      38
#define OP_RealAffinity   39
#define OP_Permutation    40
#define OP_Compare        41
#define OP_Jump           42
#define OP_Once           43
#define OP_If             44
#define OP_IfNot          45
#define OP_Column         46 /* synopsis: r[P3]=PX                         */
#define OP_Affinity       47 /* synopsis: affinity(r[P1@P2])               */
#define OP_MakeRecord     48 /* synopsis: r[P3]=mkrec(r[P1@P2])            */







|







9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
#define OP_SCopy          34 /* synopsis: r[P2]=r[P1]                      */
#define OP_ResultRow      35 /* synopsis: output=r[P1@P2]                  */
#define OP_CollSeq        36
#define OP_AddImm         37 /* synopsis: r[P1]=r[P1]+P2                   */
#define OP_MustBeInt      38
#define OP_RealAffinity   39
#define OP_Permutation    40
#define OP_Compare        41 /* synopsis: r[P1@P3] <-> r[P2@P3]            */
#define OP_Jump           42
#define OP_Once           43
#define OP_If             44
#define OP_IfNot          45
#define OP_Column         46 /* synopsis: r[P3]=PX                         */
#define OP_Affinity       47 /* synopsis: affinity(r[P1@P2])               */
#define OP_MakeRecord     48 /* synopsis: r[P3]=mkrec(r[P1@P2])            */
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
#define OP_SeekGE         61
#define OP_SeekGT         62
#define OP_Seek           63 /* synopsis: intkey=r[P2]                     */
#define OP_NoConflict     64 /* synopsis: key=r[P3@P4]                     */
#define OP_NotFound       65 /* synopsis: key=r[P3@P4]                     */
#define OP_Found          66 /* synopsis: key=r[P3@P4]                     */
#define OP_NotExists      67 /* synopsis: intkey=r[P3]                     */
#define OP_Sequence       68 /* synopsis: r[P2]=rowid                      */
#define OP_NewRowid       69 /* synopsis: r[P2]=rowid                      */
#define OP_Insert         70 /* synopsis: intkey=r[P3] data=r[P2]          */
#define OP_Or             71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And            72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
#define OP_InsertInt      73 /* synopsis: intkey=P3 data=r[P2]             */
#define OP_Delete         74
#define OP_ResetCount     75







|







9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
#define OP_SeekGE         61
#define OP_SeekGT         62
#define OP_Seek           63 /* synopsis: intkey=r[P2]                     */
#define OP_NoConflict     64 /* synopsis: key=r[P3@P4]                     */
#define OP_NotFound       65 /* synopsis: key=r[P3@P4]                     */
#define OP_Found          66 /* synopsis: key=r[P3@P4]                     */
#define OP_NotExists      67 /* synopsis: intkey=r[P3]                     */
#define OP_Sequence       68 /* synopsis: r[P2]=cursor[P1].ctr++           */
#define OP_NewRowid       69 /* synopsis: r[P2]=rowid                      */
#define OP_Insert         70 /* synopsis: intkey=r[P3] data=r[P2]          */
#define OP_Or             71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And            72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
#define OP_InsertInt      73 /* synopsis: intkey=P3 data=r[P2]             */
#define OP_Delete         74
#define OP_ResetCount     75
9234
9235
9236
9237
9238
9239
9240

9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258

9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272

9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
#define OP_IdxRowid      109 /* synopsis: r[P2]=rowid                      */
#define OP_IdxLE         110 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxGT         111 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxLT         112 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxGE         113 /* synopsis: key=r[P3@P4]                     */
#define OP_Destroy       114
#define OP_Clear         115

#define OP_CreateIndex   116 /* synopsis: r[P2]=root iDb=P1                */
#define OP_CreateTable   117 /* synopsis: r[P2]=root iDb=P1                */
#define OP_ParseSchema   118
#define OP_LoadAnalysis  119
#define OP_DropTable     120
#define OP_DropIndex     121
#define OP_DropTrigger   122
#define OP_IntegrityCk   123
#define OP_RowSetAdd     124 /* synopsis: rowset(P1)=r[P2]                 */
#define OP_RowSetRead    125 /* synopsis: r[P3]=rowset(P1)                 */
#define OP_RowSetTest    126 /* synopsis: if r[P3] in rowset(P1) goto P2   */
#define OP_Program       127
#define OP_Param         128
#define OP_FkCounter     129 /* synopsis: fkctr[P1]+=P2                    */
#define OP_FkIfZero      130 /* synopsis: if fkctr[P1]==0 goto P2          */
#define OP_MemMax        131 /* synopsis: r[P1]=max(r[P1],r[P2])           */
#define OP_IfPos         132 /* synopsis: if r[P1]>0 goto P2               */
#define OP_Real          133 /* same as TK_FLOAT, synopsis: r[P2]=P4       */

#define OP_IfNeg         134 /* synopsis: if r[P1]<0 goto P2               */
#define OP_IfZero        135 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2   */
#define OP_AggFinal      136 /* synopsis: accum=r[P1] N=P2                 */
#define OP_IncrVacuum    137
#define OP_Expire        138
#define OP_TableLock     139 /* synopsis: iDb=P1 root=P2 write=P3          */
#define OP_VBegin        140
#define OP_VCreate       141
#define OP_VDestroy      142
#define OP_ToText        143 /* same as TK_TO_TEXT                         */
#define OP_ToBlob        144 /* same as TK_TO_BLOB                         */
#define OP_ToNumeric     145 /* same as TK_TO_NUMERIC                      */
#define OP_ToInt         146 /* same as TK_TO_INT                          */
#define OP_ToReal        147 /* same as TK_TO_REAL                         */

#define OP_VOpen         148
#define OP_VColumn       149 /* synopsis: r[P3]=vcolumn(P2)                */
#define OP_VNext         150
#define OP_VRename       151
#define OP_Pagecount     152
#define OP_MaxPgcnt      153
#define OP_Init          154 /* synopsis: Start at P2                      */
#define OP_Noop          155
#define OP_Explain       156


/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */







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

>
|
|
|
|
|
|
|
|
<





>
|
|
|
|
|
|
|
|
|







9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278

9279
9280
9281
9282
9283
9284
9285
9286
9287
9288

9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
#define OP_IdxRowid      109 /* synopsis: r[P2]=rowid                      */
#define OP_IdxLE         110 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxGT         111 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxLT         112 /* synopsis: key=r[P3@P4]                     */
#define OP_IdxGE         113 /* synopsis: key=r[P3@P4]                     */
#define OP_Destroy       114
#define OP_Clear         115
#define OP_ResetSorter   116
#define OP_CreateIndex   117 /* synopsis: r[P2]=root iDb=P1                */
#define OP_CreateTable   118 /* synopsis: r[P2]=root iDb=P1                */
#define OP_ParseSchema   119
#define OP_LoadAnalysis  120
#define OP_DropTable     121
#define OP_DropIndex     122
#define OP_DropTrigger   123
#define OP_IntegrityCk   124
#define OP_RowSetAdd     125 /* synopsis: rowset(P1)=r[P2]                 */
#define OP_RowSetRead    126 /* synopsis: r[P3]=rowset(P1)                 */
#define OP_RowSetTest    127 /* synopsis: if r[P3] in rowset(P1) goto P2   */
#define OP_Program       128
#define OP_Param         129
#define OP_FkCounter     130 /* synopsis: fkctr[P1]+=P2                    */
#define OP_FkIfZero      131 /* synopsis: if fkctr[P1]==0 goto P2          */
#define OP_MemMax        132 /* synopsis: r[P1]=max(r[P1],r[P2])           */

#define OP_Real          133 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
#define OP_IfPos         134 /* synopsis: if r[P1]>0 goto P2               */
#define OP_IfNeg         135 /* synopsis: if r[P1]<0 goto P2               */
#define OP_IfZero        136 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2   */
#define OP_AggFinal      137 /* synopsis: accum=r[P1] N=P2                 */
#define OP_IncrVacuum    138
#define OP_Expire        139
#define OP_TableLock     140 /* synopsis: iDb=P1 root=P2 write=P3          */
#define OP_VBegin        141
#define OP_VCreate       142

#define OP_ToText        143 /* same as TK_TO_TEXT                         */
#define OP_ToBlob        144 /* same as TK_TO_BLOB                         */
#define OP_ToNumeric     145 /* same as TK_TO_NUMERIC                      */
#define OP_ToInt         146 /* same as TK_TO_INT                          */
#define OP_ToReal        147 /* same as TK_TO_REAL                         */
#define OP_VDestroy      148
#define OP_VOpen         149
#define OP_VColumn       150 /* synopsis: r[P3]=vcolumn(P2)                */
#define OP_VNext         151
#define OP_VRename       152
#define OP_Pagecount     153
#define OP_MaxPgcnt      154
#define OP_Init          155 /* synopsis: Start at P2                      */
#define OP_Noop          156
#define OP_Explain       157


/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
/*  56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
/*  64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\
/*  72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
/*  80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
/*  96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\
/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01,\
/* 128 */ 0x02, 0x00, 0x01, 0x08, 0x05, 0x02, 0x05, 0x05,\
/* 136 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,\
/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00,\
/* 152 */ 0x02, 0x02, 0x01, 0x00, 0x00,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.







|
|
|
|
|
|







9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
/*  56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
/*  64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\
/*  72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
/*  80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
/*  88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
/*  96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\
/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00,\
/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15,\
/* 128 */ 0x01, 0x02, 0x00, 0x01, 0x08, 0x02, 0x05, 0x05,\
/* 136 */ 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04,\
/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01,\
/* 152 */ 0x00, 0x02, 0x02, 0x01, 0x00, 0x00,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif

SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);

#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif

/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on







|


|







9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE   char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif

SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);

#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif

/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
10994
10995
10996
10997
10998
10999
11000

11001
11002
11003
11004
11005
11006
11007
** The r1 and r2 member variables are only used by the optimized comparison
** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
*/
struct UnpackedRecord {
  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
  u16 nField;         /* Number of entries in apMem[] */
  i8 default_rc;      /* Comparison result if keys are equal */

  Mem *aMem;          /* Values */
  int r1;             /* Value to return if (lhs > rhs) */
  int r2;             /* Value to return if (rhs < lhs) */
};


/*







>







11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
** The r1 and r2 member variables are only used by the optimized comparison
** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
*/
struct UnpackedRecord {
  KeyInfo *pKeyInfo;  /* Collation and sort-order information */
  u16 nField;         /* Number of entries in apMem[] */
  i8 default_rc;      /* Comparison result if keys are equal */
  u8 isCorrupt;       /* Corruption detected by xRecordCompare() */
  Mem *aMem;          /* Values */
  int r1;             /* Value to return if (lhs > rhs) */
  int r2;             /* Value to return if (rhs < lhs) */
};


/*
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
#define EP_Agg       0x000002 /* Contains one or more aggregate functions */
#define EP_Resolved  0x000004 /* IDs have been resolved to COLUMNs */
#define EP_Error     0x000008 /* Expression contains one or more errors */
#define EP_Distinct  0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate   0x000100 /* Tree contains a TK_COLLATE opeartor */
      /* unused      0x000200 */
#define EP_IntValue  0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip      0x001000 /* COLLATE, AS, or UNLIKELY */
#define EP_Reduced   0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Static    0x008000 /* Held in memory not obtained from malloc() */
#define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */







|
|







11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
#define EP_Agg       0x000002 /* Contains one or more aggregate functions */
#define EP_Resolved  0x000004 /* IDs have been resolved to COLUMNs */
#define EP_Error     0x000008 /* Expression contains one or more errors */
#define EP_Distinct  0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate   0x000100 /* Tree contains a TK_COLLATE operator */
#define EP_Generic   0x000200 /* Ignore COLLATE or affinity on this tree */
#define EP_IntValue  0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip      0x001000 /* COLLATE, AS, or UNLIKELY */
#define EP_Reduced   0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Static    0x008000 /* Held in memory not obtained from malloc() */
#define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
** column expression as it exists in a SELECT statement.  However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
** form is used for name resolution with nested FROM clauses.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The list of expressions */
    char *zName;            /* Token associated with this expression */
    char *zSpan;            /* Original text of the expression */
    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */







<







11348
11349
11350
11351
11352
11353
11354

11355
11356
11357
11358
11359
11360
11361
** column expression as it exists in a SELECT statement.  However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
** form is used for name resolution with nested FROM clauses.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */

  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The list of expressions */
    char *zName;            /* Token associated with this expression */
    char *zSpan;            /* Original text of the expression */
    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  u16 selFlags;          /* Various SF_* values */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
  u64 nSelectRow;        /* Estimated number of result rows */
  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */







|







11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  u16 selFlags;          /* Various SF_* values */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  int addrOpenEphm[2];   /* OP_OpenEphem opcodes related to this select */
  u64 nSelectRow;        /* Estimated number of result rows */
  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
*/
#define SF_Distinct        0x0001  /* Output should be DISTINCT */
#define SF_Resolved        0x0002  /* Identifiers have been resolved */
#define SF_Aggregate       0x0004  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x0040  /* Sort using a sorter */
#define SF_Values          0x0080  /* Synthesized from VALUES clause */
#define SF_Materialize     0x0100  /* NOT USED */
#define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert    0x0400  /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive       0x0800  /* The recursive part of a recursive CTE */
#define SF_Compound        0x1000  /* Part of a compound query */


/*







|

|







11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
*/
#define SF_Distinct        0x0001  /* Output should be DISTINCT */
#define SF_Resolved        0x0002  /* Identifiers have been resolved */
#define SF_Aggregate       0x0004  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x0008  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x0010  /* sqlite3SelectExpand() called on this */
#define SF_HasTypeInfo     0x0020  /* FROM subqueries have Table metadata */
                    /*     0x0040  NOT USED */
#define SF_Values          0x0080  /* Synthesized from VALUES clause */
                    /*     0x0100  NOT USED */
#define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert    0x0400  /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive       0x0800  /* The recursive part of a recursive CTE */
#define SF_Compound        0x1000  /* Part of a compound query */


/*
11628
11629
11630
11631
11632
11633
11634
11635
11636


11637
11638
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654




11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
**     SRT_Coroutine   Generate a co-routine that returns a new row of
**                     results each time it is invoked.  The entry point
**                     of the co-routine is stored in register pDest->iSDParm
**                     and the result row is stored in pDest->nDest registers
**                     starting with pDest->iSdst.
**
**     SRT_Table       Store results in temporary table pDest->iSDParm.
**                     This is like SRT_EphemTab except that the table
**                     is assumed to already be open.


**
**     SRT_DistTable   Store results in a temporary table pDest->iSDParm.
**                     But also use temporary table pDest->iSDParm+1 as
**                     a record of all prior results and ignore any duplicate
**                     rows.  Name means:  "Distinct Table".
**
**     SRT_Queue       Store results in priority queue pDest->iSDParm (really
**                     an index).  Append a sequence number so that all entries
**                     are distinct.
**
**     SRT_DistQueue   Store results in priority queue pDest->iSDParm only if
**                     the same record has never been stored before.  The
**                     index at pDest->iSDParm+1 hold all prior stores.
*/
#define SRT_Union        1  /* Store result as keys in an index */
#define SRT_Except       2  /* Remove result from a UNION index */
#define SRT_Exists       3  /* Store 1 if the result is not empty */
#define SRT_Discard      4  /* Do not save the results anywhere */





/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)

#define SRT_Output       5  /* Output each row of result */
#define SRT_Mem          6  /* Store result in a memory cell */
#define SRT_Set          7  /* Store results as keys in an index */
#define SRT_EphemTab     8  /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine    9  /* Generate a single row of result */
#define SRT_Table       10  /* Store result as data with an automatic rowid */
#define SRT_DistTable   11  /* Like SRT_Table, but unique results only */
#define SRT_Queue       12  /* Store result in an queue */
#define SRT_DistQueue   13  /* Like SRT_Queue, but unique results only */

/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
  u8 eDest;            /* How to dispose of the results.  On of SRT_* above. */







|
|
>
>

|


|













>
>
>
>


|

|
|
|
|
|
|
<
<
<







11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692



11693
11694
11695
11696
11697
11698
11699
**     SRT_Coroutine   Generate a co-routine that returns a new row of
**                     results each time it is invoked.  The entry point
**                     of the co-routine is stored in register pDest->iSDParm
**                     and the result row is stored in pDest->nDest registers
**                     starting with pDest->iSdst.
**
**     SRT_Table       Store results in temporary table pDest->iSDParm.
**     SRT_Fifo        This is like SRT_EphemTab except that the table
**                     is assumed to already be open.  SRT_Fifo has
**                     the additional property of being able to ignore
**                     the ORDER BY clause.
**
**     SRT_DistFifo    Store results in a temporary table pDest->iSDParm.
**                     But also use temporary table pDest->iSDParm+1 as
**                     a record of all prior results and ignore any duplicate
**                     rows.  Name means:  "Distinct Fifo".
**
**     SRT_Queue       Store results in priority queue pDest->iSDParm (really
**                     an index).  Append a sequence number so that all entries
**                     are distinct.
**
**     SRT_DistQueue   Store results in priority queue pDest->iSDParm only if
**                     the same record has never been stored before.  The
**                     index at pDest->iSDParm+1 hold all prior stores.
*/
#define SRT_Union        1  /* Store result as keys in an index */
#define SRT_Except       2  /* Remove result from a UNION index */
#define SRT_Exists       3  /* Store 1 if the result is not empty */
#define SRT_Discard      4  /* Do not save the results anywhere */
#define SRT_Fifo         5  /* Store result as data with an automatic rowid */
#define SRT_DistFifo     6  /* Like SRT_Fifo, but unique results only */
#define SRT_Queue        7  /* Store result in an queue */
#define SRT_DistQueue    8  /* Like SRT_Queue, but unique results only */

/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)

#define SRT_Output       9  /* Output each row of result */
#define SRT_Mem         10  /* Store result in a memory cell */
#define SRT_Set         11  /* Store results as keys in an index */
#define SRT_EphemTab    12  /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine   13  /* Generate a single row of result */
#define SRT_Table       14  /* Store result as data with an automatic rowid */




/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
  u8 eDest;            /* How to dispose of the results.  On of SRT_* above. */
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
  char *zErrMsg;       /* An error message */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int rc;              /* Return code from execution */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 checkSchema;      /* Causes schema cookie check after an error */
  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  u8 nColCache;        /* Number of entries in aColCache[] */
  u8 iColCache;        /* Next entry in aColCache[] to replace */
  u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
  u8 okConstFactor;    /* OK to factor out constants */
  int aTempReg[8];     /* Holding area for temporary registers */
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */







<
<







11783
11784
11785
11786
11787
11788
11789


11790
11791
11792
11793
11794
11795
11796
  char *zErrMsg;       /* An error message */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int rc;              /* Return code from execution */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 checkSchema;      /* Causes schema cookie check after an error */
  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */


  u8 isMultiWrite;     /* True if statement may modify/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
  u8 okConstFactor;    /* OK to factor out constants */
  int aTempReg[8];     /* Holding area for temporary registers */
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);

SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);

SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);

#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
SQLITE_PRIVATE   int sqlite3ViewGetColumnNames(Parse*,Table*);
#else







|







12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);

SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64);
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);

SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);

#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
SQLITE_PRIVATE   int sqlite3ViewGetColumnNames(Parse*,Table*);
#else
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);







|







12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
12501
12502
12503
12504
12505
12506
12507

12508
12509
12510
12511
12512
12513
12514
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);

SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
                                     u8,u8,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);







>







12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
                                     u8,u8,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
#endif

SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);







|







12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695
12696
#endif

SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
13743
13744
13745
13746
13747
13748
13749

13750
13751
13752
13753
13754
13755
13756
  int pseudoTableReg;   /* Register holding pseudotable content. */
  i16 nField;           /* Number of fields in the header */
  u16 nHdrParsed;       /* Number of header fields parsed so far */
  i8 iDb;               /* Index of cursor database in db->aDb[] (or -1) */
  u8 nullRow;           /* True if pointing to a row with no data */
  u8 rowidIsValid;      /* True if lastRowid is valid */
  u8 deferredMoveto;    /* A call to sqlite3BtreeMoveto() is needed */

  Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
  Bool isTable:1;       /* True if a table requiring integer keys */
  Bool isOrdered:1;     /* True if the underlying table is BTREE_UNORDERED */
  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Rowid being deleted by OP_Delete */







>







13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
  int pseudoTableReg;   /* Register holding pseudotable content. */
  i16 nField;           /* Number of fields in the header */
  u16 nHdrParsed;       /* Number of header fields parsed so far */
  i8 iDb;               /* Index of cursor database in db->aDb[] (or -1) */
  u8 nullRow;           /* True if pointing to a row with no data */
  u8 rowidIsValid;      /* True if lastRowid is valid */
  u8 deferredMoveto;    /* A call to sqlite3BtreeMoveto() is needed */
  Bool isEphemeral:1;   /* True for an ephemeral table */
  Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
  Bool isTable:1;       /* True if a table requiring integer keys */
  Bool isOrdered:1;     /* True if the underlying table is BTREE_UNORDERED */
  sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  i64 lastRowid;        /* Rowid being deleted by OP_Delete */
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);







|







14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097
14098
14099
14100
14101
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
14108
14109
14110
14111
14112
14113
14114

14115
14116
14117
14118
14119
14120
14121
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);

SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);

SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);








>







14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);

SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);

17847
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860
17861
  /* Round nByte up to the next valid power of two */
  for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}

  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
  ** block.  If not, then split a block of the next larger power of
  ** two in order to create a new free block of size iLogsize.
  */
  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
  if( iBin>LOGMAX ){
    testcase( sqlite3GlobalConfig.xLog!=0 );
    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
    return 0;
  }
  i = mem5.aiFreelist[iBin];
  memsys5Unlink(i, iBin);







|







17873
17874
17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886
17887
  /* Round nByte up to the next valid power of two */
  for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}

  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
  ** block.  If not, then split a block of the next larger power of
  ** two in order to create a new free block of size iLogsize.
  */
  for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
  if( iBin>LOGMAX ){
    testcase( sqlite3GlobalConfig.xLog!=0 );
    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
    return 0;
  }
  i = mem5.aiFreelist[iBin];
  memsys5Unlink(i, iBin);
20157
20158
20159
20160
20161
20162
20163
20164
20165
20166
20167
20168
20169
20170
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
  d = digit;
  digit += '0';
  *val = (*val - d)*10.0;
  return (char)digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */

/*
** Append N space characters to the given string buffer.
*/
SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
  static const char zSpaces[] = "                             ";
  while( N>=(int)sizeof(zSpaces)-1 ){
    sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
    N -= sizeof(zSpaces)-1;
  }
  if( N>0 ){
    sqlite3StrAccumAppend(pAccum, zSpaces, N);
  }
}

/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
  p->accError = eError;
  p->nAlloc = 0;
}







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







20183
20184
20185
20186
20187
20188
20189














20190
20191
20192
20193
20194
20195
20196
  d = digit;
  digit += '0';
  *val = (*val - d)*10.0;
  return (char)digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */















/*
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
  p->accError = eError;
  p->nAlloc = 0;
}
20260
20261
20262
20263
20264
20265
20266
20267
20268
20269
20270
20271
20272
20273
20274
20275
20276
20277
20278
    }
    useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
  }else{
    bArgList = useIntern = 0;
  }
  for(; (c=(*fmt))!=0; ++fmt){
    if( c!='%' ){
      int amt;
      bufpt = (char *)fmt;
      amt = 1;
      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
      sqlite3StrAccumAppend(pAccum, bufpt, amt);
      if( c==0 ) break;
    }
    if( (c=(*++fmt))==0 ){
      sqlite3StrAccumAppend(pAccum, "%", 1);
      break;
    }
    /* Find out what flags are present */







<

<
|
|







20272
20273
20274
20275
20276
20277
20278

20279

20280
20281
20282
20283
20284
20285
20286
20287
20288
    }
    useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
  }else{
    bArgList = useIntern = 0;
  }
  for(; (c=(*fmt))!=0; ++fmt){
    if( c!='%' ){

      bufpt = (char *)fmt;

      while( (c=(*++fmt))!='%' && c!=0 ){};
      sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
      if( c==0 ) break;
    }
    if( (c=(*++fmt))==0 ){
      sqlite3StrAccumAppend(pAccum, "%", 1);
      break;
    }
    /* Find out what flags are present */
20445
20446
20447
20448
20449
20450
20451
20452
20453
20454
20455
20456
20457
20458
20459
20460
20461
20462
          if( x>=4 || (longvalue/10)%10==1 ){
            x = 0;
          }
          *(--bufpt) = zOrd[x*2+1];
          *(--bufpt) = zOrd[x*2];
        }
        {
          register const char *cset;      /* Use registers for speed */
          register int base;
          cset = &aDigits[infop->charset];
          base = infop->base;
          do{                                           /* Convert to ascii */
            *(--bufpt) = cset[longvalue%base];
            longvalue = longvalue/base;
          }while( longvalue>0 );
        }
        length = (int)(&zOut[nOut-1]-bufpt);
        for(idx=precision-length; idx>0; idx--){







<
<
|
|







20455
20456
20457
20458
20459
20460
20461


20462
20463
20464
20465
20466
20467
20468
20469
20470
          if( x>=4 || (longvalue/10)%10==1 ){
            x = 0;
          }
          *(--bufpt) = zOrd[x*2+1];
          *(--bufpt) = zOrd[x*2];
        }
        {


          const char *cset = &aDigits[infop->charset];
          u8 base = infop->base;
          do{                                           /* Convert to ascii */
            *(--bufpt) = cset[longvalue%base];
            longvalue = longvalue/base;
          }while( longvalue>0 );
        }
        length = (int)(&zOut[nOut-1]-bufpt);
        for(idx=precision-length; idx>0; idx--){
20752
20753
20754
20755
20756
20757
20758
20759
20760
20761
20762
20763
20764
20765
20766
20767
20768
20769
20770
20771
20772
20773
20774
20775
20776
20777
20778
20779
20780







































































20781

20782
20783
20784
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795
20796
20797
20798
20799
20800
20801
20802
20803
20804
20805
20806
20807
20808
20809
20810
20811
20812
20813
20814
20815
20816
20817
20818
20819
20820
20821
20822
20823
20824
20825
20826
20827
20828
20829
20830
20831
20832
      }
    }/* End switch over the format type */
    /*
    ** The text of the conversion is pointed to by "bufpt" and is
    ** "length" characters long.  The field width is "width".  Do
    ** the output.
    */
    if( !flag_leftjustify ){
      register int nspace;
      nspace = width-length;
      if( nspace>0 ){
        sqlite3AppendSpace(pAccum, nspace);
      }
    }
    if( length>0 ){
      sqlite3StrAccumAppend(pAccum, bufpt, length);
    }
    if( flag_leftjustify ){
      register int nspace;
      nspace = width-length;
      if( nspace>0 ){
        sqlite3AppendSpace(pAccum, nspace);
      }
    }
    if( zExtra ) sqlite3_free(zExtra);
  }/* End for loop over the format string */
} /* End of function */

/*







































































** Append N bytes of text from z to the StrAccum object.

*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
  assert( z!=0 );
  assert( p->zText!=0 || p->nChar==0 || p->accError );
  assert( N>=0 );
  assert( p->accError==0 || p->nAlloc==0 );
  if( p->nChar+N >= p->nAlloc ){
    char *zNew;
    if( p->accError ){
      testcase(p->accError==STRACCUM_TOOBIG);
      testcase(p->accError==STRACCUM_NOMEM);
      return;
    }
    if( !p->useMalloc ){
      N = p->nAlloc - p->nChar - 1;
      setStrAccumError(p, STRACCUM_TOOBIG);
      if( N<=0 ){
        return;
      }
    }else{
      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
      i64 szNew = p->nChar;
      szNew += N + 1;
      if( szNew > p->mxAlloc ){
        sqlite3StrAccumReset(p);
        setStrAccumError(p, STRACCUM_TOOBIG);
        return;
      }else{
        p->nAlloc = (int)szNew;
      }
      if( p->useMalloc==1 ){
        zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
      }else{
        zNew = sqlite3_realloc(zOld, p->nAlloc);
      }
      if( zNew ){
        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
        p->zText = zNew;
      }else{
        sqlite3StrAccumReset(p);
        setStrAccumError(p, STRACCUM_NOMEM);
        return;
      }
    }
  }
  assert( p->zText );
  memcpy(&p->zText[p->nChar], z, N);
  p->nChar += N;
}

/*







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





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







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







20760
20761
20762
20763
20764
20765
20766


20767

20768



20769





20770
20771

20772
20773
20774
20775
20776
20777
20778
20779
20780
20781
20782
20783
20784
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795
20796
20797
20798
20799
20800
20801
20802
20803
20804
20805
20806
20807
20808
20809
20810
20811
20812
20813
20814
20815
20816
20817
20818
20819
20820
20821
20822
20823
20824
20825
20826
20827
20828
20829
20830
20831
20832
20833
20834
20835
20836
20837
20838
20839
20840
20841
20842
20843
20844
20845
20846
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857



20858
































20859
20860
20861
20862
20863
20864
20865
      }
    }/* End switch over the format type */
    /*
    ** The text of the conversion is pointed to by "bufpt" and is
    ** "length" characters long.  The field width is "width".  Do
    ** the output.
    */


    width -= length;

    if( width>0 && !flag_leftjustify ) sqlite3AppendSpace(pAccum, width);



    sqlite3StrAccumAppend(pAccum, bufpt, length);





    if( width>0 && flag_leftjustify ) sqlite3AppendSpace(pAccum, width);


    if( zExtra ) sqlite3_free(zExtra);
  }/* End for loop over the format string */
} /* End of function */

/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
**
** Return the number of bytes of text that StrAccum is able to accept
** after the attempted enlargement.  The value returned might be zero.
*/
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
  char *zNew;
  assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
  if( p->accError ){
    testcase(p->accError==STRACCUM_TOOBIG);
    testcase(p->accError==STRACCUM_NOMEM);
    return 0;
  }
  if( !p->useMalloc ){
    N = p->nAlloc - p->nChar - 1;
    setStrAccumError(p, STRACCUM_TOOBIG);
    return N;
  }else{
    char *zOld = (p->zText==p->zBase ? 0 : p->zText);
    i64 szNew = p->nChar;
    szNew += N + 1;
    if( szNew > p->mxAlloc ){
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_TOOBIG);
      return 0;
    }else{
      p->nAlloc = (int)szNew;
    }
    if( p->useMalloc==1 ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc(zOld, p->nAlloc);
    }
    if( zNew ){
      if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
    }else{
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_NOMEM);
      return 0;
    }
  }
  return N;
}

/*
** Append N space characters to the given string buffer.
*/
SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *p, int N){
  if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
  while( (N--)>0 ) p->zText[p->nChar++] = ' ';
}

/*
** The StrAccum "p" is not large enough to accept N new bytes of z[].
** So enlarge if first, then do the append.
**
** This is a helper routine to sqlite3StrAccumAppend() that does special-case
** work (enlarging the buffer) using tail recursion, so that the
** sqlite3StrAccumAppend() routine can use fast calling semantics.
*/
static void enlargeAndAppend(StrAccum *p, const char *z, int N){
  N = sqlite3StrAccumEnlarge(p, N);
  if( N>0 ){
    memcpy(&p->zText[p->nChar], z, N);
    p->nChar += N;
  }
}

/*
** Append N bytes of text from z to the StrAccum object.  Increase the
** size of the memory allocation for StrAccum if necessary.
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
  assert( z!=0 );
  assert( p->zText!=0 || p->nChar==0 || p->accError );
  assert( N>=0 );
  assert( p->accError==0 || p->nAlloc==0 );
  if( p->nChar+N >= p->nAlloc ){
    enlargeAndAppend(p,z,N);



    return;
































  }
  assert( p->zText );
  memcpy(&p->zText[p->nChar], z, N);
  p->nChar += N;
}

/*
23326
23327
23328
23329
23330
23331
23332
23333
23334
23335
23336
23337
23338
23339
23340
     /*   7 */ "NextIfOpen"       OpHelp(""),
     /*   8 */ "Prev"             OpHelp(""),
     /*   9 */ "Next"             OpHelp(""),
     /*  10 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
     /*  11 */ "Checkpoint"       OpHelp(""),
     /*  12 */ "JournalMode"      OpHelp(""),
     /*  13 */ "Vacuum"           OpHelp(""),
     /*  14 */ "VFilter"          OpHelp("iPlan=r[P3] zPlan='P4'"),
     /*  15 */ "VUpdate"          OpHelp("data=r[P3@P2]"),
     /*  16 */ "Goto"             OpHelp(""),
     /*  17 */ "Gosub"            OpHelp(""),
     /*  18 */ "Return"           OpHelp(""),
     /*  19 */ "Not"              OpHelp("r[P2]= !r[P1]"),
     /*  20 */ "InitCoroutine"    OpHelp(""),
     /*  21 */ "EndCoroutine"     OpHelp(""),







|







23359
23360
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373
     /*   7 */ "NextIfOpen"       OpHelp(""),
     /*   8 */ "Prev"             OpHelp(""),
     /*   9 */ "Next"             OpHelp(""),
     /*  10 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
     /*  11 */ "Checkpoint"       OpHelp(""),
     /*  12 */ "JournalMode"      OpHelp(""),
     /*  13 */ "Vacuum"           OpHelp(""),
     /*  14 */ "VFilter"          OpHelp("iplan=r[P3] zplan='P4'"),
     /*  15 */ "VUpdate"          OpHelp("data=r[P3@P2]"),
     /*  16 */ "Goto"             OpHelp(""),
     /*  17 */ "Gosub"            OpHelp(""),
     /*  18 */ "Return"           OpHelp(""),
     /*  19 */ "Not"              OpHelp("r[P2]= !r[P1]"),
     /*  20 */ "InitCoroutine"    OpHelp(""),
     /*  21 */ "EndCoroutine"     OpHelp(""),
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
23365
23366
23367
     /*  34 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
     /*  35 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
     /*  36 */ "CollSeq"          OpHelp(""),
     /*  37 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
     /*  38 */ "MustBeInt"        OpHelp(""),
     /*  39 */ "RealAffinity"     OpHelp(""),
     /*  40 */ "Permutation"      OpHelp(""),
     /*  41 */ "Compare"          OpHelp(""),
     /*  42 */ "Jump"             OpHelp(""),
     /*  43 */ "Once"             OpHelp(""),
     /*  44 */ "If"               OpHelp(""),
     /*  45 */ "IfNot"            OpHelp(""),
     /*  46 */ "Column"           OpHelp("r[P3]=PX"),
     /*  47 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
     /*  48 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),







|







23386
23387
23388
23389
23390
23391
23392
23393
23394
23395
23396
23397
23398
23399
23400
     /*  34 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
     /*  35 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
     /*  36 */ "CollSeq"          OpHelp(""),
     /*  37 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
     /*  38 */ "MustBeInt"        OpHelp(""),
     /*  39 */ "RealAffinity"     OpHelp(""),
     /*  40 */ "Permutation"      OpHelp(""),
     /*  41 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),
     /*  42 */ "Jump"             OpHelp(""),
     /*  43 */ "Once"             OpHelp(""),
     /*  44 */ "If"               OpHelp(""),
     /*  45 */ "IfNot"            OpHelp(""),
     /*  46 */ "Column"           OpHelp("r[P3]=PX"),
     /*  47 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
     /*  48 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),
23380
23381
23382
23383
23384
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394
     /*  61 */ "SeekGE"           OpHelp(""),
     /*  62 */ "SeekGT"           OpHelp(""),
     /*  63 */ "Seek"             OpHelp("intkey=r[P2]"),
     /*  64 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
     /*  65 */ "NotFound"         OpHelp("key=r[P3@P4]"),
     /*  66 */ "Found"            OpHelp("key=r[P3@P4]"),
     /*  67 */ "NotExists"        OpHelp("intkey=r[P3]"),
     /*  68 */ "Sequence"         OpHelp("r[P2]=rowid"),
     /*  69 */ "NewRowid"         OpHelp("r[P2]=rowid"),
     /*  70 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
     /*  71 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
     /*  72 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
     /*  73 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
     /*  74 */ "Delete"           OpHelp(""),
     /*  75 */ "ResetCount"       OpHelp(""),







|







23413
23414
23415
23416
23417
23418
23419
23420
23421
23422
23423
23424
23425
23426
23427
     /*  61 */ "SeekGE"           OpHelp(""),
     /*  62 */ "SeekGT"           OpHelp(""),
     /*  63 */ "Seek"             OpHelp("intkey=r[P2]"),
     /*  64 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
     /*  65 */ "NotFound"         OpHelp("key=r[P3@P4]"),
     /*  66 */ "Found"            OpHelp("key=r[P3@P4]"),
     /*  67 */ "NotExists"        OpHelp("intkey=r[P3]"),
     /*  68 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
     /*  69 */ "NewRowid"         OpHelp("r[P2]=rowid"),
     /*  70 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
     /*  71 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
     /*  72 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
     /*  73 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
     /*  74 */ "Delete"           OpHelp(""),
     /*  75 */ "ResetCount"       OpHelp(""),
23428
23429
23430
23431
23432
23433
23434

23435
23436
23437
23438
23439
23440
23441
23442
23443
23444
23445
23446
23447
23448
23449
23450
23451
23452

23453
23454
23455
23456
23457
23458
23459
23460
23461
23462
23463
23464
23465
23466

23467
23468
23469
23470
23471
23472
23473
23474
23475
23476
23477
23478
23479
23480
23481
23482
     /* 109 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
     /* 110 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
     /* 111 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
     /* 112 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
     /* 113 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
     /* 114 */ "Destroy"          OpHelp(""),
     /* 115 */ "Clear"            OpHelp(""),

     /* 116 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
     /* 117 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
     /* 118 */ "ParseSchema"      OpHelp(""),
     /* 119 */ "LoadAnalysis"     OpHelp(""),
     /* 120 */ "DropTable"        OpHelp(""),
     /* 121 */ "DropIndex"        OpHelp(""),
     /* 122 */ "DropTrigger"      OpHelp(""),
     /* 123 */ "IntegrityCk"      OpHelp(""),
     /* 124 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
     /* 125 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
     /* 126 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
     /* 127 */ "Program"          OpHelp(""),
     /* 128 */ "Param"            OpHelp(""),
     /* 129 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
     /* 130 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
     /* 131 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
     /* 132 */ "IfPos"            OpHelp("if r[P1]>0 goto P2"),
     /* 133 */ "Real"             OpHelp("r[P2]=P4"),

     /* 134 */ "IfNeg"            OpHelp("if r[P1]<0 goto P2"),
     /* 135 */ "IfZero"           OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
     /* 136 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
     /* 137 */ "IncrVacuum"       OpHelp(""),
     /* 138 */ "Expire"           OpHelp(""),
     /* 139 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
     /* 140 */ "VBegin"           OpHelp(""),
     /* 141 */ "VCreate"          OpHelp(""),
     /* 142 */ "VDestroy"         OpHelp(""),
     /* 143 */ "ToText"           OpHelp(""),
     /* 144 */ "ToBlob"           OpHelp(""),
     /* 145 */ "ToNumeric"        OpHelp(""),
     /* 146 */ "ToInt"            OpHelp(""),
     /* 147 */ "ToReal"           OpHelp(""),

     /* 148 */ "VOpen"            OpHelp(""),
     /* 149 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
     /* 150 */ "VNext"            OpHelp(""),
     /* 151 */ "VRename"          OpHelp(""),
     /* 152 */ "Pagecount"        OpHelp(""),
     /* 153 */ "MaxPgcnt"         OpHelp(""),
     /* 154 */ "Init"             OpHelp("Start at P2"),
     /* 155 */ "Noop"             OpHelp(""),
     /* 156 */ "Explain"          OpHelp(""),
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/







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

>
|
|
|
|
|
|
|
|
<





>
|
|
|
|
|
|
|
|
|







23461
23462
23463
23464
23465
23466
23467
23468
23469
23470
23471
23472
23473
23474
23475
23476
23477
23478
23479
23480
23481
23482
23483
23484

23485
23486
23487
23488
23489
23490
23491
23492
23493
23494

23495
23496
23497
23498
23499
23500
23501
23502
23503
23504
23505
23506
23507
23508
23509
23510
23511
23512
23513
23514
23515
23516
     /* 109 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
     /* 110 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
     /* 111 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
     /* 112 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
     /* 113 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
     /* 114 */ "Destroy"          OpHelp(""),
     /* 115 */ "Clear"            OpHelp(""),
     /* 116 */ "ResetSorter"      OpHelp(""),
     /* 117 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
     /* 118 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
     /* 119 */ "ParseSchema"      OpHelp(""),
     /* 120 */ "LoadAnalysis"     OpHelp(""),
     /* 121 */ "DropTable"        OpHelp(""),
     /* 122 */ "DropIndex"        OpHelp(""),
     /* 123 */ "DropTrigger"      OpHelp(""),
     /* 124 */ "IntegrityCk"      OpHelp(""),
     /* 125 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
     /* 126 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
     /* 127 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
     /* 128 */ "Program"          OpHelp(""),
     /* 129 */ "Param"            OpHelp(""),
     /* 130 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
     /* 131 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
     /* 132 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),

     /* 133 */ "Real"             OpHelp("r[P2]=P4"),
     /* 134 */ "IfPos"            OpHelp("if r[P1]>0 goto P2"),
     /* 135 */ "IfNeg"            OpHelp("if r[P1]<0 goto P2"),
     /* 136 */ "IfZero"           OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
     /* 137 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
     /* 138 */ "IncrVacuum"       OpHelp(""),
     /* 139 */ "Expire"           OpHelp(""),
     /* 140 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
     /* 141 */ "VBegin"           OpHelp(""),
     /* 142 */ "VCreate"          OpHelp(""),

     /* 143 */ "ToText"           OpHelp(""),
     /* 144 */ "ToBlob"           OpHelp(""),
     /* 145 */ "ToNumeric"        OpHelp(""),
     /* 146 */ "ToInt"            OpHelp(""),
     /* 147 */ "ToReal"           OpHelp(""),
     /* 148 */ "VDestroy"         OpHelp(""),
     /* 149 */ "VOpen"            OpHelp(""),
     /* 150 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
     /* 151 */ "VNext"            OpHelp(""),
     /* 152 */ "VRename"          OpHelp(""),
     /* 153 */ "Pagecount"        OpHelp(""),
     /* 154 */ "MaxPgcnt"         OpHelp(""),
     /* 155 */ "Init"             OpHelp("Start at P2"),
     /* 156 */ "Noop"             OpHelp(""),
     /* 157 */ "Explain"          OpHelp(""),
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file os_unix.c *****************************************/
24008
24009
24010
24011
24012
24013
24014

24015
24016
24017
24018
24019
24020
24021
*/
static int posixFchown(int fd, uid_t uid, gid_t gid){
  return geteuid() ? 0 : fchown(fd,uid,gid);
}

/* Forward reference */
static int openDirectory(const char*, int*);


/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
** testing and sandboxing.  The following array holds the names and pointers
** to all overrideable system calls.
*/







>







24042
24043
24044
24045
24046
24047
24048
24049
24050
24051
24052
24053
24054
24055
24056
*/
static int posixFchown(int fd, uid_t uid, gid_t gid){
  return geteuid() ? 0 : fchown(fd,uid,gid);
}

/* Forward reference */
static int openDirectory(const char*, int*);
static int unixGetpagesize(void);

/*
** Many system calls are accessed through pointer-to-functions so that
** they may be overridden at runtime to facilitate fault injection during
** testing and sandboxing.  The following array holds the names and pointers
** to all overrideable system calls.
*/
24130
24131
24132
24133
24134
24135
24136



24137
24138
24139
24140
24141
24142
24143
#if HAVE_MREMAP
  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
#else
  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
#endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
#endif




}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable







>
>
>







24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175
24176
24177
24178
24179
24180
24181
#if HAVE_MREMAP
  { "mremap",       (sqlite3_syscall_ptr)mremap,          0 },
#else
  { "mremap",       (sqlite3_syscall_ptr)0,               0 },
#endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
#endif

  { "getpagesize",  (sqlite3_syscall_ptr)unixGetpagesize, 0 },
#define osGetpagesize ((int(*)(void))aSyscall[24].pCurrent)

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
27790
27791
27792
27793
27794
27795
27796






























27797
27798
27799
27800
27801
27802
27803
27804
27805
27806
27807

27808
27809
27810
27811
27812
27813
27814
27815
27816
27817
27818
           pShmNode->sharedMask, pShmNode->exclMask));
  }
#endif

  return rc;        
}
































/*
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static void unixShmPurge(unixFile *pFd){
  unixShmNode *p = pFd->pInode->pShmNode;
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){

    int i;
    assert( p->pInode==pFd->pInode );
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i++){
      if( p->h>=0 ){
        osMunmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }
    sqlite3_free(p->apRegion);







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











>



|







27828
27829
27830
27831
27832
27833
27834
27835
27836
27837
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847
27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862
27863
27864
27865
27866
27867
27868
27869
27870
27871
27872
27873
27874
27875
27876
27877
27878
27879
27880
27881
27882
27883
27884
27885
27886
27887
           pShmNode->sharedMask, pShmNode->exclMask));
  }
#endif

  return rc;        
}

/*
** Return the system page size.
**
** This function should not be called directly by other code in this file. 
** Instead, it should be called via macro osGetpagesize().
*/
static int unixGetpagesize(void){
#if defined(_BSD_SOURCE)
  return getpagesize();
#else
  return (int)sysconf(_SC_PAGESIZE);
#endif
}

/*
** Return the minimum number of 32KB shm regions that should be mapped at
** a time, assuming that each mapping must be an integer multiple of the
** current system page-size.
**
** Usually, this is 1. The exception seems to be systems that are configured
** to use 64KB pages - in this case each mapping must cover at least two
** shm regions.
*/
static int unixShmRegionPerMap(void){
  int shmsz = 32*1024;            /* SHM region size */
  int pgsz = osGetpagesize();   /* System page size */
  assert( ((pgsz-1)&pgsz)==0 );   /* Page size must be a power of 2 */
  if( pgsz<shmsz ) return 1;
  return pgsz/shmsz;
}

/*
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
*/
static void unixShmPurge(unixFile *pFd){
  unixShmNode *p = pFd->pInode->pShmNode;
  assert( unixMutexHeld() );
  if( p && p->nRef==0 ){
    int nShmPerMap = unixShmRegionPerMap();
    int i;
    assert( p->pInode==pFd->pInode );
    sqlite3_mutex_free(p->mutex);
    for(i=0; i<p->nRegion; i+=nShmPerMap){
      if( p->h>=0 ){
        osMunmap(p->apRegion[i], p->szRegion);
      }else{
        sqlite3_free(p->apRegion[i]);
      }
    }
    sqlite3_free(p->apRegion);
28011
28012
28013
28014
28015
28016
28017


28018
28019
28020
28021
28022
28023
28024
28025
28026
28027
28028
28029
28030
28031
28032



28033
28034
28035
28036
28037
28038
28039
28040
28041
28042
  int bExtend,                    /* True to extend file if necessary */
  void volatile **pp              /* OUT: Mapped memory */
){
  unixFile *pDbFd = (unixFile*)fd;
  unixShm *p;
  unixShmNode *pShmNode;
  int rc = SQLITE_OK;



  /* If the shared-memory file has not yet been opened, open it now. */
  if( pDbFd->pShm==0 ){
    rc = unixOpenSharedMemory(pDbFd);
    if( rc!=SQLITE_OK ) return rc;
  }

  p = pDbFd->pShm;
  pShmNode = p->pShmNode;
  sqlite3_mutex_enter(pShmNode->mutex);
  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
  assert( pShmNode->pInode==pDbFd->pInode );
  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );




  if( pShmNode->nRegion<=iRegion ){
    char **apNew;                      /* New apRegion[] array */
    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
    struct stat sStat;                 /* Used by fstat() */

    pShmNode->szRegion = szRegion;

    if( pShmNode->h>=0 ){
      /* The requested region is not mapped into this processes address space.
      ** Check to see if it has been allocated (i.e. if the wal-index file is







>
>















>
>
>
|

|







28080
28081
28082
28083
28084
28085
28086
28087
28088
28089
28090
28091
28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109
28110
28111
28112
28113
28114
28115
28116
  int bExtend,                    /* True to extend file if necessary */
  void volatile **pp              /* OUT: Mapped memory */
){
  unixFile *pDbFd = (unixFile*)fd;
  unixShm *p;
  unixShmNode *pShmNode;
  int rc = SQLITE_OK;
  int nShmPerMap = unixShmRegionPerMap();
  int nReqRegion;

  /* If the shared-memory file has not yet been opened, open it now. */
  if( pDbFd->pShm==0 ){
    rc = unixOpenSharedMemory(pDbFd);
    if( rc!=SQLITE_OK ) return rc;
  }

  p = pDbFd->pShm;
  pShmNode = p->pShmNode;
  sqlite3_mutex_enter(pShmNode->mutex);
  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
  assert( pShmNode->pInode==pDbFd->pInode );
  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );

  /* Minimum number of regions required to be mapped. */
  nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;

  if( pShmNode->nRegion<nReqRegion ){
    char **apNew;                      /* New apRegion[] array */
    int nByte = nReqRegion*szRegion;   /* Minimum required file size */
    struct stat sStat;                 /* Used by fstat() */

    pShmNode->szRegion = szRegion;

    if( pShmNode->h>=0 ){
      /* The requested region is not mapped into this processes address space.
      ** Check to see if it has been allocated (i.e. if the wal-index file is
28077
28078
28079
28080
28081
28082
28083
28084
28085
28086
28087
28088
28089
28090
28091


28092
28093
28094
28095
28096
28097
28098
28099
28100
28101
28102
28103
28104
28105
28106
28107
28108
28109


28110

28111
28112
28113
28114
28115
28116
28117
28118
          }
        }
      }
    }

    /* Map the requested memory region into this processes address space. */
    apNew = (char **)sqlite3_realloc(
        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
    );
    if( !apNew ){
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while(pShmNode->nRegion<=iRegion){


      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = osMmap(0, szRegion,
            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
      }else{
        pMem = sqlite3_malloc(szRegion);
        if( pMem==0 ){
          rc = SQLITE_NOMEM;
          goto shmpage_out;
        }
        memset(pMem, 0, szRegion);
      }


      pShmNode->apRegion[pShmNode->nRegion] = pMem;

      pShmNode->nRegion++;
    }
  }

shmpage_out:
  if( pShmNode->nRegion>iRegion ){
    *pp = pShmNode->apRegion[iRegion];
  }else{







|






|
>
>


|















>
>
|
>
|







28151
28152
28153
28154
28155
28156
28157
28158
28159
28160
28161
28162
28163
28164
28165
28166
28167
28168
28169
28170
28171
28172
28173
28174
28175
28176
28177
28178
28179
28180
28181
28182
28183
28184
28185
28186
28187
28188
28189
28190
28191
28192
28193
28194
28195
28196
28197
          }
        }
      }
    }

    /* Map the requested memory region into this processes address space. */
    apNew = (char **)sqlite3_realloc(
        pShmNode->apRegion, nReqRegion*sizeof(char *)
    );
    if( !apNew ){
      rc = SQLITE_IOERR_NOMEM;
      goto shmpage_out;
    }
    pShmNode->apRegion = apNew;
    while( pShmNode->nRegion<nReqRegion ){
      int nMap = szRegion*nShmPerMap;
      int i;
      void *pMem;
      if( pShmNode->h>=0 ){
        pMem = osMmap(0, nMap,
            pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, 
            MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
        );
        if( pMem==MAP_FAILED ){
          rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
          goto shmpage_out;
        }
      }else{
        pMem = sqlite3_malloc(szRegion);
        if( pMem==0 ){
          rc = SQLITE_NOMEM;
          goto shmpage_out;
        }
        memset(pMem, 0, szRegion);
      }

      for(i=0; i<nShmPerMap; i++){
        pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
      }
      pShmNode->nRegion += nShmPerMap;
    }
  }

shmpage_out:
  if( pShmNode->nRegion>iRegion ){
    *pp = pShmNode->apRegion[iRegion];
  }else{
28318
28319
28320
28321
28322
28323
28324
28325
28326
28327
28328
28329
28330
28331
28332
28333
28334
28335
28336
28337
28338
28339
28340
28341
28342
28343
28344
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
}

/*
** Return the system page size.
*/
static int unixGetPagesize(void){
#if HAVE_MREMAP
  return 512;
#elif defined(_BSD_SOURCE)
  return getpagesize();
#else
  return (int)sysconf(_SC_PAGESIZE);
#endif
}

/*
** Attempt to set the size of the memory mapping maintained by file 
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
**
**       unixFile.pMapRegion







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







28397
28398
28399
28400
28401
28402
28403













28404
28405
28406
28407
28408
28409
28410
    osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
    pFd->pMapRegion = 0;
    pFd->mmapSize = 0;
    pFd->mmapSizeActual = 0;
  }
}














/*
** Attempt to set the size of the memory mapping maintained by file 
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
**
** If successful, this function sets the following variables:
**
**       unixFile.pMapRegion
28367
28368
28369
28370
28371
28372
28373



28374
28375

28376
28377
28378
28379
28380
28381
28382
  assert( nNew>0 );
  assert( pFd->mmapSizeActual>=pFd->mmapSize );
  assert( MAP_FAILED!=0 );

  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;

  if( pOrig ){



    const int szSyspage = unixGetPagesize();
    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));

    u8 *pReq = &pOrig[nReuse];

    /* Unmap any pages of the existing mapping that cannot be reused. */
    if( nReuse!=nOrig ){
      osMunmap(pReq, nOrig-nReuse);
    }








>
>
>
|

>







28433
28434
28435
28436
28437
28438
28439
28440
28441
28442
28443
28444
28445
28446
28447
28448
28449
28450
28451
28452
  assert( nNew>0 );
  assert( pFd->mmapSizeActual>=pFd->mmapSize );
  assert( MAP_FAILED!=0 );

  if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;

  if( pOrig ){
#if HAVE_MREMAP
    i64 nReuse = pFd->mmapSize;
#else
    const int szSyspage = osGetpagesize();
    i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
#endif
    u8 *pReq = &pOrig[nReuse];

    /* Unmap any pages of the existing mapping that cannot be reused. */
    if( nReuse!=nOrig ){
      osMunmap(pReq, nOrig-nReuse);
    }

31114
31115
31116
31117
31118
31119
31120
31121
31122
31123
31124
31125
31126
31127
31128
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==24 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}







|







31184
31185
31186
31187
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
    UNIXVFS("unix-proxy",    proxyIoFinder ),
#endif
  };
  unsigned int i;          /* Loop counter */

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==25 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  return SQLITE_OK; 
}
38995
38996
38997
38998
38999
39000
39001
39002
39003
39004
39005
39006
39007
39008
39009
39010
  struct RowSetChunk *pChunk;    /* List of all chunk allocations */
  sqlite3 *db;                   /* The database connection */
  struct RowSetEntry *pEntry;    /* List of entries using pRight */
  struct RowSetEntry *pLast;     /* Last entry on the pEntry list */
  struct RowSetEntry *pFresh;    /* Source of new entry objects */
  struct RowSetEntry *pForest;   /* List of binary trees of entries */
  u16 nFresh;                    /* Number of objects on pFresh */
  u8 rsFlags;                    /* Various flags */
  u8 iBatch;                     /* Current insert batch */
};

/*
** Allowed values for RowSet.rsFlags
*/
#define ROWSET_SORTED  0x01   /* True if RowSet.pEntry is sorted */
#define ROWSET_NEXT    0x02   /* True if sqlite3RowSetNext() has been called */







|
|







39065
39066
39067
39068
39069
39070
39071
39072
39073
39074
39075
39076
39077
39078
39079
39080
  struct RowSetChunk *pChunk;    /* List of all chunk allocations */
  sqlite3 *db;                   /* The database connection */
  struct RowSetEntry *pEntry;    /* List of entries using pRight */
  struct RowSetEntry *pLast;     /* Last entry on the pEntry list */
  struct RowSetEntry *pFresh;    /* Source of new entry objects */
  struct RowSetEntry *pForest;   /* List of binary trees of entries */
  u16 nFresh;                    /* Number of objects on pFresh */
  u16 rsFlags;                   /* Various flags */
  int iBatch;                    /* Current insert batch */
};

/*
** Allowed values for RowSet.rsFlags
*/
#define ROWSET_SORTED  0x01   /* True if RowSet.pEntry is sorted */
#define ROWSET_NEXT    0x02   /* True if sqlite3RowSetNext() has been called */
39330
39331
39332
39333
39334
39335
39336
39337
39338
39339
39340
39341
39342
39343
39344
** Check to see if element iRowid was inserted into the rowset as
** part of any insert batch prior to iBatch.  Return 1 or 0.
**
** If this is the first test of a new batch and if there exist entires
** on pRowSet->pEntry, then sort those entires into the forest at
** pRowSet->pForest so that they can be tested.
*/
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
  struct RowSetEntry *p, *pTree;

  /* This routine is never called after sqlite3RowSetNext() */
  assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );

  /* Sort entries into the forest on the first test of a new batch 
  */







|







39400
39401
39402
39403
39404
39405
39406
39407
39408
39409
39410
39411
39412
39413
39414
** Check to see if element iRowid was inserted into the rowset as
** part of any insert batch prior to iBatch.  Return 1 or 0.
**
** If this is the first test of a new batch and if there exist entires
** on pRowSet->pEntry, then sort those entires into the forest at
** pRowSet->pForest so that they can be tested.
*/
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
  struct RowSetEntry *p, *pTree;

  /* This routine is never called after sqlite3RowSetNext() */
  assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );

  /* Sort entries into the forest on the first test of a new batch 
  */
41157
41158
41159
41160
41161
41162
41163
41164
41165
41166
41167
41168
41169
41170
41171
41172
41173
41174
41175
41176
  u32 cksum = 0;                   /* Checksum of string zMaster */

  assert( pPager->setMaster==0 );
  assert( !pagerUseWal(pPager) );

  if( !zMaster 
   || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
   || pPager->journalMode==PAGER_JOURNALMODE_OFF 
  ){
    return SQLITE_OK;
  }
  pPager->setMaster = 1;
  assert( isOpen(pPager->jfd) );
  assert( pPager->journalHdr <= pPager->journalOff );

  /* Calculate the length in bytes and the checksum of zMaster */
  for(nMaster=0; zMaster[nMaster]; nMaster++){
    cksum += zMaster[nMaster];
  }








|




<







41227
41228
41229
41230
41231
41232
41233
41234
41235
41236
41237
41238

41239
41240
41241
41242
41243
41244
41245
  u32 cksum = 0;                   /* Checksum of string zMaster */

  assert( pPager->setMaster==0 );
  assert( !pagerUseWal(pPager) );

  if( !zMaster 
   || pPager->journalMode==PAGER_JOURNALMODE_MEMORY 
   || !isOpen(pPager->jfd)
  ){
    return SQLITE_OK;
  }
  pPager->setMaster = 1;

  assert( pPager->journalHdr <= pPager->journalOff );

  /* Calculate the length in bytes and the checksum of zMaster */
  for(nMaster=0; zMaster[nMaster]; nMaster++){
    cksum += zMaster[nMaster];
  }

50369
50370
50371
50372
50373
50374
50375
50376
50377
50378
50379
50380
50381
50382


50383
50384
50385
50386
50387
50388
50389
50390
50391
50392
50393
50394
50395
50396









50397
50398
50399
50400
50401
50402
50403
** found at self->pBt->mutex. 
*/
struct BtCursor {
  Btree *pBtree;            /* The Btree to which this cursor belongs */
  BtShared *pBt;            /* The BtShared this cursor points to */
  BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
#ifndef SQLITE_OMIT_INCRBLOB
  Pgno *aOverflow;          /* Cache of overflow page locations */
#endif
  Pgno pgnoRoot;            /* The root page of this tree */
  CellInfo info;            /* A parse of the cell we are pointing at */
  i64 nKey;        /* Size of pKey, or last integer key */
  void *pKey;      /* Saved key that was cursor's last known position */


  int skipNext;    /* Prev() is noop if negative. Next() is noop if positive */
  u8 wrFlag;                /* True if writable */
  u8 atLast;                /* Cursor pointing to the last entry */
  u8 validNKey;             /* True if info.nKey is valid */
  u8 eState;                /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB
  u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
#endif
  u8 hints;                             /* As configured by CursorSetHints() */
  i16 iPage;                            /* Index of current page in apPage */
  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
};










/*
** Potential values for BtCursor.eState.
**
** CURSOR_INVALID:
**   Cursor does not point to a valid entry. This can happen (for example) 
**   because the table is empty or because BtreeCursorFirst() has not been
**   called.







<

<
<

|
|
>
>

|
<
<

<
<
<






>
>
>
>
>
>
>
>
>







50438
50439
50440
50441
50442
50443
50444

50445


50446
50447
50448
50449
50450
50451
50452


50453



50454
50455
50456
50457
50458
50459
50460
50461
50462
50463
50464
50465
50466
50467
50468
50469
50470
50471
50472
50473
50474
50475
** found at self->pBt->mutex. 
*/
struct BtCursor {
  Btree *pBtree;            /* The Btree to which this cursor belongs */
  BtShared *pBt;            /* The BtShared this cursor points to */
  BtCursor *pNext, *pPrev;  /* Forms a linked list of all cursors */
  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */

  Pgno *aOverflow;          /* Cache of overflow page locations */


  CellInfo info;            /* A parse of the cell we are pointing at */
  i64 nKey;                 /* Size of pKey, or last integer key */
  void *pKey;               /* Saved key that was cursor last known position */
  Pgno pgnoRoot;            /* The root page of this tree */
  int nOvflAlloc;           /* Allocated size of aOverflow[] array */
  int skipNext;    /* Prev() is noop if negative. Next() is noop if positive */
  u8 curFlags;              /* zero or more BTCF_* flags defined below */


  u8 eState;                /* One of the CURSOR_XXX constants (see below) */



  u8 hints;                             /* As configured by CursorSetHints() */
  i16 iPage;                            /* Index of current page in apPage */
  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
};

/*
** Legal values for BtCursor.curFlags
*/
#define BTCF_WriteFlag    0x01   /* True if a write cursor */
#define BTCF_ValidNKey    0x02   /* True if info.nKey is valid */
#define BTCF_ValidOvfl    0x04   /* True if aOverflow is valid */
#define BTCF_AtLast       0x08   /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob     0x10   /* True if an incremental I/O handle */

/*
** Potential values for BtCursor.eState.
**
** CURSOR_INVALID:
**   Cursor does not point to a valid entry. This can happen (for example) 
**   because the table is empty or because BtreeCursorFirst() has not been
**   called.
51260
51261
51262
51263
51264
51265
51266
51267
51268
51269
51270

51271
51272
51273
51274
51275
51276
51277
51278
51279
51280
51281
51282
51283
51284
51285
51286
51287
51288
51289

51290
51291
51292
51293
51294
51295
51296
*/
#ifdef SQLITE_DEBUG
static int cursorHoldsMutex(BtCursor *p){
  return sqlite3_mutex_held(p->pBt->mutex);
}
#endif


#ifndef SQLITE_OMIT_INCRBLOB
/*
** Invalidate the overflow page-list cache for cursor pCur, if any.

*/
static void invalidateOverflowCache(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  sqlite3_free(pCur->aOverflow);
  pCur->aOverflow = 0;
}

/*
** Invalidate the overflow page-list cache for all cursors opened
** on the shared btree structure pBt.
*/
static void invalidateAllOverflowCache(BtShared *pBt){
  BtCursor *p;
  assert( sqlite3_mutex_held(pBt->mutex) );
  for(p=pBt->pCursor; p; p=p->pNext){
    invalidateOverflowCache(p);
  }
}


/*
** This function is called before modifying the contents of a table
** to invalidate any incrblob cursors that are open on the
** row or one of the rows being modified.
**
** If argument isClearTable is true, then the entire contents of the
** table is about to be deleted. In this case invalidate all incrblob







<
<

|
>

|
<
<
<
<













>







51332
51333
51334
51335
51336
51337
51338


51339
51340
51341
51342
51343




51344
51345
51346
51347
51348
51349
51350
51351
51352
51353
51354
51355
51356
51357
51358
51359
51360
51361
51362
51363
51364
*/
#ifdef SQLITE_DEBUG
static int cursorHoldsMutex(BtCursor *p){
  return sqlite3_mutex_held(p->pBt->mutex);
}
#endif



/*
** Invalidate the overflow cache of the cursor passed as the first argument.
** on the shared btree structure pBt.
*/
#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)





/*
** Invalidate the overflow page-list cache for all cursors opened
** on the shared btree structure pBt.
*/
static void invalidateAllOverflowCache(BtShared *pBt){
  BtCursor *p;
  assert( sqlite3_mutex_held(pBt->mutex) );
  for(p=pBt->pCursor; p; p=p->pNext){
    invalidateOverflowCache(p);
  }
}

#ifndef SQLITE_OMIT_INCRBLOB
/*
** This function is called before modifying the contents of a table
** to invalidate any incrblob cursors that are open on the
** row or one of the rows being modified.
**
** If argument isClearTable is true, then the entire contents of the
** table is about to be deleted. In this case invalidate all incrblob
51305
51306
51307
51308
51309
51310
51311
51312
51313
51314
51315
51316
51317
51318
51319
51320
51321
51322
51323
51324
51325
51326
51327
51328
  i64 iRow,               /* The rowid that might be changing */
  int isClearTable        /* True if all rows are being deleted */
){
  BtCursor *p;
  BtShared *pBt = pBtree->pBt;
  assert( sqlite3BtreeHoldsMutex(pBtree) );
  for(p=pBt->pCursor; p; p=p->pNext){
    if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){
      p->eState = CURSOR_INVALID;
    }
  }
}

#else
  /* Stub functions when INCRBLOB is omitted */
  #define invalidateOverflowCache(x)
  #define invalidateAllOverflowCache(x)
  #define invalidateIncrblobCursors(x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */

/*
** Set bit pgno of the BtShared.pHasContent bitvec. This is called 
** when a page that previously contained data becomes a free-list leaf 
** page.







|






|
<
<







51373
51374
51375
51376
51377
51378
51379
51380
51381
51382
51383
51384
51385
51386
51387


51388
51389
51390
51391
51392
51393
51394
  i64 iRow,               /* The rowid that might be changing */
  int isClearTable        /* True if all rows are being deleted */
){
  BtCursor *p;
  BtShared *pBt = pBtree->pBt;
  assert( sqlite3BtreeHoldsMutex(pBtree) );
  for(p=pBt->pCursor; p; p=p->pNext){
    if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){
      p->eState = CURSOR_INVALID;
    }
  }
}

#else
  /* Stub function when INCRBLOB is omitted */


  #define invalidateIncrblobCursors(x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */

/*
** Set bit pgno of the BtShared.pHasContent bitvec. This is called 
** when a page that previously contained data becomes a free-list leaf 
** page.
51560
51561
51562
51563
51564
51565
51566
51567








51568
51569
51570
51571




51572
51573
51574
51575
51576
51577
51578
51579
51580
51581
51582
51583
51584
51585
51586
51587

/*
** Determine whether or not a cursor has moved from the position it
** was last placed at.  Cursors can move when the row they are pointing
** at is deleted out from under them.
**
** This routine returns an error code if something goes wrong.  The
** integer *pHasMoved is set to one if the cursor has moved and 0 if not.








*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
  int rc;





  rc = restoreCursorPosition(pCur);
  if( rc ){
    *pHasMoved = 1;
    return rc;
  }
  if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
    *pHasMoved = 1;
  }else{
    *pHasMoved = 0;
  }
  return SQLITE_OK;
}

#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Given a page number of a regular database page, return the page







|
>
>
>
>
>
>
>
>




>
>
>
>


|



|

|







51626
51627
51628
51629
51630
51631
51632
51633
51634
51635
51636
51637
51638
51639
51640
51641
51642
51643
51644
51645
51646
51647
51648
51649
51650
51651
51652
51653
51654
51655
51656
51657
51658
51659
51660
51661
51662
51663
51664
51665

/*
** Determine whether or not a cursor has moved from the position it
** was last placed at.  Cursors can move when the row they are pointing
** at is deleted out from under them.
**
** This routine returns an error code if something goes wrong.  The
** integer *pHasMoved is set as follows:
**
**    0:   The cursor is unchanged
**    1:   The cursor is still pointing at the same row, but the pointers
**         returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch()
**         might now be invalid because of a balance() or other change to the
**         b-tree.
**    2:   The cursor is no longer pointing to the row.  The row might have
**         been deleted out from under the cursor.
*/
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
  int rc;

  if( pCur->eState==CURSOR_VALID ){
    *pHasMoved = 0;
    return SQLITE_OK;
  }
  rc = restoreCursorPosition(pCur);
  if( rc ){
    *pHasMoved = 2;
    return rc;
  }
  if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
    *pHasMoved = 2;
  }else{
    *pHasMoved = 1;
  }
  return SQLITE_OK;
}

#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Given a page number of a regular database page, return the page
52975
52976
52977
52978
52979
52980
52981

52982
52983
52984
52985
52986
52987
52988
52989
52990
52991
52992
52993

52994
52995
52996
52997
52998
52999
53000
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}


/*
** Change the limit on the amount of the database file that may be
** memory mapped.
*/
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}


/*
** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power
** failures.  Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage)  Level 2 is the default.  There
** is a very low but non-zero probability of damage.  Level 3 reduces the







>












>







53053
53054
53055
53056
53057
53058
53059
53060
53061
53062
53063
53064
53065
53066
53067
53068
53069
53070
53071
53072
53073
53074
53075
53076
53077
53078
53079
53080
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetCachesize(pBt->pPager, mxPage);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}

#if SQLITE_MAX_MMAP_SIZE>0
/*
** Change the limit on the amount of the database file that may be
** memory mapped.
*/
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
  BtShared *pBt = p->pBt;
  assert( sqlite3_mutex_held(p->db->mutex) );
  sqlite3BtreeEnter(p);
  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
  sqlite3BtreeLeave(p);
  return SQLITE_OK;
}
#endif /* SQLITE_MAX_MMAP_SIZE>0 */

/*
** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power
** failures.  Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage)  Level 2 is the default.  There
** is a very low but non-zero probability of damage.  Level 3 reduces the
53363
53364
53365
53366
53367
53368
53369

53370
53371
53372
53373
53374
53375
53376
53377
** is capable of reading or writing to the databse.  Cursors that
** have been tripped into the CURSOR_FAULT state are not counted.
*/
static int countValidCursors(BtShared *pBt, int wrOnly){
  BtCursor *pCur;
  int r = 0;
  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){

    if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; 
  }
  return r;
}
#endif

/*
** If there are no outstanding cursors and we are not in the middle







>
|







53443
53444
53445
53446
53447
53448
53449
53450
53451
53452
53453
53454
53455
53456
53457
53458
** is capable of reading or writing to the databse.  Cursors that
** have been tripped into the CURSOR_FAULT state are not counted.
*/
static int countValidCursors(BtShared *pBt, int wrOnly){
  BtCursor *pCur;
  int r = 0;
  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
    if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
     && pCur->eState!=CURSOR_FAULT ) r++; 
  }
  return r;
}
#endif

/*
** If there are no outstanding cursors and we are not in the middle
54438
54439
54440
54441
54442
54443
54444

54445
54446
54447
54448
54449
54450
54451
54452
  /* Now that no other errors can occur, finish filling in the BtCursor
  ** variables and link the cursor into the BtShared list.  */
  pCur->pgnoRoot = (Pgno)iTable;
  pCur->iPage = -1;
  pCur->pKeyInfo = pKeyInfo;
  pCur->pBtree = p;
  pCur->pBt = pBt;

  pCur->wrFlag = (u8)wrFlag;
  pCur->pNext = pBt->pCursor;
  if( pCur->pNext ){
    pCur->pNext->pPrev = pCur;
  }
  pBt->pCursor = pCur;
  pCur->eState = CURSOR_INVALID;
  return SQLITE_OK;







>
|







54519
54520
54521
54522
54523
54524
54525
54526
54527
54528
54529
54530
54531
54532
54533
54534
  /* Now that no other errors can occur, finish filling in the BtCursor
  ** variables and link the cursor into the BtShared list.  */
  pCur->pgnoRoot = (Pgno)iTable;
  pCur->iPage = -1;
  pCur->pKeyInfo = pKeyInfo;
  pCur->pBtree = p;
  pCur->pBt = pBt;
  assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
  pCur->curFlags = wrFlag;
  pCur->pNext = pBt->pCursor;
  if( pCur->pNext ){
    pCur->pNext->pPrev = pCur;
  }
  pBt->pCursor = pCur;
  pCur->eState = CURSOR_INVALID;
  return SQLITE_OK;
54508
54509
54510
54511
54512
54513
54514
54515
54516
54517
54518
54519
54520
54521
54522
    if( pCur->pNext ){
      pCur->pNext->pPrev = pCur->pPrev;
    }
    for(i=0; i<=pCur->iPage; i++){
      releasePage(pCur->apPage[i]);
    }
    unlockBtreeIfUnused(pBt);
    invalidateOverflowCache(pCur);
    /* sqlite3_free(pCur); */
    sqlite3BtreeLeave(pBtree);
  }
  return SQLITE_OK;
}

/*







|







54590
54591
54592
54593
54594
54595
54596
54597
54598
54599
54600
54601
54602
54603
54604
    if( pCur->pNext ){
      pCur->pNext->pPrev = pCur->pPrev;
    }
    for(i=0; i<=pCur->iPage; i++){
      releasePage(pCur->apPage[i]);
    }
    unlockBtreeIfUnused(pBt);
    sqlite3DbFree(pBtree->db, pCur->aOverflow);
    /* sqlite3_free(pCur); */
    sqlite3BtreeLeave(pBtree);
  }
  return SQLITE_OK;
}

/*
54547
54548
54549
54550
54551
54552
54553
54554
54555
54556
54557
54558
54559
54560
54561
54562
54563
54564
54565
54566
54567
54568
54569
54570
54571
54572
#endif
#ifdef _MSC_VER
  /* Use a real function in MSVC to work around bugs in that compiler. */
  static void getCellInfo(BtCursor *pCur){
    if( pCur->info.nSize==0 ){
      int iPage = pCur->iPage;
      btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
      pCur->validNKey = 1;
    }else{
      assertCellInfo(pCur);
    }
  }
#else /* if not _MSC_VER */
  /* Use a macro in all other compilers so that the function is inlined */
#define getCellInfo(pCur)                                                      \
  if( pCur->info.nSize==0 ){                                                   \
    int iPage = pCur->iPage;                                                   \
    btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
    pCur->validNKey = 1;                                                       \
  }else{                                                                       \
    assertCellInfo(pCur);                                                      \
  }
#endif /* _MSC_VER */

#ifndef NDEBUG  /* The next routine used only within assert() statements */
/*







|









|
|







54629
54630
54631
54632
54633
54634
54635
54636
54637
54638
54639
54640
54641
54642
54643
54644
54645
54646
54647
54648
54649
54650
54651
54652
54653
54654
#endif
#ifdef _MSC_VER
  /* Use a real function in MSVC to work around bugs in that compiler. */
  static void getCellInfo(BtCursor *pCur){
    if( pCur->info.nSize==0 ){
      int iPage = pCur->iPage;
      btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
      pCur->curFlags |= BTCF_ValidNKey;
    }else{
      assertCellInfo(pCur);
    }
  }
#else /* if not _MSC_VER */
  /* Use a macro in all other compilers so that the function is inlined */
#define getCellInfo(pCur)                                                      \
  if( pCur->info.nSize==0 ){                                                   \
    int iPage = pCur->iPage;                                                   \
    btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);        \
    pCur->curFlags |= BTCF_ValidNKey;                                          \
  }else{                                                                       \
    assertCellInfo(pCur);                                                      \
  }
#endif /* _MSC_VER */

#ifndef NDEBUG  /* The next routine used only within assert() statements */
/*
54729
54730
54731
54732
54733
54734
54735
54736
54737
54738
54739



54740
54741
54742
54743
54744
54745
54746
54747
54748

54749
54750
54751
54752
54753
54754
54755
54756
54757
54758
    memcpy(pBuf, pPayload, nByte);
  }
  return SQLITE_OK;
}

/*
** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. If the eOp
** parameter is 0, this is a read operation (data copied into
** buffer pBuf). If it is non-zero, a write (data copied from
** buffer pBuf).



**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
**
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the BtCursor.isIncrblobHandle flag is set, and the current
** cursor entry uses one or more overflow pages, this function

** allocates space for and lazily popluates the overflow page-list 
** cache array (BtCursor.aOverflow). Subsequent calls use this
** cache to make seeking to the supplied offset more efficient.
**
** Once an overflow page-list cache has been allocated, it may be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
**
**   * An incremental vacuum,







|
<
|
|
>
>
>







<
|
>
|
|
|







54811
54812
54813
54814
54815
54816
54817
54818

54819
54820
54821
54822
54823
54824
54825
54826
54827
54828
54829
54830

54831
54832
54833
54834
54835
54836
54837
54838
54839
54840
54841
54842
    memcpy(pBuf, pPayload, nByte);
  }
  return SQLITE_OK;
}

/*
** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. The eOp

** argument is interpreted as follows:
**
**   0: The operation is a read. Populate the overflow cache.
**   1: The operation is a write. Populate the overflow cache.
**   2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
**
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**

** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily 
** popluates the overflow page-list cache array (BtCursor.aOverflow). 
** Subsequent calls use this cache to make seeking to the supplied offset 
** more efficient.
**
** Once an overflow page-list cache has been allocated, it may be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
**
**   * An incremental vacuum,
54768
54769
54770
54771
54772
54773
54774



54775
54776
54777
54778
54779

54780
54781
54782
54783



54784
54785
54786
54787
54788
54789
54790
54791
54792
54793
54794
54795
54796
54797
54798
54799
54800
54801
54802
54803
54804
54805
54806
54807
54808
54809
54810
54811
54812
54813
54814


54815
54816
54817
54818
54819
54820
54821

54822
54823
54824

54825
54826








54827
54828
54829
54830
54831
54832
54833
54834
54835
54836
54837
54838
54839
54840
54841
54842
54843
54844
54845
54846
54847
54848
54849
54850
54851
54852
54853
54854
54855
54856



54857
54858


54859
54860
54861
54862
54863

54864
54865
54866
54867
54868
54869
54870
){
  unsigned char *aPayload;
  int rc = SQLITE_OK;
  u32 nKey;
  int iIdx = 0;
  MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
  BtShared *pBt = pCur->pBt;                  /* Btree this cursor belongs to */




  assert( pPage );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
  assert( cursorHoldsMutex(pCur) );


  getCellInfo(pCur);
  aPayload = pCur->info.pCell + pCur->info.nHeader;
  nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);




  if( NEVER(offset+amt > nKey+pCur->info.nData) 
   || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
  ){
    /* Trying to read or write past the end of the data is an error */
    return SQLITE_CORRUPT_BKPT;
  }

  /* Check if data must be read/written to/from the btree page itself. */
  if( offset<pCur->info.nLocal ){
    int a = amt;
    if( a+offset>pCur->info.nLocal ){
      a = pCur->info.nLocal - offset;
    }
    rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
    offset = 0;
    pBuf += a;
    amt -= a;
  }else{
    offset -= pCur->info.nLocal;
  }

  if( rc==SQLITE_OK && amt>0 ){
    const u32 ovflSize = pBt->usableSize - 4;  /* Bytes content per ovfl page */
    Pgno nextPage;

    nextPage = get4byte(&aPayload[pCur->info.nLocal]);

#ifndef SQLITE_OMIT_INCRBLOB
    /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[]
    ** has not been allocated, allocate it now. The array is sized at


    ** one entry for each overflow page in the overflow chain. The
    ** page number of the first overflow page is stored in aOverflow[0],
    ** etc. A value of 0 in the aOverflow[] array means "not yet known"
    ** (the cache is lazily populated).
    */
    if( pCur->isIncrblobHandle && !pCur->aOverflow ){
      int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;

      pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl);
      /* nOvfl is always positive.  If it were zero, fetchPayload would have
      ** been used instead of this routine. */

      if( ALWAYS(nOvfl) && !pCur->aOverflow ){
        rc = SQLITE_NOMEM;








      }
    }

    /* If the overflow page-list cache has been allocated and the
    ** entry for the first required overflow page is valid, skip
    ** directly to it.
    */
    if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){
      iIdx = (offset/ovflSize);
      nextPage = pCur->aOverflow[iIdx];
      offset = (offset%ovflSize);
    }
#endif

    for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){

#ifndef SQLITE_OMIT_INCRBLOB
      /* If required, populate the overflow page-list cache. */
      if( pCur->aOverflow ){
        assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
        pCur->aOverflow[iIdx] = nextPage;
      }
#endif

      if( offset>=ovflSize ){
        /* The only reason to read this page is to obtain the page
        ** number for the next page in the overflow chain. The page
        ** data is not required. So first try to lookup the overflow
        ** page-list cache, if any, then fall back to the getOverflowPage()
        ** function.



        */
#ifndef SQLITE_OMIT_INCRBLOB


        if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
          nextPage = pCur->aOverflow[iIdx+1];
        } else 
#endif
          rc = getOverflowPage(pBt, nextPage, 0, &nextPage);

        offset -= ovflSize;
      }else{
        /* Need to read this page properly. It contains some of the
        ** range of data that is being read (eOp==0) or written (eOp!=0).
        */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
        sqlite3_file *fd;







>
>
>





>




>
>
>














|













<
<
|
>
>
|
|
|
|

|

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







|




<



<

|



<







>
>
>

<
>
>
|

|
<

>







54852
54853
54854
54855
54856
54857
54858
54859
54860
54861
54862
54863
54864
54865
54866
54867
54868
54869
54870
54871
54872
54873
54874
54875
54876
54877
54878
54879
54880
54881
54882
54883
54884
54885
54886
54887
54888
54889
54890
54891
54892
54893
54894
54895
54896
54897
54898
54899
54900
54901
54902


54903
54904
54905
54906
54907
54908
54909
54910
54911
54912
54913
54914
54915

54916
54917
54918
54919
54920
54921
54922
54923
54924
54925
54926
54927
54928
54929
54930
54931
54932
54933
54934
54935
54936
54937
54938

54939
54940
54941

54942
54943
54944
54945
54946

54947
54948
54949
54950
54951
54952
54953
54954
54955
54956
54957

54958
54959
54960
54961
54962

54963
54964
54965
54966
54967
54968
54969
54970
54971
){
  unsigned char *aPayload;
  int rc = SQLITE_OK;
  u32 nKey;
  int iIdx = 0;
  MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
  BtShared *pBt = pCur->pBt;                  /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
  int bEnd;                                   /* True if reading to end of data */
#endif

  assert( pPage );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
  assert( cursorHoldsMutex(pCur) );
  assert( eOp!=2 || offset==0 );      /* Always start from beginning for eOp==2 */

  getCellInfo(pCur);
  aPayload = pCur->info.pCell + pCur->info.nHeader;
  nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
#ifdef SQLITE_DIRECT_OVERFLOW_READ
  bEnd = (offset+amt==nKey+pCur->info.nData);
#endif

  if( NEVER(offset+amt > nKey+pCur->info.nData) 
   || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
  ){
    /* Trying to read or write past the end of the data is an error */
    return SQLITE_CORRUPT_BKPT;
  }

  /* Check if data must be read/written to/from the btree page itself. */
  if( offset<pCur->info.nLocal ){
    int a = amt;
    if( a+offset>pCur->info.nLocal ){
      a = pCur->info.nLocal - offset;
    }
    rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
    offset = 0;
    pBuf += a;
    amt -= a;
  }else{
    offset -= pCur->info.nLocal;
  }

  if( rc==SQLITE_OK && amt>0 ){
    const u32 ovflSize = pBt->usableSize - 4;  /* Bytes content per ovfl page */
    Pgno nextPage;

    nextPage = get4byte(&aPayload[pCur->info.nLocal]);



    /* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
    ** Except, do not allocate aOverflow[] for eOp==2.
    **
    ** The aOverflow[] array is sized at one entry for each overflow page
    ** in the overflow chain. The page number of the first overflow page is
    ** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
    ** means "not yet known" (the cache is lazily populated).
    */
    if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
      int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
      if( nOvfl>pCur->nOvflAlloc ){
        Pgno *aNew = (Pgno*)sqlite3DbRealloc(
            pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)

        );
        if( aNew==0 ){
          rc = SQLITE_NOMEM;
        }else{
          pCur->nOvflAlloc = nOvfl*2;
          pCur->aOverflow = aNew;
        }
      }
      if( rc==SQLITE_OK ){
        memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
        pCur->curFlags |= BTCF_ValidOvfl;
      }
    }

    /* If the overflow page-list cache has been allocated and the
    ** entry for the first required overflow page is valid, skip
    ** directly to it.
    */
    if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){
      iIdx = (offset/ovflSize);
      nextPage = pCur->aOverflow[iIdx];
      offset = (offset%ovflSize);
    }


    for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){


      /* If required, populate the overflow page-list cache. */
      if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
        assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
        pCur->aOverflow[iIdx] = nextPage;
      }


      if( offset>=ovflSize ){
        /* The only reason to read this page is to obtain the page
        ** number for the next page in the overflow chain. The page
        ** data is not required. So first try to lookup the overflow
        ** page-list cache, if any, then fall back to the getOverflowPage()
        ** function.
        **
        ** Note that the aOverflow[] array must be allocated because eOp!=2
        ** here.  If eOp==2, then offset==0 and this branch is never taken.
        */

        assert( eOp!=2 );
        assert( pCur->curFlags & BTCF_ValidOvfl );
        if( pCur->aOverflow[iIdx+1] ){
          nextPage = pCur->aOverflow[iIdx+1];
        }else{

          rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
        }
        offset -= ovflSize;
      }else{
        /* Need to read this page properly. It contains some of the
        ** range of data that is being read (eOp==0) or written (eOp!=0).
        */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
        sqlite3_file *fd;
54878
54879
54880
54881
54882
54883
54884

54885
54886
54887
54888
54889
54890
54891

54892
54893
54894
54895
54896
54897
54898
54899
54900
54901
54902
54903
54904
54905
54906
54907
54908
54909
54910
54911
54912
54913
54914
54915
54916
54917
54918
54919
54920
        /* If all the following are true:
        **
        **   1) this is a read operation, and 
        **   2) data is required from the start of this overflow page, and
        **   3) the database is file-backed, and
        **   4) there is no open write-transaction, and
        **   5) the database is not a WAL database,

        **
        ** then data can be read directly from the database file into the
        ** output buffer, bypassing the page-cache altogether. This speeds
        ** up loading large records that span many overflow pages.
        */
        if( eOp==0                                             /* (1) */
         && offset==0                                          /* (2) */

         && pBt->inTransaction==TRANS_READ                     /* (4) */
         && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
         && pBt->pPage1->aData[19]==0x01                       /* (5) */
        ){
          u8 aSave[4];
          u8 *aWrite = &pBuf[-4];
          memcpy(aSave, aWrite, 4);
          rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
              (eOp==0 ? PAGER_GET_READONLY : 0)
          );
          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);
            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
          }
        }
        amt -= a;
        pBuf += a;
      }







>





|

>
















|




|







54979
54980
54981
54982
54983
54984
54985
54986
54987
54988
54989
54990
54991
54992
54993
54994
54995
54996
54997
54998
54999
55000
55001
55002
55003
55004
55005
55006
55007
55008
55009
55010
55011
55012
55013
55014
55015
55016
55017
55018
55019
55020
55021
55022
55023
        /* If all the following are true:
        **
        **   1) this is a read operation, and 
        **   2) data is required from the start of this overflow page, and
        **   3) the database is file-backed, and
        **   4) there is no open write-transaction, and
        **   5) the database is not a WAL database,
        **   6) all data from the page is being read.
        **
        ** then data can be read directly from the database file into the
        ** output buffer, bypassing the page-cache altogether. This speeds
        ** up loading large records that span many overflow pages.
        */
        if( (eOp&0x01)==0                                      /* (1) */
         && offset==0                                          /* (2) */
         && (bEnd || a==ovflSize)                              /* (6) */
         && pBt->inTransaction==TRANS_READ                     /* (4) */
         && (fd = sqlite3PagerFile(pBt->pPager))->pMethods     /* (3) */
         && pBt->pPage1->aData[19]==0x01                       /* (5) */
        ){
          u8 aSave[4];
          u8 *aWrite = &pBuf[-4];
          memcpy(aSave, aWrite, 4);
          rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
          nextPage = get4byte(aWrite);
          memcpy(aWrite, aSave, 4);
        }else
#endif

        {
          DbPage *pDbPage;
          rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
              ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
          );
          if( rc==SQLITE_OK ){
            aPayload = sqlite3PagerGetData(pDbPage);
            nextPage = get4byte(aPayload);
            rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
            sqlite3PagerUnref(pDbPage);
            offset = 0;
          }
        }
        amt -= a;
        pBuf += a;
      }
55000
55001
55002
55003
55004
55005
55006


55007
55008
55009
55010

55011
55012
55013
55014
55015
55016
55017
  u32 *pAmt            /* Write the number of available bytes here */
){
  assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
  assert( pCur->eState==CURSOR_VALID );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );


  if( pCur->info.nSize==0 ){
    btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
                   &pCur->info);
  }

  *pAmt = pCur->info.nLocal;
  return (void*)(pCur->info.pCell + pCur->info.nHeader);
}


/*
** For the entry that cursor pCur is point to, return as







>
>




>







55103
55104
55105
55106
55107
55108
55109
55110
55111
55112
55113
55114
55115
55116
55117
55118
55119
55120
55121
55122
55123
  u32 *pAmt            /* Write the number of available bytes here */
){
  assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
  assert( pCur->eState==CURSOR_VALID );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( cursorHoldsMutex(pCur) );
  assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
  assert( pCur->info.nSize>0 );
#if 0
  if( pCur->info.nSize==0 ){
    btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
                   &pCur->info);
  }
#endif
  *pAmt = pCur->info.nLocal;
  return (void*)(pCur->info.pCell + pCur->info.nHeader);
}


/*
** For the entry that cursor pCur is point to, return as
55054
55055
55056
55057
55058
55059
55060
55061
55062
55063
55064
55065
55066
55067
55068
55069
55070
55071
55072
55073
55074
55075
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
  assert( pCur->iPage>=0 );
  if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, newPgno, &pNewPage,
               pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
  if( rc ) return rc;
  pCur->apPage[i+1] = pNewPage;
  pCur->aiIdx[i+1] = 0;
  pCur->iPage++;

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }
  return SQLITE_OK;
}

#if 0







|






|







55160
55161
55162
55163
55164
55165
55166
55167
55168
55169
55170
55171
55172
55173
55174
55175
55176
55177
55178
55179
55180
55181
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
  assert( pCur->iPage>=0 );
  if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = getAndInitPage(pBt, newPgno, &pNewPage,
               (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
  if( rc ) return rc;
  pCur->apPage[i+1] = pNewPage;
  pCur->aiIdx[i+1] = 0;
  pCur->iPage++;

  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }
  return SQLITE_OK;
}

#if 0
55119
55120
55121
55122
55123
55124
55125
55126
55127
55128
55129
55130
55131
55132
55133
  );
#endif
  testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );

  releasePage(pCur->apPage[pCur->iPage]);
  pCur->iPage--;
  pCur->info.nSize = 0;
  pCur->validNKey = 0;
}

/*
** Move the cursor to point to the root page of its b-tree structure.
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a







|







55225
55226
55227
55228
55229
55230
55231
55232
55233
55234
55235
55236
55237
55238
55239
  );
#endif
  testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );

  releasePage(pCur->apPage[pCur->iPage]);
  pCur->iPage--;
  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
}

/*
** Move the cursor to point to the root page of its b-tree structure.
**
** If the table has a virtual root page, then the cursor is moved to point
** to the virtual root page instead of the actual root page. A table has a
55166
55167
55168
55169
55170
55171
55172
55173
55174
55175
55176
55177
55178
55179
55180
  if( pCur->iPage>=0 ){
    while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
                        pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;
  }
  pRoot = pCur->apPage[0];







|







55272
55273
55274
55275
55276
55277
55278
55279
55280
55281
55282
55283
55284
55285
55286
  if( pCur->iPage>=0 ){
    while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
  }else if( pCur->pgnoRoot==0 ){
    pCur->eState = CURSOR_INVALID;
    return SQLITE_OK;
  }else{
    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
                 (pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
      return rc;
    }
    pCur->iPage = 0;
  }
  pRoot = pCur->apPage[0];
55193
55194
55195
55196
55197
55198
55199
55200
55201
55202
55203
55204
55205
55206
55207
55208
  assert( pRoot->intKey==1 || pRoot->intKey==0 );
  if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }

  pCur->aiIdx[0] = 0;
  pCur->info.nSize = 0;
  pCur->atLast = 0;
  pCur->validNKey = 0;

  if( pRoot->nCell>0 ){
    pCur->eState = CURSOR_VALID;
  }else if( !pRoot->leaf ){
    Pgno subpage;
    if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
    subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);







|
<







55299
55300
55301
55302
55303
55304
55305
55306

55307
55308
55309
55310
55311
55312
55313
  assert( pRoot->intKey==1 || pRoot->intKey==0 );
  if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
    return SQLITE_CORRUPT_BKPT;
  }

  pCur->aiIdx[0] = 0;
  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);


  if( pRoot->nCell>0 ){
    pCur->eState = CURSOR_VALID;
  }else if( !pRoot->leaf ){
    Pgno subpage;
    if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
    subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
55257
55258
55259
55260
55261
55262
55263
55264
55265
55266
55267
55268
55269
55270
55271
    pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    pCur->aiIdx[pCur->iPage] = pPage->nCell;
    rc = moveToChild(pCur, pgno);
  }
  if( rc==SQLITE_OK ){
    pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
    pCur->info.nSize = 0;
    pCur->validNKey = 0;
  }
  return rc;
}

/* Move the cursor to the first entry in the table.  Return SQLITE_OK
** on success.  Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.







|







55362
55363
55364
55365
55366
55367
55368
55369
55370
55371
55372
55373
55374
55375
55376
    pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
    pCur->aiIdx[pCur->iPage] = pPage->nCell;
    rc = moveToChild(pCur, pgno);
  }
  if( rc==SQLITE_OK ){
    pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
    pCur->info.nSize = 0;
    pCur->curFlags &= ~BTCF_ValidNKey;
  }
  return rc;
}

/* Move the cursor to the first entry in the table.  Return SQLITE_OK
** on success.  Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
55296
55297
55298
55299
55300
55301
55302
55303
55304
55305
55306
55307
55308
55309
55310
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  int rc;
 
  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );

  /* If the cursor already points to the last entry, this is a no-op. */
  if( CURSOR_VALID==pCur->eState && pCur->atLast ){
#ifdef SQLITE_DEBUG
    /* This block serves to assert() that the cursor really does point 
    ** to the last entry in the b-tree. */
    int ii;
    for(ii=0; ii<pCur->iPage; ii++){
      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
    }







|







55401
55402
55403
55404
55405
55406
55407
55408
55409
55410
55411
55412
55413
55414
55415
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  int rc;
 
  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );

  /* If the cursor already points to the last entry, this is a no-op. */
  if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
#ifdef SQLITE_DEBUG
    /* This block serves to assert() that the cursor really does point 
    ** to the last entry in the b-tree. */
    int ii;
    for(ii=0; ii<pCur->iPage; ii++){
      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
    }
55319
55320
55321
55322
55323
55324
55325
55326





55327
55328
55329
55330
55331
55332
55333
    if( CURSOR_INVALID==pCur->eState ){
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->eState==CURSOR_VALID );
      *pRes = 0;
      rc = moveToRightmost(pCur);
      pCur->atLast = rc==SQLITE_OK ?1:0;





    }
  }
  return rc;
}

/* Move the cursor so that it points to an entry near the key 
** specified by pIdxKey or intKey.   Return a success code.







|
>
>
>
>
>







55424
55425
55426
55427
55428
55429
55430
55431
55432
55433
55434
55435
55436
55437
55438
55439
55440
55441
55442
55443
    if( CURSOR_INVALID==pCur->eState ){
      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
      *pRes = 1;
    }else{
      assert( pCur->eState==CURSOR_VALID );
      *pRes = 0;
      rc = moveToRightmost(pCur);
      if( rc==SQLITE_OK ){
        pCur->curFlags |= BTCF_AtLast;
      }else{
        pCur->curFlags &= ~BTCF_AtLast;
      }
   
    }
  }
  return rc;
}

/* Move the cursor so that it points to an entry near the key 
** specified by pIdxKey or intKey.   Return a success code.
55370
55371
55372
55373
55374
55375
55376
55377
55378
55379
55380
55381
55382
55383
55384
55385
55386
55387
55388
55389
55390
55391

55392
55393
55394
55395
55396
55397
55398
  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( pRes );
  assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );

  /* If the cursor is already positioned at the point we are trying
  ** to move to, then just return without doing any work */
  if( pCur->eState==CURSOR_VALID && pCur->validNKey 
   && pCur->apPage[0]->intKey 
  ){
    if( pCur->info.nKey==intKey ){
      *pRes = 0;
      return SQLITE_OK;
    }
    if( pCur->atLast && pCur->info.nKey<intKey ){
      *pRes = -1;
      return SQLITE_OK;
    }
  }

  if( pIdxKey ){
    xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);

    assert( pIdxKey->default_rc==1 
         || pIdxKey->default_rc==0 
         || pIdxKey->default_rc==-1
    );
  }else{
    xRecordCompare = 0; /* All keys are integers */
  }







|






|







>







55480
55481
55482
55483
55484
55485
55486
55487
55488
55489
55490
55491
55492
55493
55494
55495
55496
55497
55498
55499
55500
55501
55502
55503
55504
55505
55506
55507
55508
55509
  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  assert( pRes );
  assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );

  /* If the cursor is already positioned at the point we are trying
  ** to move to, then just return without doing any work */
  if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
   && pCur->apPage[0]->intKey 
  ){
    if( pCur->info.nKey==intKey ){
      *pRes = 0;
      return SQLITE_OK;
    }
    if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
      *pRes = -1;
      return SQLITE_OK;
    }
  }

  if( pIdxKey ){
    xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
    pIdxKey->isCorrupt = 0;
    assert( pIdxKey->default_rc==1 
         || pIdxKey->default_rc==0 
         || pIdxKey->default_rc==-1
    );
  }else{
    xRecordCompare = 0; /* All keys are integers */
  }
55443
55444
55445
55446
55447
55448
55449
55450
55451
55452
55453
55454
55455
55456
55457
          lwr = idx+1;
          if( lwr>upr ){ c = -1; break; }
        }else if( nCellKey>intKey ){
          upr = idx-1;
          if( lwr>upr ){ c = +1; break; }
        }else{
          assert( nCellKey==intKey );
          pCur->validNKey = 1;
          pCur->info.nKey = nCellKey;
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          if( !pPage->leaf ){
            lwr = idx;
            goto moveto_next_layer;
          }else{
            *pRes = 0;







|







55554
55555
55556
55557
55558
55559
55560
55561
55562
55563
55564
55565
55566
55567
55568
          lwr = idx+1;
          if( lwr>upr ){ c = -1; break; }
        }else if( nCellKey>intKey ){
          upr = idx-1;
          if( lwr>upr ){ c = +1; break; }
        }else{
          assert( nCellKey==intKey );
          pCur->curFlags |= BTCF_ValidNKey;
          pCur->info.nKey = nCellKey;
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          if( !pPage->leaf ){
            lwr = idx;
            goto moveto_next_layer;
          }else{
            *pRes = 0;
55500
55501
55502
55503
55504
55505
55506
55507
55508
55509
55510
55511
55512
55513
55514

55515
55516
55517
55518
55519
55520
55521
55522
55523

55524
55525
55526
55527
55528
55529
55530
          nCell = (int)pCur->info.nKey;
          pCellKey = sqlite3Malloc( nCell );
          if( pCellKey==0 ){
            rc = SQLITE_NOMEM;
            goto moveto_finish;
          }
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
          sqlite3_free(pCellKey);
        }

        if( c<0 ){
          lwr = idx+1;
        }else if( c>0 ){
          upr = idx-1;
        }else{
          assert( c==0 );
          *pRes = 0;
          rc = SQLITE_OK;
          pCur->aiIdx[pCur->iPage] = (u16)idx;

          goto moveto_finish;
        }
        if( lwr>upr ) break;
        assert( lwr+upr>=0 );
        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2 */
      }
    }







|







>









>







55611
55612
55613
55614
55615
55616
55617
55618
55619
55620
55621
55622
55623
55624
55625
55626
55627
55628
55629
55630
55631
55632
55633
55634
55635
55636
55637
55638
55639
55640
55641
55642
55643
          nCell = (int)pCur->info.nKey;
          pCellKey = sqlite3Malloc( nCell );
          if( pCellKey==0 ){
            rc = SQLITE_NOMEM;
            goto moveto_finish;
          }
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
          if( rc ){
            sqlite3_free(pCellKey);
            goto moveto_finish;
          }
          c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
          sqlite3_free(pCellKey);
        }
        assert( pIdxKey->isCorrupt==0 || c==0 );
        if( c<0 ){
          lwr = idx+1;
        }else if( c>0 ){
          upr = idx-1;
        }else{
          assert( c==0 );
          *pRes = 0;
          rc = SQLITE_OK;
          pCur->aiIdx[pCur->iPage] = (u16)idx;
          if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
          goto moveto_finish;
        }
        if( lwr>upr ) break;
        assert( lwr+upr>=0 );
        idx = (lwr+upr)>>1;  /* idx = (lwr+upr)/2 */
      }
    }
55545
55546
55547
55548
55549
55550
55551
55552
55553
55554
55555
55556
55557
55558
55559
    }
    pCur->aiIdx[pCur->iPage] = (u16)lwr;
    rc = moveToChild(pCur, chldPg);
    if( rc ) break;
  }
moveto_finish:
  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  return rc;
}


/*
** Return TRUE if the cursor is not pointing at an entry of the table.
**







|







55658
55659
55660
55661
55662
55663
55664
55665
55666
55667
55668
55669
55670
55671
55672
    }
    pCur->aiIdx[pCur->iPage] = (u16)lwr;
    rc = moveToChild(pCur, chldPg);
    if( rc ) break;
  }
moveto_finish:
  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  return rc;
}


/*
** Return TRUE if the cursor is not pointing at an entry of the table.
**
55590
55591
55592
55593
55594
55595
55596

55597
55598
55599
55600
55601
55602
55603
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( *pRes==0 || *pRes==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  if( pCur->eState!=CURSOR_VALID ){

    rc = restoreCursorPosition(pCur);
    if( rc!=SQLITE_OK ){
      *pRes = 0;
      return rc;
    }
    if( CURSOR_INVALID==pCur->eState ){
      *pRes = 1;







>







55703
55704
55705
55706
55707
55708
55709
55710
55711
55712
55713
55714
55715
55716
55717
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( *pRes==0 || *pRes==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  if( pCur->eState!=CURSOR_VALID ){
    invalidateOverflowCache(pCur);
    rc = restoreCursorPosition(pCur);
    if( rc!=SQLITE_OK ){
      *pRes = 0;
      return rc;
    }
    if( CURSOR_INVALID==pCur->eState ){
      *pRes = 1;
55623
55624
55625
55626
55627
55628
55629
55630
55631
55632
55633
55634
55635
55636
55637
  ** to be invalid here. This can only occur if a second cursor modifies
  ** the page while cursor pCur is holding a reference to it. Which can
  ** only happen if the database is corrupt in such a way as to link the
  ** page into more than one b-tree structure. */
  testcase( idx>pPage->nCell );

  pCur->info.nSize = 0;
  pCur->validNKey = 0;
  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ){
        *pRes = 0;
        return rc;
      }







|







55737
55738
55739
55740
55741
55742
55743
55744
55745
55746
55747
55748
55749
55750
55751
  ** to be invalid here. This can only occur if a second cursor modifies
  ** the page while cursor pCur is holding a reference to it. Which can
  ** only happen if the database is corrupt in such a way as to link the
  ** page into more than one b-tree structure. */
  testcase( idx>pPage->nCell );

  pCur->info.nSize = 0;
  pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
  if( idx>=pPage->nCell ){
    if( !pPage->leaf ){
      rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
      if( rc ){
        *pRes = 0;
        return rc;
      }
55684
55685
55686
55687
55688
55689
55690
55691
55692
55693
55694
55695
55696
55697
55698
  int rc;
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( *pRes==0 || *pRes==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  pCur->atLast = 0;
  if( pCur->eState!=CURSOR_VALID ){
    if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
      rc = btreeRestoreCursorPosition(pCur);
      if( rc!=SQLITE_OK ){
        *pRes = 0;
        return rc;
      }







|







55798
55799
55800
55801
55802
55803
55804
55805
55806
55807
55808
55809
55810
55811
55812
  int rc;
  MemPage *pPage;

  assert( cursorHoldsMutex(pCur) );
  assert( pRes!=0 );
  assert( *pRes==0 || *pRes==1 );
  assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
  pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl);
  if( pCur->eState!=CURSOR_VALID ){
    if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
      rc = btreeRestoreCursorPosition(pCur);
      if( rc!=SQLITE_OK ){
        *pRes = 0;
        return rc;
      }
55729
55730
55731
55732
55733
55734
55735
55736
55737
55738
55739
55740
55741
55742
55743
        pCur->eState = CURSOR_INVALID;
        *pRes = 1;
        return SQLITE_OK;
      }
      moveToParent(pCur);
    }
    pCur->info.nSize = 0;
    pCur->validNKey = 0;

    pCur->aiIdx[pCur->iPage]--;
    pPage = pCur->apPage[pCur->iPage];
    if( pPage->intKey && !pPage->leaf ){
      rc = sqlite3BtreePrevious(pCur, pRes);
    }else{
      rc = SQLITE_OK;







|







55843
55844
55845
55846
55847
55848
55849
55850
55851
55852
55853
55854
55855
55856
55857
        pCur->eState = CURSOR_INVALID;
        *pRes = 1;
        return SQLITE_OK;
      }
      moveToParent(pCur);
    }
    pCur->info.nSize = 0;
    pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);

    pCur->aiIdx[pCur->iPage]--;
    pPage = pCur->apPage[pCur->iPage];
    if( pPage->intKey && !pPage->leaf ){
      rc = sqlite3BtreePrevious(pCur, pRes);
    }else{
      rc = SQLITE_OK;
57754
57755
57756
57757
57758
57759
57760
57761
57762
57763
57764
57765
57766
57767
57768

  if( pCur->eState==CURSOR_FAULT ){
    assert( pCur->skipNext!=SQLITE_OK );
    return pCur->skipNext;
  }

  assert( cursorHoldsMutex(pCur) );
  assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
              && (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );

  /* Assert that the caller has been consistent. If this cursor was opened
  ** expecting an index b-tree, then the caller should be inserting blob
  ** keys with no associated data. If the cursor was opened expecting an
  ** intkey table, the caller should be inserting integer keys with a







|







57868
57869
57870
57871
57872
57873
57874
57875
57876
57877
57878
57879
57880
57881
57882

  if( pCur->eState==CURSOR_FAULT ){
    assert( pCur->skipNext!=SQLITE_OK );
    return pCur->skipNext;
  }

  assert( cursorHoldsMutex(pCur) );
  assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE
              && (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );

  /* Assert that the caller has been consistent. If this cursor was opened
  ** expecting an index b-tree, then the caller should be inserting blob
  ** keys with no associated data. If the cursor was opened expecting an
  ** intkey table, the caller should be inserting integer keys with a
57787
57788
57789
57790
57791
57792
57793
57794
57795
57796
57797
57798
57799
57800
57801
    /* If this is an insert into a table b-tree, invalidate any incrblob 
    ** cursors open on the row being replaced */
    invalidateIncrblobCursors(p, nKey, 0);

    /* If the cursor is currently on the last row and we are appending a
    ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
    ** call */
    if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){
      loc = -1;
    }
  }

  if( !loc ){
    rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
    if( rc ) return rc;







|







57901
57902
57903
57904
57905
57906
57907
57908
57909
57910
57911
57912
57913
57914
57915
    /* If this is an insert into a table b-tree, invalidate any incrblob 
    ** cursors open on the row being replaced */
    invalidateIncrblobCursors(p, nKey, 0);

    /* If the cursor is currently on the last row and we are appending a
    ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
    ** call */
    if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){
      loc = -1;
    }
  }

  if( !loc ){
    rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc);
    if( rc ) return rc;
57840
57841
57842
57843
57844
57845
57846
57847
57848
57849
57850
57851
57852
57853
57854
57855
57856
57857
57858
57859
57860
57861
57862
57863
57864
57865
57866
57867
57868
57869
57870
57871
57872
57873
57874
    assert( pPage->leaf );
  }
  insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
  assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );

  /* If no error has occurred and pPage has an overflow cell, call balance() 
  ** to redistribute the cells within the tree. Since balance() may move
  ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
  ** variables.
  **
  ** Previous versions of SQLite called moveToRoot() to move the cursor
  ** back to the root page as balance() used to invalidate the contents
  ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
  ** set the cursor state to "invalid". This makes common insert operations
  ** slightly faster.
  **
  ** There is a subtle but important optimization here too. When inserting
  ** multiple records into an intkey b-tree using a single cursor (as can
  ** happen while processing an "INSERT INTO ... SELECT" statement), it
  ** is advantageous to leave the cursor pointing to the last entry in
  ** the b-tree if possible. If the cursor is left pointing to the last
  ** entry in the table, and the next row inserted has an integer key
  ** larger than the largest existing key, it is possible to insert the
  ** row without seeking the cursor. This can be a big performance boost.
  */
  pCur->info.nSize = 0;
  if( rc==SQLITE_OK && pPage->nOverflow ){
    pCur->validNKey = 0;
    rc = balance(pCur);

    /* Must make sure nOverflow is reset to zero even if the balance()
    ** fails. Internal data structure corruption will result otherwise. 
    ** Also, set the cursor state to invalid. This stops saveCursorPosition()
    ** from trying to save the current position of the cursor.  */
    pCur->apPage[pCur->iPage]->nOverflow = 0;







|



















|







57954
57955
57956
57957
57958
57959
57960
57961
57962
57963
57964
57965
57966
57967
57968
57969
57970
57971
57972
57973
57974
57975
57976
57977
57978
57979
57980
57981
57982
57983
57984
57985
57986
57987
57988
    assert( pPage->leaf );
  }
  insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
  assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );

  /* If no error has occurred and pPage has an overflow cell, call balance() 
  ** to redistribute the cells within the tree. Since balance() may move
  ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
  ** variables.
  **
  ** Previous versions of SQLite called moveToRoot() to move the cursor
  ** back to the root page as balance() used to invalidate the contents
  ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
  ** set the cursor state to "invalid". This makes common insert operations
  ** slightly faster.
  **
  ** There is a subtle but important optimization here too. When inserting
  ** multiple records into an intkey b-tree using a single cursor (as can
  ** happen while processing an "INSERT INTO ... SELECT" statement), it
  ** is advantageous to leave the cursor pointing to the last entry in
  ** the b-tree if possible. If the cursor is left pointing to the last
  ** entry in the table, and the next row inserted has an integer key
  ** larger than the largest existing key, it is possible to insert the
  ** row without seeking the cursor. This can be a big performance boost.
  */
  pCur->info.nSize = 0;
  if( rc==SQLITE_OK && pPage->nOverflow ){
    pCur->curFlags &= ~(BTCF_ValidNKey);
    rc = balance(pCur);

    /* Must make sure nOverflow is reset to zero even if the balance()
    ** fails. Internal data structure corruption will result otherwise. 
    ** Also, set the cursor state to invalid. This stops saveCursorPosition()
    ** from trying to save the current position of the cursor.  */
    pCur->apPage[pCur->iPage]->nOverflow = 0;
57892
57893
57894
57895
57896
57897
57898
57899
57900
57901
57902
57903
57904
57905
57906
  unsigned char *pCell;                /* Pointer to cell to delete */
  int iCellIdx;                        /* Index of cell to delete */
  int iCellDepth;                      /* Depth of node containing pCell */ 

  assert( cursorHoldsMutex(pCur) );
  assert( pBt->inTransaction==TRANS_WRITE );
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( pCur->wrFlag );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
  assert( !hasReadConflicts(p, pCur->pgnoRoot) );

  if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) 
   || NEVER(pCur->eState!=CURSOR_VALID)
  ){
    return SQLITE_ERROR;  /* Something has gone awry. */







|







58006
58007
58008
58009
58010
58011
58012
58013
58014
58015
58016
58017
58018
58019
58020
  unsigned char *pCell;                /* Pointer to cell to delete */
  int iCellIdx;                        /* Index of cell to delete */
  int iCellDepth;                      /* Depth of node containing pCell */ 

  assert( cursorHoldsMutex(pCur) );
  assert( pBt->inTransaction==TRANS_WRITE );
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( pCur->curFlags & BTCF_WriteFlag );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
  assert( !hasReadConflicts(p, pCur->pgnoRoot) );

  if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell) 
   || NEVER(pCur->eState!=CURSOR_VALID)
  ){
    return SQLITE_ERROR;  /* Something has gone awry. */
58236
58237
58238
58239
58240
58241
58242









58243
58244
58245
58246
58247
58248
58249
    ** a no-op).  */
    invalidateIncrblobCursors(p, 0, 1);
    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
  }
  sqlite3BtreeLeave(p);
  return rc;
}










/*
** Erase all information in a table and add the root of the table to
** the freelist.  Except, the root of the principle table (the one on
** page 1) is never added to the freelist.
**
** This routine will fail with SQLITE_LOCKED if there are any open







>
>
>
>
>
>
>
>
>







58350
58351
58352
58353
58354
58355
58356
58357
58358
58359
58360
58361
58362
58363
58364
58365
58366
58367
58368
58369
58370
58371
58372
    ** a no-op).  */
    invalidateIncrblobCursors(p, 0, 1);
    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
** Delete all information from the single table that pCur is open on.
**
** This routine only work for pCur on an ephemeral table.
*/
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
  return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
}

/*
** Erase all information in a table and add the root of the table to
** the freelist.  Except, the root of the principle table (the one on
** page 1) is never added to the freelist.
**
** This routine will fail with SQLITE_LOCKED if there are any open
59196
59197
59198
59199
59200
59201
59202
59203
59204
59205
59206
59207
59208
59209
59210
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
*/
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
  int rc;
  assert( cursorHoldsMutex(pCsr) );
  assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
  assert( pCsr->isIncrblobHandle );

  rc = restoreCursorPosition(pCsr);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pCsr->eState!=CURSOR_REQUIRESEEK );
  if( pCsr->eState!=CURSOR_VALID ){







|







59319
59320
59321
59322
59323
59324
59325
59326
59327
59328
59329
59330
59331
59332
59333
** parameters that attempt to write past the end of the existing data,
** no modifications are made and SQLITE_CORRUPT is returned.
*/
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
  int rc;
  assert( cursorHoldsMutex(pCsr) );
  assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
  assert( pCsr->curFlags & BTCF_Incrblob );

  rc = restoreCursorPosition(pCsr);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pCsr->eState!=CURSOR_REQUIRESEEK );
  if( pCsr->eState!=CURSOR_VALID ){
59225
59226
59227
59228
59229
59230
59231
59232
59233
59234
59235
59236
59237
59238
59239
59240
59241
59242
59243
59244
59245
59246
59247
59248
59249
59250
59251
59252
59253
59254
59255
59256
59257
59258
59259
59260
59261
59262
59263
59264
59265
  /* Check some assumptions: 
  **   (a) the cursor is open for writing,
  **   (b) there is a read/write transaction open,
  **   (c) the connection holds a write-lock on the table (if required),
  **   (d) there are no conflicting read-locks, and
  **   (e) the cursor points at a valid row of an intKey table.
  */
  if( !pCsr->wrFlag ){
    return SQLITE_READONLY;
  }
  assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
              && pCsr->pBt->inTransaction==TRANS_WRITE );
  assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
  assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
  assert( pCsr->apPage[pCsr->iPage]->intKey );

  return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}

/* 
** Set a flag on this cursor to cache the locations of pages from the 
** overflow list for the current row. This is used by cursors opened
** for incremental blob IO only.
**
** This function sets a flag only. The actual page location cache
** (stored in BtCursor.aOverflow[]) is allocated and used by function
** accessPayload() (the worker function for sqlite3BtreeData() and
** sqlite3BtreePutData()).
*/
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
  assert( cursorHoldsMutex(pCur) );
  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  invalidateOverflowCache(pCur);
  pCur->isIncrblobHandle = 1;
}
#endif

/*
** Set both the "read version" (single byte at byte offset 18) and 
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.







|












<
<
|
<
<
<
<
<

|
<
<
<
|







59348
59349
59350
59351
59352
59353
59354
59355
59356
59357
59358
59359
59360
59361
59362
59363
59364
59365
59366
59367


59368





59369
59370



59371
59372
59373
59374
59375
59376
59377
59378
  /* Check some assumptions: 
  **   (a) the cursor is open for writing,
  **   (b) there is a read/write transaction open,
  **   (c) the connection holds a write-lock on the table (if required),
  **   (d) there are no conflicting read-locks, and
  **   (e) the cursor points at a valid row of an intKey table.
  */
  if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
    return SQLITE_READONLY;
  }
  assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
              && pCsr->pBt->inTransaction==TRANS_WRITE );
  assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
  assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
  assert( pCsr->apPage[pCsr->iPage]->intKey );

  return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}

/* 


** Mark this cursor as an incremental blob cursor.





*/
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *pCur){



  pCur->curFlags |= BTCF_Incrblob;
}
#endif

/*
** Set both the "read version" (single byte at byte offset 18) and 
** "write version" (single byte at byte offset 19) fields in the database
** header to iVersion.
61622
61623
61624
61625
61626
61627
61628
61629
61630
61631
61632
61633
61634
61635
61636
** a prior call to sqlite3VdbeMakeLabel().
*/
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
  Parse *p = v->pParse;
  int j = -1-x;
  assert( v->magic==VDBE_MAGIC_INIT );
  assert( j<p->nLabel );
  if( j>=0 && p->aLabel ){
    p->aLabel[j] = v->nOp;
  }
  p->iFixedOp = v->nOp - 1;
}

/*
** Mark the VDBE as one that can only be run one time.







|







61735
61736
61737
61738
61739
61740
61741
61742
61743
61744
61745
61746
61747
61748
61749
** a prior call to sqlite3VdbeMakeLabel().
*/
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
  Parse *p = v->pParse;
  int j = -1-x;
  assert( v->magic==VDBE_MAGIC_INIT );
  assert( j<p->nLabel );
  if( ALWAYS(j>=0) && p->aLabel ){
    p->aLabel[j] = v->nOp;
  }
  p->iFixedOp = v->nOp - 1;
}

/*
** Mark the VDBE as one that can only be run one time.
62129
62130
62131
62132
62133
62134
62135
62136


62137
62138
62139
62140
62141
62142
62143
  }
  assert( p->nOp>0 );
  assert( addr<p->nOp );
  if( addr<0 ){
    addr = p->nOp - 1;
  }
  pOp = &p->aOp[addr];
  assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );


  freeP4(db, pOp->p4type, pOp->p4.p);
  pOp->p4.p = 0;
  if( n==P4_INT32 ){
    /* Note: this cast is safe, because the origin data point was an int
    ** that was cast to a (const char *). */
    pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
    pOp->p4type = P4_INT32;







|
>
>







62242
62243
62244
62245
62246
62247
62248
62249
62250
62251
62252
62253
62254
62255
62256
62257
62258
  }
  assert( p->nOp>0 );
  assert( addr<p->nOp );
  if( addr<0 ){
    addr = p->nOp - 1;
  }
  pOp = &p->aOp[addr];
  assert( pOp->p4type==P4_NOTUSED
       || pOp->p4type==P4_INT32
       || pOp->p4type==P4_KEYINFO );
  freeP4(db, pOp->p4type, pOp->p4.p);
  pOp->p4.p = 0;
  if( n==P4_INT32 ){
    /* Note: this cast is safe, because the origin data point was an int
    ** that was cast to a (const char *). */
    pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
    pOp->p4type = P4_INT32;
64079
64080
64081
64082
64083
64084
64085
64086
64087
64088
64089
64090
64091
64092
64093
    p->cacheStatus = CACHE_STALE;
  }else if( p->pCursor ){
    int hasMoved;
    int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
    if( rc ) return rc;
    if( hasMoved ){
      p->cacheStatus = CACHE_STALE;
      p->nullRow = 1;
    }
  }
  return SQLITE_OK;
}

/*
** The following functions:







|







64194
64195
64196
64197
64198
64199
64200
64201
64202
64203
64204
64205
64206
64207
64208
    p->cacheStatus = CACHE_STALE;
  }else if( p->pCursor ){
    int hasMoved;
    int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
    if( rc ) return rc;
    if( hasMoved ){
      p->cacheStatus = CACHE_STALE;
      if( hasMoved==2 ) p->nullRow = 1;
    }
  }
  return SQLITE_OK;
}

/*
** The following functions:
64749
64750
64751
64752
64753
64754
64755



64756
64757
64758
64759
64760
64761
64762
64763
64764
64765
64766
**
** If argument bSkip is non-zero, it is assumed that the caller has already
** determined that the first fields of the keys are equal.
**
** Key1 and Key2 do not have to contain the same number of fields. If all 
** fields that appear in both keys are equal, then pPKey2->default_rc is 
** returned.



*/
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
  int nKey1, const void *pKey1,   /* Left key */
  const UnpackedRecord *pPKey2,   /* Right key */
  int bSkip                       /* If true, skip the first field */
){
  u32 d1;                         /* Offset into aKey[] of next data element */
  int i;                          /* Index of next field to compare */
  u32 szHdr1;                     /* Size of record header in bytes */
  u32 idx1;                       /* Offset of first type in header */
  int rc = 0;                     /* Return value */







>
>
>



|







64864
64865
64866
64867
64868
64869
64870
64871
64872
64873
64874
64875
64876
64877
64878
64879
64880
64881
64882
64883
64884
**
** If argument bSkip is non-zero, it is assumed that the caller has already
** determined that the first fields of the keys are equal.
**
** Key1 and Key2 do not have to contain the same number of fields. If all 
** fields that appear in both keys are equal, then pPKey2->default_rc is 
** returned.
**
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
** and return 0.
*/
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
  int nKey1, const void *pKey1,   /* Left key */
  UnpackedRecord *pPKey2,         /* Right key */
  int bSkip                       /* If true, skip the first field */
){
  u32 d1;                         /* Offset into aKey[] of next data element */
  int i;                          /* Index of next field to compare */
  u32 szHdr1;                     /* Size of record header in bytes */
  u32 idx1;                       /* Offset of first type in header */
  int rc = 0;                     /* Return value */
64778
64779
64780
64781
64782
64783
64784




64785
64786
64787
64788
64789
64790
64791
    szHdr1 = aKey1[0];
    d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
    i = 1;
    pRhs++;
  }else{
    idx1 = getVarint32(aKey1, szHdr1);
    d1 = szHdr1;




    i = 0;
  }

  VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
  assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField 
       || CORRUPT_DB );
  assert( pPKey2->pKeyInfo->aSortOrder!=0 );







>
>
>
>







64896
64897
64898
64899
64900
64901
64902
64903
64904
64905
64906
64907
64908
64909
64910
64911
64912
64913
    szHdr1 = aKey1[0];
    d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
    i = 1;
    pRhs++;
  }else{
    idx1 = getVarint32(aKey1, szHdr1);
    d1 = szHdr1;
    if( d1>(unsigned)nKey1 ){ 
      pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
      return 0;  /* Corruption */
    }
    i = 0;
  }

  VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
  assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField 
       || CORRUPT_DB );
  assert( pPKey2->pKeyInfo->aSortOrder!=0 );
64854
64855
64856
64857
64858
64859
64860

64861
64862
64863
64864
64865
64866
64867
64868
      }else if( !(serial_type & 0x01) ){
        rc = +1;
      }else{
        mem1.n = (serial_type - 12) / 2;
        testcase( (d1+mem1.n)==(unsigned)nKey1 );
        testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
        if( (d1+mem1.n) > (unsigned)nKey1 ){

          rc = 1;                /* Corruption */
        }else if( pKeyInfo->aColl[i] ){
          mem1.enc = pKeyInfo->enc;
          mem1.db = pKeyInfo->db;
          mem1.flags = MEM_Str;
          mem1.z = (char*)&aKey1[d1];
          rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
        }else{







>
|







64976
64977
64978
64979
64980
64981
64982
64983
64984
64985
64986
64987
64988
64989
64990
64991
      }else if( !(serial_type & 0x01) ){
        rc = +1;
      }else{
        mem1.n = (serial_type - 12) / 2;
        testcase( (d1+mem1.n)==(unsigned)nKey1 );
        testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
        if( (d1+mem1.n) > (unsigned)nKey1 ){
          pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
          return 0;                /* Corruption */
        }else if( pKeyInfo->aColl[i] ){
          mem1.enc = pKeyInfo->enc;
          mem1.db = pKeyInfo->db;
          mem1.flags = MEM_Str;
          mem1.z = (char*)&aKey1[d1];
          rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
        }else{
64880
64881
64882
64883
64884
64885
64886

64887
64888
64889
64890
64891
64892
64893
64894
      if( serial_type<12 || (serial_type & 0x01) ){
        rc = -1;
      }else{
        int nStr = (serial_type - 12) / 2;
        testcase( (d1+nStr)==(unsigned)nKey1 );
        testcase( (d1+nStr+1)==(unsigned)nKey1 );
        if( (d1+nStr) > (unsigned)nKey1 ){

          rc = 1;                /* Corruption */
        }else{
          int nCmp = MIN(nStr, pRhs->n);
          rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
          if( rc==0 ) rc = nStr - pRhs->n;
        }
      }
    }







>
|







65003
65004
65005
65006
65007
65008
65009
65010
65011
65012
65013
65014
65015
65016
65017
65018
      if( serial_type<12 || (serial_type & 0x01) ){
        rc = -1;
      }else{
        int nStr = (serial_type - 12) / 2;
        testcase( (d1+nStr)==(unsigned)nKey1 );
        testcase( (d1+nStr+1)==(unsigned)nKey1 );
        if( (d1+nStr) > (unsigned)nKey1 ){
          pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
          return 0;                /* Corruption */
        }else{
          int nCmp = MIN(nStr, pRhs->n);
          rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
          if( rc==0 ) rc = nStr - pRhs->n;
        }
      }
    }
64933
64934
64935
64936
64937
64938
64939



64940
64941
64942
64943
64944
64945
64946
64947
64948
64949
64950
64951
64952
64953
64954
64955

64956
64957
64958
64959
64960
64961
64962
}

/*
** This function is an optimized version of sqlite3VdbeRecordCompare() 
** that (a) the first field of pPKey2 is an integer, and (b) the 
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
** byte (i.e. is less than 128).



*/
static int vdbeRecordCompareInt(
  int nKey1, const void *pKey1, /* Left key */
  const UnpackedRecord *pPKey2, /* Right key */
  int bSkip                     /* Ignored */
){
  const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
  int serial_type = ((const u8*)pKey1)[1];
  int res;
  u32 y;
  u64 x;
  i64 v = pPKey2->aMem[0].u.i;
  i64 lhs;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );

  switch( serial_type ){
    case 1: { /* 1-byte signed integer */
      lhs = ONE_BYTE_INT(aKey);
      testcase( lhs<0 );
      break;
    }
    case 2: { /* 2-byte signed integer */







>
>
>



|












>







65057
65058
65059
65060
65061
65062
65063
65064
65065
65066
65067
65068
65069
65070
65071
65072
65073
65074
65075
65076
65077
65078
65079
65080
65081
65082
65083
65084
65085
65086
65087
65088
65089
65090
}

/*
** This function is an optimized version of sqlite3VdbeRecordCompare() 
** that (a) the first field of pPKey2 is an integer, and (b) the 
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
** byte (i.e. is less than 128).
**
** To avoid concerns about buffer overreads, this routine is only used
** on schemas where the maximum valid header size is 63 bytes or less.
*/
static int vdbeRecordCompareInt(
  int nKey1, const void *pKey1, /* Left key */
  UnpackedRecord *pPKey2,       /* Right key */
  int bSkip                     /* Ignored */
){
  const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
  int serial_type = ((const u8*)pKey1)[1];
  int res;
  u32 y;
  u64 x;
  i64 v = pPKey2->aMem[0].u.i;
  i64 lhs;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );
  assert( (*(u8*)pKey1)<=0x3F || CORRUPT_DB );
  switch( serial_type ){
    case 1: { /* 1-byte signed integer */
      lhs = ONE_BYTE_INT(aKey);
      testcase( lhs<0 );
      break;
    }
    case 2: { /* 2-byte signed integer */
65033
65034
65035
65036
65037
65038
65039
65040
65041
65042
65043
65044
65045
65046
65047
65048
65049
65050
65051
65052
65053
65054
65055
65056
65057
65058
65059
65060
65061



65062
65063
65064
65065
65066
65067
65068
** This function is an optimized version of sqlite3VdbeRecordCompare() 
** that (a) the first field of pPKey2 is a string, that (b) the first field
** uses the collation sequence BINARY and (c) that the size-of-header varint 
** at the start of (pKey1/nKey1) fits in a single byte.
*/
static int vdbeRecordCompareString(
  int nKey1, const void *pKey1, /* Left key */
  const UnpackedRecord *pPKey2, /* Right key */
  int bSkip
){
  const u8 *aKey1 = (const u8*)pKey1;
  int serial_type;
  int res;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );
  getVarint32(&aKey1[1], serial_type);

  if( serial_type<12 ){
    res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  }else if( !(serial_type & 0x01) ){ 
    res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  }else{
    int nCmp;
    int nStr;
    int szHdr = aKey1[0];

    nStr = (serial_type-12) / 2;
    if( (szHdr + nStr) > nKey1 ) return 0;    /* Corruption */



    nCmp = MIN( pPKey2->aMem[0].n, nStr );
    res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);

    if( res==0 ){
      res = nStr - pPKey2->aMem[0].n;
      if( res==0 ){
        if( pPKey2->nField>1 ){







|




















|
>
>
>







65161
65162
65163
65164
65165
65166
65167
65168
65169
65170
65171
65172
65173
65174
65175
65176
65177
65178
65179
65180
65181
65182
65183
65184
65185
65186
65187
65188
65189
65190
65191
65192
65193
65194
65195
65196
65197
65198
65199
** This function is an optimized version of sqlite3VdbeRecordCompare() 
** that (a) the first field of pPKey2 is a string, that (b) the first field
** uses the collation sequence BINARY and (c) that the size-of-header varint 
** at the start of (pKey1/nKey1) fits in a single byte.
*/
static int vdbeRecordCompareString(
  int nKey1, const void *pKey1, /* Left key */
  UnpackedRecord *pPKey2,       /* Right key */
  int bSkip
){
  const u8 *aKey1 = (const u8*)pKey1;
  int serial_type;
  int res;
  UNUSED_PARAMETER(bSkip);

  assert( bSkip==0 );
  getVarint32(&aKey1[1], serial_type);

  if( serial_type<12 ){
    res = pPKey2->r1;      /* (pKey1/nKey1) is a number or a null */
  }else if( !(serial_type & 0x01) ){ 
    res = pPKey2->r2;      /* (pKey1/nKey1) is a blob */
  }else{
    int nCmp;
    int nStr;
    int szHdr = aKey1[0];

    nStr = (serial_type-12) / 2;
    if( (szHdr + nStr) > nKey1 ){
      pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
      return 0;    /* Corruption */
    }
    nCmp = MIN( pPKey2->aMem[0].n, nStr );
    res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);

    if( res==0 ){
      res = nStr - pPKey2->aMem[0].n;
      if( res==0 ){
        if( pPKey2->nField>1 ){
65219
65220
65221
65222
65223
65224
65225
65226
65227
65228
65229
65230
65231
65232
65233
** pUnpacked is either created without a rowid or is truncated so that it
** omits the rowid at the end.  The rowid at the end of the index entry
** is ignored as well.  Hence, this routine only compares the prefixes 
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
  VdbeCursor *pC,                  /* The cursor to compare against */
  const UnpackedRecord *pUnpacked, /* Unpacked version of key */
  int *res                         /* Write the comparison result here */
){
  i64 nCellKey = 0;
  int rc;
  BtCursor *pCur = pC->pCursor;
  Mem m;








|







65350
65351
65352
65353
65354
65355
65356
65357
65358
65359
65360
65361
65362
65363
65364
** pUnpacked is either created without a rowid or is truncated so that it
** omits the rowid at the end.  The rowid at the end of the index entry
** is ignored as well.  Hence, this routine only compares the prefixes 
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
  VdbeCursor *pC,                  /* The cursor to compare against */
  UnpackedRecord *pUnpacked,       /* Unpacked version of key */
  int *res                         /* Write the comparison result here */
){
  i64 nCellKey = 0;
  int rc;
  BtCursor *pCur = pC->pCursor;
  Mem m;

67309
67310
67311
67312
67313
67314
67315























67316
67317
67318
67319
67320
67321
67322
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
  sqlite3_value *pVal, 
  u8 affinity, 
  u8 enc
){
  applyAffinity((Mem *)pVal, affinity, enc);
}
























#ifdef SQLITE_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){







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







67440
67441
67442
67443
67444
67445
67446
67447
67448
67449
67450
67451
67452
67453
67454
67455
67456
67457
67458
67459
67460
67461
67462
67463
67464
67465
67466
67467
67468
67469
67470
67471
67472
67473
67474
67475
67476
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(
  sqlite3_value *pVal, 
  u8 affinity, 
  u8 enc
){
  applyAffinity((Mem *)pVal, affinity, enc);
}

/*
** Return the numeric type for pMem, either MEM_Int or MEM_Real or both or
** none.  
**
** Unlike applyNumericAffinity(), this routine does not modify pMem->flags.
** But it does set pMem->r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
  if( pMem->flags & (MEM_Int|MEM_Real) ){
    return pMem->flags & (MEM_Int|MEM_Real);
  }
  if( pMem->flags & (MEM_Str|MEM_Blob) ){
    if( sqlite3AtoF(pMem->z, &pMem->r, pMem->n, pMem->enc)==0 ){
      return 0;
    }
    if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
      return MEM_Int;
    }
    return MEM_Real;
  }
  return 0;
}

#ifdef SQLITE_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
68169
68170
68171
68172
68173
68174
68175
68176
68177
68178
68179

68180
68181
68182
68183
68184
68185
68186
68187
68188
68189
68190
68191
68192
68193
68194
68195
68196
68197
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Move P1 P2 P3 * *
** Synopsis:  r[P2@P3]=r[P1@P3]
**
** Move the values in register P1..P1+P3 over into
** registers P2..P2+P3.  Registers P1..P1+P3 are
** left holding a NULL.  It is an error for register ranges
** P1..P1+P3 and P2..P2+P3 to overlap.

*/
case OP_Move: {
  char *zMalloc;   /* Holding variable for allocated memory */
  int n;           /* Number of registers left to copy */
  int p1;          /* Register to copy from */
  int p2;          /* Register to copy to */

  n = pOp->p3;
  p1 = pOp->p1;
  p2 = pOp->p2;
  assert( n>=0 && p1>0 && p2>0 );
  assert( p1+n<=p2 || p2+n<=p1 );

  pIn1 = &aMem[p1];
  pOut = &aMem[p2];
  do{
    assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
    assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );







|
|

|
>










|







68323
68324
68325
68326
68327
68328
68329
68330
68331
68332
68333
68334
68335
68336
68337
68338
68339
68340
68341
68342
68343
68344
68345
68346
68347
68348
68349
68350
68351
68352
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Move P1 P2 P3 * *
** Synopsis:  r[P2@P3]=r[P1@P3]
**
** Move the P3 values in register P1..P1+P3-1 over into
** registers P2..P2+P3-1.  Registers P1..P1+P3-1 are
** left holding a NULL.  It is an error for register ranges
** P1..P1+P3-1 and P2..P2+P3-1 to overlap.  It is an error
** for P3 to be less than 1.
*/
case OP_Move: {
  char *zMalloc;   /* Holding variable for allocated memory */
  int n;           /* Number of registers left to copy */
  int p1;          /* Register to copy from */
  int p2;          /* Register to copy to */

  n = pOp->p3;
  p1 = pOp->p1;
  p2 = pOp->p2;
  assert( n>0 && p1>0 && p2>0 );
  assert( p1+n<=p2 || p2+n<=p1 );

  pIn1 = &aMem[p1];
  pOut = &aMem[p2];
  do{
    assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
    assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
68207
68208
68209
68210
68211
68212
68213
68214
68215
68216
68217
68218
68219
68220
68221
#endif
    pIn1->flags = MEM_Undefined;
    pIn1->xDel = 0;
    pIn1->zMalloc = zMalloc;
    REGISTER_TRACE(p2++, pOut);
    pIn1++;
    pOut++;
  }while( n-- );
  break;
}

/* Opcode: Copy P1 P2 P3 * *
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.







|







68362
68363
68364
68365
68366
68367
68368
68369
68370
68371
68372
68373
68374
68375
68376
#endif
    pIn1->flags = MEM_Undefined;
    pIn1->xDel = 0;
    pIn1->zMalloc = zMalloc;
    REGISTER_TRACE(p2++, pOut);
    pIn1++;
    pOut++;
  }while( --n );
  break;
}

/* Opcode: Copy P1 P2 P3 * *
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
68439
68440
68441
68442
68443
68444
68445
68446


68447
68448
68449
68450
68451
68452
68453
68454
68455
68456
68457
68458
68459
68460
68461
68462
68463
68464
68465
68466
*/
case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
  char bIntint;   /* Started out as two integer operands */
  int flags;      /* Combined MEM_* flags from both inputs */


  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  double rA;      /* Real value of left operand */
  double rB;      /* Real value of right operand */

  pIn1 = &aMem[pOp->p1];
  applyNumericAffinity(pIn1);
  pIn2 = &aMem[pOp->p2];
  applyNumericAffinity(pIn2);
  pOut = &aMem[pOp->p3];
  flags = pIn1->flags | pIn2->flags;
  if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
  if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    bIntint = 1;
    switch( pOp->opcode ){
      case OP_Add:       if( sqlite3AddInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite3SubInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite3MulInt64(&iB,iA) ) goto fp_math;  break;







|
>
>






|

|



|







68594
68595
68596
68597
68598
68599
68600
68601
68602
68603
68604
68605
68606
68607
68608
68609
68610
68611
68612
68613
68614
68615
68616
68617
68618
68619
68620
68621
68622
68623
*/
case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
  char bIntint;   /* Started out as two integer operands */
  u16 flags;      /* Combined MEM_* flags from both inputs */
  u16 type1;      /* Numeric type of left operand */
  u16 type2;      /* Numeric type of right operand */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  double rA;      /* Real value of left operand */
  double rB;      /* Real value of right operand */

  pIn1 = &aMem[pOp->p1];
  type1 = numericType(pIn1);
  pIn2 = &aMem[pOp->p2];
  type2 = numericType(pIn2);
  pOut = &aMem[pOp->p3];
  flags = pIn1->flags | pIn2->flags;
  if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
  if( (type1 & type2 & MEM_Int)!=0 ){
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    bIntint = 1;
    switch( pOp->opcode ){
      case OP_Add:       if( sqlite3AddInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite3SubInt64(&iB,iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite3MulInt64(&iB,iA) ) goto fp_math;  break;
68508
68509
68510
68511
68512
68513
68514
68515
68516
68517
68518
68519
68520
68521
68522
    MemSetTypeFlag(pOut, MEM_Int);
#else
    if( sqlite3IsNaN(rB) ){
      goto arithmetic_result_is_null;
    }
    pOut->r = rB;
    MemSetTypeFlag(pOut, MEM_Real);
    if( (flags & MEM_Real)==0 && !bIntint ){
      sqlite3VdbeIntegerAffinity(pOut);
    }
#endif
  }
  break;

arithmetic_result_is_null:







|







68665
68666
68667
68668
68669
68670
68671
68672
68673
68674
68675
68676
68677
68678
68679
    MemSetTypeFlag(pOut, MEM_Int);
#else
    if( sqlite3IsNaN(rB) ){
      goto arithmetic_result_is_null;
    }
    pOut->r = rB;
    MemSetTypeFlag(pOut, MEM_Real);
    if( ((type1|type2)&MEM_Real)==0 && !bIntint ){
      sqlite3VdbeIntegerAffinity(pOut);
    }
#endif
  }
  break;

arithmetic_result_is_null:
69084
69085
69086
69087
69088
69089
69090

69091
69092
69093
69094
69095
69096
69097
  assert( pOp->p4type==P4_INTARRAY );
  assert( pOp->p4.ai );
  aPermute = pOp->p4.ai;
  break;
}

/* Opcode: Compare P1 P2 P3 P4 P5

**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
** the comparison for use by the next OP_Jump instruct.
**
** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
** determined by the most recent OP_Permutation operator.  If the







>







69241
69242
69243
69244
69245
69246
69247
69248
69249
69250
69251
69252
69253
69254
69255
  assert( pOp->p4type==P4_INTARRAY );
  assert( pOp->p4.ai );
  aPermute = pOp->p4.ai;
  break;
}

/* Opcode: Compare P1 P2 P3 P4 P5
** Synopsis: r[P1@P3] <-> r[P2@P3]
**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
** the comparison for use by the next OP_Jump instruct.
**
** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
** determined by the most recent OP_Permutation operator.  If the
70419
70420
70421
70422
70423
70424
70425

70426
70427
70428
70429
70430
70431
70432
      SQLITE_OPEN_DELETEONCLOSE |
      SQLITE_OPEN_TRANSIENT_DB;
  assert( pOp->p1>=0 );
  assert( pOp->p2>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;

  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, 
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
  }
  if( rc==SQLITE_OK ){
    /* If a transient index is required, create it by calling







>







70577
70578
70579
70580
70581
70582
70583
70584
70585
70586
70587
70588
70589
70590
70591
      SQLITE_OPEN_DELETEONCLOSE |
      SQLITE_OPEN_TRANSIENT_DB;
  assert( pOp->p1>=0 );
  assert( pOp->p2>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->isEphemeral = 1;
  rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, 
                        BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
  }
  if( rc==SQLITE_OK ){
    /* If a transient index is required, create it by calling
70909
70910
70911
70912
70913
70914
70915
70916
70917
70918
70919
70920
70921
70922
70923
    assert( pC->rowidIsValid==0 );
  }
  pC->seekResult = res;
  break;
}

/* Opcode: Sequence P1 P2 * * *
** Synopsis: r[P2]=rowid
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
** instruction.  
*/
case OP_Sequence: {           /* out2-prerelease */







|







71068
71069
71070
71071
71072
71073
71074
71075
71076
71077
71078
71079
71080
71081
71082
    assert( pC->rowidIsValid==0 );
  }
  pC->seekResult = res;
  break;
}

/* Opcode: Sequence P1 P2 * * *
** Synopsis: r[P2]=cursor[P1].ctr++
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
** instruction.  
*/
case OP_Sequence: {           /* out2-prerelease */
71600
71601
71602
71603
71604
71605
71606

71607
71608
71609
71610
71611
71612
71613
*/
case OP_SorterNext: {  /* jump */
  VdbeCursor *pC;
  int res;

  pC = p->apCsr[pOp->p1];
  assert( isSorter(pC) );

  rc = sqlite3VdbeSorterNext(db, pC, &res);
  goto next_tail;
case OP_PrevIfOpen:    /* jump */
case OP_NextIfOpen:    /* jump */
  if( p->apCsr[pOp->p1]==0 ) break;
  /* Fall through */
case OP_Prev:          /* jump */







>







71759
71760
71761
71762
71763
71764
71765
71766
71767
71768
71769
71770
71771
71772
71773
*/
case OP_SorterNext: {  /* jump */
  VdbeCursor *pC;
  int res;

  pC = p->apCsr[pOp->p1];
  assert( isSorter(pC) );
  res = 0;
  rc = sqlite3VdbeSorterNext(db, pC, &res);
  goto next_tail;
case OP_PrevIfOpen:    /* jump */
case OP_NextIfOpen:    /* jump */
  if( p->apCsr[pOp->p1]==0 ) break;
  /* Fall through */
case OP_Prev:          /* jump */
71957
71958
71959
71960
71961
71962
71963























71964
71965
71966
71967
71968
71969
71970
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
      aMem[pOp->p3].u.i += nChange;
    }
  }
  break;
}
























/* Opcode: CreateTable P1 P2 * * *
** Synopsis: r[P2]=root iDb=P1
**
** Allocate a new table in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
** P1>1.  Write the root page number of the new table into







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







72117
72118
72119
72120
72121
72122
72123
72124
72125
72126
72127
72128
72129
72130
72131
72132
72133
72134
72135
72136
72137
72138
72139
72140
72141
72142
72143
72144
72145
72146
72147
72148
72149
72150
72151
72152
72153
      assert( memIsValid(&aMem[pOp->p3]) );
      memAboutToChange(p, &aMem[pOp->p3]);
      aMem[pOp->p3].u.i += nChange;
    }
  }
  break;
}

/* Opcode: ResetSorter P1 * * * *
**
** Delete all contents from the ephemeral table or sorter
** that is open on cursor P1.
**
** This opcode only works for cursors used for sorting and
** opened with OP_OpenEphemeral or OP_SorterOpen.
*/
case OP_ResetSorter: {
  VdbeCursor *pC;
 
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  if( pC->pSorter ){
    sqlite3VdbeSorterReset(db, pC->pSorter);
  }else{
    assert( pC->isEphemeral );
    rc = sqlite3BtreeClearTableOfCursor(pC->pCursor);
  }
  break;
}

/* Opcode: CreateTable P1 P2 * * *
** Synopsis: r[P2]=root iDb=P1
**
** Allocate a new table in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
** P1>1.  Write the root page number of the new table into
72264
72265
72266
72267
72268
72269
72270
72271
72272
72273
72274
72275
72276
72277
72278
72279
72280
    sqlite3VdbeMemSetRowSet(pIn1);
    if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  }

  assert( pOp->p4type==P4_INT32 );
  assert( iSet==-1 || iSet>=0 );
  if( iSet ){
    exists = sqlite3RowSetTest(pIn1->u.pRowSet, 
                               (u8)(iSet>=0 ? iSet & 0xf : 0xff),
                               pIn3->u.i);
    VdbeBranchTaken(exists!=0,2);
    if( exists ){
      pc = pOp->p2 - 1;
      break;
    }
  }
  if( iSet>=0 ){







|
<
<







72447
72448
72449
72450
72451
72452
72453
72454


72455
72456
72457
72458
72459
72460
72461
    sqlite3VdbeMemSetRowSet(pIn1);
    if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  }

  assert( pOp->p4type==P4_INT32 );
  assert( iSet==-1 || iSet>=0 );
  if( iSet ){
    exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);


    VdbeBranchTaken(exists!=0,2);
    if( exists ){
      pc = pOp->p2 - 1;
      break;
    }
  }
  if( iSet>=0 ){
72966
72967
72968
72969
72970
72971
72972
72973
72974
72975
72976
72977
72978
72979
72980
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iPlan=r[P3] zPlan='P4'
**
** P1 is a cursor opened using VOpen.  P2 is an address to jump to if
** the filtered result set is empty.
**
** P4 is either NULL or a string that was generated by the xBestIndex
** method of the module.  The interpretation of the P4 string is left
** to the module implementation.







|







73147
73148
73149
73150
73151
73152
73153
73154
73155
73156
73157
73158
73159
73160
73161
  }
  break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iplan=r[P3] zplan='P4'
**
** P1 is a cursor opened using VOpen.  P2 is an address to jump to if
** the filtered result set is empty.
**
** P4 is either NULL or a string that was generated by the xBestIndex
** method of the module.  The interpretation of the P4 string is left
** to the module implementation.
73534
73535
73536
73537
73538
73539
73540
73541
73542
73543
73544
73545
73546
73547
73548
73549
73550
      rc = SQLITE_ERROR;
      sqlite3_finalize(p->pStmt);
      p->pStmt = 0;
    }else{
      p->iOffset = pC->aType[p->iCol + pC->nField];
      p->nByte = sqlite3VdbeSerialTypeLen(type);
      p->pCsr =  pC->pCursor;
      sqlite3BtreeEnterCursor(p->pCsr);
      sqlite3BtreeCacheOverflow(p->pCsr);
      sqlite3BtreeLeaveCursor(p->pCsr);
    }
  }

  if( rc==SQLITE_ROW ){
    rc = SQLITE_OK;
  }else if( p->pStmt ){
    rc = sqlite3_finalize(p->pStmt);







|
<
<







73715
73716
73717
73718
73719
73720
73721
73722


73723
73724
73725
73726
73727
73728
73729
      rc = SQLITE_ERROR;
      sqlite3_finalize(p->pStmt);
      p->pStmt = 0;
    }else{
      p->iOffset = pC->aType[p->iCol + pC->nField];
      p->nByte = sqlite3VdbeSerialTypeLen(type);
      p->pCsr =  pC->pCursor;
      sqlite3BtreeIncrblobCursor(p->pCsr);


    }
  }

  if( rc==SQLITE_ROW ){
    rc = SQLITE_OK;
  }else if( p->pStmt ){
    rc = sqlite3_finalize(p->pStmt);
74429
74430
74431
74432
74433
74434
74435



























74436
74437
74438
74439
74440
74441
74442
74443
74444
74445
74446
74447
74448
74449
74450
74451
74452
74453
74454
74455
74456
74457
74458
74459
74460
  SorterRecord *p;
  SorterRecord *pNext;
  for(p=pRecord; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}




























/*
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
  VdbeSorter *pSorter = pCsr->pSorter;
  if( pSorter ){
    if( pSorter->aIter ){
      int i;
      for(i=0; i<pSorter->nTree; i++){
        vdbeSorterIterZero(db, &pSorter->aIter[i]);
      }
      sqlite3DbFree(db, pSorter->aIter);
    }
    if( pSorter->pTemp1 ){
      sqlite3OsCloseFree(pSorter->pTemp1);
    }
    vdbeSorterRecordFree(db, pSorter->pRecord);
    sqlite3DbFree(db, pSorter->pUnpacked);
    sqlite3DbFree(db, pSorter);
    pCsr->pSorter = 0;
  }
}

/*







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







<
<
<
<
<
|
<
<
<
<
<







74608
74609
74610
74611
74612
74613
74614
74615
74616
74617
74618
74619
74620
74621
74622
74623
74624
74625
74626
74627
74628
74629
74630
74631
74632
74633
74634
74635
74636
74637
74638
74639
74640
74641
74642
74643
74644
74645
74646
74647
74648





74649





74650
74651
74652
74653
74654
74655
74656
  SorterRecord *p;
  SorterRecord *pNext;
  for(p=pRecord; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}

/*
** Reset a sorting cursor back to its original empty state.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
  if( pSorter->aIter ){
    int i;
    for(i=0; i<pSorter->nTree; i++){
      vdbeSorterIterZero(db, &pSorter->aIter[i]);
    }
    sqlite3DbFree(db, pSorter->aIter);
    pSorter->aIter = 0;
  }
  if( pSorter->pTemp1 ){
    sqlite3OsCloseFree(pSorter->pTemp1);
    pSorter->pTemp1 = 0;
  }
  vdbeSorterRecordFree(db, pSorter->pRecord);
  pSorter->pRecord = 0;
  pSorter->iWriteOff = 0;
  pSorter->iReadOff = 0;
  pSorter->nInMemory = 0;
  pSorter->nTree = 0;
  pSorter->nPMA = 0;
  pSorter->aTree = 0;
}


/*
** Free any cursor components allocated by sqlite3VdbeSorterXXX routines.
*/
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
  VdbeSorter *pSorter = pCsr->pSorter;
  if( pSorter ){





    sqlite3VdbeSorterReset(db, pSorter);





    sqlite3DbFree(db, pSorter->pUnpacked);
    sqlite3DbFree(db, pSorter);
    pCsr->pSorter = 0;
  }
}

/*
74882
74883
74884
74885
74886
74887
74888


74889



74890


74891



74892







74893


74894
74895





















74896

74897
74898
74899
74900
74901
74902
74903
*/
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc;                         /* Return code */

  if( pSorter->aTree ){
    int iPrev = pSorter->aTree[1];/* Index of iterator to advance */


    int i;                        /* Index of aTree[] to recalculate */






    rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);



    for(i=(pSorter->nTree+iPrev)/2; rc==SQLITE_OK && i>0; i=i/2){







      rc = vdbeSorterDoCompare(pCsr, i);


    }






















    *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);

  }else{
    SorterRecord *pFree = pSorter->pRecord;
    pSorter->pRecord = pFree->pNext;
    pFree->pNext = 0;
    vdbeSorterRecordFree(db, pFree);
    *pbEof = !pSorter->pRecord;
    rc = SQLITE_OK;







>
>
|
>
>
>

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

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







75078
75079
75080
75081
75082
75083
75084
75085
75086
75087
75088
75089
75090
75091
75092
75093
75094
75095
75096
75097
75098
75099
75100
75101
75102
75103
75104
75105
75106
75107
75108
75109
75110
75111
75112
75113
75114
75115
75116
75117
75118
75119
75120
75121
75122
75123
75124
75125
75126
75127
75128
75129
75130
75131
75132
75133
75134
75135
75136
75137
75138
75139
75140
*/
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
  VdbeSorter *pSorter = pCsr->pSorter;
  int rc;                         /* Return code */

  if( pSorter->aTree ){
    int iPrev = pSorter->aTree[1];/* Index of iterator to advance */
    rc = vdbeSorterIterNext(db, &pSorter->aIter[iPrev]);
    if( rc==SQLITE_OK ){
      int i;                      /* Index of aTree[] to recalculate */
      VdbeSorterIter *pIter1;     /* First iterator to compare */
      VdbeSorterIter *pIter2;     /* Second iterator to compare */
      u8 *pKey2;                  /* To pIter2->aKey, or 0 if record cached */

      /* Find the first two iterators to compare. The one that was just
      ** advanced (iPrev) and the one next to it in the array.  */
      pIter1 = &pSorter->aIter[(iPrev & 0xFFFE)];
      pIter2 = &pSorter->aIter[(iPrev | 0x0001)];
      pKey2 = pIter2->aKey;

      for(i=(pSorter->nTree+iPrev)/2; i>0; i=i/2){
        /* Compare pIter1 and pIter2. Store the result in variable iRes. */
        int iRes;
        if( pIter1->pFile==0 ){
          iRes = +1;
        }else if( pIter2->pFile==0 ){
          iRes = -1;
        }else{
          vdbeSorterCompare(pCsr, 0, 
              pIter1->aKey, pIter1->nKey, pKey2, pIter2->nKey, &iRes
          );
        }

        /* If pIter1 contained the smaller value, set aTree[i] to its index.
        ** Then set pIter2 to the next iterator to compare to pIter1. In this
        ** case there is no cache of pIter2 in pSorter->pUnpacked, so set
        ** pKey2 to point to the record belonging to pIter2.
        **
        ** Alternatively, if pIter2 contains the smaller of the two values,
        ** set aTree[i] to its index and update pIter1. If vdbeSorterCompare()
        ** was actually called above, then pSorter->pUnpacked now contains
        ** a value equivalent to pIter2. So set pKey2 to NULL to prevent
        ** vdbeSorterCompare() from decoding pIter2 again.  */
        if( iRes<=0 ){
          pSorter->aTree[i] = (int)(pIter1 - pSorter->aIter);
          pIter2 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
          pKey2 = pIter2->aKey;
        }else{
          if( pIter1->pFile ) pKey2 = 0;
          pSorter->aTree[i] = (int)(pIter2 - pSorter->aIter);
          pIter1 = &pSorter->aIter[ pSorter->aTree[i ^ 0x0001] ];
        }

      }
      *pbEof = (pSorter->aIter[pSorter->aTree[1]].pFile==0);
    }
  }else{
    SorterRecord *pFree = pSorter->pRecord;
    pSorter->pRecord = pFree->pNext;
    pFree->pNext = 0;
    vdbeSorterRecordFree(db, pFree);
    *pbEof = !pSorter->pRecord;
    rc = SQLITE_OK;
77125
77126
77127
77128
77129
77130
77131

77132
77133
77134
77135
77136
77137
77138
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
  int op;
  pExpr = sqlite3ExprSkipCollate(pExpr);

  op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){







>







77362
77363
77364
77365
77366
77367
77368
77369
77370
77371
77372
77373
77374
77375
77376
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
  int op;
  pExpr = sqlite3ExprSkipCollate(pExpr);
  if( pExpr->flags & EP_Generic ) return SQLITE_AFF_NONE;
  op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){
77157
77158
77159
77160
77161
77162
77163
77164




77165
77166
77167
77168
77169
77170
77171
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken.   Return a pointer to a new Expr node that
** implements the COLLATE operator.
**
** If a memory allocation error occurs, that fact is recorded in pParse->db
** and the pExpr parameter is returned unchanged.
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){




  if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate|EP_Skip;
      pExpr = pNew;
    }







|
>
>
>
>







77395
77396
77397
77398
77399
77400
77401
77402
77403
77404
77405
77406
77407
77408
77409
77410
77411
77412
77413
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken.   Return a pointer to a new Expr node that
** implements the COLLATE operator.
**
** If a memory allocation error occurs, that fact is recorded in pParse->db
** and the pExpr parameter is returned unchanged.
*/
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
  Parse *pParse,           /* Parsing context */
  Expr *pExpr,             /* Add the "COLLATE" clause to this expression */
  const Token *pCollName   /* Name of collating sequence */
){
  if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate|EP_Skip;
      pExpr = pNew;
    }
77210
77211
77212
77213
77214
77215
77216

77217
77218
77219
77220
77221
77222
77223
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
  sqlite3 *db = pParse->db;
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( p ){
    int op = p->op;

    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
      continue;
    }
    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      break;







>







77452
77453
77454
77455
77456
77457
77458
77459
77460
77461
77462
77463
77464
77465
77466
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
  sqlite3 *db = pParse->db;
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( p ){
    int op = p->op;
    if( p->flags & EP_Generic ) break;
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
      continue;
    }
    if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
      break;
78041
78042
78043
78044
78045
78046
78047
78048
78049
78050
78051
78052
78053
78054
78055
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
  ExprList *pNew;
  struct ExprList_item *pItem, *pOldItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->iECursor = 0;
  pNew->nExpr = i = p->nExpr;
  if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
  pNew->a = pItem = sqlite3DbMallocRaw(db,  i*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  } 







<







78284
78285
78286
78287
78288
78289
78290

78291
78292
78293
78294
78295
78296
78297
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
  ExprList *pNew;
  struct ExprList_item *pItem, *pOldItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;

  pNew->nExpr = i = p->nExpr;
  if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; i<p->nExpr; i+=i){}
  pNew->a = pItem = sqlite3DbMallocRaw(db,  i*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqlite3DbFree(db, pNew);
    return 0;
  } 
78154
78155
78156
78157
78158
78159
78160
78161
78162
78163
78164
78165
78166
78167
78168
  pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
  pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
  pNew->iLimit = 0;
  pNew->iOffset = 0;
  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  pNew->nSelectRow = p->nSelectRow;
  pNew->pWith = withDup(db, p->pWith);
  return pNew;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
  assert( p==0 );







<







78396
78397
78398
78399
78400
78401
78402

78403
78404
78405
78406
78407
78408
78409
  pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
  pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
  pNew->iLimit = 0;
  pNew->iOffset = 0;
  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;

  pNew->nSelectRow = p->nSelectRow;
  pNew->pWith = withDup(db, p->pWith);
  return pNew;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
  assert( p==0 );
78722
78723
78724
78725
78726
78727
78728
78729
78730
78731
78732
78733
78734
78735
78736
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( prNotFound ){
      *prNotFound = rMayHaveNull = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
    }else{
      testcase( pParse->nQueryLoop>0 );
      pParse->nQueryLoop = 0;
      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
        eType = IN_INDEX_ROWID;
      }
    }
    sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
    pParse->nQueryLoop = savedNQueryLoop;







<







78963
78964
78965
78966
78967
78968
78969

78970
78971
78972
78973
78974
78975
78976
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( prNotFound ){
      *prNotFound = rMayHaveNull = ++pParse->nMem;
      sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
    }else{

      pParse->nQueryLoop = 0;
      if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
        eType = IN_INDEX_ROWID;
      }
    }
    sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
    pParse->nQueryLoop = savedNQueryLoop;
78972
78973
78974
78975
78976
78977
78978
78979
78980
78981
78982
78983
78984
78985
78986
      break;
    }
  }

  if( testAddr>=0 ){
    sqlite3VdbeJumpHere(v, testAddr);
  }
  sqlite3ExprCachePop(pParse, 1);

  return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */

#ifndef SQLITE_OMIT_SUBQUERY
/*







|







79212
79213
79214
79215
79216
79217
79218
79219
79220
79221
79222
79223
79224
79225
79226
      break;
    }
  }

  if( testAddr>=0 ){
    sqlite3VdbeJumpHere(v, testAddr);
  }
  sqlite3ExprCachePop(pParse);

  return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */

#ifndef SQLITE_OMIT_SUBQUERY
/*
79107
79108
79109
79110
79111
79112
79113
79114
79115
79116
79117
79118
79119
79120
79121
      /* The OP_Found at the top of this branch jumps here when true, 
      ** causing the overall IN expression evaluation to fall through.
      */
      sqlite3VdbeJumpHere(v, j1);
    }
  }
  sqlite3ReleaseTempReg(pParse, r1);
  sqlite3ExprCachePop(pParse, 1);
  VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */

/*
** Duplicate an 8-byte value
*/







|







79347
79348
79349
79350
79351
79352
79353
79354
79355
79356
79357
79358
79359
79360
79361
      /* The OP_Found at the top of this branch jumps here when true, 
      ** causing the overall IN expression evaluation to fall through.
      */
      sqlite3VdbeJumpHere(v, j1);
    }
  }
  sqlite3ReleaseTempReg(pParse, r1);
  sqlite3ExprCachePop(pParse);
  VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */

/*
** Duplicate an 8-byte value
*/
79290
79291
79292
79293
79294
79295
79296
79297
79298
79299
79300
79301
79302
79303
79304
79305
79306
79307
79308
79309
79310
79311
79312
    printf("PUSH to %d\n", pParse->iCacheLevel);
  }
#endif
}

/*
** Remove from the column cache any entries that were added since the
** the previous N Push operations.  In other words, restore the cache
** to the state it was in N Pushes ago.
*/
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse, int N){
  int i;
  struct yColCache *p;
  assert( N>0 );
  assert( pParse->iCacheLevel>=N );
  pParse->iCacheLevel -= N;
#ifdef SQLITE_DEBUG
  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
    printf("POP  to %d\n", pParse->iCacheLevel);
  }
#endif
  for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
    if( p->iReg && p->iLevel>pParse->iCacheLevel ){







|
|

|


<
|
|







79530
79531
79532
79533
79534
79535
79536
79537
79538
79539
79540
79541
79542

79543
79544
79545
79546
79547
79548
79549
79550
79551
    printf("PUSH to %d\n", pParse->iCacheLevel);
  }
#endif
}

/*
** Remove from the column cache any entries that were added since the
** the previous sqlite3ExprCachePush operation.  In other words, restore
** the cache to the state it was in prior the most recent Push.
*/
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
  int i;
  struct yColCache *p;

  assert( pParse->iCacheLevel>=1 );
  pParse->iCacheLevel--;
#ifdef SQLITE_DEBUG
  if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
    printf("POP  to %d\n", pParse->iCacheLevel);
  }
#endif
  for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
    if( p->iReg && p->iLevel>pParse->iCacheLevel ){
79427
79428
79429
79430
79431
79432
79433
79434
79435
79436
79437
79438
79439
79440
79441
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
  int i;
  struct yColCache *p;
  assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
  for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
    int x = p->iReg;
    if( x>=iFrom && x<iFrom+nReg ){
      p->iReg += iTo-iFrom;
    }
  }
}







|







79666
79667
79668
79669
79670
79671
79672
79673
79674
79675
79676
79677
79678
79679
79680
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
  int i;
  struct yColCache *p;
  assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
  sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
  for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
    int x = p->iReg;
    if( x>=iFrom && x<iFrom+nReg ){
      p->iReg += iTo-iFrom;
    }
  }
}
79776
79777
79778
79779
79780
79781
79782
79783
79784
79785
79786
79787
79788
79789
79790
        sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
        for(i=1; i<nFarg; i++){
          sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
          VdbeCoverage(v);
          sqlite3ExprCacheRemove(pParse, target, 1);
          sqlite3ExprCachePush(pParse);
          sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
          sqlite3ExprCachePop(pParse, 1);
        }
        sqlite3VdbeResolveLabel(v, endCoalesce);
        break;
      }

      /* The UNLIKELY() function is a no-op.  The result is the value
      ** of the first argument.







|







80015
80016
80017
80018
80019
80020
80021
80022
80023
80024
80025
80026
80027
80028
80029
        sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
        for(i=1; i<nFarg; i++){
          sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
          VdbeCoverage(v);
          sqlite3ExprCacheRemove(pParse, target, 1);
          sqlite3ExprCachePush(pParse);
          sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
          sqlite3ExprCachePop(pParse);
        }
        sqlite3VdbeResolveLabel(v, endCoalesce);
        break;
      }

      /* The UNLIKELY() function is a no-op.  The result is the value
      ** of the first argument.
79828
79829
79830
79831
79832
79833
79834
79835
79836
79837
79838
79839
79840
79841
79842
79843
79844
            testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
            pFarg->a[0].pExpr->op2 = 
                  pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
          }
        }

        sqlite3ExprCachePush(pParse);     /* Ticket 2ea2425d34be */
        sqlite3ExprCodeExprList(pParse, pFarg, r1, 
                                SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
        sqlite3ExprCachePop(pParse, 1);   /* Ticket 2ea2425d34be */
      }else{
        r1 = 0;
      }
#ifndef SQLITE_OMIT_VIRTUALTABLE
      /* Possibly overload the function if the first argument is
      ** a virtual table column.
      **







|

|







80067
80068
80069
80070
80071
80072
80073
80074
80075
80076
80077
80078
80079
80080
80081
80082
80083
            testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
            pFarg->a[0].pExpr->op2 = 
                  pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
          }
        }

        sqlite3ExprCachePush(pParse);     /* Ticket 2ea2425d34be */
        sqlite3ExprCodeExprList(pParse, pFarg, r1,
                                SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
        sqlite3ExprCachePop(pParse);      /* Ticket 2ea2425d34be */
      }else{
        r1 = 0;
      }
#ifndef SQLITE_OMIT_VIRTUALTABLE
      /* Possibly overload the function if the first argument is
      ** a virtual table column.
      **
80050
80051
80052
80053
80054
80055
80056
80057
80058
80059
80060
80061
80062
80063
80064
80065
80066
80067
80068
80069
80070
        }
        nextCase = sqlite3VdbeMakeLabel(v);
        testcase( pTest->op==TK_COLUMN );
        sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
        testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
        sqlite3ExprCachePop(pParse, 1);
        sqlite3VdbeResolveLabel(v, nextCase);
      }
      if( (nExpr&1)!=0 ){
        sqlite3ExprCachePush(pParse);
        sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
        sqlite3ExprCachePop(pParse, 1);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      }
      assert( db->mallocFailed || pParse->nErr>0 
           || pParse->iCacheLevel==iCacheLevel );
      sqlite3VdbeResolveLabel(v, endLabel);
      break;







|





|







80289
80290
80291
80292
80293
80294
80295
80296
80297
80298
80299
80300
80301
80302
80303
80304
80305
80306
80307
80308
80309
        }
        nextCase = sqlite3VdbeMakeLabel(v);
        testcase( pTest->op==TK_COLUMN );
        sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
        testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
        sqlite3ExprCachePop(pParse);
        sqlite3VdbeResolveLabel(v, nextCase);
      }
      if( (nExpr&1)!=0 ){
        sqlite3ExprCachePush(pParse);
        sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
        sqlite3ExprCachePop(pParse);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      }
      assert( db->mallocFailed || pParse->nErr>0 
           || pParse->iCacheLevel==iCacheLevel );
      sqlite3VdbeResolveLabel(v, endLabel);
      break;
80635
80636
80637
80638
80639
80640
80641
80642
80643
80644
80645
80646
80647
80648
80649
80650
80651
80652
80653
80654
80655
80656
80657
    case TK_AND: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
      sqlite3ExprCachePop(pParse, 1);
      break;
    }
    case TK_OR: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3ExprCachePop(pParse, 1);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }







|







|







80874
80875
80876
80877
80878
80879
80880
80881
80882
80883
80884
80885
80886
80887
80888
80889
80890
80891
80892
80893
80894
80895
80896
    case TK_AND: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
      sqlite3ExprCachePop(pParse);
      break;
    }
    case TK_OR: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3ExprCachePop(pParse);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
80789
80790
80791
80792
80793
80794
80795
80796
80797
80798
80799
80800
80801
80802
80803
80804
80805
80806
80807
80808
80809
80810
80811
80812
80813

  switch( pExpr->op ){
    case TK_AND: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3ExprCachePop(pParse, 1);
      break;
    }
    case TK_OR: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
      sqlite3ExprCachePop(pParse, 1);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }







|









|







81028
81029
81030
81031
81032
81033
81034
81035
81036
81037
81038
81039
81040
81041
81042
81043
81044
81045
81046
81047
81048
81049
81050
81051
81052

  switch( pExpr->op ){
    case TK_AND: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3ExprCachePop(pParse);
      break;
    }
    case TK_OR: {
      int d2 = sqlite3VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite3VdbeResolveLabel(v, d2);
      sqlite3ExprCachePop(pParse);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
81463
81464
81465
81466
81467
81468
81469

81470
81471
81472
81473
81474
81475
81476
  unsigned char const *zNew = sqlite3_value_text(argv[2]);

  unsigned const char *z;         /* Pointer to token */
  int n;                          /* Length of token z */
  int token;                      /* Type of token */

  UNUSED_PARAMETER(NotUsed);

  for(z=zInput; *z; z=z+n){
    n = sqlite3GetToken(z, &token);
    if( token==TK_REFERENCES ){
      char *zParent;
      do {
        z += n;
        n = sqlite3GetToken(z, &token);







>







81702
81703
81704
81705
81706
81707
81708
81709
81710
81711
81712
81713
81714
81715
81716
  unsigned char const *zNew = sqlite3_value_text(argv[2]);

  unsigned const char *z;         /* Pointer to token */
  int n;                          /* Length of token z */
  int token;                      /* Type of token */

  UNUSED_PARAMETER(NotUsed);
  if( zInput==0 || zOld==0 ) return;
  for(z=zInput; *z; z=z+n){
    n = sqlite3GetToken(z, &token);
    if( token==TK_REFERENCES ){
      char *zParent;
      do {
        z += n;
        n = sqlite3GetToken(z, &token);
87457
87458
87459
87460
87461
87462
87463
87464
87465
87466
87467
87468
87469
87470
87471
  ** records into the sorter. */
  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
  regRecord = sqlite3GetTempReg(pParse);

  sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
  sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  sqlite3VdbeResolveLabel(v, iPartIdxLabel);
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);
  if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO);
  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));








|







87697
87698
87699
87700
87701
87702
87703
87704
87705
87706
87707
87708
87709
87710
87711
  ** records into the sorter. */
  sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
  addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
  regRecord = sqlite3GetTempReg(pParse);

  sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
  sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
  sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
  sqlite3VdbeJumpHere(v, addr1);
  if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO);
  sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));

90234
90235
90236
90237
90238
90239
90240
90241
90242
90243
90244
90245
90246
90247
90248
90249
90250
90251
90252
90253
90254
90255
90256
90257
90258
90259

90260
90261
90262
90263
90264
90265
90266
90267
90268
90269
90270
    if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
    if( pIdx==pPk ) continue;
    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
                                 &iPartIdxLabel, pPrior, r1);
    sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
                      pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
    sqlite3VdbeResolveLabel(v, iPartIdxLabel);
    pPrior = pIdx;
  }
}

/*
** Generate code that will assemble an index key and stores it in register
** regOut.  The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.  If pTab is a WITHOUT ROWID table, then
** iCur must be the cursor of the PRIMARY KEY index.
**
** Return a register number which is the first in a block of
** registers that holds the elements of the index key.  The
** block of registers has already been deallocated by the time
** this routine returns.
**
** If *piPartIdxLabel is not NULL, fill it in with a label and jump
** to that label if pIdx is a partial index that should be skipped.

** A partial index should be skipped if its WHERE clause evaluates
** to false or null.  If pIdx is not a partial index, *piPartIdxLabel
** will be set to zero which is an empty label that is ignored by
** sqlite3VdbeResolveLabel().
**
** The pPrior and regPrior parameters are used to implement a cache to
** avoid unnecessary register loads.  If pPrior is not NULL, then it is
** a pointer to a different index for which an index key has just been
** computed into register regPrior.  If the current pIdx index is generating
** its key into the same sequence of registers and if pPrior and pIdx share
** a column in common, then the register corresponding to that column already







|


















>



|







90474
90475
90476
90477
90478
90479
90480
90481
90482
90483
90484
90485
90486
90487
90488
90489
90490
90491
90492
90493
90494
90495
90496
90497
90498
90499
90500
90501
90502
90503
90504
90505
90506
90507
90508
90509
90510
90511
    if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
    if( pIdx==pPk ) continue;
    VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
                                 &iPartIdxLabel, pPrior, r1);
    sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
                      pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
    sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
    pPrior = pIdx;
  }
}

/*
** Generate code that will assemble an index key and stores it in register
** regOut.  The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.  If pTab is a WITHOUT ROWID table, then
** iCur must be the cursor of the PRIMARY KEY index.
**
** Return a register number which is the first in a block of
** registers that holds the elements of the index key.  The
** block of registers has already been deallocated by the time
** this routine returns.
**
** If *piPartIdxLabel is not NULL, fill it in with a label and jump
** to that label if pIdx is a partial index that should be skipped.
** The label should be resolved using sqlite3ResolvePartIdxLabel().
** A partial index should be skipped if its WHERE clause evaluates
** to false or null.  If pIdx is not a partial index, *piPartIdxLabel
** will be set to zero which is an empty label that is ignored by
** sqlite3ResolvePartIdxLabel().
**
** The pPrior and regPrior parameters are used to implement a cache to
** avoid unnecessary register loads.  If pPrior is not NULL, then it is
** a pointer to a different index for which an index key has just been
** computed into register regPrior.  If the current pIdx index is generating
** its key into the same sequence of registers and if pPrior and pIdx share
** a column in common, then the register corresponding to that column already
90289
90290
90291
90292
90293
90294
90295

90296
90297
90298
90299
90300
90301
90302
  int regBase;
  int nCol;

  if( piPartIdxLabel ){
    if( pIdx->pPartIdxWhere ){
      *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
      pParse->iPartIdxTab = iDataCur;

      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, 
                         SQLITE_JUMPIFNULL);
    }else{
      *piPartIdxLabel = 0;
    }
  }
  nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;







>







90530
90531
90532
90533
90534
90535
90536
90537
90538
90539
90540
90541
90542
90543
90544
  int regBase;
  int nCol;

  if( piPartIdxLabel ){
    if( pIdx->pPartIdxWhere ){
      *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
      pParse->iPartIdxTab = iDataCur;
      sqlite3ExprCachePush(pParse);
      sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel, 
                         SQLITE_JUMPIFNULL);
    }else{
      *piPartIdxLabel = 0;
    }
  }
  nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
90316
90317
90318
90319
90320
90321
90322












90323
90324
90325
90326
90327
90328
90329
  }
  if( regOut ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol);
  return regBase;
}













/************** End of delete.c **********************************************/
/************** Begin file func.c ********************************************/
/*
** 2002 February 23
**
** The author disclaims copyright to this source code.  In place of







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







90558
90559
90560
90561
90562
90563
90564
90565
90566
90567
90568
90569
90570
90571
90572
90573
90574
90575
90576
90577
90578
90579
90580
90581
90582
90583
  }
  if( regOut ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol);
  return regBase;
}

/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
** because it was a partial index, then this routine should be called to
** resolve that label.
*/
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
  if( iLabel ){
    sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
    sqlite3ExprCachePop(pParse);
  }
}

/************** End of delete.c **********************************************/
/************** Begin file func.c ********************************************/
/*
** 2002 February 23
**
** The author disclaims copyright to this source code.  In place of
98714
98715
98716
98717
98718
98719
98720
98721
98722
98723
98724
98725
98726
98727
98728
      /* Do the b-tree integrity checks */
      sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
      sqlite3VdbeChangeP5(v, (u8)i);
      addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
      sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
         sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
         P4_DYNAMIC);
      sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
      sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
      sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
      sqlite3VdbeJumpHere(v, addr);

      /* Make sure all the indices are constructed correctly.
      */
      for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){







|







98968
98969
98970
98971
98972
98973
98974
98975
98976
98977
98978
98979
98980
98981
98982
      /* Do the b-tree integrity checks */
      sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
      sqlite3VdbeChangeP5(v, (u8)i);
      addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
      sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
         sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
         P4_DYNAMIC);
      sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
      sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
      sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
      sqlite3VdbeJumpHere(v, addr);

      /* Make sure all the indices are constructed correctly.
      */
      for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
98767
98768
98769
98770
98771
98772
98773
98774
98775
98776
98777
98778
98779
98780
98781
          sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
          jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
          sqlite3VdbeAddOp0(v, OP_Halt);
          sqlite3VdbeJumpHere(v, jmp4);
          sqlite3VdbeJumpHere(v, jmp2);
          sqlite3VdbeResolveLabel(v, jmp3);
        }
        sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
        sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, 
                     "wrong # of entries in index ", P4_STATIC);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){







|







99021
99022
99023
99024
99025
99026
99027
99028
99029
99030
99031
99032
99033
99034
99035
          sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
          sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
          sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
          jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
          sqlite3VdbeAddOp0(v, OP_Halt);
          sqlite3VdbeJumpHere(v, jmp4);
          sqlite3VdbeJumpHere(v, jmp2);
          sqlite3ResolvePartIdxLabel(pParse, jmp3);
        }
        sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
        sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
        sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, 
                     "wrong # of entries in index ", P4_STATIC);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
100052
100053
100054
100055
100056
100057
100058




























100059
100060
100061
100062
100063
100064
100065
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
*/






























/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
static void clearSelect(sqlite3 *db, Select *p){
  sqlite3ExprListDelete(db, p->pEList);







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







100306
100307
100308
100309
100310
100311
100312
100313
100314
100315
100316
100317
100318
100319
100320
100321
100322
100323
100324
100325
100326
100327
100328
100329
100330
100331
100332
100333
100334
100335
100336
100337
100338
100339
100340
100341
100342
100343
100344
100345
100346
100347
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
*/

/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
  u8 isTnct;      /* True if the DISTINCT keyword is present */
  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
};

/*
** An instance of the following object is used to record information about
** the ORDER BY (or GROUP BY) clause of query is being coded.
*/
typedef struct SortCtx SortCtx;
struct SortCtx {
  ExprList *pOrderBy;   /* The ORDER BY (or GROUP BY clause) */
  int nOBSat;           /* Number of ORDER BY terms satisfied by indices */
  int iECursor;         /* Cursor number for the sorter */
  int regReturn;        /* Register holding block-output return address */
  int labelBkOut;       /* Start label for the block-output subroutine */
  int addrSortIndex;    /* Address of the OP_SorterOpen or OP_OpenEphemeral */
  u8 sortFlags;         /* Zero or more SORTFLAG_* bits */
};
#define SORTFLAG_UseSorter  0x01   /* Use SorterOpen instead of OpenEphemeral */

/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
static void clearSelect(sqlite3 *db, Select *p){
  sqlite3ExprListDelete(db, p->pEList);
100125
100126
100127
100128
100129
100130
100131
100132
100133
100134
100135
100136
100137
100138
100139
  pNew->selFlags = selFlags;
  pNew->op = TK_SELECT;
  pNew->pLimit = pLimit;
  pNew->pOffset = pOffset;
  assert( pOffset==0 || pLimit!=0 );
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  if( db->mallocFailed ) {
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
    pNew = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }







<







100407
100408
100409
100410
100411
100412
100413

100414
100415
100416
100417
100418
100419
100420
  pNew->selFlags = selFlags;
  pNew->op = TK_SELECT;
  pNew->pLimit = pLimit;
  pNew->pOffset = pOffset;
  assert( pOffset==0 || pLimit!=0 );
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;

  if( db->mallocFailed ) {
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite3DbFree(db, pNew);
    pNew = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
100457
100458
100459
100460
100461
100462
100463








100464
100465
100466
100467
100468
100469
100470
100471
100472
100473
100474
100475
100476
100477

100478
100479
100480
100481
100482
100483







100484























100485
100486
100487
100488
100489

100490
100491

100492
100493
100494
100495
100496
100497
100498
100499
100500
100501
100502
100503
100504
100505
100506
100507
100508
100509
100510
100511
100512
100513
100514
100515
100516
100517
100518
100519
100520
100521
100522
100523
100524
100525
                     isOuter, &p->pWhere);
      }
    }
  }
  return 0;
}









/*
** Insert code into "v" that will push the record on the top of the
** stack into the sorter.
*/
static void pushOntoSorter(
  Parse *pParse,         /* Parser context */
  ExprList *pOrderBy,    /* The ORDER BY clause */
  Select *pSelect,       /* The whole SELECT statement */
  int regData            /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
  int regRecord = sqlite3GetTempReg(pParse);

  int op;
  sqlite3ExprCacheClear(pParse);
  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);







  if( pSelect->selFlags & SF_UseSorter ){























    op = OP_SorterInsert;
  }else{
    op = OP_IdxInsert;
  }
  sqlite3VdbeAddOp2(v, op, pOrderBy->iECursor, regRecord);

  sqlite3ReleaseTempReg(pParse, regRecord);
  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);

  if( pSelect->iLimit ){
    int addr1, addr2;
    int iLimit;
    if( pSelect->iOffset ){
      iLimit = pSelect->iOffset+1;
    }else{
      iLimit = pSelect->iLimit;
    }
    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
    addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
    sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
    sqlite3VdbeJumpHere(v, addr2);
  }
}

/*
** Add code to implement the OFFSET
*/
static void codeOffset(
  Vdbe *v,          /* Generate code into this VM */
  int iOffset,      /* Register holding the offset counter */
  int iContinue     /* Jump here to skip the current record */
){
  if( iOffset>0 && iContinue!=0 ){
    int addr;
    sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
    addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
    VdbeComment((v, "skip OFFSET records"));
    sqlite3VdbeJumpHere(v, addr);
  }







>
>
>
>
>
>
>
>

|
|



|




|


>


|
|

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




|
>
|
|
>












|
|












|







100738
100739
100740
100741
100742
100743
100744
100745
100746
100747
100748
100749
100750
100751
100752
100753
100754
100755
100756
100757
100758
100759
100760
100761
100762
100763
100764
100765
100766
100767
100768
100769
100770
100771
100772
100773
100774
100775
100776
100777
100778
100779
100780
100781
100782
100783
100784
100785
100786
100787
100788
100789
100790
100791
100792
100793
100794
100795
100796
100797
100798
100799
100800
100801
100802
100803
100804
100805
100806
100807
100808
100809
100810
100811
100812
100813
100814
100815
100816
100817
100818
100819
100820
100821
100822
100823
100824
100825
100826
100827
100828
100829
100830
100831
100832
100833
100834
100835
100836
100837
100838
100839
100840
100841
100842
100843
100844
100845
100846
100847
                     isOuter, &p->pWhere);
      }
    }
  }
  return 0;
}

/* Forward reference */
static KeyInfo *keyInfoFromExprList(
  Parse *pParse,       /* Parsing context */
  ExprList *pList,     /* Form the KeyInfo object from this ExprList */
  int iStart,          /* Begin with this column of pList */
  int nExtra           /* Add this many extra columns to the end */
);

/*
** Insert code into "v" that will push the record in register regData
** into the sorter.
*/
static void pushOntoSorter(
  Parse *pParse,         /* Parser context */
  SortCtx *pSort,        /* Information about the ORDER BY clause */
  Select *pSelect,       /* The whole SELECT statement */
  int regData            /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pSort->pOrderBy->nExpr;
  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
  int regRecord = sqlite3GetTempReg(pParse);
  int nOBSat = pSort->nOBSat;
  int op;
  sqlite3ExprCacheClear(pParse);
  sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
  sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat, regRecord);
  if( nOBSat>0 ){
    int regPrevKey;   /* The first nOBSat columns of the previous row */
    int addrFirst;    /* Address of the OP_IfNot opcode */
    int addrJmp;      /* Address of the OP_Jump opcode */
    VdbeOp *pOp;      /* Opcode that opens the sorter */
    int nKey;         /* Number of sorting key columns, including OP_Sequence */
    KeyInfo *pKI;     /* Original KeyInfo on the sorter table */

    regPrevKey = pParse->nMem+1;
    pParse->nMem += pSort->nOBSat;
    nKey = nExpr - pSort->nOBSat + 1;
    addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
    sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
    pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
    if( pParse->db->mallocFailed ) return;
    pOp->p2 = nKey + 1;
    pKI = pOp->p4.pKeyInfo;
    memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
    sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
    pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1);
    addrJmp = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
    pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
    pSort->regReturn = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
    sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
    sqlite3VdbeJumpHere(v, addrFirst);
    sqlite3VdbeAddOp3(v, OP_Move, regBase, regPrevKey, pSort->nOBSat);
    sqlite3VdbeJumpHere(v, addrJmp);
  }
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    op = OP_SorterInsert;
  }else{
    op = OP_IdxInsert;
  }
  sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
  if( nOBSat==0 ){
    sqlite3ReleaseTempReg(pParse, regRecord);
    sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
  }
  if( pSelect->iLimit ){
    int addr1, addr2;
    int iLimit;
    if( pSelect->iOffset ){
      iLimit = pSelect->iOffset+1;
    }else{
      iLimit = pSelect->iLimit;
    }
    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
    addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
    sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
    sqlite3VdbeJumpHere(v, addr2);
  }
}

/*
** Add code to implement the OFFSET
*/
static void codeOffset(
  Vdbe *v,          /* Generate code into this VM */
  int iOffset,      /* Register holding the offset counter */
  int iContinue     /* Jump here to skip the current record */
){
  if( iOffset>0 ){
    int addr;
    sqlite3VdbeAddOp2(v, OP_AddImm, iOffset, -1);
    addr = sqlite3VdbeAddOp1(v, OP_IfNeg, iOffset); VdbeCoverage(v);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
    VdbeComment((v, "skip OFFSET records"));
    sqlite3VdbeJumpHere(v, addr);
  }
100572
100573
100574
100575
100576
100577
100578
100579
100580
100581
100582
100583
100584
100585
100586
100587
100588
100589
100590
100591
100592
100593
100594
100595
100596
100597
100598
100599
100600
100601
100602
100603
100604
100605
100606
100607
100608
100609
100610
100611
100612
100613
100614
100615
100616
100617
100618
100619
100620
100621
100622

100623

100624
100625
100626
100627
100628
100629
100630
    return 1;
  }else{
    return 0;
  }
}
#endif

/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
** into the selectInnerLoop() routine.
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
  u8 isTnct;      /* True if the DISTINCT keyword is present */
  u8 eTnctType;   /* One of the WHERE_DISTINCT_* operators */
  int tabTnct;    /* Ephemeral table used for DISTINCT processing */
  int addrTnct;   /* Address of OP_OpenEphemeral opcode for tabTnct */
};

/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab is negative, then the pEList expressions
** are evaluated in order to get the data for this row.  If srcTab is
** zero or more, then data is pulled from srcTab and pEList is used only 
** to get number columns and the datatype for each column.
*/
static void selectInnerLoop(
  Parse *pParse,          /* The parser context */
  Select *p,              /* The complete select statement being coded */
  ExprList *pEList,       /* List of values being extracted */
  int srcTab,             /* Pull data from this table */
  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
  DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
  SelectDest *pDest,      /* How to dispose of the results */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int hasDistinct;        /* True if the DISTINCT keyword is present */
  int regResult;              /* Start of memory holding result set */
  int eDest = pDest->eDest;   /* How to dispose of results */
  int iParm = pDest->iSDParm; /* First argument to disposal method */
  int nResultCol;             /* Number of result columns */

  assert( v );
  assert( pEList!=0 );
  hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;

  if( pOrderBy==0 && !hasDistinct ){

    codeOffset(v, p->iOffset, iContinue);
  }

  /* Pull the requested columns.
  */
  nResultCol = pEList->nExpr;








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














|
















>
|
>







100894
100895
100896
100897
100898
100899
100900













100901
100902
100903
100904
100905
100906
100907
100908
100909
100910
100911
100912
100913
100914
100915
100916
100917
100918
100919
100920
100921
100922
100923
100924
100925
100926
100927
100928
100929
100930
100931
100932
100933
100934
100935
100936
100937
100938
100939
100940
100941
    return 1;
  }else{
    return 0;
  }
}
#endif














/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab is negative, then the pEList expressions
** are evaluated in order to get the data for this row.  If srcTab is
** zero or more, then data is pulled from srcTab and pEList is used only 
** to get number columns and the datatype for each column.
*/
static void selectInnerLoop(
  Parse *pParse,          /* The parser context */
  Select *p,              /* The complete select statement being coded */
  ExprList *pEList,       /* List of values being extracted */
  int srcTab,             /* Pull data from this table */
  SortCtx *pSort,         /* If not NULL, info on how to process ORDER BY */
  DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
  SelectDest *pDest,      /* How to dispose of the results */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int hasDistinct;        /* True if the DISTINCT keyword is present */
  int regResult;              /* Start of memory holding result set */
  int eDest = pDest->eDest;   /* How to dispose of results */
  int iParm = pDest->iSDParm; /* First argument to disposal method */
  int nResultCol;             /* Number of result columns */

  assert( v );
  assert( pEList!=0 );
  hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
  if( pSort && pSort->pOrderBy==0 ) pSort = 0;
  if( pSort==0 && !hasDistinct ){
    assert( iContinue!=0 );
    codeOffset(v, p->iOffset, iContinue);
  }

  /* Pull the requested columns.
  */
  nResultCol = pEList->nExpr;

100706
100707
100708
100709
100710
100711
100712
100713
100714
100715
100716
100717
100718
100719
100720

      default: {
        assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
        break;
      }
    }
    if( pOrderBy==0 ){
      codeOffset(v, p->iOffset, iContinue);
    }
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.







|







101017
101018
101019
101020
101021
101022
101023
101024
101025
101026
101027
101028
101029
101030
101031

      default: {
        assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
        codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
        break;
      }
    }
    if( pSort==0 ){
      codeOffset(v, p->iOffset, iContinue);
    }
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
100737
100738
100739
100740
100741
100742
100743

100744
100745
100746
100747
100748
100749
100750
100751
100752
100753
100754
100755
100756
100757
100758
100759
100760
100761
100762
100763
100764
100765
100766
100767
100768
100769
100770
100771
100772
100773
100774
100775
100776
100777
100778
100779
100780
100781
100782
100783
100784
100785
100786
100787
100788
100789
100790
100791
100792
100793
100794
100795
100796
100797
100798
      sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
      break;
    }
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

    /* Store the result as data using a unique key.
    */

    case SRT_DistTable:
    case SRT_Table:
    case SRT_EphemTab: {
      int r1 = sqlite3GetTempReg(pParse);
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
#ifndef SQLITE_OMIT_CTE
      if( eDest==SRT_DistTable ){
        /* If the destination is DistTable, then cursor (iParm+1) is open
        ** on an ephemeral index. If the current row is already present
        ** in the index, do not write it to the output. If not, add the
        ** current row to the index and proceed with writing it to the
        ** output table as well.  */
        int addr = sqlite3VdbeCurrentAddr(v) + 4;
        sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
        assert( pOrderBy==0 );
      }
#endif
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p, r1);
      }else{
        int r2 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      sqlite3ReleaseTempReg(pParse, r1);
      break;
    }

#ifndef SQLITE_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      assert( nResultCol==1 );
      pDest->affSdst =
                  sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        pushOntoSorter(pParse, pOrderBy, p, regResult);
      }else{
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
        sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }







>
|







|
|







|


|
|




















|




|







101048
101049
101050
101051
101052
101053
101054
101055
101056
101057
101058
101059
101060
101061
101062
101063
101064
101065
101066
101067
101068
101069
101070
101071
101072
101073
101074
101075
101076
101077
101078
101079
101080
101081
101082
101083
101084
101085
101086
101087
101088
101089
101090
101091
101092
101093
101094
101095
101096
101097
101098
101099
101100
101101
101102
101103
101104
101105
101106
101107
101108
101109
101110
      sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nResultCol);
      break;
    }
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

    /* Store the result as data using a unique key.
    */
    case SRT_Fifo:
    case SRT_DistFifo:
    case SRT_Table:
    case SRT_EphemTab: {
      int r1 = sqlite3GetTempReg(pParse);
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
#ifndef SQLITE_OMIT_CTE
      if( eDest==SRT_DistFifo ){
        /* If the destination is DistFifo, then cursor (iParm+1) is open
        ** on an ephemeral index. If the current row is already present
        ** in the index, do not write it to the output. If not, add the
        ** current row to the index and proceed with writing it to the
        ** output table as well.  */
        int addr = sqlite3VdbeCurrentAddr(v) + 4;
        sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
        assert( pSort==0 );
      }
#endif
      if( pSort ){
        pushOntoSorter(pParse, pSort, p, r1);
      }else{
        int r2 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      sqlite3ReleaseTempReg(pParse, r1);
      break;
    }

#ifndef SQLITE_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      assert( nResultCol==1 );
      pDest->affSdst =
                  sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
      if( pSort ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        pushOntoSorter(pParse, pSort, p, regResult);
      }else{
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
        sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }
100809
100810
100811
100812
100813
100814
100815
100816
100817
100818
100819
100820
100821
100822
100823
100824
100825
100826
100827
100828
100829
100830
100831
100832
100833
100834
100835
100836
100837
100838
100839
100840

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nResultCol==1 );
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p, regResult);
      }else{
        sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    case SRT_Coroutine:       /* Send data to a co-routine */
    case SRT_Output: {        /* Return the results */
      testcase( eDest==SRT_Coroutine );
      testcase( eDest==SRT_Output );
      if( pOrderBy ){
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }else if( eDest==SRT_Coroutine ){
        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
        sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
      }







|
|












|


|







101121
101122
101123
101124
101125
101126
101127
101128
101129
101130
101131
101132
101133
101134
101135
101136
101137
101138
101139
101140
101141
101142
101143
101144
101145
101146
101147
101148
101149
101150
101151
101152

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nResultCol==1 );
      if( pSort ){
        pushOntoSorter(pParse, pSort, p, regResult);
      }else{
        sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    case SRT_Coroutine:       /* Send data to a co-routine */
    case SRT_Output: {        /* Return the results */
      testcase( eDest==SRT_Coroutine );
      testcase( eDest==SRT_Output );
      if( pSort ){
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
        pushOntoSorter(pParse, pSort, p, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }else if( eDest==SRT_Coroutine ){
        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
        sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
      }
100903
100904
100905
100906
100907
100908
100909
100910
100911
100912
100913
100914
100915
100916
100917
#endif
  }

  /* Jump to the end of the loop if the LIMIT is reached.  Except, if
  ** there is a sorter, in which case the sorter has already limited
  ** the output for us.
  */
  if( pOrderBy==0 && p->iLimit ){
    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
  }
}

/*
** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.







|







101215
101216
101217
101218
101219
101220
101221
101222
101223
101224
101225
101226
101227
101228
101229
#endif
  }

  /* Jump to the end of the loop if the LIMIT is reached.  Except, if
  ** there is a sorter, in which case the sorter has already limited
  ** the output for us.
  */
  if( pSort==0 && p->iLimit ){
    sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
  }
}

/*
** Allocate a KeyInfo object sufficient for an index of N key columns and
** X extra columns.
100974
100975
100976
100977
100978
100979
100980
100981





100982
100983
100984
100985
100986
100987
100988
100989
100990
100991
100992
100993
100994
100995
100996
100997
100998
100999
101000
101001
101002
101003
101004
** then the KeyInfo structure is appropriate for initializing a virtual
** index to implement a DISTINCT test.
**
** Space to hold the KeyInfo structure is obtain from malloc.  The calling
** function is responsible for seeing that this structure is eventually
** freed.
*/
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList, int nExtra){





  int nExpr;
  KeyInfo *pInfo;
  struct ExprList_item *pItem;
  sqlite3 *db = pParse->db;
  int i;

  nExpr = pList->nExpr;
  pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra, 1);
  if( pInfo ){
    assert( sqlite3KeyInfoIsWriteable(pInfo) );
    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
      CollSeq *pColl;
      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      if( !pColl ) pColl = db->pDfltColl;
      pInfo->aColl[i] = pColl;
      pInfo->aSortOrder[i] = pItem->sortOrder;
    }
  }
  return pInfo;
}

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*







|
>
>
>
>
>







|


|



|
|







101286
101287
101288
101289
101290
101291
101292
101293
101294
101295
101296
101297
101298
101299
101300
101301
101302
101303
101304
101305
101306
101307
101308
101309
101310
101311
101312
101313
101314
101315
101316
101317
101318
101319
101320
101321
** then the KeyInfo structure is appropriate for initializing a virtual
** index to implement a DISTINCT test.
**
** Space to hold the KeyInfo structure is obtain from malloc.  The calling
** function is responsible for seeing that this structure is eventually
** freed.
*/
static KeyInfo *keyInfoFromExprList(
  Parse *pParse,       /* Parsing context */
  ExprList *pList,     /* Form the KeyInfo object from this ExprList */
  int iStart,          /* Begin with this column of pList */
  int nExtra           /* Add this many extra columns to the end */
){
  int nExpr;
  KeyInfo *pInfo;
  struct ExprList_item *pItem;
  sqlite3 *db = pParse->db;
  int i;

  nExpr = pList->nExpr;
  pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1);
  if( pInfo ){
    assert( sqlite3KeyInfoIsWriteable(pInfo) );
    for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
      CollSeq *pColl;
      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
      if( !pColl ) pColl = db->pDfltColl;
      pInfo->aColl[i-iStart] = pColl;
      pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
    }
  }
  return pInfo;
}

#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
101092
101093
101094
101095
101096
101097
101098
101099
101100
101101
101102

101103
101104
101105

101106
101107
101108
101109
101110
101111
101112
101113
101114

101115






101116
101117
101118
101119
101120
101121
101122
101123
101124

101125
101126
101127
101128

101129
101130
101131
101132
101133
101134
101135

101136
101137
101138
101139
101140
101141
101142
101143
101144
101145
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.
*/
static void generateSortTail(
  Parse *pParse,    /* Parsing context */
  Select *p,        /* The SELECT statement */
  Vdbe *v,          /* Generate code into this VDBE */
  int nColumn,      /* Number of columns of data */
  SelectDest *pDest /* Write the sorted results here */
){

  int addrBreak = sqlite3VdbeMakeLabel(v);     /* Jump here to exit loop */
  int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
  int addr;

  int iTab;
  int pseudoTab = 0;
  ExprList *pOrderBy = p->pOrderBy;

  int eDest = pDest->eDest;
  int iParm = pDest->iSDParm;

  int regRow;
  int regRowid;








  iTab = pOrderBy->iECursor;
  regRow = sqlite3GetTempReg(pParse);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    pseudoTab = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
    regRowid = 0;
  }else{
    regRowid = sqlite3GetTempReg(pParse);
  }

  if( p->selFlags & SF_UseSorter ){
    int regSortOut = ++pParse->nMem;
    int ptab2 = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, pOrderBy->nExpr+2);

    addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
    VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
    sqlite3VdbeAddOp3(v, OP_Column, ptab2, pOrderBy->nExpr+1, regRow);
    sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
  }else{

    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr+1, regRow);
  }
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);







|



>



>


|
<


<


>

>
>
>
>
>
>
|








>
|


|
>




|


>


|







101409
101410
101411
101412
101413
101414
101415
101416
101417
101418
101419
101420
101421
101422
101423
101424
101425
101426
101427

101428
101429

101430
101431
101432
101433
101434
101435
101436
101437
101438
101439
101440
101441
101442
101443
101444
101445
101446
101447
101448
101449
101450
101451
101452
101453
101454
101455
101456
101457
101458
101459
101460
101461
101462
101463
101464
101465
101466
101467
101468
101469
101470
101471
101472
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.
*/
static void generateSortTail(
  Parse *pParse,    /* Parsing context */
  Select *p,        /* The SELECT statement */
  SortCtx *pSort,   /* Information on the ORDER BY clause */
  int nColumn,      /* Number of columns of data */
  SelectDest *pDest /* Write the sorted results here */
){
  Vdbe *v = pParse->pVdbe;                     /* The prepared statement */
  int addrBreak = sqlite3VdbeMakeLabel(v);     /* Jump here to exit loop */
  int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
  int addr;
  int addrOnce = 0;
  int iTab;
  int pseudoTab = 0;
  ExprList *pOrderBy = pSort->pOrderBy;

  int eDest = pDest->eDest;
  int iParm = pDest->iSDParm;

  int regRow;
  int regRowid;
  int nKey;

  if( pSort->labelBkOut ){
    sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
    sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
    addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
  }
  iTab = pSort->iECursor;
  regRow = sqlite3GetTempReg(pParse);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    pseudoTab = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
    regRowid = 0;
  }else{
    regRowid = sqlite3GetTempReg(pParse);
  }
  nKey = pOrderBy->nExpr - pSort->nOBSat;
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    int regSortOut = ++pParse->nMem;
    int ptab2 = pParse->nTab++;
    sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
    addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
    VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
    sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
    sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
  }else{
    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
  }
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
101186
101187
101188
101189
101190
101191
101192
101193
101194
101195
101196
101197

101198
101199
101200
101201
101202
101203
101204
  }
  sqlite3ReleaseTempReg(pParse, regRow);
  sqlite3ReleaseTempReg(pParse, regRowid);

  /* The bottom of the loop
  */
  sqlite3VdbeResolveLabel(v, addrContinue);
  if( p->selFlags & SF_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
  }

  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
  }
}

/*







|




>







101513
101514
101515
101516
101517
101518
101519
101520
101521
101522
101523
101524
101525
101526
101527
101528
101529
101530
101531
101532
  }
  sqlite3ReleaseTempReg(pParse, regRow);
  sqlite3ReleaseTempReg(pParse, regRowid);

  /* The bottom of the loop
  */
  sqlite3VdbeResolveLabel(v, addrContinue);
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
  }
  if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
  }
}

/*
101872
101873
101874
101875
101876
101877
101878
101879
101880
101881
101882
101883
101884
101885
101886
  Select *pSetup = p->pPrior;   /* The setup query */
  int addrTop;                  /* Top of the loop */
  int addrCont, addrBreak;      /* CONTINUE and BREAK addresses */
  int iCurrent = 0;             /* The Current table */
  int regCurrent;               /* Register holding Current table */
  int iQueue;                   /* The Queue table */
  int iDistinct = 0;            /* To ensure unique results if UNION */
  int eDest = SRT_Table;        /* How to write to Queue */
  SelectDest destQueue;         /* SelectDest targetting the Queue table */
  int i;                        /* Loop counter */
  int rc;                       /* Result code */
  ExprList *pOrderBy;           /* The ORDER BY clause */
  Expr *pLimit, *pOffset;       /* Saved LIMIT and OFFSET */
  int regLimit, regOffset;      /* Registers used by LIMIT and OFFSET */








|







102200
102201
102202
102203
102204
102205
102206
102207
102208
102209
102210
102211
102212
102213
102214
  Select *pSetup = p->pPrior;   /* The setup query */
  int addrTop;                  /* Top of the loop */
  int addrCont, addrBreak;      /* CONTINUE and BREAK addresses */
  int iCurrent = 0;             /* The Current table */
  int regCurrent;               /* Register holding Current table */
  int iQueue;                   /* The Queue table */
  int iDistinct = 0;            /* To ensure unique results if UNION */
  int eDest = SRT_Fifo;         /* How to write to Queue */
  SelectDest destQueue;         /* SelectDest targetting the Queue table */
  int i;                        /* Loop counter */
  int rc;                       /* Result code */
  ExprList *pOrderBy;           /* The ORDER BY clause */
  Expr *pLimit, *pOffset;       /* Saved LIMIT and OFFSET */
  int regLimit, regOffset;      /* Registers used by LIMIT and OFFSET */

101904
101905
101906
101907
101908
101909
101910
101911
101912
101913
101914
101915
101916
101917
101918
101919
101920
101921
101922
101923
101924
      iCurrent = pSrc->a[i].iCursor;
      break;
    }
  }

  /* Allocate cursors numbers for Queue and Distinct.  The cursor number for
  ** the Distinct table must be exactly one greater than Queue in order
  ** for the SRT_DistTable and SRT_DistQueue destinations to work. */
  iQueue = pParse->nTab++;
  if( p->op==TK_UNION ){
    eDest = pOrderBy ? SRT_DistQueue : SRT_DistTable;
    iDistinct = pParse->nTab++;
  }else{
    eDest = pOrderBy ? SRT_Queue : SRT_Table;
  }
  sqlite3SelectDestInit(&destQueue, eDest, iQueue);

  /* Allocate cursors for Current, Queue, and Distinct. */
  regCurrent = ++pParse->nMem;
  sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
  if( pOrderBy ){







|


|


|







102232
102233
102234
102235
102236
102237
102238
102239
102240
102241
102242
102243
102244
102245
102246
102247
102248
102249
102250
102251
102252
      iCurrent = pSrc->a[i].iCursor;
      break;
    }
  }

  /* Allocate cursors numbers for Queue and Distinct.  The cursor number for
  ** the Distinct table must be exactly one greater than Queue in order
  ** for the SRT_DistFifo and SRT_DistQueue destinations to work. */
  iQueue = pParse->nTab++;
  if( p->op==TK_UNION ){
    eDest = pOrderBy ? SRT_DistQueue : SRT_DistFifo;
    iDistinct = pParse->nTab++;
  }else{
    eDest = pOrderBy ? SRT_Queue : SRT_Fifo;
  }
  sqlite3SelectDestInit(&destQueue, eDest, iQueue);

  /* Allocate cursors for Current, Queue, and Distinct. */
  regCurrent = ++pParse->nMem;
  sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
  if( pOrderBy ){
101976
101977
101978
101979
101980
101981
101982

101983
101984
101985
101986
101987
101988
101989
  p->pPrior = pSetup;

  /* Keep running the loop until the Queue is empty */
  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
  sqlite3VdbeResolveLabel(v, addrBreak);

end_of_recursive_query:

  p->pOrderBy = pOrderBy;
  p->pLimit = pLimit;
  p->pOffset = pOffset;
  return;
}
#endif /* SQLITE_OMIT_CTE */








>







102304
102305
102306
102307
102308
102309
102310
102311
102312
102313
102314
102315
102316
102317
102318
  p->pPrior = pSetup;

  /* Keep running the loop until the Queue is empty */
  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
  sqlite3VdbeResolveLabel(v, addrBreak);

end_of_recursive_query:
  sqlite3ExprListDelete(pParse->db, p->pOrderBy);
  p->pOrderBy = pOrderBy;
  p->pLimit = pLimit;
  p->pOffset = pOffset;
  return;
}
#endif /* SQLITE_OMIT_CTE */

104347
104348
104349
104350
104351
104352
104353
104354
104355
104356
104357
104358
104359
104360
104361
      Expr *pE = pFunc->pExpr;
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0);
        sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
                          (char*)pKeyInfo, P4_KEYINFO);
      }
    }
  }
}








|







104676
104677
104678
104679
104680
104681
104682
104683
104684
104685
104686
104687
104688
104689
104690
      Expr *pE = pFunc->pExpr;
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0);
        sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
                          (char*)pKeyInfo, P4_KEYINFO);
      }
    }
  }
}

104502
104503
104504
104505
104506
104507
104508
104509
104510
104511
104512
104513
104514

104515
104516
104517
104518
104519
104520
104521
104522
104523
104524
104525
104526
104527
104528
104529
104530




104531
104532
104533


104534
104535
104536
104537
104538
104539
104540

104541
104542
104543
104544
104545
104546
104547
104548
  int i, j;              /* Loop counters */
  WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */
  Vdbe *v;               /* The virtual machine under construction */
  int isAgg;             /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of columns to extract. */
  SrcList *pTabList;     /* List of tables to select from */
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int rc = 1;            /* Value to return from this function */
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
  DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */

  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */

#ifndef SQLITE_OMIT_EXPLAIN
  int iRestoreSelectId = pParse->iSelectId;
  pParse->iSelectId = pParse->iNextSelectId++;
#endif

  db = pParse->db;
  if( p==0 || db->mallocFailed || pParse->nErr ){
    return 1;
  }
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
  memset(&sAggInfo, 0, sizeof(sAggInfo));





  if( IgnorableOrderby(pDest) ){
    assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);


    /* If ORDER BY makes no difference in the output then neither does
    ** DISTINCT so it can be removed too. */
    sqlite3ExprListDelete(db, p->pOrderBy);
    p->pOrderBy = 0;
    p->selFlags &= ~SF_Distinct;
  }
  sqlite3SelectPrep(pParse, p, 0);

  pOrderBy = p->pOrderBy;
  pTabList = p->pSrc;
  pEList = p->pEList;
  if( pParse->nErr || db->mallocFailed ){
    goto select_end;
  }
  isAgg = (p->selFlags & SF_Aggregate)!=0;
  assert( pEList!=0 );







<



<

>
















>
>
>
>


|
>
>







>
|







104831
104832
104833
104834
104835
104836
104837

104838
104839
104840

104841
104842
104843
104844
104845
104846
104847
104848
104849
104850
104851
104852
104853
104854
104855
104856
104857
104858
104859
104860
104861
104862
104863
104864
104865
104866
104867
104868
104869
104870
104871
104872
104873
104874
104875
104876
104877
104878
104879
104880
104881
104882
104883
  int i, j;              /* Loop counters */
  WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */
  Vdbe *v;               /* The virtual machine under construction */
  int isAgg;             /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of columns to extract. */
  SrcList *pTabList;     /* List of tables to select from */
  Expr *pWhere;          /* The WHERE clause.  May be NULL */

  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int rc = 1;            /* Value to return from this function */

  DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
  SortCtx sSort;         /* Info on how to code the ORDER BY clause */
  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite3 *db;           /* The database connection */

#ifndef SQLITE_OMIT_EXPLAIN
  int iRestoreSelectId = pParse->iSelectId;
  pParse->iSelectId = pParse->iNextSelectId++;
#endif

  db = pParse->db;
  if( p==0 || db->mallocFailed || pParse->nErr ){
    return 1;
  }
  if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
  memset(&sAggInfo, 0, sizeof(sAggInfo));

  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
  assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
  if( IgnorableOrderby(pDest) ){
    assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
           pDest->eDest==SRT_Queue  || pDest->eDest==SRT_DistFifo ||
           pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
    /* If ORDER BY makes no difference in the output then neither does
    ** DISTINCT so it can be removed too. */
    sqlite3ExprListDelete(db, p->pOrderBy);
    p->pOrderBy = 0;
    p->selFlags &= ~SF_Distinct;
  }
  sqlite3SelectPrep(pParse, p, 0);
  memset(&sSort, 0, sizeof(sSort));
  sSort.pOrderBy = p->pOrderBy;
  pTabList = p->pSrc;
  pEList = p->pEList;
  if( pParse->nErr || db->mallocFailed ){
    goto select_end;
  }
  isAgg = (p->selFlags & SF_Aggregate)!=0;
  assert( pEList!=0 );
104656
104657
104658
104659
104660
104661
104662
104663
104664
104665
104666
104667
104668
104669
104670
    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
    }
    pParse->nHeight -= sqlite3SelectExprHeight(p);
    pTabList = p->pSrc;
    if( !IgnorableOrderby(pDest) ){
      pOrderBy = p->pOrderBy;
    }
  }
  pEList = p->pEList;
#endif
  pWhere = p->pWhere;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;







|







104991
104992
104993
104994
104995
104996
104997
104998
104999
105000
105001
105002
105003
105004
105005
    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
    }
    pParse->nHeight -= sqlite3SelectExprHeight(p);
    pTabList = p->pSrc;
    if( !IgnorableOrderby(pDest) ){
      sSort.pOrderBy = p->pOrderBy;
    }
  }
  pEList = p->pEList;
#endif
  pWhere = p->pWhere;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;
104683
104684
104685
104686
104687
104688
104689
104690
104691
104692
104693
104694
104695
104696
104697
104698
104699
104700
104701
104702
104703
104704
104705
104706
104707
104708
104709
104710
104711
104712
104713
104714
104715
104716
104717
104718
104719
104720
104721
104722
104723
104724
104725
104726
104727
104728
104729
104730
104731
104732
104733
104734
104735
104736
104737
104738
104739
104740
104741
104742
104743
104744
104745
104746
104747
104748
104749
104750
104751
104752
104753
104754
104755
104756
104757
104758
104759
104760
104761
104762
104763
104764
104765
104766
104767
104768
104769
104770
104771
104772
104773
104774
104775
104776
104777
104778
104779
104780
104781
104782
104783
104784
104785

104786




104787
104788
104789
104790
104791
104792
104793
104794
104795
104796
104797
104798
104799
104800
104801
104802
104803
104804
104805
  /* If there is both a GROUP BY and an ORDER BY clause and they are
  ** identical, then disable the ORDER BY clause since the GROUP BY
  ** will cause elements to come out in the correct order.  This is
  ** an optimization - the correct answer should result regardless.
  ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
  ** to disable this optimization for testing purposes.
  */
  if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy, -1)==0
         && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
    pOrderBy = 0;
  }

  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
  ** if the select-list is the same as the ORDER BY list, then this query
  ** can be rewritten as a GROUP BY. In other words, this:
  **
  **     SELECT DISTINCT xyz FROM ... ORDER BY xyz
  **
  ** is transformed to:
  **
  **     SELECT xyz FROM ... GROUP BY xyz
  **
  ** The second form is preferred as a single index (or temp-table) may be 
  ** used for both the ORDER BY and DISTINCT processing. As originally 
  ** written the query must use a temp-table for at least one of the ORDER 
  ** BY and DISTINCT, and an index or separate temp-table for the other.
  */
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
   && sqlite3ExprListCompare(pOrderBy, p->pEList, -1)==0
  ){
    p->selFlags &= ~SF_Distinct;
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
    pGroupBy = p->pGroupBy;
    pOrderBy = 0;
    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
    ** original setting of the SF_Distinct flag, not the current setting */
    assert( sDistinct.isTnct );
  }

  /* If there is an ORDER BY clause, then this sorting
  ** index might end up being unused if the data can be 
  ** extracted in pre-sorted order.  If that is the case, then the
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
  ** we figure out that the sorting index is not needed.  The addrSortIndex
  ** variable is used to facilitate that change.
  */
  if( pOrderBy ){
    KeyInfo *pKeyInfo;
    pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 0);
    pOrderBy->iECursor = pParse->nTab++;
    p->addrOpenEphm[2] = addrSortIndex =
      sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
                           pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
                           (char*)pKeyInfo, P4_KEYINFO);
  }else{
    addrSortIndex = -1;
  }

  /* If the output is destined for a temporary table, open that table.
  */
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && addrSortIndex>=0 ){
    sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
    p->selFlags |= SF_UseSorter;
  }

  /* Open a virtual index to use for the distinct set.
  */
  if( p->selFlags & SF_Distinct ){
    sDistinct.tabTnct = pParse->nTab++;
    sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
                                sDistinct.tabTnct, 0, 0,
                                (char*)keyInfoFromExprList(pParse, p->pEList, 0),
                                P4_KEYINFO);
    sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
    sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
  }else{
    sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
  }

  if( !isAgg && pGroupBy==0 ){
    /* No aggregate functions and no GROUP BY clause */
    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);

    /* Begin the database scan. */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList,
                               wctrlFlags, 0);
    if( pWInfo==0 ) goto select_end;
    if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
      p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
    }
    if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
      sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
    }

    if( pOrderBy && sqlite3WhereIsOrdered(pWInfo) ) pOrderBy = 0;





    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( addrSortIndex>=0 && pOrderBy==0 ){
      sqlite3VdbeChangeToNoop(v, addrSortIndex);
      p->addrOpenEphm[2] = -1;
    }

    /* Use the standard inner loop. */
    selectInnerLoop(pParse, p, pEList, -1, pOrderBy, &sDistinct, pDest,
                    sqlite3WhereContinueLabel(pWInfo),
                    sqlite3WhereBreakLabel(pWInfo));

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);
  }else{







|

|


















|




|













|

|
|
|

|


|













|
|
|








|












|
|







>
|
>
>
>
>





|
|
<



|







105018
105019
105020
105021
105022
105023
105024
105025
105026
105027
105028
105029
105030
105031
105032
105033
105034
105035
105036
105037
105038
105039
105040
105041
105042
105043
105044
105045
105046
105047
105048
105049
105050
105051
105052
105053
105054
105055
105056
105057
105058
105059
105060
105061
105062
105063
105064
105065
105066
105067
105068
105069
105070
105071
105072
105073
105074
105075
105076
105077
105078
105079
105080
105081
105082
105083
105084
105085
105086
105087
105088
105089
105090
105091
105092
105093
105094
105095
105096
105097
105098
105099
105100
105101
105102
105103
105104
105105
105106
105107
105108
105109
105110
105111
105112
105113
105114
105115
105116
105117
105118
105119
105120
105121
105122
105123
105124
105125
105126
105127
105128
105129
105130
105131
105132
105133

105134
105135
105136
105137
105138
105139
105140
105141
105142
105143
105144
  /* If there is both a GROUP BY and an ORDER BY clause and they are
  ** identical, then disable the ORDER BY clause since the GROUP BY
  ** will cause elements to come out in the correct order.  This is
  ** an optimization - the correct answer should result regardless.
  ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
  ** to disable this optimization for testing purposes.
  */
  if( sqlite3ExprListCompare(p->pGroupBy, sSort.pOrderBy, -1)==0
         && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
    sSort.pOrderBy = 0;
  }

  /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and 
  ** if the select-list is the same as the ORDER BY list, then this query
  ** can be rewritten as a GROUP BY. In other words, this:
  **
  **     SELECT DISTINCT xyz FROM ... ORDER BY xyz
  **
  ** is transformed to:
  **
  **     SELECT xyz FROM ... GROUP BY xyz
  **
  ** The second form is preferred as a single index (or temp-table) may be 
  ** used for both the ORDER BY and DISTINCT processing. As originally 
  ** written the query must use a temp-table for at least one of the ORDER 
  ** BY and DISTINCT, and an index or separate temp-table for the other.
  */
  if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct 
   && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
  ){
    p->selFlags &= ~SF_Distinct;
    p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
    pGroupBy = p->pGroupBy;
    sSort.pOrderBy = 0;
    /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
    ** the sDistinct.isTnct is still set.  Hence, isTnct represents the
    ** original setting of the SF_Distinct flag, not the current setting */
    assert( sDistinct.isTnct );
  }

  /* If there is an ORDER BY clause, then this sorting
  ** index might end up being unused if the data can be 
  ** extracted in pre-sorted order.  If that is the case, then the
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
  ** we figure out that the sorting index is not needed.  The addrSortIndex
  ** variable is used to facilitate that change.
  */
  if( sSort.pOrderBy ){
    KeyInfo *pKeyInfo;
    pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0);
    sSort.iECursor = pParse->nTab++;
    sSort.addrSortIndex =
      sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
                           sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
                           (char*)pKeyInfo, P4_KEYINFO);
  }else{
    sSort.addrSortIndex = -1;
  }

  /* If the output is destined for a temporary table, open that table.
  */
  if( pDest->eDest==SRT_EphemTab ){
    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
  }

  /* Set the limiter.
  */
  iEnd = sqlite3VdbeMakeLabel(v);
  p->nSelectRow = LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
    sqlite3VdbeGetOp(v, sSort.addrSortIndex)->opcode = OP_SorterOpen;
    sSort.sortFlags |= SORTFLAG_UseSorter;
  }

  /* Open a virtual index to use for the distinct set.
  */
  if( p->selFlags & SF_Distinct ){
    sDistinct.tabTnct = pParse->nTab++;
    sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
                                sDistinct.tabTnct, 0, 0,
                                (char*)keyInfoFromExprList(pParse, p->pEList,0,0),
                                P4_KEYINFO);
    sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
    sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
  }else{
    sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
  }

  if( !isAgg && pGroupBy==0 ){
    /* No aggregate functions and no GROUP BY clause */
    u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);

    /* Begin the database scan. */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
                               p->pEList, wctrlFlags, 0);
    if( pWInfo==0 ) goto select_end;
    if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
      p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
    }
    if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
      sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
    }
    if( sSort.pOrderBy ){
      sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
      if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
        sSort.pOrderBy = 0;
      }
    }

    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( sSort.addrSortIndex>=0 && sSort.pOrderBy==0 ){
      sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);

    }

    /* Use the standard inner loop. */
    selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest,
                    sqlite3WhereContinueLabel(pWInfo),
                    sqlite3WhereBreakLabel(pWInfo));

    /* End the database scan loop.
    */
    sqlite3WhereEnd(pWInfo);
  }else{
104847
104848
104849
104850
104851
104852
104853
104854
104855
104856
104857
104858
104859
104860
104861
    sNC.pParse = pParse;
    sNC.pSrcList = pTabList;
    sNC.pAggInfo = &sAggInfo;
    sAggInfo.mnReg = pParse->nMem+1;
    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
    sAggInfo.pGroupBy = pGroupBy;
    sqlite3ExprAnalyzeAggList(&sNC, pEList);
    sqlite3ExprAnalyzeAggList(&sNC, pOrderBy);
    if( pHaving ){
      sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
    }
    sAggInfo.nAccumulator = sAggInfo.nColumn;
    for(i=0; i<sAggInfo.nFunc; i++){
      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
      sNC.ncFlags |= NC_InAggFunc;







|







105186
105187
105188
105189
105190
105191
105192
105193
105194
105195
105196
105197
105198
105199
105200
    sNC.pParse = pParse;
    sNC.pSrcList = pTabList;
    sNC.pAggInfo = &sAggInfo;
    sAggInfo.mnReg = pParse->nMem+1;
    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
    sAggInfo.pGroupBy = pGroupBy;
    sqlite3ExprAnalyzeAggList(&sNC, pEList);
    sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
    if( pHaving ){
      sqlite3ExprAnalyzeAggregates(&sNC, pHaving);
    }
    sAggInfo.nAccumulator = sAggInfo.nColumn;
    for(i=0; i<sAggInfo.nFunc; i++){
      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
      sNC.ncFlags |= NC_InAggFunc;
104881
104882
104883
104884
104885
104886
104887
104888
104889
104890
104891
104892
104893
104894
104895

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0);
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;







|







105220
105221
105222
105223
105224
105225
105226
105227
105228
105229
105230
105231
105232
105233
105234

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0);
      addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;
104910
104911
104912
104913
104914
104915
104916
104917
104918
104919
104920
104921
104922
104923
104924
104925
104926
104927

      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 
                                 WHERE_GROUPBY, 0);
      if( pWInfo==0 ) goto select_end;
      if( sqlite3WhereIsOrdered(pWInfo) ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        groupBySort = 0;
      }else{
        /* Rows are coming out in undetermined order.  We have to push







|


|







105249
105250
105251
105252
105253
105254
105255
105256
105257
105258
105259
105260
105261
105262
105263
105264
105265
105266

      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
                                 WHERE_GROUPBY, 0);
      if( pWInfo==0 ) goto select_end;
      if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        groupBySort = 0;
      }else{
        /* Rows are coming out in undetermined order.  We have to push
105064
105065
105066
105067
105068
105069
105070
105071
105072
105073
105074
105075
105076
105077
105078
      sqlite3VdbeResolveLabel(v, addrOutputRow);
      addrOutputRow = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
      VdbeComment((v, "Groupby result generator entry point"));
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      finalizeAggFunctions(pParse, &sAggInfo);
      sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, -1, pOrderBy,
                      &sDistinct, pDest,
                      addrOutputRow+1, addrSetAbort);
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      VdbeComment((v, "end groupby result generator"));

      /* Generate a subroutine that will reset the group-by accumulator
      */







|







105403
105404
105405
105406
105407
105408
105409
105410
105411
105412
105413
105414
105415
105416
105417
      sqlite3VdbeResolveLabel(v, addrOutputRow);
      addrOutputRow = sqlite3VdbeCurrentAddr(v);
      sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
      VdbeComment((v, "Groupby result generator entry point"));
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      finalizeAggFunctions(pParse, &sAggInfo);
      sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, -1, &sSort,
                      &sDistinct, pDest,
                      addrOutputRow+1, addrSetAbort);
      sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
      VdbeComment((v, "end groupby result generator"));

      /* Generate a subroutine that will reset the group-by accumulator
      */
105196
105197
105198
105199
105200
105201
105202
105203
105204
105205
105206
105207
105208
105209
105210
105211
105212
105213
105214
105215
105216
105217
105218
105219
105220
105221
105222
105223
105224
105225
105226
105227
105228
105229
105230
105231
105232
105233
105234
105235
105236
105237
105238
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
        if( pWInfo==0 ){
          sqlite3ExprListDelete(db, pDel);
          goto select_end;
        }
        updateAccumulator(pParse, &sAggInfo);
        assert( pMinMax==0 || pMinMax->nExpr==1 );
        if( sqlite3WhereIsOrdered(pWInfo) ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
          VdbeComment((v, "%s() by index",
                (flag==WHERE_ORDERBY_MIN?"min":"max")));
        }
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, &sAggInfo);
      }

      pOrderBy = 0;
      sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, 
                      pDest, addrEnd, addrEnd);
      sqlite3ExprListDelete(db, pDel);
    }
    sqlite3VdbeResolveLabel(v, addrEnd);
    
  } /* endif aggregate query */

  if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
    explainTempTable(pParse, "DISTINCT");
  }

  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( pOrderBy ){
    explainTempTable(pParse, "ORDER BY");
    generateSortTail(pParse, p, v, pEList->nExpr, pDest);
  }

  /* Jump here to skip this query
  */
  sqlite3VdbeResolveLabel(v, iEnd);

  /* The SELECT was successfully coded.   Set the return code to 0







|








|
















|
|
|







105535
105536
105537
105538
105539
105540
105541
105542
105543
105544
105545
105546
105547
105548
105549
105550
105551
105552
105553
105554
105555
105556
105557
105558
105559
105560
105561
105562
105563
105564
105565
105566
105567
105568
105569
105570
105571
105572
105573
105574
105575
105576
105577
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
        if( pWInfo==0 ){
          sqlite3ExprListDelete(db, pDel);
          goto select_end;
        }
        updateAccumulator(pParse, &sAggInfo);
        assert( pMinMax==0 || pMinMax->nExpr==1 );
        if( sqlite3WhereIsOrdered(pWInfo)>0 ){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
          VdbeComment((v, "%s() by index",
                (flag==WHERE_ORDERBY_MIN?"min":"max")));
        }
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, &sAggInfo);
      }

      sSort.pOrderBy = 0;
      sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, -1, 0, 0, 
                      pDest, addrEnd, addrEnd);
      sqlite3ExprListDelete(db, pDel);
    }
    sqlite3VdbeResolveLabel(v, addrEnd);
    
  } /* endif aggregate query */

  if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
    explainTempTable(pParse, "DISTINCT");
  }

  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( sSort.pOrderBy ){
    explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
    generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
  }

  /* Jump here to skip this query
  */
  sqlite3VdbeResolveLabel(v, iEnd);

  /* The SELECT was successfully coded.   Set the return code to 0
109062
109063
109064
109065
109066
109067
109068
109069
109070
109071
109072
109073
109074
109075
109076
      u16 nEq;               /* Number of equality constraints */
      u16 nSkip;             /* Number of initial index columns to skip */
      Index *pIndex;         /* Index used, or NULL */
    } btree;
    struct {               /* Information for virtual tables */
      int idxNum;            /* Index number */
      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
      u8 isOrdered;          /* True if satisfies ORDER BY */
      u16 omitMask;          /* Terms that may be omitted */
      char *idxStr;          /* Index identifier string */
    } vtab;
  } u;
  u32 wsFlags;          /* WHERE_* flags describing the plan */
  u16 nLTerm;           /* Number of entries in aLTerm[] */
  /**** whereLoopXfer() copies fields above ***********************/







|







109401
109402
109403
109404
109405
109406
109407
109408
109409
109410
109411
109412
109413
109414
109415
      u16 nEq;               /* Number of equality constraints */
      u16 nSkip;             /* Number of initial index columns to skip */
      Index *pIndex;         /* Index used, or NULL */
    } btree;
    struct {               /* Information for virtual tables */
      int idxNum;            /* Index number */
      u8 needFree;           /* True if sqlite3_free(idxStr) is needed */
      i8 isOrdered;          /* True if satisfies ORDER BY */
      u16 omitMask;          /* Terms that may be omitted */
      char *idxStr;          /* Index identifier string */
    } vtab;
  } u;
  u32 wsFlags;          /* WHERE_* flags describing the plan */
  u16 nLTerm;           /* Number of entries in aLTerm[] */
  /**** whereLoopXfer() copies fields above ***********************/
109124
109125
109126
109127
109128
109129
109130
109131
109132
109133
109134
109135
109136
109137
109138
109139
** at the end is the choosen query plan.
*/
struct WherePath {
  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
  Bitmask revLoop;      /* aLoop[]s that should be reversed for ORDER BY */
  LogEst nRow;          /* Estimated number of rows generated by this path */
  LogEst rCost;         /* Total cost of this path */
  u8 isOrdered;         /* True if this path satisfies ORDER BY */
  u8 isOrderedValid;    /* True if the isOrdered field is valid */
  WhereLoop **aLoop;    /* Array of WhereLoop objects implementing this path */
};

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by AND operators,







|
<







109463
109464
109465
109466
109467
109468
109469
109470

109471
109472
109473
109474
109475
109476
109477
** at the end is the choosen query plan.
*/
struct WherePath {
  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
  Bitmask revLoop;      /* aLoop[]s that should be reversed for ORDER BY */
  LogEst nRow;          /* Estimated number of rows generated by this path */
  LogEst rCost;         /* Total cost of this path */
  i8 isOrdered;         /* No. of ORDER BY terms satisfied. -1 for unknown */

  WhereLoop **aLoop;    /* Array of WhereLoop objects implementing this path */
};

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by AND operators,
109339
109340
109341
109342
109343
109344
109345
109346
109347
109348
109349
109350
109351
109352
109353
  SrcList *pTabList;        /* List of tables in the join */
  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
  ExprList *pResultSet;     /* Result set. DISTINCT operates on these */
  WhereLoop *pLoops;        /* List of all WhereLoop objects */
  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
  LogEst nRowOut;           /* Estimated number of output rows */
  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
  u8 bOBSat;                /* ORDER BY satisfied by indices */
  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
  u8 nLevel;                /* Number of nested loop */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */







|







109677
109678
109679
109680
109681
109682
109683
109684
109685
109686
109687
109688
109689
109690
109691
  SrcList *pTabList;        /* List of tables in the join */
  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
  ExprList *pResultSet;     /* Result set. DISTINCT operates on these */
  WhereLoop *pLoops;        /* List of all WhereLoop objects */
  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
  LogEst nRowOut;           /* Estimated number of output rows */
  u16 wctrlFlags;           /* Flags originally passed to sqlite3WhereBegin() */
  i8 nOBSat;                /* Number of ORDER BY terms satisfied by indices */
  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
  u8 nLevel;                /* Number of nested loop */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */
109423
109424
109425
109426
109427
109428
109429
109430
109431
109432
109433
109434
109435
109436
109437

109438
109439
109440
109441
109442
109443
109444
}

/*
** Return TRUE if the WHERE clause returns rows in ORDER BY order.
** Return FALSE if the output needs to be sorted.
*/
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
  return pWInfo->bOBSat!=0;
}

/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){

  return pWInfo->iContinue;
}

/*
** Return the VDBE address or label to jump to in order to break
** out of a WHERE loop.
*/







|







>







109761
109762
109763
109764
109765
109766
109767
109768
109769
109770
109771
109772
109773
109774
109775
109776
109777
109778
109779
109780
109781
109782
109783
}

/*
** Return TRUE if the WHERE clause returns rows in ORDER BY order.
** Return FALSE if the output needs to be sorted.
*/
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
  return pWInfo->nOBSat;
}

/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
  assert( pWInfo->iContinue!=0 );
  return pWInfo->iContinue;
}

/*
** Return the VDBE address or label to jump to in order to break
** out of a WHERE loop.
*/
112224
112225
112226
112227
112228
112229
112230
112231
112232
112233
112234
112235
112236
112237
112238
        disableTerm(pLevel, pLoop->aLTerm[j]);
      }
    }
    pLevel->op = OP_VNext;
    pLevel->p1 = iCur;
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
    sqlite3ExprCachePop(pParse, 1);
  }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */

  if( (pLoop->wsFlags & WHERE_IPK)!=0
   && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
  ){
    /* Case 2:  We can directly reference a single row using an







|







112563
112564
112565
112566
112567
112568
112569
112570
112571
112572
112573
112574
112575
112576
112577
        disableTerm(pLevel, pLoop->aLTerm[j]);
      }
    }
    pLevel->op = OP_VNext;
    pLevel->p1 = iCur;
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
    sqlite3ExprCachePop(pParse);
  }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */

  if( (pLoop->wsFlags & WHERE_IPK)!=0
   && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
  ){
    /* Case 2:  We can directly reference a single row using an
112420
112421
112422
112423
112424
112425
112426



112427
112428
112429
112430
112431
112432
112433
112434
112435
    ** was passed to this function to implement a "SELECT min(x) ..." 
    ** query, then the caller will only allow the loop to run for
    ** a single iteration. This means that the first row returned
    ** should not have a NULL value stored in 'x'. If column 'x' is
    ** the first one after the nEq equality constraints in the index,
    ** this requires some special handling.
    */



    if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
     && (pWInfo->bOBSat!=0)
     && (pIdx->nKeyCol>nEq)
    ){
      assert( pLoop->u.btree.nSkip==0 );
      bSeekPastNull = 1;
      nExtraReg = 1;
    }








>
>
>

|







112759
112760
112761
112762
112763
112764
112765
112766
112767
112768
112769
112770
112771
112772
112773
112774
112775
112776
112777
    ** was passed to this function to implement a "SELECT min(x) ..." 
    ** query, then the caller will only allow the loop to run for
    ** a single iteration. This means that the first row returned
    ** should not have a NULL value stored in 'x'. If column 'x' is
    ** the first one after the nEq equality constraints in the index,
    ** this requires some special handling.
    */
    assert( pWInfo->pOrderBy==0
         || pWInfo->pOrderBy->nExpr==1
         || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
    if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
     && pWInfo->nOBSat>0
     && (pIdx->nKeyCol>nEq)
    ){
      assert( pLoop->u.btree.nSkip==0 );
      bSeekPastNull = 1;
      nExtraReg = 1;
    }

112592
112593
112594
112595
112596
112597
112598
112599
112600
112601
112602
112603
112604
112605
112606
112607
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
    }
    pLevel->p1 = iIdxCur;
    assert( (WHERE_UNQ_WANTED>>16)==1 );
    pLevel->p3 = (pLoop->wsFlags>>16)&1;
    if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
    }else{
      assert( pLevel->p5==0 );
    }
  }else








<
|







112934
112935
112936
112937
112938
112939
112940

112941
112942
112943
112944
112945
112946
112947
112948
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
    }
    pLevel->p1 = iIdxCur;

    pLevel->p3 = (pLoop->wsFlags&WHERE_UNQ_WANTED)!=0 ? 1:0;
    if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
      pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
    }else{
      assert( pLevel->p5==0 );
    }
  }else

113091
113092
113093
113094
113095
113096
113097



































































































































113098
113099
113100
113101
113102
113103
113104
113105
113106
113107
113108
113109
113110
113111
113112
113113
113114
113115
113116
113117
113118
113119
113120
113121
113122
113123
113124
113125
113126
113127
113128
113129
113130
113131
113132
113133
      WhereLoop *p = pWInfo->pLoops;
      pWInfo->pLoops = p->pNextLoop;
      whereLoopDelete(db, p);
    }
    sqlite3DbFree(db, pWInfo);
  }
}




































































































































/*
** Insert or replace a WhereLoop entry using the template supplied.
**
** An existing WhereLoop entry might be overwritten if the new template
** is better and has fewer dependencies.  Or the template will be ignored
** and no insert will occur if an existing WhereLoop is faster and has
** fewer dependencies than the template.  Otherwise a new WhereLoop is
** added based on the template.
**
** If pBuilder->pOrSet is not NULL then we only care about only the
** prerequisites and rRun and nOut costs of the N best loops.  That
** information is gathered in the pBuilder->pOrSet object.  This special
** processing mode is used only for OR clause processing.
**
** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
** still might overwrite similar loops with the new template if the
** template is better.  Loops may be overwritten if the following 
** conditions are met:
**
**    (1)  They have the same iTab.
**    (2)  They have the same iSortIdx.
**    (3)  The template has same or fewer dependencies than the current loop
**    (4)  The template has the same or lower cost than the current loop
**    (5)  The template uses more terms of the same index but has no additional
**         dependencies          
*/
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
  WhereLoop **ppPrev, *p, *pNext = 0;
  WhereInfo *pWInfo = pBuilder->pWInfo;
  sqlite3 *db = pWInfo->pParse->db;

  /* If pBuilder->pOrSet is defined, then only keep track of the costs
  ** and prereqs.
  */
  if( pBuilder->pOrSet!=0 ){







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










|






|






<
<


|







113432
113433
113434
113435
113436
113437
113438
113439
113440
113441
113442
113443
113444
113445
113446
113447
113448
113449
113450
113451
113452
113453
113454
113455
113456
113457
113458
113459
113460
113461
113462
113463
113464
113465
113466
113467
113468
113469
113470
113471
113472
113473
113474
113475
113476
113477
113478
113479
113480
113481
113482
113483
113484
113485
113486
113487
113488
113489
113490
113491
113492
113493
113494
113495
113496
113497
113498
113499
113500
113501
113502
113503
113504
113505
113506
113507
113508
113509
113510
113511
113512
113513
113514
113515
113516
113517
113518
113519
113520
113521
113522
113523
113524
113525
113526
113527
113528
113529
113530
113531
113532
113533
113534
113535
113536
113537
113538
113539
113540
113541
113542
113543
113544
113545
113546
113547
113548
113549
113550
113551
113552
113553
113554
113555
113556
113557
113558
113559
113560
113561
113562
113563
113564
113565
113566
113567
113568
113569
113570
113571
113572
113573
113574
113575
113576
113577
113578
113579
113580
113581
113582
113583
113584
113585
113586
113587
113588
113589
113590
113591
113592
113593


113594
113595
113596
113597
113598
113599
113600
113601
113602
113603
      WhereLoop *p = pWInfo->pLoops;
      pWInfo->pLoops = p->pNextLoop;
      whereLoopDelete(db, p);
    }
    sqlite3DbFree(db, pWInfo);
  }
}

/*
** Return TRUE if both of the following are true:
**
**   (1)  X has the same or lower cost that Y
**   (2)  X is a proper subset of Y
**
** By "proper subset" we mean that X uses fewer WHERE clause terms
** than Y and that every WHERE clause term used by X is also used
** by Y.
**
** If X is a proper subset of Y then Y is a better choice and ought
** to have a lower cost.  This routine returns TRUE when that cost 
** relationship is inverted and needs to be adjusted.
*/
static int whereLoopCheaperProperSubset(
  const WhereLoop *pX,       /* First WhereLoop to compare */
  const WhereLoop *pY        /* Compare against this WhereLoop */
){
  int i, j;
  if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */
  if( pX->rRun >= pY->rRun ){
    if( pX->rRun > pY->rRun ) return 0;    /* X costs more than Y */
    if( pX->nOut > pY->nOut ) return 0;    /* X costs more than Y */
  }
  for(j=0, i=pX->nLTerm-1; i>=0; i--){
    for(j=pY->nLTerm-1; j>=0; j--){
      if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
    }
    if( j<0 ) return 0;  /* X not a subset of Y since term X[i] not used by Y */
  }
  return 1;  /* All conditions meet */
}

/*
** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so
** that:
**
**   (1) pTemplate costs less than any other WhereLoops that are a proper
**       subset of pTemplate
**
**   (2) pTemplate costs more than any other WhereLoops for which pTemplate
**       is a proper subset.
**
** To say "WhereLoop X is a proper subset of Y" means that X uses fewer
** WHERE clause terms than Y and that every WHERE clause term used by X is
** also used by Y.
*/
static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
  if( (pTemplate->wsFlags & WHERE_INDEXED)==0 ) return;
  for(; p; p=p->pNextLoop){
    if( p->iTab!=pTemplate->iTab ) continue;
    if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
    if( whereLoopCheaperProperSubset(p, pTemplate) ){
      /* Adjust pTemplate cost downward so that it is cheaper than its 
      ** subset p */
      pTemplate->rRun = p->rRun;
      pTemplate->nOut = p->nOut - 1;
    }else if( whereLoopCheaperProperSubset(pTemplate, p) ){
      /* Adjust pTemplate cost upward so that it is costlier than p since
      ** pTemplate is a proper subset of p */
      pTemplate->rRun = p->rRun;
      pTemplate->nOut = p->nOut + 1;
    }
  }
}

/*
** Search the list of WhereLoops in *ppPrev looking for one that can be
** supplanted by pTemplate.
**
** Return NULL if the WhereLoop list contains an entry that can supplant
** pTemplate, in other words if pTemplate does not belong on the list.
**
** If pX is a WhereLoop that pTemplate can supplant, then return the
** link that points to pX.
**
** If pTemplate cannot supplant any existing element of the list but needs
** to be added to the list, then return a pointer to the tail of the list.
*/
static WhereLoop **whereLoopFindLesser(
  WhereLoop **ppPrev,
  const WhereLoop *pTemplate
){
  WhereLoop *p;
  for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){
    if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
      /* If either the iTab or iSortIdx values for two WhereLoop are different
      ** then those WhereLoops need to be considered separately.  Neither is
      ** a candidate to replace the other. */
      continue;
    }
    /* In the current implementation, the rSetup value is either zero
    ** or the cost of building an automatic index (NlogN) and the NlogN
    ** is the same for compatible WhereLoops. */
    assert( p->rSetup==0 || pTemplate->rSetup==0 
                 || p->rSetup==pTemplate->rSetup );

    /* whereLoopAddBtree() always generates and inserts the automatic index
    ** case first.  Hence compatible candidate WhereLoops never have a larger
    ** rSetup. Call this SETUP-INVARIANT */
    assert( p->rSetup>=pTemplate->rSetup );

    /* If existing WhereLoop p is better than pTemplate, pTemplate can be
    ** discarded.  WhereLoop p is better if:
    **   (1)  p has no more dependencies than pTemplate, and
    **   (2)  p has an equal or lower cost than pTemplate
    */
    if( (p->prereq & pTemplate->prereq)==p->prereq    /* (1)  */
     && p->rSetup<=pTemplate->rSetup                  /* (2a) */
     && p->rRun<=pTemplate->rRun                      /* (2b) */
     && p->nOut<=pTemplate->nOut                      /* (2c) */
    ){
      return 0;  /* Discard pTemplate */
    }

    /* If pTemplate is always better than p, then cause p to be overwritten
    ** with pTemplate.  pTemplate is better than p if:
    **   (1)  pTemplate has no more dependences than p, and
    **   (2)  pTemplate has an equal or lower cost than p.
    */
    if( (p->prereq & pTemplate->prereq)==pTemplate->prereq   /* (1)  */
     && p->rRun>=pTemplate->rRun                             /* (2a) */
     && p->nOut>=pTemplate->nOut                             /* (2b) */
    ){
      assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
      break;   /* Cause p to be overwritten by pTemplate */
    }
  }
  return ppPrev;
}

/*
** Insert or replace a WhereLoop entry using the template supplied.
**
** An existing WhereLoop entry might be overwritten if the new template
** is better and has fewer dependencies.  Or the template will be ignored
** and no insert will occur if an existing WhereLoop is faster and has
** fewer dependencies than the template.  Otherwise a new WhereLoop is
** added based on the template.
**
** If pBuilder->pOrSet is not NULL then we care about only the
** prerequisites and rRun and nOut costs of the N best loops.  That
** information is gathered in the pBuilder->pOrSet object.  This special
** processing mode is used only for OR clause processing.
**
** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
** still might overwrite similar loops with the new template if the
** new template is better.  Loops may be overwritten if the following 
** conditions are met:
**
**    (1)  They have the same iTab.
**    (2)  They have the same iSortIdx.
**    (3)  The template has same or fewer dependencies than the current loop
**    (4)  The template has the same or lower cost than the current loop


*/
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
  WhereLoop **ppPrev, *p;
  WhereInfo *pWInfo = pBuilder->pWInfo;
  sqlite3 *db = pWInfo->pParse->db;

  /* If pBuilder->pOrSet is defined, then only keep track of the costs
  ** and prereqs.
  */
  if( pBuilder->pOrSet!=0 ){
113142
113143
113144
113145
113146
113147
113148
113149
113150
113151
113152
113153
113154
113155
113156
113157
113158
113159
113160

113161
113162
113163
113164
113165
113166
113167

113168
113169
113170
113171
113172
113173
113174
113175
113176
113177
113178
113179
113180
113181
113182
113183
113184
113185
113186
113187
113188
113189
113190
113191
113192
113193
113194
113195
113196
113197
113198
113199
113200
113201
113202
113203
113204
113205
113206
113207
113208
113209
113210
113211
113212
113213
113214
113215
113216
113217
113218
113219
113220
113221
113222
113223

113224
113225
113226

















113227




113228
113229
113230
113231
113232
113233
113234
113235
113236
113237
113238
113239
113240
113241
113242
113243
113244
113245
113246
113247
113248
113249
113250
113251
113252
113253
113254
      sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
      whereLoopPrint(pTemplate, pBuilder->pWC);
    }
#endif
    return SQLITE_OK;
  }

  /* Search for an existing WhereLoop to overwrite, or which takes
  ** priority over pTemplate.
  */
  for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
    if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
      /* If either the iTab or iSortIdx values for two WhereLoop are different
      ** then those WhereLoops need to be considered separately.  Neither is
      ** a candidate to replace the other. */
      continue;
    }
    /* In the current implementation, the rSetup value is either zero
    ** or the cost of building an automatic index (NlogN) and the NlogN

    ** is the same for compatible WhereLoops. */
    assert( p->rSetup==0 || pTemplate->rSetup==0 
                 || p->rSetup==pTemplate->rSetup );

    /* whereLoopAddBtree() always generates and inserts the automatic index
    ** case first.  Hence compatible candidate WhereLoops never have a larger
    ** rSetup. Call this SETUP-INVARIANT */

    assert( p->rSetup>=pTemplate->rSetup );

    if( (p->prereq & pTemplate->prereq)==p->prereq
     && p->rSetup<=pTemplate->rSetup
     && p->rRun<=pTemplate->rRun
     && p->nOut<=pTemplate->nOut
    ){
      /* This branch taken when p is equal or better than pTemplate in 
      ** all of (1) dependencies (2) setup-cost, (3) run-cost, and
      ** (4) number of output rows. */
      assert( p->rSetup==pTemplate->rSetup );
      if( p->prereq==pTemplate->prereq
       && p->nLTerm<pTemplate->nLTerm
       && (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0
       && (p->u.btree.pIndex==pTemplate->u.btree.pIndex
          || pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm)
      ){
        /* Overwrite an existing WhereLoop with an similar one that uses
        ** more terms of the index */
        pNext = p->pNextLoop;
        break;
      }else{
        /* pTemplate is not helpful.
        ** Return without changing or adding anything */
        goto whereLoopInsert_noop;
      }
    }
    if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
     && p->rRun>=pTemplate->rRun
     && p->nOut>=pTemplate->nOut
    ){
      /* Overwrite an existing WhereLoop with a better one: one that is
      ** better at one of (1) dependencies, (2) setup-cost, (3) run-cost
      ** or (4) number of output rows, and is no worse in any of those
      ** categories. */
      assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
      pNext = p->pNextLoop;
      break;
    }
  }

  /* If we reach this point it means that either p[] should be overwritten
  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
  ** WhereLoop and insert it.
  */
#if WHERETRACE_ENABLED /* 0x8 */
  if( sqlite3WhereTrace & 0x8 ){
    if( p!=0 ){
      sqlite3DebugPrintf("ins-del:  ");
      whereLoopPrint(p, pBuilder->pWC);
    }
    sqlite3DebugPrintf("ins-new:  ");
    whereLoopPrint(pTemplate, pBuilder->pWC);
  }
#endif
  if( p==0 ){

    p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
    if( p==0 ) return SQLITE_NOMEM;
    whereLoopInit(p);

















  }




  whereLoopXfer(db, p, pTemplate);
  p->pNextLoop = pNext;
  *ppPrev = p;
  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
    Index *pIndex = p->u.btree.pIndex;
    if( pIndex && pIndex->tnum==0 ){
      p->u.btree.pIndex = 0;
    }
  }
  return SQLITE_OK;

  /* Jump here if the insert is a no-op */
whereLoopInsert_noop:
#if WHERETRACE_ENABLED /* 0x8 */
  if( sqlite3WhereTrace & 0x8 ){
    sqlite3DebugPrintf("ins-noop: ");
    whereLoopPrint(pTemplate, pBuilder->pWC);
  }
#endif
  return SQLITE_OK;  
}

/*
** Adjust the WhereLoop.nOut value downward to account for terms of the
** WHERE clause that reference the loop but which are not used by an
** index.
**







|
<

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

















>
|


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

<
<







<
<
<
<
<
<
<
<
<
<







113612
113613
113614
113615
113616
113617
113618
113619

113620
113621
113622




113623


113624
113625

113626
113627

113628

113629
113630
113631
















113632

113633
113634















113635

113636
113637
113638
113639
113640
113641
113642
113643
113644
113645
113646
113647
113648
113649
113650
113651
113652
113653
113654
113655
113656
113657
113658
113659
113660
113661
113662
113663
113664
113665
113666
113667
113668
113669
113670
113671
113672
113673
113674
113675
113676
113677
113678
113679


113680
113681
113682
113683
113684
113685
113686










113687
113688
113689
113690
113691
113692
113693
      sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
      whereLoopPrint(pTemplate, pBuilder->pWC);
    }
#endif
    return SQLITE_OK;
  }

  /* Look for an existing WhereLoop to replace with pTemplate

  */
  whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
  ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);







  if( ppPrev==0 ){
    /* There already exists a WhereLoop on the list that is better

    ** than pTemplate, so just ignore pTemplate */
#if WHERETRACE_ENABLED /* 0x8 */

    if( sqlite3WhereTrace & 0x8 ){

      sqlite3DebugPrintf("ins-noop: ");
      whereLoopPrint(pTemplate, pBuilder->pWC);
    }
















#endif

    return SQLITE_OK;  
  }else{















    p = *ppPrev;

  }

  /* If we reach this point it means that either p[] should be overwritten
  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
  ** WhereLoop and insert it.
  */
#if WHERETRACE_ENABLED /* 0x8 */
  if( sqlite3WhereTrace & 0x8 ){
    if( p!=0 ){
      sqlite3DebugPrintf("ins-del:  ");
      whereLoopPrint(p, pBuilder->pWC);
    }
    sqlite3DebugPrintf("ins-new:  ");
    whereLoopPrint(pTemplate, pBuilder->pWC);
  }
#endif
  if( p==0 ){
    /* Allocate a new WhereLoop to add to the end of the list */
    *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
    if( p==0 ) return SQLITE_NOMEM;
    whereLoopInit(p);
    p->pNextLoop = 0;
  }else{
    /* We will be overwriting WhereLoop p[].  But before we do, first
    ** go through the rest of the list and delete any other entries besides
    ** p[] that are also supplated by pTemplate */
    WhereLoop **ppTail = &p->pNextLoop;
    WhereLoop *pToDel;
    while( *ppTail ){
      ppTail = whereLoopFindLesser(ppTail, pTemplate);
      if( NEVER(ppTail==0) ) break;
      pToDel = *ppTail;
      if( pToDel==0 ) break;
      *ppTail = pToDel->pNextLoop;
#if WHERETRACE_ENABLED /* 0x8 */
      if( sqlite3WhereTrace & 0x8 ){
        sqlite3DebugPrintf("ins-del: ");
        whereLoopPrint(pToDel, pBuilder->pWC);
      }
#endif
      whereLoopDelete(db, pToDel);
    }
  }
  whereLoopXfer(db, p, pTemplate);


  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
    Index *pIndex = p->u.btree.pIndex;
    if( pIndex && pIndex->tnum==0 ){
      p->u.btree.pIndex = 0;
    }
  }
  return SQLITE_OK;










}

/*
** Adjust the WhereLoop.nOut value downward to account for terms of the
** WHERE clause that reference the loop but which are not used by an
** index.
**
113394
113395
113396
113397
113398
113399
113400


113401
113402
113403
113404
113405
113406
113407
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
        nIn = 46;  assert( 46==sqlite3LogEst(25) );
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
      }


      pNew->rRun += nIn;
      pNew->u.btree.nEq++;
      pNew->nOut = nRowEst + nInMul + nIn;
    }else if( pTerm->eOperator & (WO_EQ) ){
      assert(
        (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN|WHERE_SKIPSCAN))!=0
        || nInMul==0







>
>







113833
113834
113835
113836
113837
113838
113839
113840
113841
113842
113843
113844
113845
113846
113847
113848
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
        nIn = 46;  assert( 46==sqlite3LogEst(25) );
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
      }
      assert( nIn>0 );  /* RHS always has 2 or more terms...  The parser
                        ** changes "x IN (?)" into "x=?". */
      pNew->rRun += nIn;
      pNew->u.btree.nEq++;
      pNew->nOut = nRowEst + nInMul + nIn;
    }else if( pTerm->eOperator & (WO_EQ) ){
      assert(
        (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN|WHERE_SKIPSCAN))!=0
        || nInMul==0
113707
113708
113709
113710
113711
113712
113713




113714
113715
113716
113717
113718



113719
113720
113721
113722
113723
113724










113725
113726
113727
113728
113729
113730
113731
113732
         && (pProbe->szIdxRow<pTab->szTabRow)
         && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
         && sqlite3GlobalConfig.bUseCis
         && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
          )
      ){
        pNew->iSortIdx = b ? iSortIdx : 0;




        if( m==0 ){
          /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
          **  +  The extra factor K of between 1.1 and 3.0 that depends
          **     on the relative sizes of the table and the index.  K
          **     is smaller for smaller indices, thus favoring them.



          */
          pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
                        (15*pProbe->szIdxRow)/pTab->szTabRow;
        }else{
          /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
          ** which we will simplify to just N*log2(N) */










          pNew->rRun = rSize + rLogSize;
        }
        whereLoopOutputAdjust(pWC, pNew);
        rc = whereLoopInsert(pBuilder, pNew);
        pNew->nOut = rSize;
        if( rc ) break;
      }
    }







>
>
>
>





>
>
>

<
|

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







114148
114149
114150
114151
114152
114153
114154
114155
114156
114157
114158
114159
114160
114161
114162
114163
114164
114165
114166
114167

114168
114169
114170
114171
114172
114173
114174
114175
114176
114177
114178
114179
114180
114181
114182
114183
114184
114185
114186
114187
114188
114189
         && (pProbe->szIdxRow<pTab->szTabRow)
         && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
         && sqlite3GlobalConfig.bUseCis
         && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
          )
      ){
        pNew->iSortIdx = b ? iSortIdx : 0;
        /* TUNING:  The base cost of an index scan is N + log2(N).
        ** The log2(N) is for the initial seek to the beginning and the N
        ** is for the scan itself. */
        pNew->rRun = sqlite3LogEstAdd(rSize, rLogSize);
        if( m==0 ){
          /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
          **  +  The extra factor K of between 1.1 and 3.0 that depends
          **     on the relative sizes of the table and the index.  K
          **     is smaller for smaller indices, thus favoring them.
          **     The upper bound on K (3.0) matches the penalty factor
          **     on a full table scan that tries to encourage the use of
          **     indexed lookups over full scans.
          */

          pNew->rRun +=  1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
        }else{
          /* TUNING: The cost of scanning a non-covering index is multiplied
          ** by log2(N) to account for the binary search of the main table
          ** that must happen for each row of the index.
          ** TODO: Should there be a multiplier here, analogous to the 3x
          ** multiplier for a fulltable scan or covering index scan, to
          ** further discourage the use of an index scan?  Or is the log2(N)
          ** term sufficient discouragement?
          ** TODO: What if some or all of the WHERE clause terms can be
          ** computed without reference to the original table.  Then the
          ** penality should reduce to logK where K is the number of output
          ** rows.
          */
          pNew->rRun += rLogSize;
        }
        whereLoopOutputAdjust(pWC, pNew);
        rc = whereLoopInsert(pBuilder, pNew);
        pNew->nOut = rSize;
        if( rc ) break;
      }
    }
113890
113891
113892
113893
113894
113895
113896
113897
113898
113899
113900
113901
113902
113903
113904
113905
    if( i>=nConstraint ){
      pNew->nLTerm = mxTerm+1;
      assert( pNew->nLTerm<=pNew->nLSlot );
      pNew->u.vtab.idxNum = pIdxInfo->idxNum;
      pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
      pIdxInfo->needToFreeIdxStr = 0;
      pNew->u.vtab.idxStr = pIdxInfo->idxStr;
      pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
                                     && pIdxInfo->orderByConsumed);
      pNew->rSetup = 0;
      pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
      pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
      whereLoopInsert(pBuilder, pNew);
      if( pNew->u.vtab.needFree ){
        sqlite3_free(pNew->u.vtab.idxStr);
        pNew->u.vtab.needFree = 0;







|
|







114347
114348
114349
114350
114351
114352
114353
114354
114355
114356
114357
114358
114359
114360
114361
114362
    if( i>=nConstraint ){
      pNew->nLTerm = mxTerm+1;
      assert( pNew->nLTerm<=pNew->nLSlot );
      pNew->u.vtab.idxNum = pIdxInfo->idxNum;
      pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
      pIdxInfo->needToFreeIdxStr = 0;
      pNew->u.vtab.idxStr = pIdxInfo->idxStr;
      pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
                                      pIdxInfo->nOrderBy : 0);
      pNew->rSetup = 0;
      pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
      pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
      whereLoopInsert(pBuilder, pNew);
      if( pNew->u.vtab.needFree ){
        sqlite3_free(pNew->u.vtab.idxStr);
        pNew->u.vtab.needFree = 0;
114052
114053
114054
114055
114056
114057
114058
114059
114060
114061
114062
114063
114064
114065
114066
114067
114068
114069
114070
114071
114072
114073
114074
114075
114076
114077
114078
114079
114080
  whereLoopClear(db, pNew);
  return rc;
}

/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
** parameters) to see if it outputs rows in the requested ORDER BY
** (or GROUP BY) without requiring a separate sort operation.  Return:
** 
**    0:  ORDER BY is not satisfied.  Sorting required
**    1:  ORDER BY is satisfied.      Omit sorting
**   -1:  Unknown at this time
**
** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
** strict.  With GROUP BY and DISTINCT the only requirement is that
** equivalent rows appear immediately adjacent to one another.  GROUP BY
** and DISTINT do not require rows to appear in any particular order as long
** as equivelent rows are grouped together.  Thus for GROUP BY and DISTINCT
** the pOrderBy terms can be matched in any order.  With ORDER BY, the 
** pOrderBy terms must be matched in strict left-to-right order.
*/
static int wherePathSatisfiesOrderBy(
  WhereInfo *pWInfo,    /* The WHERE clause */
  ExprList *pOrderBy,   /* ORDER BY or GROUP BY or DISTINCT clause to check */
  WherePath *pPath,     /* The WherePath to check */
  u16 wctrlFlags,       /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
  u16 nLoop,            /* Number of entries in pPath->aLoop[] */
  WhereLoop *pLast,     /* Add this WhereLoop to the end of pPath->aLoop[] */
  Bitmask *pRevMask     /* OUT: Mask of WhereLoops to run in reverse order */







|

|
|
|









|







114509
114510
114511
114512
114513
114514
114515
114516
114517
114518
114519
114520
114521
114522
114523
114524
114525
114526
114527
114528
114529
114530
114531
114532
114533
114534
114535
114536
114537
  whereLoopClear(db, pNew);
  return rc;
}

/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
** parameters) to see if it outputs rows in the requested ORDER BY
** (or GROUP BY) without requiring a separate sort operation.  Return N:
** 
**   N>0:   N terms of the ORDER BY clause are satisfied
**   N==0:  No terms of the ORDER BY clause are satisfied
**   N<0:   Unknown yet how many terms of ORDER BY might be satisfied.   
**
** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
** strict.  With GROUP BY and DISTINCT the only requirement is that
** equivalent rows appear immediately adjacent to one another.  GROUP BY
** and DISTINT do not require rows to appear in any particular order as long
** as equivelent rows are grouped together.  Thus for GROUP BY and DISTINCT
** the pOrderBy terms can be matched in any order.  With ORDER BY, the 
** pOrderBy terms must be matched in strict left-to-right order.
*/
static i8 wherePathSatisfiesOrderBy(
  WhereInfo *pWInfo,    /* The WHERE clause */
  ExprList *pOrderBy,   /* ORDER BY or GROUP BY or DISTINCT clause to check */
  WherePath *pPath,     /* The WherePath to check */
  u16 wctrlFlags,       /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
  u16 nLoop,            /* Number of entries in pPath->aLoop[] */
  WhereLoop *pLast,     /* Add this WhereLoop to the end of pPath->aLoop[] */
  Bitmask *pRevMask     /* OUT: Mask of WhereLoops to run in reverse order */
114250
114251
114252
114253
114254
114255
114256











114257
114258
114259
114260
114261
114262
114263
114264
114265
114266
114267
114268
114269
114270
114271
114272
114273
114274
114275
114276
114277
114278
114279
114280
114281
          if( iColumn>=0 ){
            pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
            if( !pColl ) pColl = db->pDfltColl;
            if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
          }
          isMatch = 1;
          break;











        }
        if( isMatch ){
          if( iColumn<0 ){
            testcase( distinctColumns==0 );
            distinctColumns = 1;
          }
          obSat |= MASKBIT(i);
          if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
            /* Make sure the sort order is compatible in an ORDER BY clause.
            ** Sort order is irrelevant for a GROUP BY clause. */
            if( revSet ){
              if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0;
            }else{
              rev = revIdx ^ pOrderBy->a[i].sortOrder;
              if( rev ) *pRevMask |= MASKBIT(iLoop);
              revSet = 1;
            }
          }
        }else{
          /* No match found */
          if( j==0 || j<nKeyCol ){
            testcase( isOrderDistinct!=0 );
            isOrderDistinct = 0;
          }
          break;







>
>
>
>
>
>
>
>
>
>
>







<
<
<
<
<
<
<
<
<
<
<







114707
114708
114709
114710
114711
114712
114713
114714
114715
114716
114717
114718
114719
114720
114721
114722
114723
114724
114725
114726
114727
114728
114729
114730
114731











114732
114733
114734
114735
114736
114737
114738
          if( iColumn>=0 ){
            pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
            if( !pColl ) pColl = db->pDfltColl;
            if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
          }
          isMatch = 1;
          break;
        }
        if( isMatch && (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
          /* Make sure the sort order is compatible in an ORDER BY clause.
          ** Sort order is irrelevant for a GROUP BY clause. */
          if( revSet ){
            if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
          }else{
            rev = revIdx ^ pOrderBy->a[i].sortOrder;
            if( rev ) *pRevMask |= MASKBIT(iLoop);
            revSet = 1;
          }
        }
        if( isMatch ){
          if( iColumn<0 ){
            testcase( distinctColumns==0 );
            distinctColumns = 1;
          }
          obSat |= MASKBIT(i);











        }else{
          /* No match found */
          if( j==0 || j<nKeyCol ){
            testcase( isOrderDistinct!=0 );
            isOrderDistinct = 0;
          }
          break;
114299
114300
114301
114302
114303
114304
114305
114306
114307






114308
114309
114310
114311
114312
114313
114314
        if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
        if( (mTerm&~orderDistinctMask)==0 ){
          obSat |= MASKBIT(i);
        }
      }
    }
  } /* End the loop over all WhereLoops from outer-most down to inner-most */
  if( obSat==obDone ) return 1;
  if( !isOrderDistinct ) return 0;






  return -1;
}

#ifdef WHERETRACE_ENABLED
/* For debugging use only: */
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
  static char zName[65];







|
|
>
>
>
>
>
>







114756
114757
114758
114759
114760
114761
114762
114763
114764
114765
114766
114767
114768
114769
114770
114771
114772
114773
114774
114775
114776
114777
        if( mTerm==0 && !sqlite3ExprIsConstant(p) ) continue;
        if( (mTerm&~orderDistinctMask)==0 ){
          obSat |= MASKBIT(i);
        }
      }
    }
  } /* End the loop over all WhereLoops from outer-most down to inner-most */
  if( obSat==obDone ) return (i8)nOrderBy;
  if( !isOrderDistinct ){
    for(i=nOrderBy-1; i>0; i--){
      Bitmask m = MASKBIT(i) - 1;
      if( (obSat&m)==m ) return i;
    }
    return 0;
  }
  return -1;
}

#ifdef WHERETRACE_ENABLED
/* For debugging use only: */
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
  static char zName[65];
114337
114338
114339
114340
114341
114342
114343

114344
114345
114346
114347
114348
114349
114350
114351
114352
114353
114354
114355
  int mxChoice;             /* Maximum number of simultaneous paths tracked */
  int nLoop;                /* Number of terms in the join */
  Parse *pParse;            /* Parsing context */
  sqlite3 *db;              /* The database connection */
  int iLoop;                /* Loop counter over the terms of the join */
  int ii, jj;               /* Loop counters */
  int mxI = 0;              /* Index of next entry to replace */

  LogEst rCost;             /* Cost of a path */
  LogEst nOut;              /* Number of outputs */
  LogEst mxCost = 0;        /* Maximum cost of a set of paths */
  LogEst mxOut = 0;         /* Maximum nOut value on the set of paths */
  LogEst rSortCost;         /* Cost to do a sort */
  int nTo, nFrom;           /* Number of valid entries in aTo[] and aFrom[] */
  WherePath *aFrom;         /* All nFrom paths at the previous level */
  WherePath *aTo;           /* The nTo best paths at the current level */
  WherePath *pFrom;         /* An element of aFrom[] that we are working on */
  WherePath *pTo;           /* An element of aTo[] that we are working on */
  WhereLoop *pWLoop;        /* One of the WhereLoop objects */
  WhereLoop **pX;           /* Used to divy up the pSpace memory */







>




<







114800
114801
114802
114803
114804
114805
114806
114807
114808
114809
114810
114811

114812
114813
114814
114815
114816
114817
114818
  int mxChoice;             /* Maximum number of simultaneous paths tracked */
  int nLoop;                /* Number of terms in the join */
  Parse *pParse;            /* Parsing context */
  sqlite3 *db;              /* The database connection */
  int iLoop;                /* Loop counter over the terms of the join */
  int ii, jj;               /* Loop counters */
  int mxI = 0;              /* Index of next entry to replace */
  int nOrderBy;             /* Number of ORDER BY clause terms */
  LogEst rCost;             /* Cost of a path */
  LogEst nOut;              /* Number of outputs */
  LogEst mxCost = 0;        /* Maximum cost of a set of paths */
  LogEst mxOut = 0;         /* Maximum nOut value on the set of paths */

  int nTo, nFrom;           /* Number of valid entries in aTo[] and aFrom[] */
  WherePath *aFrom;         /* All nFrom paths at the previous level */
  WherePath *aTo;           /* The nTo best paths at the current level */
  WherePath *pFrom;         /* An element of aFrom[] that we are working on */
  WherePath *pTo;           /* An element of aTo[] that we are working on */
  WhereLoop *pWLoop;        /* One of the WhereLoop objects */
  WhereLoop **pX;           /* Used to divy up the pSpace memory */
114383
114384
114385
114386
114387
114388
114389
114390
114391
114392

114393
114394
114395
114396
114397
114398
114399
114400
114401
114402
114403
114404
114405
114406
114407
114408
114409
114410
114411
114412
114413
114414
114415
114416
114417
114418
114419
114420
114421
114422
114423
114424
114425
114426

114427


114428
114429




114430










114431

114432
114433
114434
114435
114436
114437
114438
114439
114440
114441
114442
114443
114444
114445
114446
114447
114448
114449
114450
114451
114452
114453
114454
114455
114456
114457
114458
114459
114460
114461
114462
114463
114464
114465
114466
114467
114468
114469
114470
114471
114472
114473
114474
114475
114476
114477
114478
114479
114480
114481
114482
114483
114484
114485
114486
114487
114488
114489
114490
114491
114492
114493
114494
114495
114496
114497
114498
114499
114500
114501
114502
114503
114504
114505
114506
114507
114508
114509
114510
114511
114512
114513
114514
114515
114516
114517
114518
114519
114520
  ** of computing an automatic index is not paid back within the first 25
  ** rows, then do not use the automatic index. */
  aFrom[0].nRow = MIN(pParse->nQueryLoop, 46);  assert( 46==sqlite3LogEst(25) );
  nFrom = 1;

  /* Precompute the cost of sorting the final result set, if the caller
  ** to sqlite3WhereBegin() was concerned about sorting */
  rSortCost = 0;
  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
    aFrom[0].isOrderedValid = 1;

  }else{
    /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
    ** number of output rows. The 48 is the expected size of a row to sort. 
    ** FIXME:  compute a better estimate of the 48 multiplier based on the
    ** result set expressions. */
    rSortCost = nRowEst + estLog(nRowEst);
    WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
  }

  /* Compute successively longer WherePaths using the previous generation
  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  ** best paths at each generation */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    nTo = 0;
    for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
        Bitmask maskNew;
        Bitmask revMask = 0;
        u8 isOrderedValid = pFrom->isOrderedValid;
        u8 isOrdered = pFrom->isOrdered;
        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
        /* At this point, pWLoop is a candidate to be the next loop. 
        ** Compute its cost */
        rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
        rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
        nOut = pFrom->nRow + pWLoop->nOut;
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
        if( !isOrderedValid ){
          switch( wherePathSatisfiesOrderBy(pWInfo,
                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
                       iLoop, pWLoop, &revMask) ){
            case 1:  /* Yes.  pFrom+pWLoop does satisfy the ORDER BY clause */
              isOrdered = 1;

              isOrderedValid = 1;


              break;
            case 0:  /* No.  pFrom+pWLoop will require a separate sort */




              isOrdered = 0;










              isOrderedValid = 1;

              rCost = sqlite3LogEstAdd(rCost, rSortCost);
              break;
            default: /* Cannot tell yet.  Try again on the next iteration */
              break;
          }
        }else{
          revMask = pFrom->revLoop;
        }
        /* Check to see if pWLoop should be added to the mxChoice best so far */
        for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
          if( pTo->maskLoop==maskNew
           && pTo->isOrderedValid==isOrderedValid
           && ((pTo->rCost<=rCost && pTo->nRow<=nOut) ||
                (pTo->rCost>=rCost && pTo->nRow>=nOut))
          ){
            testcase( jj==nTo-1 );
            break;
          }
        }
        if( jj>=nTo ){
          if( nTo>=mxChoice && rCost>=mxCost ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
            if( sqlite3WhereTrace&0x4 ){
              sqlite3DebugPrintf("Skip   %s cost=%-3d,%3d order=%c\n",
                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                  isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
            }
#endif
            continue;
          }
          /* Add a new Path to the aTo[] set */
          if( nTo<mxChoice ){
            /* Increase the size of the aTo set by one */
            jj = nTo++;
          }else{
            /* New path replaces the prior worst to keep count below mxChoice */
            jj = mxI;
          }
          pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED /* 0x4 */
          if( sqlite3WhereTrace&0x4 ){
            sqlite3DebugPrintf("New    %s cost=%-3d,%3d order=%c\n",
                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
          }
#endif
        }else{
          if( pTo->rCost<=rCost && pTo->nRow<=nOut ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
            if( sqlite3WhereTrace&0x4 ){
              sqlite3DebugPrintf(
                  "Skip   %s cost=%-3d,%3d order=%c",
                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                  isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
              sqlite3DebugPrintf("   vs %s cost=%-3d,%d order=%c\n",
                  wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
                  pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
            }
#endif
            testcase( pTo->rCost==rCost );
            continue;
          }
          testcase( pTo->rCost==rCost+1 );
          /* A new and better score for a previously created equivalent path */
#ifdef WHERETRACE_ENABLED /* 0x4 */
          if( sqlite3WhereTrace&0x4 ){
            sqlite3DebugPrintf(
                "Update %s cost=%-3d,%3d order=%c",
                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
            sqlite3DebugPrintf("  was %s cost=%-3d,%3d order=%c\n",
                wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
                pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
          }
#endif
        }
        /* pWLoop is a winner.  Add it to the set of best so far */
        pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
        pTo->revLoop = revMask;
        pTo->nRow = nOut;
        pTo->rCost = rCost;
        pTo->isOrderedValid = isOrderedValid;
        pTo->isOrdered = isOrdered;
        memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
        pTo->aLoop[iLoop] = pWLoop;
        if( nTo>=mxChoice ){
          mxI = 0;
          mxCost = aTo[0].rCost;
          mxOut = aTo[0].nRow;







<

|
>

|
|
<
<
<
<











<
|








|
|

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







|













|

















|









|


|












|


|








<







114846
114847
114848
114849
114850
114851
114852

114853
114854
114855
114856
114857
114858




114859
114860
114861
114862
114863
114864
114865
114866
114867
114868
114869

114870
114871
114872
114873
114874
114875
114876
114877
114878
114879
114880
114881
114882

114883
114884
114885
114886
114887
114888
114889
114890
114891
114892
114893
114894
114895
114896
114897
114898
114899
114900
114901
114902
114903
114904
114905
114906
114907



114908
114909
114910
114911
114912
114913
114914
114915
114916
114917
114918
114919
114920
114921
114922
114923
114924
114925
114926
114927
114928
114929
114930
114931
114932
114933
114934
114935
114936
114937
114938
114939
114940
114941
114942
114943
114944
114945
114946
114947
114948
114949
114950
114951
114952
114953
114954
114955
114956
114957
114958
114959
114960
114961
114962
114963
114964
114965
114966
114967
114968
114969
114970
114971
114972
114973
114974
114975
114976
114977
114978
114979
114980
114981
114982
114983
114984

114985
114986
114987
114988
114989
114990
114991
  ** of computing an automatic index is not paid back within the first 25
  ** rows, then do not use the automatic index. */
  aFrom[0].nRow = MIN(pParse->nQueryLoop, 46);  assert( 46==sqlite3LogEst(25) );
  nFrom = 1;

  /* Precompute the cost of sorting the final result set, if the caller
  ** to sqlite3WhereBegin() was concerned about sorting */

  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
    aFrom[0].isOrdered = 0;
    nOrderBy = 0;
  }else{
    aFrom[0].isOrdered = -1;
    nOrderBy = pWInfo->pOrderBy->nExpr;




  }

  /* Compute successively longer WherePaths using the previous generation
  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  ** best paths at each generation */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    nTo = 0;
    for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
        Bitmask maskNew;
        Bitmask revMask = 0;

        i8 isOrdered = pFrom->isOrdered;
        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
        /* At this point, pWLoop is a candidate to be the next loop. 
        ** Compute its cost */
        rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
        rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
        nOut = pFrom->nRow + pWLoop->nOut;
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
        if( isOrdered<0 ){
          isOrdered = wherePathSatisfiesOrderBy(pWInfo,
                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
                       iLoop, pWLoop, &revMask);

          if( isOrdered>=0 && isOrdered<nOrderBy ){
            /* TUNING: Estimated cost of sorting is N*log(N).
            ** If the order-by clause has X terms but only the last Y terms
            ** are out of order, then block-sorting will reduce the sorting
            ** cost to N*log(N)*log(Y/X).  The log(Y/X) term is computed
            ** by rScale.
            ** TODO: Should the sorting cost get a small multiplier to help
            ** discourage the use of sorting and encourage the use of index
            ** scans instead?
            */
            LogEst rScale, rSortCost;
            assert( nOrderBy>0 );
            rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
            rSortCost = nRowEst + estLog(nRowEst) + rScale;
            /* TUNING: The cost of implementing DISTINCT using a B-TREE is
            ** also N*log(N) but it has a larger constant of proportionality.
            ** Multiply by 3.0. */
            if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
              rSortCost += 16;
            }
            WHERETRACE(0x002,
               ("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
                rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost,
                sqlite3LogEstAdd(rCost,rSortCost)));
            rCost = sqlite3LogEstAdd(rCost, rSortCost);



          }
        }else{
          revMask = pFrom->revLoop;
        }
        /* Check to see if pWLoop should be added to the mxChoice best so far */
        for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
          if( pTo->maskLoop==maskNew
           && ((pTo->isOrdered^isOrdered)&80)==0
           && ((pTo->rCost<=rCost && pTo->nRow<=nOut) ||
                (pTo->rCost>=rCost && pTo->nRow>=nOut))
          ){
            testcase( jj==nTo-1 );
            break;
          }
        }
        if( jj>=nTo ){
          if( nTo>=mxChoice && rCost>=mxCost ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
            if( sqlite3WhereTrace&0x4 ){
              sqlite3DebugPrintf("Skip   %s cost=%-3d,%3d order=%c\n",
                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                  isOrdered>=0 ? isOrdered+'0' : '?');
            }
#endif
            continue;
          }
          /* Add a new Path to the aTo[] set */
          if( nTo<mxChoice ){
            /* Increase the size of the aTo set by one */
            jj = nTo++;
          }else{
            /* New path replaces the prior worst to keep count below mxChoice */
            jj = mxI;
          }
          pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED /* 0x4 */
          if( sqlite3WhereTrace&0x4 ){
            sqlite3DebugPrintf("New    %s cost=%-3d,%3d order=%c\n",
                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                isOrdered>=0 ? isOrdered+'0' : '?');
          }
#endif
        }else{
          if( pTo->rCost<=rCost && pTo->nRow<=nOut ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
            if( sqlite3WhereTrace&0x4 ){
              sqlite3DebugPrintf(
                  "Skip   %s cost=%-3d,%3d order=%c",
                  wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                  isOrdered>=0 ? isOrdered+'0' : '?');
              sqlite3DebugPrintf("   vs %s cost=%-3d,%d order=%c\n",
                  wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
                  pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
            }
#endif
            testcase( pTo->rCost==rCost );
            continue;
          }
          testcase( pTo->rCost==rCost+1 );
          /* A new and better score for a previously created equivalent path */
#ifdef WHERETRACE_ENABLED /* 0x4 */
          if( sqlite3WhereTrace&0x4 ){
            sqlite3DebugPrintf(
                "Update %s cost=%-3d,%3d order=%c",
                wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
                isOrdered>=0 ? isOrdered+'0' : '?');
            sqlite3DebugPrintf("  was %s cost=%-3d,%3d order=%c\n",
                wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
                pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
          }
#endif
        }
        /* pWLoop is a winner.  Add it to the set of best so far */
        pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
        pTo->revLoop = revMask;
        pTo->nRow = nOut;
        pTo->rCost = rCost;

        pTo->isOrdered = isOrdered;
        memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
        pTo->aLoop[iLoop] = pWLoop;
        if( nTo>=mxChoice ){
          mxI = 0;
          mxCost = aTo[0].rCost;
          mxOut = aTo[0].nRow;
114531
114532
114533
114534
114535
114536
114537
114538
114539
114540
114541
114542
114543
114544
114545
114546

#ifdef WHERETRACE_ENABLED  /* >=2 */
    if( sqlite3WhereTrace>=2 ){
      sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
      for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
        sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
           wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
           pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
        if( pTo->isOrderedValid && pTo->isOrdered ){
          sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
        }else{
          sqlite3DebugPrintf("\n");
        }
      }
    }
#endif







|
|







115002
115003
115004
115005
115006
115007
115008
115009
115010
115011
115012
115013
115014
115015
115016
115017

#ifdef WHERETRACE_ENABLED  /* >=2 */
    if( sqlite3WhereTrace>=2 ){
      sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
      for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
        sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
           wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
           pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
        if( pTo->isOrdered>0 ){
          sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
        }else{
          sqlite3DebugPrintf("\n");
        }
      }
    }
#endif
114575
114576
114577
114578
114579
114580
114581

114582
114583

114584
114585

114586

114587
114588

114589
114590
114591
114592
114593
114594
114595
   && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
   && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
   && nRowEst
  ){
    Bitmask notUsed;
    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
                 WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);

    if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
  }

  if( pFrom->isOrdered ){
    if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){

      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;

    }else{
      pWInfo->bOBSat = 1;

      pWInfo->revMask = pFrom->revLoop;
    }
  }
  pWInfo->nRowOut = pFrom->nRow;

  /* Free temporary memory and return success */
  sqlite3DbFree(db, pSpace);







>
|
|
>
|

>
|
>

|
>







115046
115047
115048
115049
115050
115051
115052
115053
115054
115055
115056
115057
115058
115059
115060
115061
115062
115063
115064
115065
115066
115067
115068
115069
115070
115071
   && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
   && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
   && nRowEst
  ){
    Bitmask notUsed;
    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
                 WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
    if( rc==pWInfo->pResultSet->nExpr ){
      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
    }
  }
  if( pWInfo->pOrderBy ){
    if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
      if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
        pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
      }
    }else{
      pWInfo->nOBSat = pFrom->isOrdered;
      if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
      pWInfo->revMask = pFrom->revLoop;
    }
  }
  pWInfo->nRowOut = pFrom->nRow;

  /* Free temporary memory and return success */
  sqlite3DbFree(db, pSpace);
114666
114667
114668
114669
114670
114671
114672
114673
114674
114675
114676
114677
114678
114679
114680
  }
  if( pLoop->wsFlags ){
    pLoop->nOut = (LogEst)1;
    pWInfo->a[0].pWLoop = pLoop;
    pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
    pWInfo->a[0].iTabCur = iCur;
    pWInfo->nRowOut = 1;
    if( pWInfo->pOrderBy ) pWInfo->bOBSat =  1;
    if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
#ifdef SQLITE_DEBUG
    pLoop->cId = '0';
#endif
    return 1;







|







115142
115143
115144
115145
115146
115147
115148
115149
115150
115151
115152
115153
115154
115155
115156
  }
  if( pLoop->wsFlags ){
    pLoop->nOut = (LogEst)1;
    pWInfo->a[0].pWLoop = pLoop;
    pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
    pWInfo->a[0].iTabCur = iCur;
    pWInfo->nRowOut = 1;
    if( pWInfo->pOrderBy ) pWInfo->nOBSat =  pWInfo->pOrderBy->nExpr;
    if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
#ifdef SQLITE_DEBUG
    pLoop->cId = '0';
#endif
    return 1;
114770
114771
114772
114773
114774
114775
114776
114777
114778
114779
114780
114781
114782
114783
114784
** be used to compute the appropriate cursor depending on which index is
** used.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList *pOrderBy,   /* An ORDER BY clause, or NULL */
  ExprList *pResultSet, /* Result set of the query */
  u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
  int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */







|







115246
115247
115248
115249
115250
115251
115252
115253
115254
115255
115256
115257
115258
115259
115260
** be used to compute the appropriate cursor depending on which index is
** used.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList *pOrderBy,   /* An ORDER BY (or GROUP BY) clause, or NULL */
  ExprList *pResultSet, /* Result set of the query */
  u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
  int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
114792
114793
114794
114795
114796
114797
114798




114799
114800
114801
114802
114803
114804
114805
  sqlite3 *db;               /* Database connection */
  int rc;                    /* Return code */


  /* Variable initialization */
  db = pParse->db;
  memset(&sWLB, 0, sizeof(sWLB));




  sWLB.pOrderBy = pOrderBy;

  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
    wctrlFlags &= ~WHERE_WANT_DISTINCT;
  }







>
>
>
>







115268
115269
115270
115271
115272
115273
115274
115275
115276
115277
115278
115279
115280
115281
115282
115283
115284
115285
  sqlite3 *db;               /* Database connection */
  int rc;                    /* Return code */


  /* Variable initialization */
  db = pParse->db;
  memset(&sWLB, 0, sizeof(sWLB));

  /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
  testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
  if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
  sWLB.pOrderBy = pOrderBy;

  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
    wctrlFlags &= ~WHERE_WANT_DISTINCT;
  }
114836
114837
114838
114839
114840
114841
114842
114843
114844
114845
114846
114847
114848
114849
114850
  }
  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
  pWInfo->nLevel = nTabList;
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  pWInfo->pOrderBy = pOrderBy;
  pWInfo->pResultSet = pResultSet;
  pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = &pWInfo->sMaskSet;
  sWLB.pWInfo = pWInfo;
  sWLB.pWC = &pWInfo->sWC;
  sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
  assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );







|







115316
115317
115318
115319
115320
115321
115322
115323
115324
115325
115326
115327
115328
115329
115330
  }
  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
  pWInfo->nLevel = nTabList;
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  pWInfo->pOrderBy = pOrderBy;
  pWInfo->pResultSet = pResultSet;
  pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = &pWInfo->sMaskSet;
  sWLB.pWInfo = pWInfo;
  sWLB.pWC = &pWInfo->sWC;
  sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
  assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
114870
114871
114872
114873
114874
114875
114876
114877
114878
114879
114880
114881
114882
114883
114884
      sWLB.pWC->a[ii].wtFlags |= TERM_CODED;
    }
  }

  /* Special case: No FROM clause
  */
  if( nTabList==0 ){
    if( pOrderBy ) pWInfo->bOBSat = 1;
    if( wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
  }

  /* Assign a bit from the bitmask to every term in the FROM clause.
  **







|







115350
115351
115352
115353
115354
115355
115356
115357
115358
115359
115360
115361
115362
115363
115364
      sWLB.pWC->a[ii].wtFlags |= TERM_CODED;
    }
  }

  /* Special case: No FROM clause
  */
  if( nTabList==0 ){
    if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
    if( wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
  }

  /* Assign a bit from the bitmask to every term in the FROM clause.
  **
114981
114982
114983
114984
114985
114986
114987
114988
114989
114990
114991
114992
114993
114994
114995
114996
  if( pParse->nErr || NEVER(db->mallocFailed) ){
    goto whereBeginError;
  }
#ifdef WHERETRACE_ENABLED /* !=0 */
  if( sqlite3WhereTrace ){
    int ii;
    sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
    if( pWInfo->bOBSat ){
      sqlite3DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask);
    }
    switch( pWInfo->eDistinct ){
      case WHERE_DISTINCT_UNIQUE: {
        sqlite3DebugPrintf("  DISTINCT=unique");
        break;
      }
      case WHERE_DISTINCT_ORDERED: {







|
|







115461
115462
115463
115464
115465
115466
115467
115468
115469
115470
115471
115472
115473
115474
115475
115476
  if( pParse->nErr || NEVER(db->mallocFailed) ){
    goto whereBeginError;
  }
#ifdef WHERETRACE_ENABLED /* !=0 */
  if( sqlite3WhereTrace ){
    int ii;
    sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
    if( pWInfo->nOBSat>0 ){
      sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
    }
    switch( pWInfo->eDistinct ){
      case WHERE_DISTINCT_UNIQUE: {
        sqlite3DebugPrintf("  DISTINCT=unique");
        break;
      }
      case WHERE_DISTINCT_ORDERED: {
115264
115265
115266
115267
115268
115269
115270
115271
115272
115273
115274
115275
115276
115277
115278
    if( pTabItem->viaCoroutine && !db->mallocFailed ){
      last = sqlite3VdbeCurrentAddr(v);
      k = pLevel->addrBody;
      pOp = sqlite3VdbeGetOp(v, k);
      for(; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column ){
          pOp->opcode = OP_SCopy;
          pOp->p1 = pOp->p2 + pTabItem->regResult;
          pOp->p2 = pOp->p3;
          pOp->p3 = 0;
        }else if( pOp->opcode==OP_Rowid ){
          pOp->opcode = OP_Null;
          pOp->p1 = 0;
          pOp->p3 = 0;







|







115744
115745
115746
115747
115748
115749
115750
115751
115752
115753
115754
115755
115756
115757
115758
    if( pTabItem->viaCoroutine && !db->mallocFailed ){
      last = sqlite3VdbeCurrentAddr(v);
      k = pLevel->addrBody;
      pOp = sqlite3VdbeGetOp(v, k);
      for(; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column ){
          pOp->opcode = OP_Copy;
          pOp->p1 = pOp->p2 + pTabItem->regResult;
          pOp->p2 = pOp->p3;
          pOp->p3 = 0;
        }else if( pOp->opcode==OP_Rowid ){
          pOp->opcode = OP_Null;
          pOp->p1 = 0;
          pOp->p3 = 0;
118212
118213
118214
118215
118216
118217
118218



























118219
118220
118221
118222
118223
118224
118225
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy328]);
      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy346.pExpr);



























    }else{
      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
      if( yygotominor.yy346.pExpr ){
        yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14;
        sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
      }else{
        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);







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







118692
118693
118694
118695
118696
118697
118698
118699
118700
118701
118702
118703
118704
118705
118706
118707
118708
118709
118710
118711
118712
118713
118714
118715
118716
118717
118718
118719
118720
118721
118722
118723
118724
118725
118726
118727
118728
118729
118730
118731
118732
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy328]);
      sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy346.pExpr);
    }else if( yymsp[-1].minor.yy14->nExpr==1 ){
      /* Expressions of the form:
      **
      **      expr1 IN (?1)
      **      expr1 NOT IN (?2)
      **
      ** with exactly one value on the RHS can be simplified to something
      ** like this:
      **
      **      expr1 == ?1
      **      expr1 <> ?2
      **
      ** But, the RHS of the == or <> is marked with the EP_Generic flag
      ** so that it may not contribute to the computation of comparison
      ** affinity or the collating sequence to use for comparison.  Otherwise,
      ** the semantics would be subtly different from IN or NOT IN.
      */
      Expr *pRHS = yymsp[-1].minor.yy14->a[0].pExpr;
      yymsp[-1].minor.yy14->a[0].pExpr = 0;
      sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
      /* pRHS cannot be NULL because a malloc error would have been detected
      ** before now and control would have never reached this point */
      if( ALWAYS(pRHS) ){
        pRHS->flags &= ~EP_Collate;
        pRHS->flags |= EP_Generic;
      }
      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, yymsp[-3].minor.yy328 ? TK_NE : TK_EQ, yymsp[-4].minor.yy346.pExpr, pRHS, 0);
    }else{
      yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
      if( yygotominor.yy346.pExpr ){
        yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14;
        sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
      }else{
        sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
120832
120833
120834
120835
120836
120837
120838

120839
120840
120841
120842
120843
120844
120845
      HashElem *p;
      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
        Table *pTab = (Table *)sqliteHashData(p);
        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
      }
    }
  }

  sqlite3BtreeLeaveAll(db);
#else
  UNUSED_PARAMETER(db);
#endif
}

/*







>







121339
121340
121341
121342
121343
121344
121345
121346
121347
121348
121349
121350
121351
121352
121353
      HashElem *p;
      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
        Table *pTab = (Table *)sqliteHashData(p);
        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
      }
    }
  }
  sqlite3VtabUnlockList(db);
  sqlite3BtreeLeaveAll(db);
#else
  UNUSED_PARAMETER(db);
#endif
}

/*
123235
123236
123237
123238
123239
123240
123241
















123242
123243
123244
123245
123246
123247
123248
    **    }
    */
    case SQLITE_TESTCTRL_ALWAYS: {
      int x = va_arg(ap,int);
      rc = ALWAYS(x);
      break;
    }

















    /*   sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
    **
    ** Set the nReserve size to N for the main database on the database
    ** connection db.
    */
    case SQLITE_TESTCTRL_RESERVE: {







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







123743
123744
123745
123746
123747
123748
123749
123750
123751
123752
123753
123754
123755
123756
123757
123758
123759
123760
123761
123762
123763
123764
123765
123766
123767
123768
123769
123770
123771
123772
    **    }
    */
    case SQLITE_TESTCTRL_ALWAYS: {
      int x = va_arg(ap,int);
      rc = ALWAYS(x);
      break;
    }

    /*
    **   sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
    **
    ** The integer returned reveals the byte-order of the computer on which
    ** SQLite is running:
    **
    **       1     big-endian,    determined at run-time
    **      10     little-endian, determined at run-time
    **  432101     big-endian,    determined at compile-time
    **  123410     little-endian, determined at compile-time
    */ 
    case SQLITE_TESTCTRL_BYTEORDER: {
      rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
      break;
    }

    /*   sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
    **
    ** Set the nReserve size to N for the main database on the database
    ** connection db.
    */
    case SQLITE_TESTCTRL_RESERVE: {
124571
124572
124573
124574
124575
124576
124577
124578
124579
124580
124581
124582
124583
124584
124585
  sqlite3_stmt *aStmt[37];

  char *zReadExprlist;
  char *zWriteExprlist;

  int nNodeSize;                  /* Soft limit for node size */
  u8 bFts4;                       /* True for FTS4, false for FTS3 */
  u8 bHasStat;                    /* True if %_stat table exists */
  u8 bHasDocsize;                 /* True if %_docsize table exists */
  u8 bDescIdx;                    /* True if doclists are in reverse order */
  u8 bIgnoreSavepoint;            /* True to ignore xSavepoint invocations */
  int nPgsz;                      /* Page size for host database */
  char *zSegmentsTbl;             /* Name of %_segments table */
  sqlite3_blob *pSegments;        /* Blob handle open on %_segments table */








|







125095
125096
125097
125098
125099
125100
125101
125102
125103
125104
125105
125106
125107
125108
125109
  sqlite3_stmt *aStmt[37];

  char *zReadExprlist;
  char *zWriteExprlist;

  int nNodeSize;                  /* Soft limit for node size */
  u8 bFts4;                       /* True for FTS4, false for FTS3 */
  u8 bHasStat;                    /* True if %_stat table exists (2==unknown) */
  u8 bHasDocsize;                 /* True if %_docsize table exists */
  u8 bDescIdx;                    /* True if doclists are in reverse order */
  u8 bIgnoreSavepoint;            /* True to ignore xSavepoint invocations */
  int nPgsz;                      /* Page size for host database */
  char *zSegmentsTbl;             /* Name of %_segments table */
  sqlite3_blob *pSegments;        /* Blob handle open on %_segments table */

126063
126064
126065
126066
126067
126068
126069
126070
126071
126072
126073
126074
126075
126076
126077
126078
126079
126080
    rc = fts3CreateTables(p);
  }

  /* Check to see if a legacy fts3 table has been "upgraded" by the
  ** addition of a %_stat table so that it can use incremental merge.
  */
  if( !isFts4 && !isCreate ){
    int rc2 = SQLITE_OK;
    fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2",
               p->zDb, p->zName);
    if( rc2==SQLITE_OK ) p->bHasStat = 1;
  }

  /* Figure out the page-size for the database. This is required in order to
  ** estimate the cost of loading large doclists from the database.  */
  fts3DatabasePageSize(&rc, p);
  p->nNodeSize = p->nPgsz-35;








<
<
<
|







126587
126588
126589
126590
126591
126592
126593



126594
126595
126596
126597
126598
126599
126600
126601
    rc = fts3CreateTables(p);
  }

  /* Check to see if a legacy fts3 table has been "upgraded" by the
  ** addition of a %_stat table so that it can use incremental merge.
  */
  if( !isFts4 && !isCreate ){



    p->bHasStat = 2;
  }

  /* Figure out the page-size for the database. This is required in order to
  ** estimate the cost of loading large doclists from the database.  */
  fts3DatabasePageSize(&rc, p);
  p->nNodeSize = p->nPgsz-35;

127973
127974
127975
127976
127977
127978
127979



























127980
127981
127982
127983
127984
127985
127986
127987
127988
127989
127990
127991
127992
127993
127994
127995
127996
127997
127998
    if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
  }
  sqlite3Fts3SegmentsClose(p);
  return rc;
}

/*



























** Implementation of xBegin() method. This is a no-op.
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(pVtab);
  assert( p->pSegments==0 );
  assert( p->nPendingData==0 );
  assert( p->inTransaction!=1 );
  TESTONLY( p->inTransaction = 1 );
  TESTONLY( p->mxSavepoint = -1; );
  p->nLeafAdd = 0;
  return SQLITE_OK;
}

/*
** Implementation of xCommit() method. This is a no-op. The contents of
** the pending-terms hash-table have already been flushed into the database
** by fts3SyncMethod().
*/







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










|







128494
128495
128496
128497
128498
128499
128500
128501
128502
128503
128504
128505
128506
128507
128508
128509
128510
128511
128512
128513
128514
128515
128516
128517
128518
128519
128520
128521
128522
128523
128524
128525
128526
128527
128528
128529
128530
128531
128532
128533
128534
128535
128536
128537
128538
128539
128540
128541
128542
128543
128544
128545
128546
    if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
  }
  sqlite3Fts3SegmentsClose(p);
  return rc;
}

/*
** If it is currently unknown whether or not the FTS table has an %_stat
** table (if p->bHasStat==2), attempt to determine this (set p->bHasStat
** to 0 or 1). Return SQLITE_OK if successful, or an SQLite error code
** if an error occurs.
*/
static int fts3SetHasStat(Fts3Table *p){
  int rc = SQLITE_OK;
  if( p->bHasStat==2 ){
    const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
    char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
    if( zSql ){
      sqlite3_stmt *pStmt = 0;
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      if( rc==SQLITE_OK ){
        int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
        rc = sqlite3_finalize(pStmt);
        if( rc==SQLITE_OK ) p->bHasStat = bHasStat;
      }
      sqlite3_free(zSql);
    }else{
      rc = SQLITE_NOMEM;
    }
  }
  return rc;
}

/*
** Implementation of xBegin() method. 
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
  Fts3Table *p = (Fts3Table*)pVtab;
  UNUSED_PARAMETER(pVtab);
  assert( p->pSegments==0 );
  assert( p->nPendingData==0 );
  assert( p->inTransaction!=1 );
  TESTONLY( p->inTransaction = 1 );
  TESTONLY( p->mxSavepoint = -1; );
  p->nLeafAdd = 0;
  return fts3SetHasStat(p);
}

/*
** Implementation of xCommit() method. This is a no-op. The contents of
** the pending-terms hash-table have already been flushed into the database
** by fts3SyncMethod().
*/
128233
128234
128235
128236
128237
128238
128239




128240
128241
128242
128243
128244
128245
128246

128247

128248
128249
128250
128251
128252
128253
128254
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  const char *zName               /* New name of table */
){
  Fts3Table *p = (Fts3Table *)pVtab;
  sqlite3 *db = p->db;            /* Database connection */
  int rc;                         /* Return Code */





  /* As it happens, the pending terms table is always empty here. This is
  ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction 
  ** always opens a savepoint transaction. And the xSavepoint() method 
  ** flushes the pending terms table. But leave the (no-op) call to
  ** PendingTermsFlush() in in case that changes.
  */
  assert( p->nPendingData==0 );

  rc = sqlite3Fts3PendingTermsFlush(p);


  if( p->zContentTbl==0 ){
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';",
      p->zDb, p->zName, zName
    );
  }







>
>
>
>







>
|
>







128781
128782
128783
128784
128785
128786
128787
128788
128789
128790
128791
128792
128793
128794
128795
128796
128797
128798
128799
128800
128801
128802
128803
128804
128805
128806
128807
128808
  sqlite3_vtab *pVtab,            /* Virtual table handle */
  const char *zName               /* New name of table */
){
  Fts3Table *p = (Fts3Table *)pVtab;
  sqlite3 *db = p->db;            /* Database connection */
  int rc;                         /* Return Code */

  /* At this point it must be known if the %_stat table exists or not.
  ** So bHasStat may not be 2.  */
  rc = fts3SetHasStat(p);
  
  /* As it happens, the pending terms table is always empty here. This is
  ** because an "ALTER TABLE RENAME TABLE" statement inside a transaction 
  ** always opens a savepoint transaction. And the xSavepoint() method 
  ** flushes the pending terms table. But leave the (no-op) call to
  ** PendingTermsFlush() in in case that changes.
  */
  assert( p->nPendingData==0 );
  if( rc==SQLITE_OK ){
    rc = sqlite3Fts3PendingTermsFlush(p);
  }

  if( p->zContentTbl==0 ){
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';",
      p->zDb, p->zName, zName
    );
  }
139752
139753
139754
139755
139756
139757
139758




139759
139760
139761
139762
139763
139764
139765
  int rc = SQLITE_OK;             /* Return Code */
  int isRemove = 0;               /* True for an UPDATE or DELETE */
  u32 *aSzIns = 0;                /* Sizes of inserted documents */
  u32 *aSzDel = 0;                /* Sizes of deleted documents */
  int nChng = 0;                  /* Net change in number of documents */
  int bInsertDone = 0;





  assert( p->pSegments==0 );
  assert( 
      nArg==1                     /* DELETE operations */
   || nArg==(2 + p->nColumn + 3)  /* INSERT or UPDATE operations */
  );

  /* Check for a "special" INSERT operation. One of the form:







>
>
>
>







140306
140307
140308
140309
140310
140311
140312
140313
140314
140315
140316
140317
140318
140319
140320
140321
140322
140323
  int rc = SQLITE_OK;             /* Return Code */
  int isRemove = 0;               /* True for an UPDATE or DELETE */
  u32 *aSzIns = 0;                /* Sizes of inserted documents */
  u32 *aSzDel = 0;                /* Sizes of deleted documents */
  int nChng = 0;                  /* Net change in number of documents */
  int bInsertDone = 0;

  /* At this point it must be known if the %_stat table exists or not.
  ** So bHasStat may not be 2.  */
  assert( p->bHasStat==0 || p->bHasStat==1 );

  assert( p->pSegments==0 );
  assert( 
      nArg==1                     /* DELETE operations */
   || nArg==(2 + p->nColumn + 3)  /* INSERT or UPDATE operations */
  );

  /* Check for a "special" INSERT operation. One of the form:
145133
145134
145135
145136
145137
145138
145139
145140

145141
145142
145143
145144




145145
145146
145147
145148
145149
145150
145151
145152
145153
145154
145155
145156
145157
145158
145159


145160
145161
145162
145163
145164
145165
145166

/*
** This function populates the pRtree->nRowEst variable with an estimate
** of the number of rows in the virtual table. If possible, this is based
** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
*/
static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
  const char *zSql = "SELECT stat FROM sqlite_stat1 WHERE tbl= ? || '_rowid'";

  sqlite3_stmt *p;
  int rc;
  i64 nRow = 0;





  rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
  if( rc==SQLITE_OK ){
    sqlite3_bind_text(p, 1, pRtree->zName, -1, SQLITE_STATIC);
    if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
    rc = sqlite3_finalize(p);
  }else if( rc!=SQLITE_NOMEM ){
    rc = SQLITE_OK;
  }

  if( rc==SQLITE_OK ){
    if( nRow==0 ){
      pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
    }else{
      pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
    }


  }

  return rc;
}

static sqlite3_module rtreeModule = {
  0,                          /* iVersion */







|
>




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

|
|
|
|
|
|
>
>







145691
145692
145693
145694
145695
145696
145697
145698
145699
145700
145701
145702
145703
145704
145705
145706
145707
145708
145709

145710
145711
145712
145713
145714
145715
145716
145717
145718
145719
145720
145721
145722
145723
145724
145725
145726
145727
145728
145729
145730

/*
** This function populates the pRtree->nRowEst variable with an estimate
** of the number of rows in the virtual table. If possible, this is based
** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
*/
static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
  const char *zFmt = "SELECT stat FROM %Q.sqlite_stat1 WHERE tbl = '%q_rowid'";
  char *zSql;
  sqlite3_stmt *p;
  int rc;
  i64 nRow = 0;

  zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
  if( zSql==0 ){
    rc = SQLITE_NOMEM;
  }else{
    rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
    if( rc==SQLITE_OK ){

      if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
      rc = sqlite3_finalize(p);
    }else if( rc!=SQLITE_NOMEM ){
      rc = SQLITE_OK;
    }

    if( rc==SQLITE_OK ){
      if( nRow==0 ){
        pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
      }else{
        pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
      }
    }
    sqlite3_free(zSql);
  }

  return rc;
}

static sqlite3_module rtreeModule = {
  0,                          /* iVersion */
145421
145422
145423
145424
145425
145426
145427


145428
145429
145430
145431
145432
145433
145434
      sqlite3_free(zSql);
    }
  }

  if( rc==SQLITE_OK ){
    *ppVtab = (sqlite3_vtab *)pRtree;
  }else{


    rtreeRelease(pRtree);
  }
  return rc;
}


/*







>
>







145985
145986
145987
145988
145989
145990
145991
145992
145993
145994
145995
145996
145997
145998
145999
146000
      sqlite3_free(zSql);
    }
  }

  if( rc==SQLITE_OK ){
    *ppVtab = (sqlite3_vtab *)pRtree;
  }else{
    assert( *ppVtab==0 );
    assert( pRtree->nBusy==1 );
    rtreeRelease(pRtree);
  }
  return rc;
}


/*
Changes to src/sqlite3.h.
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.4.1"
#define SQLITE_VERSION_NUMBER 3008004
#define SQLITE_SOURCE_ID      "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|
|
|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.8.5"
#define SQLITE_VERSION_NUMBER 3008005
#define SQLITE_SOURCE_ID      "2014-04-18 22:20:31 9a5d38c79d2482a23bcfbc3ff35ca4fa269c768d"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
6119
6120
6121
6122
6123
6124
6125

6126
6127
6128
6129
6130
6131
6132
6133
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21

#define SQLITE_TESTCTRL_LAST                    21

/*
** 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







>
|







6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
#define SQLITE_TESTCTRL_OPTIMIZATIONS           15
#define SQLITE_TESTCTRL_ISKEYWORD               16
#define SQLITE_TESTCTRL_SCRATCHMALLOC           17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT         18
#define SQLITE_TESTCTRL_EXPLAIN_STMT            19
#define SQLITE_TESTCTRL_NEVER_CORRUPT           20
#define SQLITE_TESTCTRL_VDBE_COVERAGE           21
#define SQLITE_TESTCTRL_BYTEORDER               22
#define SQLITE_TESTCTRL_LAST                    22

/*
** 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/stash.c.
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied.
**
** SUMMARY:
**  fossil stash
**  fossil stash save ?-m|--comment COMMENT? ?FILES...?
**  fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
**  fossil stash list|ls  ?-v|--verbose?
**  fossil stash show ?STASHID? ?DIFF-OPTIONS?
**  fossil stash pop
**  fossil stash apply ?STASHID?
**  fossil stash goto ?STASHID?
**  fossil stash rm|drop ?STASHID? ?-a|--all?
**  fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
*/







|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied.
**
** SUMMARY:
**  fossil stash
**  fossil stash save ?-m|--comment COMMENT? ?FILES...?
**  fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
**  fossil stash list|ls  ?-v|--verbose? ?-W|--width <num>?
**  fossil stash show ?STASHID? ?DIFF-OPTIONS?
**  fossil stash pop
**  fossil stash apply ?STASHID?
**  fossil stash goto ?STASHID?
**  fossil stash rm|drop ?STASHID? ?-a|--all?
**  fossil stash [g]diff ?STASHID? ?DIFF-OPTIONS?
*/
514
515
516
517
518
519
520
521
522










523
524
525
526
527
528
529
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q, q2;
    int n = 0;
    int verboseFlag = find_option("verbose","v",0)!=0;










    if( !verboseFlag ){
      verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
    }
    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
       "       comment, datetime(ctime) FROM stash"







|

>
>
>
>
>
>
>
>
>
>







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
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q, q2;
    int n = 0, width;
    int verboseFlag = find_option("verbose","v",0)!=0;
    const char *zWidth = find_option("width","W",1);

    if( zWidth ){
      width = atoi(zWidth);
      if( (width!=0) && (width<=46) ){
        fossil_fatal("-W|--width value must be >46 or 0");
      }
    }else{
      width = 79;
    }
    if( !verboseFlag ){
      verboseFlag = find_option("detail","l",0)!=0; /* deprecated */
    }
    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
       "       comment, datetime(ctime) FROM stash"
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
        stashid,
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 7, 79);
      }
      if( verboseFlag ){
        db_bind_int(&q2, "$id", stashid);
        while( db_step(&q2)==SQLITE_ROW ){
          int isAdded = db_column_int(&q2, 0);
          int isRemoved = db_column_int(&q2, 1);
          const char *zOrig = db_column_text(&q2, 2);







|







551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
        stashid,
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 7, width);
      }
      if( verboseFlag ){
        db_bind_int(&q2, "$id", stashid);
        while( db_step(&q2)==SQLITE_ROW ){
          int isAdded = db_column_int(&q2, 0);
          int isRemoved = db_column_int(&q2, 1);
          const char *zOrig = db_column_text(&q2, 2);
Changes to src/style.c.
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
  },
  { "pre.th1error",
    "format for th1 script errors",
    @   white-space: pre-wrap;
    @   word-wrap: break-word;
    @   color: red;
  },
  { "table.tale-value th",
    "The label/value pairs on (for example) the ci page",
    @   vertical-align: top;
    @   text-align: right;
    @   padding: 0.2ex 2ex;
  },
  { ".statistics-report-graph-line",
    "for the /reports views",







|







1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
  },
  { "pre.th1error",
    "format for th1 script errors",
    @   white-space: pre-wrap;
    @   word-wrap: break-word;
    @   color: red;
  },
  { "table.label-value th",
    "The label/value pairs on (for example) the ci page",
    @   vertical-align: top;
    @   text-align: right;
    @   padding: 0.2ex 2ex;
  },
  { ".statistics-report-graph-line",
    "for the /reports views",
Changes to src/sync.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
76
77
78
79
80
81
    if( is_false(zAutosync) ){
      return 0;   /* Autosync is completely off */
    }
  }else{
    /* Autosync defaults on.  To make it default off, "return" here. */
  }
  url_parse(0, URL_REMEMBER);
  if( g.urlProtocol==0 ) return 0;  
  if( g.urlUser!=0 && g.urlPasswd==0 ){
    g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
    g.urlFlags |= URL_PROMPT_PW;
    url_prompt_for_password();
  }
  g.zHttpAuth = get_httpauth();
  url_remember();
#if 0 /* Disabled for now */
  if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
    /* When doing an automatic pull, also automatically pull shuns from
    ** the server if pull_shuns is enabled.
    **
    ** TODO:  What happens if the shun list gets really big? 
    ** Maybe the shunning list should only be pulled on every 10th
    ** autosync, or something?
    */
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  fossil_print("Autosync:  %s\n", g.urlCanonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  if( rc ) fossil_warning("Autosync failed");
  return rc;
}

/*







|
|
|
|

















|







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
    if( is_false(zAutosync) ){
      return 0;   /* Autosync is completely off */
    }
  }else{
    /* Autosync defaults on.  To make it default off, "return" here. */
  }
  url_parse(0, URL_REMEMBER);
  if( g.url.protocol==0 ) return 0;  
  if( g.url.user!=0 && g.url.passwd==0 ){
    g.url.passwd = unobscure(db_get("last-sync-pw", 0));
    g.url.flags |= URL_PROMPT_PW;
    url_prompt_for_password();
  }
  g.zHttpAuth = get_httpauth();
  url_remember();
#if 0 /* Disabled for now */
  if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
    /* When doing an automatic pull, also automatically pull shuns from
    ** the server if pull_shuns is enabled.
    **
    ** TODO:  What happens if the shun list gets really big? 
    ** Maybe the shunning list should only be pulled on every 10th
    ** autosync, or something?
    */
    configSync = CONFIGSET_SHUN;
  }
#endif
  if( find_option("verbose","v",0)!=0 ) flags |= SYNC_VERBOSE;
  fossil_print("Autosync:  %s\n", g.url.canonical);
  url_enable_proxy("via proxy: ");
  rc = client_sync(flags, configSync, 0);
  if( rc ) fossil_warning("Autosync failed");
  return rc;
}

/*
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  }
  if( urlFlags & URL_REMEMBER ){
    clone_ssh_db_set_options();
  }
  url_parse(zUrl, urlFlags);
  remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl);
  url_remember();
  if( g.urlProtocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){
    if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
      fossil_print("Sync with %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PUSH ){
      fossil_print("Push to %s\n", g.urlCanonical);
    }else if( (*pSyncFlags) & SYNC_PULL ){
      fossil_print("Pull from %s\n", g.urlCanonical);
    }
  }
  url_enable_proxy("via proxy: ");
  *pConfigFlags |= configSync;
}

/*







|






|

|

|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  }
  if( urlFlags & URL_REMEMBER ){
    clone_ssh_db_set_options();
  }
  url_parse(zUrl, urlFlags);
  remember_or_get_http_auth(zHttpAuth, urlFlags & URL_REMEMBER, zUrl);
  url_remember();
  if( g.url.protocol==0 ){
    if( urlOptional ) fossil_exit(0);
    usage("URL");
  }
  user_select();
  if( g.argc==2 ){
    if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
      fossil_print("Sync with %s\n", g.url.canonical);
    }else if( (*pSyncFlags) & SYNC_PUSH ){
      fossil_print("Push to %s\n", g.url.canonical);
    }else if( (*pSyncFlags) & SYNC_PULL ){
      fossil_print("Pull from %s\n", g.url.canonical);
    }
  }
  url_enable_proxy("via proxy: ");
  *pConfigFlags |= configSync;
}

/*
276
277
278
279
280
281
282
283
284
285
  url_remember();
  zUrl = db_get("last-sync-url", 0);
  if( zUrl==0 ){
    fossil_print("off\n");
    return;
  }else{
    url_parse(zUrl, 0);
    fossil_print("%s\n", g.urlCanonical);
  }
}







|


276
277
278
279
280
281
282
283
284
285
  url_remember();
  zUrl = db_get("last-sync-url", 0);
  if( zUrl==0 ){
    fossil_print("off\n");
    return;
  }else{
    url_parse(zUrl, 0);
    fossil_print("%s\n", g.url.canonical);
  }
}
Changes to src/tar.c.
569
570
571
572
573
574
575









576
577
578
579
580
581
582

/*
** WEBPAGE: tarball
** URL: /tarball/RID.tar.gz
**
** Generate a compressed tarball for a checkin.
** Return that tarball as the HTTP reply content.









*/
void tarball_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob tarball;








>
>
>
>
>
>
>
>
>







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591

/*
** WEBPAGE: tarball
** URL: /tarball/RID.tar.gz
**
** Generate a compressed tarball for a checkin.
** Return that tarball as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=base name of the output file. Defaults to
** something project/version-specific.
**
** - uuid=the version to tar (may be a tag/branch name).
** Defaults to trunk.
**
*/
void tarball_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob tarball;

Changes to src/th.c.
126
127
128
129
130
131
132

133
134
135
136
137
138
139
**
** results in nByte being set to 2.
*/
static int thNextCommand(Th_Interp*, const char *z, int n, int *pN);
static int thNextEscape (Th_Interp*, const char *z, int n, int *pN);
static int thNextVarname(Th_Interp*, const char *z, int n, int *pN);
static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);

static int thNextSpace  (Th_Interp*, const char *z, int n, int *pN);

/*
** Given that the input string (z, n) contains a language construct of
** the relevant type (a command enclosed in [], an escape sequence
** like "\xFF" or a variable reference like "${varname}", perform
** substitution on the string and store the resulting string in







>







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
**
** results in nByte being set to 2.
*/
static int thNextCommand(Th_Interp*, const char *z, int n, int *pN);
static int thNextEscape (Th_Interp*, const char *z, int n, int *pN);
static int thNextVarname(Th_Interp*, const char *z, int n, int *pN);
static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);
static int thNextInteger (Th_Interp*, const char *z, int n, int *pN);
static int thNextSpace  (Th_Interp*, const char *z, int n, int *pN);

/*
** Given that the input string (z, n) contains a language construct of
** the relevant type (a command enclosed in [], an escape sequence
** like "\xFF" or a variable reference like "${varname}", perform
** substitution on the string and store the resulting string in
1864
1865
1866
1867
1868
1869
1870

































1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
  {">",  OP_GT,             5, ARG_NUMBER},
  {"&",  OP_BITWISE_AND,    8, ARG_INTEGER},
  {"^",  OP_BITWISE_XOR,    9, ARG_INTEGER},
  {"|",  OP_BITWISE_OR,    10, ARG_INTEGER},

  {0,0,0,0}
};


































/*
** The first part of the string (zInput,nInput) contains a number.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextNumber(
  Th_Interp *interp,
  const char *zInput,
  int nInput,
  int *pnLiteral
){
  int i;
  int seenDot = 0;
  for(i=0; i<nInput; i++){
    char c = zInput[i];
    if( (seenDot || c!='.') && !th_isdigit(c) ) break;
    if( c=='.' ) seenDot = 1;
  }
  *pnLiteral = i;
  return TH_OK;
}







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











|

|







1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
  {">",  OP_GT,             5, ARG_NUMBER},
  {"&",  OP_BITWISE_AND,    8, ARG_INTEGER},
  {"^",  OP_BITWISE_XOR,    9, ARG_INTEGER},
  {"|",  OP_BITWISE_OR,    10, ARG_INTEGER},

  {0,0,0,0}
};

/*
** The first part of the string (zInput,nInput) contains an integer.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextInteger(
  Th_Interp *interp,
  const char *zInput,
  int nInput,
  int *pnLiteral
){
  int i;
  int (*isdigit)(char) = th_isdigit;
  char c;

  if( nInput<2) return TH_ERROR;
  assert(zInput[0]=='0');
  c = zInput[1];
  if( c>='A' && c<='Z' ) c += 'a' - 'A';
  if( c=='x' ){
    isdigit = th_ishexdig;
  }else if( c!='o' && c!='b' ){
    return TH_ERROR;
  }
  for(i=2; i<nInput; i++){
    c = zInput[i];
    if( !isdigit(c) ){
      break;
    }
  }
  *pnLiteral = i;
  return TH_OK;
}

/*
** The first part of the string (zInput,nInput) contains a number.
** Set *pnVarname to the number of bytes in the numeric string.
*/
static int thNextNumber(
  Th_Interp *interp,
  const char *zInput,
  int nInput,
  int *pnLiteral
){
  int i = 0;
  int seenDot = 0;
  for(; i<nInput; i++){
    char c = zInput[i];
    if( (seenDot || c!='.') && !th_isdigit(c) ) break;
    if( c=='.' ) seenDot = 1;
  }
  *pnLiteral = i;
  return TH_OK;
}
1994
1995
1996
1997
1998
1999
2000

2001
2002
2003
2004
2005
2006
2007
        case OP_BITWISE_AND:  iRes = iLeft&iRight;  break;
        case OP_BITWISE_XOR:  iRes = iLeft^iRight;  break;
        case OP_BITWISE_OR:   iRes = iLeft|iRight;  break;
        case OP_LOGICAL_AND:  iRes = iLeft&&iRight; break;
        case OP_LOGICAL_OR:   iRes = iLeft||iRight; break;
        case OP_UNARY_MINUS:  iRes = -iLeft;        break;
        case OP_UNARY_PLUS:   iRes = +iLeft;        break;

        case OP_LOGICAL_NOT:  iRes = !iLeft;        break;
        default: assert(!"Internal error");
      }
      Th_SetResultInt(interp, iRes);
    }else if( rc==TH_OK && eArgType==ARG_NUMBER ){
      switch( pExpr->pOp->eOp ) {
        case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight);    break;







>







2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
        case OP_BITWISE_AND:  iRes = iLeft&iRight;  break;
        case OP_BITWISE_XOR:  iRes = iLeft^iRight;  break;
        case OP_BITWISE_OR:   iRes = iLeft|iRight;  break;
        case OP_LOGICAL_AND:  iRes = iLeft&&iRight; break;
        case OP_LOGICAL_OR:   iRes = iLeft||iRight; break;
        case OP_UNARY_MINUS:  iRes = -iLeft;        break;
        case OP_UNARY_PLUS:   iRes = +iLeft;        break;
        case OP_BITWISE_NOT:  iRes = ~iLeft;        break;
        case OP_LOGICAL_NOT:  iRes = !iLeft;        break;
        default: assert(!"Internal error");
      }
      Th_SetResultInt(interp, iRes);
    }else if( rc==TH_OK && eArgType==ARG_NUMBER ){
      switch( pExpr->pOp->eOp ) {
        case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight);    break;
2152
2153
2154
2155
2156
2157
2158





2159
2160
2161
2162
2163
2164
2165
2166
2167
    if( th_isspace(c) ){                                /* White-space     */
      i++;
    }else{
      Expr *pNew = (Expr *)Th_Malloc(interp, sizeof(Expr));
      const char *z = &zExpr[i];

      switch (c) {





        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
          thNextNumber(interp, z, nExpr-i, &pNew->nValue);
          break;

        case '$':
          thNextVarname(interp, z, nExpr-i, &pNew->nValue);
          break;








>
>
>
>
>
|
|







2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
    if( th_isspace(c) ){                                /* White-space     */
      i++;
    }else{
      Expr *pNew = (Expr *)Th_Malloc(interp, sizeof(Expr));
      const char *z = &zExpr[i];

      switch (c) {
        case '0':
          if( thNextInteger(interp, z, nExpr-i, &pNew->nValue)==TH_OK ){
            break;
          }
          /* fall through */
        case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          thNextNumber(interp, z, nExpr-i, &pNew->nValue);
          break;

        case '$':
          thNextVarname(interp, z, nExpr-i, &pNew->nValue);
          break;

2408
2409
2410
2411
2412
2413
2414
2415

2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
**     '\n'   0x0A
**     '\v'   0x0B
**     '\f'   0x0C
**     '\r'   0x0D
**
** Whitespace characters have the 0x01 flag set. Decimal digits have the
** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
** Alphabet characters have the 0x8 bit set.

**
** The special list characters have the 0x10 flag set
**
**    { } [ ] \ ; ' "
**
**    " 0x22
**
*/
static unsigned char aCharProp[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,     0,  1,  1,  1,  1,  1,  0,  0,   /* 0x0. */
  0,  0,  1,  1,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x1. */
  5,  4, 20,  4,  4,  4,  4,  4,     4,  4,  4,  4,  4,  4,  4,  4,   /* 0x2. */
  6,  6,  6,  6,  6,  6,  6,  6,     6,  6,  4, 20,  4,  4,  4,  4,   /* 0x3. */
  4, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 12, 12, 12, 12, 12,   /* 0x4. */
 12, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 20, 20, 20,  4,  4,   /* 0x5. */
  4, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 12, 12, 12, 12, 12,   /* 0x6. */
 12, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 20,  4, 20,  4,  4,   /* 0x7. */

  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x8. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x9. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xA. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xB. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xC. */







|
>












|
|

|







2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
**     '\n'   0x0A
**     '\v'   0x0B
**     '\f'   0x0C
**     '\r'   0x0D
**
** Whitespace characters have the 0x01 flag set. Decimal digits have the
** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
** Alphabet characters have the 0x8 bit set. Hexadecimal digits have the
** 0x20 flag set.
**
** The special list characters have the 0x10 flag set
**
**    { } [ ] \ ; ' "
**
**    " 0x22
**
*/
static unsigned char aCharProp[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,     0,  1,  1,  1,  1,  1,  0,  0,   /* 0x0. */
  0,  0,  1,  1,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x1. */
  5,  4, 20,  4,  4,  4,  4,  4,     4,  4,  4,  4,  4,  4,  4,  4,   /* 0x2. */
 38, 38, 38, 38, 38, 38, 38, 38,    38, 38,  4, 20,  4,  4,  4,  4,   /* 0x3. */
  4, 44, 44, 44, 44, 44, 44, 12,    12, 12, 12, 12, 12, 12, 12, 12,   /* 0x4. */
 12, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 20, 20, 20,  4,  4,   /* 0x5. */
  4, 44, 44, 44, 44, 44, 44, 12,    12, 12, 12, 12, 12, 12, 12, 12,   /* 0x6. */
 12, 12, 12, 12, 12, 12, 12, 12,    12, 12, 12, 20,  4, 20,  4,  4,   /* 0x7. */

  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x8. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0x9. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xA. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xB. */
  0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0,   /* 0xC. */
2452
2453
2454
2455
2456
2457
2458












2459
2460
2461
2462
2463
2464
2465
}
int th_isspecial(char c){
  return (aCharProp[(unsigned char)c] & 0x11);
}
int th_isalnum(char c){
  return (aCharProp[(unsigned char)c] & 0x0A);
}













#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif


/*







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







2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
}
int th_isspecial(char c){
  return (aCharProp[(unsigned char)c] & 0x11);
}
int th_isalnum(char c){
  return (aCharProp[(unsigned char)c] & 0x0A);
}
int th_isalpha(char c){
  return (aCharProp[(unsigned char)c] & 0x08);
}
int th_ishexdig(char c){
  return (aCharProp[(unsigned char)c] & 0x20);
}
int th_isoctdig(char c){
  return ((c|7) == '7');
}
int th_isbindig(char c){
  return ((c|1) == '1');
}

#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif


/*
2568
2569
2570
2571
2572
2573
2574


2575
2576
2577
2578
2579
2580
2581
2582

















2583

2584
2585
2586
2587







2588
2589
2590
2591
2592
2593
2594
2595
** If the string cannot be converted to an integer, return TH_ERROR.
** If the interp argument is not NULL, leave an error message in the
** interpreter result too.
*/
int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
  int i = 0;
  int iOut = 0;



  if( n<0 ){
    n = th_strlen(z);
  }

  if( n>0 && (z[0]=='-' || z[0]=='+') ){
    i = 1;
  }

















  for(; i<n; i++){

    if( !th_isdigit(z[i]) ){
      Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
      return TH_ERROR;
    }







    iOut = iOut * 10 + (z[i] - 48);
  }

  if( n>0 && z[0]=='-' ){
    iOut *= -1;
  }

  *piOut = iOut;







>
>








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

>
|



>
>
>
>
>
>
>
|







2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
** If the string cannot be converted to an integer, return TH_ERROR.
** If the interp argument is not NULL, leave an error message in the
** interpreter result too.
*/
int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
  int i = 0;
  int iOut = 0;
  int base = 10;
  int (*isdigit)(char) = th_isdigit;

  if( n<0 ){
    n = th_strlen(z);
  }

  if( n>0 && (z[0]=='-' || z[0]=='+') ){
    i = 1;
  }
  if( n>2 ){
    if( z[i]=='0' ){
      if( z[i+1]=='x' || z[i+1]=='X' ){
        i += 2;
        base = 16;
        isdigit = th_ishexdig;
      }else if( z[i+1]=='o' || z[i+1]=='O' ){
        i += 2;
        base = 8;
        isdigit = th_isoctdig;
      }else if( z[i+1]=='b' || z[i+1]=='B' ){
        i += 2;
        base = 2;
        isdigit = th_isbindig;
      }
    }
  }
  for(; i<n; i++){
    char c = z[i];
    if( !isdigit(c) ){
      Th_ErrorMessage(interp, "expected integer, got: \"", z, n);
      return TH_ERROR;
    }
    if( c>='a' ){
      c -= 'a'-10;
    }else if( c>='A' ){
      c -= 'A'-10;
    }else{
      c -= '0';
    }
    iOut = iOut * base + c;
  }

  if( n>0 && z[0]=='-' ){
    iOut *= -1;
  }

  *piOut = iOut;
Changes to src/th.h.
143
144
145
146
147
148
149

150



151
152
153
154
155
156
157
/*
** Drop in replacements for the corresponding standard library functions.
*/
int th_strlen(const char *);
int th_isdigit(char);
int th_isspace(char);
int th_isalnum(char);

int th_isspecial(char);



char *th_strdup(Th_Interp *interp, const char *z, int n);

/*
** Interfaces to register the language extensions.
*/
int th_register_language(Th_Interp *interp);            /* th_lang.c */
int th_register_sqlite(Th_Interp *interp);              /* th_sqlite.c */







>

>
>
>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
** Drop in replacements for the corresponding standard library functions.
*/
int th_strlen(const char *);
int th_isdigit(char);
int th_isspace(char);
int th_isalnum(char);
int th_isalpha(char);
int th_isspecial(char);
int th_ishexdig(char);
int th_isoctdig(char);
int th_isbindig(char);
char *th_strdup(Th_Interp *interp, const char *z, int n);

/*
** Interfaces to register the language extensions.
*/
int th_register_language(Th_Interp *interp);            /* th_lang.c */
int th_register_sqlite(Th_Interp *interp);              /* th_sqlite.c */
Changes to src/timeline.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
76
77
78
/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
  char z[UUID_SIZE+1];
  shorten_uuid(z, zUuid);
  if( g.perm.Hyperlink ){
    @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a>
  }else{
    @ <span class="timelineHistDsp">[%s(z)]</span>
  }
}

/*
** Generate a hyperlink to a diff between two versions.
*/
void hyperlink_to_diff(const char *zV1, const char *zV2){
  if( g.perm.Hyperlink ){
    if( zV2==0 ){
      @ %z(href("%R/diff?v2=%s",zV1))[diff]</a>
    }else{
      @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff]</a>
    }
  }
}

/*
** Generate a hyperlink to a date & time.
*/
void hyperlink_to_date(const char *zDate, const char *zSuffix){
  if( zSuffix==0 ) zSuffix = "";
  if( g.perm.Hyperlink ){
    @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix)







|





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







46
47
48
49
50
51
52
53
54
55
56
57
58













59
60
61
62
63
64
65
/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
  char z[UUID_SIZE+1];
  shorten_uuid(z, zUuid);
  if( g.perm.Hyperlink ){
    @ %z(xhref("class='timelineHistLink'","%R/info/%s",zUuid))[%s(z)]</a>
  }else{
    @ <span class="timelineHistDsp">[%s(z)]</span>
  }
}














/*
** Generate a hyperlink to a date & time.
*/
void hyperlink_to_date(const char *zDate, const char *zSuffix){
  if( zSuffix==0 ) zSuffix = "";
  if( g.perm.Hyperlink ){
    @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix)
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
      @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
    }else{
      @ (user: %h(zDispUser)%s(zTagList?",":"\051")
    }

    /* Generate a "detail" link for tags. */
    if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
      @ [%z(href("%R/info/%S",zUuid))details</a>]
    }

    /* Generate the "tags: TAGLIST" at the end of the comment, together
    ** with hyperlinks to the tag list.
    */
    if( zTagList ){
      if( g.perm.Hyperlink ){







|







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
      @ (user: %z(href("%z",zLink))%h(zDispUser)</a>%s(zTagList?",":"\051")
    }else{
      @ (user: %h(zDispUser)%s(zTagList?",":"\051")
    }

    /* Generate a "detail" link for tags. */
    if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
      @ [%z(href("%R/info/%s",zUuid))details</a>]
    }

    /* Generate the "tags: TAGLIST" at the end of the comment, together
    ** with hyperlinks to the tag list.
    */
    if( zTagList ){
      if( g.perm.Hyperlink ){
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
          if( !isNew && !isDel && zOldName!=0 ){
            @ <li> %h(zOldName) &rarr; %h(zFilename)
          }
          continue;
        }
        if( isNew ){
          @ <li> %h(zFilename) (new file) &nbsp;
          @ %z(href("%R/artifact/%S",zNew))[view]</a></li>
        }else if( isDel ){
          @ <li> %h(zFilename) (deleted)</li>
        }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
          @ <li> %h(zOldName) &rarr; %h(zFilename)
          @ %z(href("%R/artifact/%S",zNew))[view]</a></li>
        }else{
          if( zOldName!=0 ){
            @ <li> %h(zOldName) &rarr; %h(zFilename)
          }else{
            @ <li> %h(zFilename) &nbsp;
          }
          @ %z(href("%R/fdiff?v1=%S&v2=%S&sbs=1",zOld,zNew))[diff]</a></li>
        }
      }
      db_reset(&fchngQuery);
      if( inUl ){
        @ </ul>
      }
    }







|




|






|







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
          if( !isNew && !isDel && zOldName!=0 ){
            @ <li> %h(zOldName) &rarr; %h(zFilename)
          }
          continue;
        }
        if( isNew ){
          @ <li> %h(zFilename) (new file) &nbsp;
          @ %z(href("%R/artifact/%s",zNew))[view]</a></li>
        }else if( isDel ){
          @ <li> %h(zFilename) (deleted)</li>
        }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
          @ <li> %h(zOldName) &rarr; %h(zFilename)
          @ %z(href("%R/artifact/%s",zNew))[view]</a></li>
        }else{
          if( zOldName!=0 ){
            @ <li> %h(zOldName) &rarr; %h(zFilename)
          }else{
            @ <li> %h(zFilename) &nbsp;
          }
          @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zOld,zNew))[diff]</a></li>
        }
      }
      db_reset(&fchngQuery);
      if( inUl ){
        @ </ul>
      }
    }
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
      blob_appendf(&desc, "%d most recent %ss", n, zEType);
    }else{
      blob_appendf(&desc, "%d %ss", n, zEType);
    }
    if( zUses ){
      char *zFilenames = names_of_file(zUses);
      blob_appendf(&desc, " using file %s version %z%S</a>", zFilenames,
                   href("%R/artifact/%S",zUses), zUses);
      tmFlags |= TIMELINE_DISJOINT;
    }
    if( renameOnly ){
      blob_appendf(&desc, " that contain filename changes");
      tmFlags |= TIMELINE_DISJOINT|TIMELINE_FRENAMES;
    }
    if( zUser ){







|







1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
      blob_appendf(&desc, "%d most recent %ss", n, zEType);
    }else{
      blob_appendf(&desc, "%d %ss", n, zEType);
    }
    if( zUses ){
      char *zFilenames = names_of_file(zUses);
      blob_appendf(&desc, " using file %s version %z%S</a>", zFilenames,
                   href("%R/artifact/%s",zUses), zUses);
      tmFlags |= TIMELINE_DISJOINT;
    }
    if( renameOnly ){
      blob_appendf(&desc, " that contain filename changes");
      tmFlags |= TIMELINE_DISJOINT|TIMELINE_FRENAMES;
    }
    if( zUser ){
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
    n = atoi(zLimit);
  }else{
    n = -20;
  }
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("--width|-W value must be >20 or 0");
    }
  }else{
    width = 79;
  }
  zOffset = find_option("offset",0,1);
  iOffset = zOffset ? atoi(zOffset) : 0;
  if( g.argc>=4 ){







|







1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
    n = atoi(zLimit);
  }else{
    n = -20;
  }
  if( zWidth ){
    width = atoi(zWidth);
    if( (width!=0) && (width<=20) ){
      fossil_fatal("-W|--width value must be >20 or 0");
    }
  }else{
    width = 79;
  }
  zOffset = find_option("offset",0,1);
  iOffset = zOffset ? atoi(zOffset) : 0;
  if( g.argc>=4 ){
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
     "  FROM plink p, plink c, blob"
     " WHERE p.cid=c.pid  AND p.mtime>c.mtime"
     "   AND blob.rid=c.cid"
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    @ <li>
    @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)&amp;unhide">%S(zUuid)</a>
  }
  db_finalize(&q);
  style_footer();
}


/*







|







1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
     "  FROM plink p, plink c, blob"
     " WHERE p.cid=c.pid  AND p.mtime>c.mtime"
     "   AND blob.rid=c.cid"
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q, 0);
    @ <li>
    @ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
  }
  db_finalize(&q);
  style_footer();
}


/*
2382
2383
2384
2385
2386
2387
2388





































































2389
2390
2391
2392
2393
2394
2395
    */
  }
  @ </tbody></table>
  db_finalize(&query);
  output_table_sorting_javascript("statsTable","tnx");
}







































































/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_year_weeks(const char * zUserName){







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







2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
    */
  }
  @ </tbody></table>
  db_finalize(&query);
  output_table_sorting_javascript("statsTable","tnx");
}

/*
** Implements the "byweekday" view for /reports.
*/
static void stats_report_day_of_week(){
  Stmt query = empty_Stmt;
  int nRowNumber = 0;                /* current TR number */
  int nEventTotal = 0;               /* Total event count */
  int rowClass = 0;                  /* counter for alternating
                                        row colors */
  Blob sql = empty_blob;             /* SQL */
  int nMaxEvents = 1;                /* max number of events for
                                        all rows. */
  static char const * daysOfWeek[] = {
  "Monday", "Tuesday", "Wednesday", "Thursday",
  "Friday", "Saturday", "Sunday"
  };
      
  stats_report_init_view();
  stats_report_event_types_menu("byweekday", NULL);
  blob_append(&sql,
               "SELECT cast(mtime %% 7 AS INTEGER) dow, "
               "COUNT(*) AS eventCount "
               "FROM v_reports "
               "GROUP BY dow ORDER BY dow",
              -1);
  db_prepare(&query, blob_str(&sql));
  blob_reset(&sql);
  @ <h1>Timeline Events
  @ (%s(stats_report_label_for_type())) by Day of the Week</h1>
  @ <table class='statistics-report-table-events' border='0'
  @ cellpadding='2' cellspacing='0' id='statsTable'>
  @ <thead><tr>
  @ <th>DoW</th>
  @ <th>Day</th>
  @ <th>Events</th>
  @ <th width='90%%'><!-- relative commits graph --></th>
  @ </tr></thead><tbody>
  while( SQLITE_ROW == db_step(&query) ){
    const int nCount = db_column_int(&query, 1);
    if(nCount>nMaxEvents){
      nMaxEvents = nCount;
    }
  }
  db_reset(&query);
  while( SQLITE_ROW == db_step(&query) ){
    int const dayNum =db_column_int(&query, 0);
    const int nCount = db_column_int(&query, 1);
    int nSize = nCount
      ? (int)(100 * nCount / nMaxEvents)
      : 0;
    if(!nCount) continue /* arguable! Possible? */;
    else if(!nSize) nSize = 1;
    rowClass = ++nRowNumber % 2;
    nEventTotal += nCount;
    @<tr class='row%d(rowClass)'>
    @ <td>%d(dayNum)</td>
    @ <td>%s(daysOfWeek[dayNum])</td>
    @ <td>%d(nCount)</td>
    @ <td>
    @ <div class='statistics-report-graph-line'
    @  style='width:%d(nSize)%%;'>&nbsp;</div>
    @ </td>
    @</tr>
  }
  @ </tbody></table>
  db_finalize(&query);
  output_table_sorting_javascript("statsTable","ntnx");
}


/*
** Helper for stats_report_by_month_year(), which generates a list of
** week numbers. zTimeframe should be either a timeframe in the form YYYY
** or YYYY-MM.
*/
static void stats_report_year_weeks(const char * zUserName){
2552
2553
2554
2555
2556
2557
2558

2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569


2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
  if(zUserName && *zUserName){
    url_add_parameter(&url,"user", zUserName);
    timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
  }
  timeline_submenu(&url, "By Year", "view", "byyear", 0);
  timeline_submenu(&url, "By Month", "view", "bymonth", 0);
  timeline_submenu(&url, "By Week", "view", "byweek", 0);

  timeline_submenu(&url, "By User", "view", "byuser", "user");
  url_reset(&url);
  style_header("Activity Reports");
  if(0==fossil_strcmp(zView,"byyear")){
    stats_report_by_month_year(0, 0, zUserName);
  }else if(0==fossil_strcmp(zView,"bymonth")){
    stats_report_by_month_year(1, 0, zUserName);
  }else if(0==fossil_strcmp(zView,"byweek")){
    stats_report_year_weeks(zUserName);
  }else if(0==fossil_strcmp(zView,"byuser")){
    stats_report_by_user();


  }else{
    @ <h1>Select a report to show:</h1>
    @ <ul>
    @ <li><a href='?view=byyear'>Events by year</a></li>
    @ <li><a href='?view=bymonth'>Events by month</a></li>
    @ <li><a href='?view=byweek'>Events by calendar week</a></li>

    @ <li><a href='?view=byuser'>Events by user</a></li>
    @ </ul>
  }

  style_footer();
}







>











>
>






>






2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
  if(zUserName && *zUserName){
    url_add_parameter(&url,"user", zUserName);
    timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
  }
  timeline_submenu(&url, "By Year", "view", "byyear", 0);
  timeline_submenu(&url, "By Month", "view", "bymonth", 0);
  timeline_submenu(&url, "By Week", "view", "byweek", 0);
  timeline_submenu(&url, "By Weekday", "view", "byweekday", 0);
  timeline_submenu(&url, "By User", "view", "byuser", "user");
  url_reset(&url);
  style_header("Activity Reports");
  if(0==fossil_strcmp(zView,"byyear")){
    stats_report_by_month_year(0, 0, zUserName);
  }else if(0==fossil_strcmp(zView,"bymonth")){
    stats_report_by_month_year(1, 0, zUserName);
  }else if(0==fossil_strcmp(zView,"byweek")){
    stats_report_year_weeks(zUserName);
  }else if(0==fossil_strcmp(zView,"byuser")){
    stats_report_by_user();
  }else if(0==fossil_strcmp(zView,"byweekday")){
    stats_report_day_of_week();
  }else{
    @ <h1>Select a report to show:</h1>
    @ <ul>
    @ <li><a href='?view=byyear'>Events by year</a></li>
    @ <li><a href='?view=bymonth'>Events by month</a></li>
    @ <li><a href='?view=byweek'>Events by calendar week</a></li>
    @ <li><a href='?view=byweekday'>Events by day of the week</a></li>
    @ <li><a href='?view=byuser'>Events by user</a></li>
    @ </ul>
  }

  style_footer();
}
Changes to src/tkt.c.
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  }
  if( g.perm.ApndTkt && g.perm.Attach ){
    style_submenu_element("Attach", "Add An Attachment",
        "%s/attachadd?tkt=%T&from=%s/tktview/%t",
        g.zTop, zUuid, g.zTop, zUuid);
  }
  if( P("plaintext") ){
    style_submenu_element("Formatted", "Formatted", "%R/tktview/%S", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/tktview/%S?plaintext", zUuid);
  }
  style_header("View Ticket");
  if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
  ticket_init();
  initializeVariablesFromCGI();
  getAllTicketFields();
  initializeVariablesFromDb();







|


|







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
  }
  if( g.perm.ApndTkt && g.perm.Attach ){
    style_submenu_element("Attach", "Add An Attachment",
        "%s/attachadd?tkt=%T&from=%s/tktview/%t",
        g.zTop, zUuid, g.zTop, zUuid);
  }
  if( P("plaintext") ){
    style_submenu_element("Formatted", "Formatted", "%R/tktview/%s", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/tktview/%s?plaintext", zUuid);
  }
  style_header("View Ticket");
  if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
  ticket_init();
  initializeVariablesFromCGI();
  getAllTicketFields();
  initializeVariablesFromDb();
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
    "%s/info/%s", g.zTop, zUuid);
  style_submenu_element("Check-ins", "Check-ins",
    "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid);
  style_submenu_element("Timeline", "Timeline",
    "%s/tkttimeline?name=%s", g.zTop, zUuid);
  if( P("plaintext")!=0 ){
    style_submenu_element("Formatted", "Formatted",
                          "%R/tkthistory/%S", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/tkthistory/%S?plaintext", zUuid);
  }
  style_header(zTitle);
  free(zTitle);

  tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
  if( tagid==0 ){
    @ No such ticket: %h(zUuid)







|


|







893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
    "%s/info/%s", g.zTop, zUuid);
  style_submenu_element("Check-ins", "Check-ins",
    "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid);
  style_submenu_element("Timeline", "Timeline",
    "%s/tkttimeline?name=%s", g.zTop, zUuid);
  if( P("plaintext")!=0 ){
    style_submenu_element("Formatted", "Formatted",
                          "%R/tkthistory/%s", zUuid);
  }else{
    style_submenu_element("Plaintext", "Plaintext",
                          "%R/tkthistory/%s?plaintext", zUuid);
  }
  style_header(zTitle);
  free(zTitle);

  tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",zUuid);
  if( tagid==0 ){
    @ No such ticket: %h(zUuid)
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
    " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)"
    "   AND blob.rid=attachid"
    " ORDER BY 1",
    timeline_utc(), tagid, timeline_utc(), tagid
  );
  while( db_step(&q)==SQLITE_ROW ){
    Manifest *pTicket;
    char zShort[12];
    const char *zDate = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    const char *zChngUuid = db_column_text(&q, 2);
    const char *zFile = db_column_text(&q, 4);
    memcpy(zShort, zChngUuid, 10);
    zShort[10] = 0;
    if( nChng==0 ){
      @ <ol>
    }
    nChng++;
    if( zFile!=0 ){
      const char *zSrc = db_column_text(&q, 3);
      const char *zUser = db_column_text(&q, 5);
      if( zSrc==0 || zSrc[0]==0 ){
        @
        @ <li><p>Delete attachment "%h(zFile)"
      }else{
        @
        @ <li><p>Add attachment
        @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>"
      }
      @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
      @ (rid %d(rid)) by
      hyperlink_to_user(zUser,zDate," on");
      hyperlink_to_date(zDate, ".</p>");
    }else{
      pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
      if( pTicket ){
        @
        @ <li><p>Ticket change
        @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
        @ (rid %d(rid)) by
        hyperlink_to_user(pTicket->zUser,zDate," on");
        hyperlink_to_date(zDate, ":");
        @ </p>
        ticket_output_change_artifact(pTicket, "a");
      }
      manifest_destroy(pTicket);







<




<
<













|

|








|







922
923
924
925
926
927
928

929
930
931
932


933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
    " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)"
    "   AND blob.rid=attachid"
    " ORDER BY 1",
    timeline_utc(), tagid, timeline_utc(), tagid
  );
  while( db_step(&q)==SQLITE_ROW ){
    Manifest *pTicket;

    const char *zDate = db_column_text(&q, 0);
    int rid = db_column_int(&q, 1);
    const char *zChngUuid = db_column_text(&q, 2);
    const char *zFile = db_column_text(&q, 4);


    if( nChng==0 ){
      @ <ol>
    }
    nChng++;
    if( zFile!=0 ){
      const char *zSrc = db_column_text(&q, 3);
      const char *zUser = db_column_text(&q, 5);
      if( zSrc==0 || zSrc[0]==0 ){
        @
        @ <li><p>Delete attachment "%h(zFile)"
      }else{
        @
        @ <li><p>Add attachment
        @ "%z(href("%R/artifact/%s",zSrc))%s(zFile)</a>"
      }
      @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)</a>]
      @ (rid %d(rid)) by
      hyperlink_to_user(zUser,zDate," on");
      hyperlink_to_date(zDate, ".</p>");
    }else{
      pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
      if( pTicket ){
        @
        @ <li><p>Ticket change
        @ [%z(href("%R/artifact/%s",zChngUuid))%.10s(zChngUuid)</a>]
        @ (rid %d(rid)) by
        hyperlink_to_user(pTicket->zUser,zDate," on");
        hyperlink_to_date(zDate, ":");
        @ </p>
        ticket_output_change_artifact(pTicket, "a");
      }
      manifest_destroy(pTicket);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
        }
        tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
                       zTktUuid);
        if( tagid==0 ){
          fossil_fatal("no such ticket %h", zTktUuid);
        }
        db_prepare(&q,
          "SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL"
          "  FROM event, blob"
          " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
          "   AND blob.rid=event.objid"
          " UNION "
          "SELECT datetime(mtime%s), attachid, uuid, src, "
          "       filename, user"
          "  FROM attachment, blob"
          " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)"
          "   AND blob.rid=attachid"
          " ORDER BY 1 DESC",
          timeline_utc(), tagid, timeline_utc(), tagid
        );
        while( db_step(&q)==SQLITE_ROW ){
          Manifest *pTicket;
          char zShort[12];
          const char *zDate = db_column_text(&q, 0);
          int rid = db_column_int(&q, 1);
          const char *zChngUuid = db_column_text(&q, 2);
          const char *zFile = db_column_text(&q, 4);
          memcpy(zShort, zChngUuid, 10);
          zShort[10] = 0;
          if( zFile!=0 ){
            const char *zSrc = db_column_text(&q, 3);
            const char *zUser = db_column_text(&q, 5);
            if( zSrc==0 || zSrc[0]==0 ){
              fossil_print("Delete attachment %s\n", zFile);
            }else{
              fossil_print("Add attachment %s\n", zFile);
            }
            fossil_print(" by %s on %s\n", zUser, zDate);
          }else{







|




|
|








<


<
|
<
<


|







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235

1236
1237

1238


1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
        }
        tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
                       zTktUuid);
        if( tagid==0 ){
          fossil_fatal("no such ticket %h", zTktUuid);
        }
        db_prepare(&q,
          "SELECT datetime(mtime%s), objid, NULL, NULL, NULL"
          "  FROM event, blob"
          " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
          "   AND blob.rid=event.objid"
          " UNION "
          "SELECT datetime(mtime%s), attachid, filename, "
          "       src, user"
          "  FROM attachment, blob"
          " WHERE target=(SELECT substr(tagname,5) FROM tag WHERE tagid=%d)"
          "   AND blob.rid=attachid"
          " ORDER BY 1 DESC",
          timeline_utc(), tagid, timeline_utc(), tagid
        );
        while( db_step(&q)==SQLITE_ROW ){
          Manifest *pTicket;

          const char *zDate = db_column_text(&q, 0);
          int rid = db_column_int(&q, 1);

          const char *zFile = db_column_text(&q, 2);


          if( zFile!=0 ){
            const char *zSrc = db_column_text(&q, 3);
            const char *zUser = db_column_text(&q, 4);
            if( zSrc==0 || zSrc[0]==0 ){
              fossil_print("Delete attachment %s\n", zFile);
            }else{
              fossil_print("Add attachment %s\n", zFile);
            }
            fossil_print(" by %s on %s\n", zUser, zDate);
          }else{
Changes to src/update.c.
623
624
625
626
627
628
629


630
631
632
633
634
635
636
){
  Manifest *pManifest;
  ManifestFile *pFile;
  int rid=0;
  
  if( revision ){
    rid = name_to_typed_rid(revision,"ci");


  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }







>
>







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
){
  Manifest *pManifest;
  ManifestFile *pFile;
  int rid=0;
  
  if( revision ){
    rid = name_to_typed_rid(revision,"ci");
  }else if( !g.localOpen ){
    rid = name_to_typed_rid(db_get("main-branch","trunk"),"ci");
  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }
Changes to src/url.c.
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
  }
}

/*
** Parse the given URL, which describes a sync server.  Populate variables 
** in the global "g" structure as follows:
**
**      g.urlIsFile      True if FILE:
**      g.urlIsHttps     True if HTTPS: 
**      g.urlIsSsh       True if SSH:
**      g.urlProtocol    "http" or "https" or "file"
**      g.urlName        Hostname for HTTP:, HTTPS:, SSH:.  Filename for FILE:
**      g.urlPort        TCP port number for HTTP or HTTPS.
**      g.urlDfltPort    Default TCP port number (80 or 443).
**      g.urlPath        Path name for HTTP or HTTPS.
**      g.urlUser        Userid.
**      g.urlPasswd      Password.
**      g.urlHostname    HOST:PORT or just HOST if port is the default.
**      g.urlCanonical   The URL in canonical form, omitting the password
**
** HTTP url format as follows (HTTPS is the same with a different scheme):
**
**     http://userid:password@host:port/path
**
** SSH url format is:
**
**     ssh://userid@host:port/path?fossil=path/to/fossil.exe
**
*/
void url_parse(const char *zUrl, unsigned int urlFlags){
  url_parse_local(zUrl, urlFlags, GLOBAL_URL());
}

/*
** COMMAND: test-urlparser
**
** Usage: %fossil test-urlparser URL ?options?
**







|
|
|
|
|
|
|
|
|
|
|
|











|







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
  }
}

/*
** Parse the given URL, which describes a sync server.  Populate variables 
** in the global "g" structure as follows:
**
**      g.url.isFile      True if FILE:
**      g.url.isHttps     True if HTTPS: 
**      g.url.isSsh       True if SSH:
**      g.url.protocol    "http" or "https" or "file"
**      g.url.name        Hostname for HTTP:, HTTPS:, SSH:.  Filename for FILE:
**      g.url.port        TCP port number for HTTP or HTTPS.
**      g.url.dfltPort    Default TCP port number (80 or 443).
**      g.url.path        Path name for HTTP or HTTPS.
**      g.url.user        Userid.
**      g.url.passwd      Password.
**      g.url.hostname    HOST:PORT or just HOST if port is the default.
**      g.url.canonical   The URL in canonical form, omitting the password
**
** HTTP url format as follows (HTTPS is the same with a different scheme):
**
**     http://userid:password@host:port/path
**
** SSH url format is:
**
**     ssh://userid@host:port/path?fossil=path/to/fossil.exe
**
*/
void url_parse(const char *zUrl, unsigned int urlFlags){
  url_parse_local(zUrl, urlFlags, &g.url);
}

/*
** COMMAND: test-urlparser
**
** Usage: %fossil test-urlparser URL ?options?
**
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
347
348
349
  }
  if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
  if( g.argc!=3 && g.argc!=4 ){
    usage("URL");
  }
  url_parse(g.argv[2], fg);
  for(i=0; i<2; i++){
    fossil_print("g.urlIsFile    = %d\n", g.urlIsFile);
    fossil_print("g.urlIsHttps   = %d\n", g.urlIsHttps);
    fossil_print("g.urlIsSsh     = %d\n", g.urlIsSsh);
    fossil_print("g.urlProtocol  = %s\n", g.urlProtocol);
    fossil_print("g.urlName      = %s\n", g.urlName);
    fossil_print("g.urlPort      = %d\n", g.urlPort);
    fossil_print("g.urlDfltPort  = %d\n", g.urlDfltPort);
    fossil_print("g.urlHostname  = %s\n", g.urlHostname);
    fossil_print("g.urlPath      = %s\n", g.urlPath);
    fossil_print("g.urlUser      = %s\n", g.urlUser);
    fossil_print("g.urlPasswd    = %s\n", g.urlPasswd);
    fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
    fossil_print("g.urlFossil    = %s\n", g.urlFossil);
    fossil_print("g.urlFlags     = 0x%02x\n", g.urlFlags);
    if( g.urlIsFile || g.urlIsSsh ) break;
    if( i==0 ){
      fossil_print("********\n");
      url_enable_proxy("Using proxy: ");
    }
  }
}








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
347
348
349
  }
  if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
  if( g.argc!=3 && g.argc!=4 ){
    usage("URL");
  }
  url_parse(g.argv[2], fg);
  for(i=0; i<2; i++){
    fossil_print("g.url.isFile    = %d\n", g.url.isFile);
    fossil_print("g.url.isHttps   = %d\n", g.url.isHttps);
    fossil_print("g.url.isSsh     = %d\n", g.url.isSsh);
    fossil_print("g.url.protocol  = %s\n", g.url.protocol);
    fossil_print("g.url.name      = %s\n", g.url.name);
    fossil_print("g.url.port      = %d\n", g.url.port);
    fossil_print("g.url.dfltPort  = %d\n", g.url.dfltPort);
    fossil_print("g.url.hostname  = %s\n", g.url.hostname);
    fossil_print("g.url.path      = %s\n", g.url.path);
    fossil_print("g.url.user      = %s\n", g.url.user);
    fossil_print("g.url.passwd    = %s\n", g.url.passwd);
    fossil_print("g.url.canonical = %s\n", g.url.canonical);
    fossil_print("g.url.fossil    = %s\n", g.url.fossil);
    fossil_print("g.url.flags     = 0x%02x\n", g.url.flags);
    if( g.url.isFile || g.url.isSsh ) break;
    if( i==0 ){
      fossil_print("********\n");
      url_enable_proxy("Using proxy: ");
    }
  }
}

383
384
385
386
387
388
389
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
  if( zProxy==0 ){
    zProxy = db_get("proxy", 0);
    if( zProxy==0 || zProxy[0]==0 || is_truth(zProxy) ){
      zProxy = fossil_getenv("http_proxy");
    }
  }
  if( zProxy && zProxy[0] && !is_false(zProxy)
      && !g.urlIsSsh && !g.urlIsFile ){
    char *zOriginalUrl = g.urlCanonical;
    char *zOriginalHost = g.urlHostname;
    int fOriginalIsHttps = g.urlIsHttps;
    char *zOriginalUser = g.urlUser;
    char *zOriginalPasswd = g.urlPasswd;
    char *zOriginalUrlPath = g.urlPath;
    int iOriginalPort = g.urlPort;
    unsigned uOriginalFlags = g.urlFlags;
    g.urlUser = 0;
    g.urlPasswd = "";
    url_parse(zProxy, 0);
    if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
    g.urlPath = zOriginalUrl;
    g.urlHostname = zOriginalHost;
    if( g.urlUser ){
      char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
      char *zCredentials2 = encode64(zCredentials1, -1);
      g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
      free(zCredentials1);
    }
    g.urlUser = zOriginalUser;
    g.urlPasswd = zOriginalPasswd;
    g.urlIsHttps = fOriginalIsHttps;
    g.useProxy = 1;
    g.proxyUrlPath = zOriginalUrlPath;
    g.proxyOrigPort = iOriginalPort;
    g.urlFlags = uOriginalFlags;
  }
}

#if INTERFACE
/*
** An instance of this object is used to build a URL with query parameters.
*/







|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|


|
|
|
|
|
|
|







383
384
385
386
387
388
389
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
  if( zProxy==0 ){
    zProxy = db_get("proxy", 0);
    if( zProxy==0 || zProxy[0]==0 || is_truth(zProxy) ){
      zProxy = fossil_getenv("http_proxy");
    }
  }
  if( zProxy && zProxy[0] && !is_false(zProxy)
      && !g.url.isSsh && !g.url.isFile ){
    char *zOriginalUrl = g.url.canonical;
    char *zOriginalHost = g.url.hostname;
    int fOriginalIsHttps = g.url.isHttps;
    char *zOriginalUser = g.url.user;
    char *zOriginalPasswd = g.url.passwd;
    char *zOriginalUrlPath = g.url.path;
    int iOriginalPort = g.url.port;
    unsigned uOriginalFlags = g.url.flags;
    g.url.user = 0;
    g.url.passwd = "";
    url_parse(zProxy, 0);
    if( zMsg ) fossil_print("%s%s\n", zMsg, g.url.canonical);
    g.url.path = zOriginalUrl;
    g.url.hostname = zOriginalHost;
    if( g.url.user ){
      char *zCredentials1 = mprintf("%s:%s", g.url.user, g.url.passwd);
      char *zCredentials2 = encode64(zCredentials1, -1);
      g.url.proxyAuth = mprintf("Basic %z", zCredentials2);
      free(zCredentials1);
    }
    g.url.user = zOriginalUser;
    g.url.passwd = zOriginalPasswd;
    g.url.isHttps = fOriginalIsHttps;
    g.url.useProxy = 1;
    g.url.proxyUrlPath = zOriginalUrlPath;
    g.url.proxyOrigPort = iOriginalPort;
    g.url.flags = uOriginalFlags;
  }
}

#if INTERFACE
/*
** An instance of this object is used to build a URL with query parameters.
*/
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
  }else{
    fossil_fatal("missing or incorrect password for user \"%s\"",
                 pUrlData->user);
  }
}

/*
** Prompt the user for the password for g.urlUser.  Store the result
** in g.urlPasswd.
*/
void url_prompt_for_password(void){
  url_prompt_for_password_local(GLOBAL_URL());
}

/*
** Remember the URL and password if requested.
*/
void url_remember(void){
  if( g.urlFlags & URL_REMEMBER ){
    db_set("last-sync-url", g.urlCanonical, 0);
    if( g.urlUser!=0 && g.urlPasswd!=0 && ( g.urlFlags & URL_REMEMBER_PW ) ){
      db_set("last-sync-pw", obscure(g.urlPasswd), 0);
    }
  }
}

/* Preemptively prompt for a password if a username is given in the
** URL but no password.
*/
void url_get_password_if_needed(void){
  if( (g.urlUser && g.urlUser[0])
   && (g.urlPasswd==0 || g.urlPasswd[0]==0)
   && isatty(fileno(stdin))
  ){
    url_prompt_for_password();
  }
}







|
|


|






|
|
|
|








|
|





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
  }else{
    fossil_fatal("missing or incorrect password for user \"%s\"",
                 pUrlData->user);
  }
}

/*
** Prompt the user for the password for g.url.user.  Store the result
** in g.url.passwd.
*/
void url_prompt_for_password(void){
  url_prompt_for_password_local(&g.url);
}

/*
** Remember the URL and password if requested.
*/
void url_remember(void){
  if( g.url.flags & URL_REMEMBER ){
    db_set("last-sync-url", g.url.canonical, 0);
    if( g.url.user!=0 && g.url.passwd!=0 && ( g.url.flags & URL_REMEMBER_PW ) ){
      db_set("last-sync-pw", obscure(g.url.passwd), 0);
    }
  }
}

/* Preemptively prompt for a password if a username is given in the
** URL but no password.
*/
void url_get_password_if_needed(void){
  if( (g.url.user && g.url.user[0])
   && (g.url.passwd==0 || g.url.passwd[0]==0)
   && isatty(fileno(stdin))
  ){
    url_prompt_for_password();
  }
}
Changes to src/user.c.
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  if( attempt_user(fossil_getenv("USER")) ) return;

  if( attempt_user(fossil_getenv("LOGNAME")) ) return;

  if( attempt_user(fossil_getenv("USERNAME")) ) return;

  url_parse(0, 0);
  if( g.urlUser && attempt_user(g.urlUser) ) return;

  fossil_print(
    "Cannot figure out who you are!  Consider using the --user\n"
    "command line option, setting your USER environment variable,\n"
    "or setting a default user with \"fossil user default USER\".\n"
  );
  fossil_fatal("cannot determine user");







|







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  if( attempt_user(fossil_getenv("USER")) ) return;

  if( attempt_user(fossil_getenv("LOGNAME")) ) return;

  if( attempt_user(fossil_getenv("USERNAME")) ) return;

  url_parse(0, 0);
  if( g.url.user && attempt_user(g.url.user) ) return;

  fossil_print(
    "Cannot figure out who you are!  Consider using the --user\n"
    "command line option, setting your USER environment variable,\n"
    "or setting a default user with \"fossil user default USER\".\n"
  );
  fossil_fatal("cannot determine user");
Changes to src/util.c.
310
311
312
313
314
315
316










int is_valid_fd(int fd){
#ifdef _WIN32
  return 1;
#else
  return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
#endif
}

















>
>
>
>
>
>
>
>
>
>
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
int is_valid_fd(int fd){
#ifdef _WIN32
  return 1;
#else
  return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
#endif
}

/*
** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
** only lower-case ASCII hexadecimal values.
*/
int fossil_is_uuid(char const * zSym){
  return zSym
    && (UUID_SIZE==strlen(zSym))
    && validate16(zSym, UUID_SIZE);
}
Changes to src/wiki.c.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  zMimetype = wiki_filter_mimetypes(zMimetype);
  if( !g.isHome ){
    if( rid ){
      style_submenu_element("Diff", "Last change",
                 "%R/wdiff?name=%T&a=%d", zPageName, rid);
      zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
      style_submenu_element("Details", "Details",
                   "%R/info/%S", zUuid);
    }
    if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
      if( db_get_boolean("wysiwyg-wiki", 0) ){
        style_submenu_element("Edit", "Edit Wiki Page",
             "%s/wikiedit?name=%T&wysiwyg=1",
             g.zTop, zPageName);
      }else{







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  zMimetype = wiki_filter_mimetypes(zMimetype);
  if( !g.isHome ){
    if( rid ){
      style_submenu_element("Diff", "Last change",
                 "%R/wdiff?name=%T&a=%d", zPageName, rid);
      zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
      style_submenu_element("Details", "Details",
                   "%R/info/%s", zUuid);
    }
    if( (rid && g.perm.WrWiki) || (!rid && g.perm.NewWiki) ){
      if( db_get_boolean("wysiwyg-wiki", 0) ){
        style_submenu_element("Edit", "Edit Wiki Page",
             "%s/wikiedit?name=%T&wysiwyg=1",
             g.zTop, zPageName);
      }else{
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
  @ <h2>Formatting Rule Summary</h2>
  @ <ol>
  @ <li>Blank lines are paragraph breaks</li>
  @ <li>Bullets are "*" surrounded by two spaces at the beginning of the
  @ line.</li>
  @ <li>Enumeration items are "#" surrounded by two spaces at the beginning of
  @ a line.</li>
  @ <li>Indented pargraphs begin with a tab or two spaces.</li>
  @ <li>Hyperlinks are contained with square brackets:  "[target]" or
  @ "[target|name]".</li>
  @ <li>Most ordinary HTML works.</li>
  @ <li>&lt;verbatim&gt; and &lt;nowiki&gt;.</li>
  @ </ol>
  @ <p>We call the first five rules above "wiki" formatting rules.  The
  @ last two rules are the HTML formatting rule.</p>







|







889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
  @ <h2>Formatting Rule Summary</h2>
  @ <ol>
  @ <li>Blank lines are paragraph breaks</li>
  @ <li>Bullets are "*" surrounded by two spaces at the beginning of the
  @ line.</li>
  @ <li>Enumeration items are "#" surrounded by two spaces at the beginning of
  @ a line.</li>
  @ <li>Indented paragraphs begin with a tab or two spaces.</li>
  @ <li>Hyperlinks are contained with square brackets:  "[target]" or
  @ "[target|name]".</li>
  @ <li>Most ordinary HTML works.</li>
  @ <li>&lt;verbatim&gt; and &lt;nowiki&gt;.</li>
  @ </ol>
  @ <p>We call the first five rules above "wiki" formatting rules.  The
  @ last two rules are the HTML formatting rule.</p>
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
  @ Text within square brackets ("[...]") becomes a hyperlink.  The
  @ target can be a wiki page name, the artifact ID of a check-in or ticket,
  @ the name of an image, or a URL.  By default, the target is displayed
  @ as the text of the hyperlink.  But you can specify alternative text
  @ after the target name separated by a "|" character.</p>
  @ <p>You can also link to internal anchor names using [#anchor-name], providing
  @ you have added the necessary "&lt;a name="anchor-name"&gt;&lt;/a&gt;"
  @ tag to your wiki page.</p></li>
  @ <li> <p><span class="wikiruleHead">HTML</span>.
  @ The following standard HTML elements may be used:
  show_allowed_wiki_markup();
  @ . There are two non-standard elements available:
  @ &lt;verbatim&gt; and &lt;nowiki&gt;.
  @ No other elements are allowed.  All attributes are checked and







|







925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
  @ Text within square brackets ("[...]") becomes a hyperlink.  The
  @ target can be a wiki page name, the artifact ID of a check-in or ticket,
  @ the name of an image, or a URL.  By default, the target is displayed
  @ as the text of the hyperlink.  But you can specify alternative text
  @ after the target name separated by a "|" character.</p>
  @ <p>You can also link to internal anchor names using [#anchor-name], providing
  @ you have added the necessary "&lt;a name='anchor-name'&gt;&lt;/a&gt;"
  @ tag to your wiki page.</p></li>
  @ <li> <p><span class="wikiruleHead">HTML</span>.
  @ The following standard HTML elements may be used:
  show_allowed_wiki_markup();
  @ . There are two non-standard elements available:
  @ &lt;verbatim&gt; and &lt;nowiki&gt;.
  @ No other elements are allowed.  All attributes are checked and
Changes to src/xfer.c.
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
** Floating-point absolute value
*/
static double fossil_fabs(double x){
  return x>0.0 ? x : -x;
}

/*
** Sync to the host identified in g.urlName and g.urlPath.  This
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true.  Records
** are pulled if pullFlag is true.  A full sync occurs if both are
** true.
*/
int client_sync(







|







1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
** Floating-point absolute value
*/
static double fossil_fabs(double x){
  return x>0.0 ? x : -x;
}

/*
** Sync to the host identified in g.url.name and g.url.path.  This
** routine is called by the client.
**
** Records are pushed to the server if pushFlag is true.  Records
** are pulled if pullFlag is true.  A full sync occurs if both are
** true.
*/
int client_sync(
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
        if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
          char *zMsg = blob_terminate(&xfer.aToken[1]);
          defossilize(zMsg);
          fossil_force_newline();
          fossil_print("Error: %s\n", zMsg);
          if( fossil_strcmp(zMsg, "login failed")==0 ){
            if( nCycle<2 ){
              g.urlPasswd = 0;
              go = 1;
              if( g.cgiOutput==0 ){
                g.urlFlags |= URL_PROMPT_PW;
                g.urlFlags &= ~URL_PROMPTED;
                url_prompt_for_password();
                url_remember();
              }
            }
          }else{
            blob_appendf(&xfer.err, "server says: %s\n", zMsg);
            nErr++;







|


|
|







1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
        if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
          char *zMsg = blob_terminate(&xfer.aToken[1]);
          defossilize(zMsg);
          fossil_force_newline();
          fossil_print("Error: %s\n", zMsg);
          if( fossil_strcmp(zMsg, "login failed")==0 ){
            if( nCycle<2 ){
              g.url.passwd = 0;
              go = 1;
              if( g.cgiOutput==0 ){
                g.url.flags |= URL_PROMPT_PW;
                g.url.flags &= ~URL_PROMPTED;
                url_prompt_for_password();
                url_remember();
              }
            }
          }else{
            blob_appendf(&xfer.err, "server says: %s\n", zMsg);
            nErr++;
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
     g.clockSkewSeen = 1;
  }

  fossil_force_newline();
  fossil_print(
     "%s finished with %lld bytes sent, %lld bytes received\n",
     zOpType, nSent, nRcvd);
  transport_close(GLOBAL_URL());
  transport_global_shutdown(GLOBAL_URL());
  db_multi_exec("DROP TABLE onremote");
  manifest_crosslink_end(MC_PERMIT_HOOKS);
  content_enable_dephantomize(1);
  db_end_transaction(0);
  return nErr;
}







|
|






1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
     g.clockSkewSeen = 1;
  }

  fossil_force_newline();
  fossil_print(
     "%s finished with %lld bytes sent, %lld bytes received\n",
     zOpType, nSent, nRcvd);
  transport_close(&g.url);
  transport_global_shutdown(&g.url);
  db_multi_exec("DROP TABLE onremote");
  manifest_crosslink_end(MC_PERMIT_HOOKS);
  content_enable_dephantomize(1);
  db_end_transaction(0);
  return nErr;
}
Changes to src/xfersetup.c.
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
  setup_menu_entry("Commit", "xfersetup_commit",
    "Specific TH1 code to run after processing a commit.");
  setup_menu_entry("Ticket", "xfersetup_ticket",
    "Specific TH1 code to run after processing a ticket change.");
  @ </table>

  url_parse(0, 0);
  if( g.urlProtocol ){
    unsigned syncFlags;
    const char *zButton;
    char *zWarning;

    if( db_get_boolean("dont-push", 0) ){
      syncFlags = SYNC_PULL;
      zButton = "Pull";
      zWarning = 0;
    }else{
      syncFlags = SYNC_PUSH | SYNC_PULL;
      zButton = "Synchronize";
      zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
                         g.urlCanonical);
    }
    if( P("sync") ){
      user_select();
      url_enable_proxy(0);
      client_sync(syncFlags, 0, 0);
    }
    @ <p>Press the %h(zButton) button below to synchronize with the
    @ "%h(g.urlCanonical)" repository now.  This may be useful when
    @ testing the various transfer scripts.</p>
    @ <p>You can use the "http -async" command in your scripts, but
    @ make sure the "th1-uri-regexp" setting is set first.</p>
    if( zWarning ){
      @
      @ <big><b>%h(zWarning)</b></big>
      free(zWarning);







|












|







|







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
  setup_menu_entry("Commit", "xfersetup_commit",
    "Specific TH1 code to run after processing a commit.");
  setup_menu_entry("Ticket", "xfersetup_ticket",
    "Specific TH1 code to run after processing a ticket change.");
  @ </table>

  url_parse(0, 0);
  if( g.url.protocol ){
    unsigned syncFlags;
    const char *zButton;
    char *zWarning;

    if( db_get_boolean("dont-push", 0) ){
      syncFlags = SYNC_PULL;
      zButton = "Pull";
      zWarning = 0;
    }else{
      syncFlags = SYNC_PUSH | SYNC_PULL;
      zButton = "Synchronize";
      zWarning = mprintf("WARNING: Pushing to \"%s\" is enabled.",
                         g.url.canonical);
    }
    if( P("sync") ){
      user_select();
      url_enable_proxy(0);
      client_sync(syncFlags, 0, 0);
    }
    @ <p>Press the %h(zButton) button below to synchronize with the
    @ "%h(g.url.canonical)" repository now.  This may be useful when
    @ testing the various transfer scripts.</p>
    @ <p>You can use the "http -async" command in your scripts, but
    @ make sure the "th1-uri-regexp" setting is set first.</p>
    if( zWarning ){
      @
      @ <big><b>%h(zWarning)</b></big>
      free(zWarning);
Changes to src/zip.c.
416
417
418
419
420
421
422









423
424
425
426
427
428
429

/*
** WEBPAGE: zip
** URL: /zip/RID.zip
**
** Generate a ZIP archive for the baseline.
** Return that ZIP archive as the HTTP reply content.









*/
void baseline_zip_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob zip;








>
>
>
>
>
>
>
>
>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

/*
** WEBPAGE: zip
** URL: /zip/RID.zip
**
** Generate a ZIP archive for the baseline.
** Return that ZIP archive as the HTTP reply content.
**
** Optional URL Parameters:
**
** - name=base name of the output file. Defaults to
** something project/version-specific.
**
** - uuid=the version to zip (may be a tag/branch name).
** Defaults to trunk.
**
*/
void baseline_zip_page(void){
  int rid;
  char *zName, *zRid;
  int nName, nRid;
  Blob zip;

Changes to test/file1.test.
22
23
24
25
26
27
28









29
30
31
32
33
34
35
36
37
38
39
40
41
42











  set i 1
  foreach {path result} $args {
    fossil test-simplify-name $path
    test simplify-name-$testname.$i {$::RESULT=="\[$path\] -> \[$result\]"}
    incr i
  }
}










simplify-name 100 . . .// . .. .. ..///// ..
simplify-name 101 {} {} / / ///////// / ././././ .
simplify-name 102 x x /x /x ///x //x
simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y

if {$::tcl_platform(os)=="Windows NT"} {
  simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {}
  simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {}
}


















>
>
>
>
>
>
>
>
>














>
>
>
>
>
>
>
>
>
>
>
22
23
24
25
26
27
28
29
30
31
32
33
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
  set i 1
  foreach {path result} $args {
    fossil test-simplify-name $path
    test simplify-name-$testname.$i {$::RESULT=="\[$path\] -> \[$result\]"}
    incr i
  }
}

proc relative-name {testname args} {
  set i 1
  foreach {subdir path result} $args {
    fossil test-relative-name --chdir $subdir $path
    test relative-name-$testname.$i {$::RESULT==$result}
    incr i
  }
}

simplify-name 100 . . .// . .. .. ..///// ..
simplify-name 101 {} {} / / ///////// / ././././ .
simplify-name 102 x x /x /x ///x //x
simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y

if {$::tcl_platform(os)=="Windows NT"} {
  simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {}
  simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {}
}

# Those directories are only needed for the testcase being able to "--chdir" to it.
file mkdir test1
file mkdir test1/test2

relative-name 100 . . . test1 [pwd] .. test1 [pwd]/ .. test1 [pwd]/test ../test
relative-name 101 test1/test2 [pwd] ../.. test1/test2 [pwd]/ ../.. test1/test2 [pwd]/test ../../test
relative-name 102 test1 [pwd]/test ../test . [pwd]/file1 ./file1 . [pwd]/file1/file2 ./file1/file2

catch {file delete test1/test2}
catch {file delete test1}
Changes to test/th1.test.
360
361
362
363
364
365
366

















































































































fossil test-th-eval "expr +2147483649"
test th1-expr-12 {$RESULT eq {-2147483647}}

###############################################################################

fossil test-th-eval "expr +2147483649.0"
test th1-expr-13 {$RESULT eq {2147483649.0}}
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
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
fossil test-th-eval "expr +2147483649"
test th1-expr-12 {$RESULT eq {-2147483647}}

###############################################################################

fossil test-th-eval "expr +2147483649.0"
test th1-expr-13 {$RESULT eq {2147483649.0}}

###############################################################################

fossil test-th-eval "expr ~(-1)"
test th1-expr-14 {$RESULT eq {0}}

###############################################################################

fossil test-th-eval "expr ~-1"
test th1-expr-15 {$RESULT eq {0}}

###############################################################################

fossil test-th-eval "expr ~0"
test th1-expr-16 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr ~+0"
test th1-expr-17 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr ~-0"
test th1-expr-18 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr ~(+0)"
test th1-expr-19 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr ~(-0)"
test th1-expr-20 {$RESULT eq {-1}}

###############################################################################

fossil test-th-eval "expr ~1"
test th1-expr-21 {$RESULT eq {-2}}

###############################################################################

fossil test-th-eval "expr ~+1"
test th1-expr-22 {$RESULT eq {-2}}

###############################################################################

fossil test-th-eval "expr ~(+1)"
test th1-expr-23 {$RESULT eq {-2}}

###############################################################################

fossil test-th-eval "expr 0+0b11"
test th1-expr-24 {$RESULT eq 3}

###############################################################################

fossil test-th-eval "expr 0+0o15"
test th1-expr-25 {$RESULT eq 13}

###############################################################################

fossil test-th-eval "expr 0+0x15"
test th1-expr-26 {$RESULT eq 21}

###############################################################################

fossil test-th-eval "expr 0+0b2"
test th1-expr-27 {$RESULT eq {TH_ERROR: expected number, got: "0b2"}}

###############################################################################

fossil test-th-eval "expr 0+0o8"
test th1-expr-28 {$RESULT eq {TH_ERROR: expected number, got: "0o8"}}

###############################################################################

fossil test-th-eval "expr 0+0xg"
test th1-expr-29 {$RESULT eq {TH_ERROR: syntax error in expression: "0+0xg"}}

###############################################################################

fossil test-th-eval "expr 0+0b1."
test th1-expr-30 {$RESULT eq {TH_ERROR: syntax error in expression: "0+0b1."}}

###############################################################################

fossil test-th-eval "expr 0+0o1."
test th1-expr-31 {$RESULT eq {TH_ERROR: syntax error in expression: "0+0o1."}}

###############################################################################

fossil test-th-eval "expr 0+0x1."
test th1-expr-32 {$RESULT eq {TH_ERROR: syntax error in expression: "0+0x1."}}

###############################################################################

fossil test-th-eval "expr 0ne5"
test th1-expr-33 {$RESULT eq {1}}

###############################################################################

fossil test-th-eval "expr 0b1+5"
test th1-expr-34 {$RESULT eq {6}}


###############################################################################

fossil test-th-eval "expr 0+0b"
test th1-expr-35 {$RESULT eq {TH_ERROR: expected number, got: "0b"}}


Changes to win/Makefile.mingw.
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1f/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1f

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







|
|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean








|
<
<
<
<







667
668
669
670
671
672
673
674




675
676
677
678
679
680
681
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o





zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif







<


|
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o


$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o

Changes to win/Makefile.mingw.mistachkin.
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1f/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1f

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage







|
|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
ZLIBDIR = $(SRCDIR)/../compat/zlib

#### The directories where the OpenSSL include and library files are located.
#    The recommended usage here is to use the Sysinternals junction tool
#    to create a hard link between an "openssl-1.x" sub-directory of the
#    Fossil source code directory and the target OpenSSL source directory.
#
OPENSSLINCDIR = $(SRCDIR)/../compat/openssl-1.0.1g/include
OPENSSLLIBDIR = $(SRCDIR)/../compat/openssl-1.0.1g

#### Either the directory where the Tcl library is installed or the Tcl
#    source code directory resides (depending on the value of the macro
#    FOSSIL_TCL_SOURCE).  If this points to the Tcl install directory,
#    this directory must have "include" and "lib" sub-directories.  If
#    this points to the Tcl source code directory, this directory must
#    have "generic" and "win" sub-directories.  The recommended usage
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/cson_amalgamation.o

ifdef FOSSIL_ENABLE_TCL
EXTRAOBJ +=  $(OBJDIR)/th_tcl.o
endif

zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean








|
<
<
<
<







667
668
669
670
671
672
673
674




675
676
677
678
679
680
681
# the repository after running the tests.
test:	$(OBJDIR) $(APPNAME)
	$(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME)

$(OBJDIR)/VERSION.h:	$(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(VERSION)
	$(VERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h

EXTRAOBJ =  $(OBJDIR)/sqlite3.o  $(OBJDIR)/shell.o  $(OBJDIR)/th.o  $(OBJDIR)/th_lang.o  $(OBJDIR)/th_tcl.o  $(OBJDIR)/cson_amalgamation.o





zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc libz.a

clean-zlib:
	$(MAKE) -C $(ZLIBDIR) PREFIX=$(PREFIX) -f win32/Makefile.gcc clean

1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753

$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o

ifdef FOSSIL_ENABLE_TCL
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o
endif







<


<
1739
1740
1741
1742
1743
1744
1745

1746
1747


$(OBJDIR)/th.o:	$(SRCDIR)/th.c
	$(XTCC) -c $(SRCDIR)/th.c -o $(OBJDIR)/th.o

$(OBJDIR)/th_lang.o:	$(SRCDIR)/th_lang.c
	$(XTCC) -c $(SRCDIR)/th_lang.c -o $(OBJDIR)/th_lang.o


$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o

Changes to win/Makefile.msc.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1f\include
SSLLIBDIR = $(B)\compat\openssl-1.0.1f\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic







|
|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Uncomment to enable SSL support
# FOSSIL_ENABLE_SSL = 1

# Uncomment to enable Tcl support
# FOSSIL_ENABLE_TCL = 1

!ifdef FOSSIL_ENABLE_SSL
SSLINCDIR = $(B)\compat\openssl-1.0.1g\include
SSLLIBDIR = $(B)\compat\openssl-1.0.1g\out32
SSLLIB    = ssleay32.lib libeay32.lib user32.lib gdi32.lib
!endif

!ifdef FOSSIL_ENABLE_TCL
TCLDIR    = $(B)\compat\tcl-8.6
TCLSRCDIR = $(TCLDIR)
TCLINCDIR = $(TCLSRCDIR)\generic
308
309
310
311
312
313
314

315
316
317
318
319
320
321
        $(OX)\style$O \
        $(OX)\sync$O \
        $(OX)\tag$O \
        $(OX)\tar$O \
        $(OX)\th$O \
        $(OX)\th_lang$O \
        $(OX)\th_main$O \

        $(OX)\timeline$O \
        $(OX)\tkt$O \
        $(OX)\tktsetup$O \
        $(OX)\undo$O \
        $(OX)\unicode$O \
        $(OX)\update$O \
        $(OX)\url$O \







>







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
        $(OX)\style$O \
        $(OX)\sync$O \
        $(OX)\tag$O \
        $(OX)\tar$O \
        $(OX)\th$O \
        $(OX)\th_lang$O \
        $(OX)\th_main$O \
        $(OX)\th_tcl$O \
        $(OX)\timeline$O \
        $(OX)\tkt$O \
        $(OX)\tktsetup$O \
        $(OX)\undo$O \
        $(OX)\unicode$O \
        $(OX)\update$O \
        $(OX)\url$O \
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
        $(OX)\winhttp$O \
        $(OX)\wysiwyg$O \
        $(OX)\xfer$O \
        $(OX)\xfersetup$O \
        $(OX)\zip$O \
        $(OX)\fossil.res

!ifdef FOSSIL_ENABLE_TCL
OBJ   = $(OBJ) $(OX)\th_tcl$O
!endif

APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)

all: $(OX) $(APPNAME)

zlib:







<
<
<







331
332
333
334
335
336
337



338
339
340
341
342
343
344
        $(OX)\winhttp$O \
        $(OX)\wysiwyg$O \
        $(OX)\xfer$O \
        $(OX)\xfersetup$O \
        $(OX)\zip$O \
        $(OX)\fossil.res





APPNAME = $(OX)\fossil$(E)
PDBNAME = $(OX)\fossil$(P)

all: $(OX) $(APPNAME)

zlib:
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
	echo $(OX)\style.obj >> $@
	echo $(OX)\sync.obj >> $@
	echo $(OX)\tag.obj >> $@
	echo $(OX)\tar.obj >> $@
	echo $(OX)\th.obj >> $@
	echo $(OX)\th_lang.obj >> $@
	echo $(OX)\th_main.obj >> $@

	echo $(OX)\timeline.obj >> $@
	echo $(OX)\tkt.obj >> $@
	echo $(OX)\tktsetup.obj >> $@
	echo $(OX)\undo.obj >> $@
	echo $(OX)\unicode.obj >> $@
	echo $(OX)\update.obj >> $@
	echo $(OX)\url.obj >> $@
	echo $(OX)\user.obj >> $@
	echo $(OX)\utf8.obj >> $@
	echo $(OX)\util.obj >> $@
	echo $(OX)\verify.obj >> $@
	echo $(OX)\vfile.obj >> $@
	echo $(OX)\wiki.obj >> $@
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winfile.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\wysiwyg.obj >> $@
	echo $(OX)\xfer.obj >> $@
	echo $(OX)\xfersetup.obj >> $@
	echo $(OX)\zip.obj >> $@
!ifdef FOSSIL_ENABLE_TCL
	echo $(OX)\th_tcl.obj >> $@
!endif
	echo $(LIBS) >> $@

$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**







>




















<
<
<







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
	echo $(OX)\style.obj >> $@
	echo $(OX)\sync.obj >> $@
	echo $(OX)\tag.obj >> $@
	echo $(OX)\tar.obj >> $@
	echo $(OX)\th.obj >> $@
	echo $(OX)\th_lang.obj >> $@
	echo $(OX)\th_main.obj >> $@
	echo $(OX)\th_tcl.obj >> $@
	echo $(OX)\timeline.obj >> $@
	echo $(OX)\tkt.obj >> $@
	echo $(OX)\tktsetup.obj >> $@
	echo $(OX)\undo.obj >> $@
	echo $(OX)\unicode.obj >> $@
	echo $(OX)\update.obj >> $@
	echo $(OX)\url.obj >> $@
	echo $(OX)\user.obj >> $@
	echo $(OX)\utf8.obj >> $@
	echo $(OX)\util.obj >> $@
	echo $(OX)\verify.obj >> $@
	echo $(OX)\vfile.obj >> $@
	echo $(OX)\wiki.obj >> $@
	echo $(OX)\wikiformat.obj >> $@
	echo $(OX)\winfile.obj >> $@
	echo $(OX)\winhttp.obj >> $@
	echo $(OX)\wysiwyg.obj >> $@
	echo $(OX)\xfer.obj >> $@
	echo $(OX)\xfersetup.obj >> $@
	echo $(OX)\zip.obj >> $@



	echo $(LIBS) >> $@

$(OX):
	@-mkdir $@

translate$E: $(SRCDIR)\translate.c
	$(BCC) $**
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

$(OX)\th$O : $(SRCDIR)\th.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**

!ifdef FOSSIL_ENABLE_TCL
$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**
!endif

VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 







<


<







490
491
492
493
494
495
496

497
498

499
500
501
502
503
504
505

$(OX)\th$O : $(SRCDIR)\th.c
	$(TCC) /Fo$@ -c $**

$(OX)\th_lang$O : $(SRCDIR)\th_lang.c
	$(TCC) /Fo$@ -c $**


$(OX)\th_tcl$O : $(SRCDIR)\th_tcl.c
	$(TCC) /Fo$@ -c $**


VERSION.h : mkversion$E $B\manifest.uuid $B\manifest $B\VERSION
	$** > $@
$(OX)\cson_amalgamation$O : $(SRCDIR)\cson_amalgamation.c
	$(TCC) /Fo$@ /c $**

page_index.h: mkindex$E $(SRC) 
Changes to www/changes.wiki.
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
<title>Change Log</title>

<h2>Changes For Version 1.29 (as yet unreleased)</h2>
  *  Add the ability to display content, diffs and annotations for UTF16
     text files in the web interface.

  *  Add the "SaveAs..." button to the graphical diff display that results
     from using the --tk option with the [/help/diff | fossil diff] command.
  *  Honor timezones in imports from git.
  *  The [/reports] page now requires Read ("o") permissions. The "byweek"
     report now properly propagates the selected year through the event type
     filter links.
  *  The [/help/info | info command] now shows leaf status of the checkout.
  *  Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
  *  Add option --empty to the "[/help?cmd=open | fossil open]" command.
  *  Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter.
  *  Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to
     [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame],
     [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff].
  *  Add --strip-trailing-cr option to [/help?cmd=diff|fossil (g)diff] and
     [/help?cmd=stash|fossil stash diff].
  *  Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff
     and /vdiff UI pages.



























<h2>Changes For Version 1.28 (2014-01-27)</h2>
  *  Enhance [/help?cmd=/reports | /reports] to support event type filtering.
  *  When cloning a repository, the user name passed via the URL (if any)
     is now used as the default local admin user's name.
  *  Enhance the SSH transport mechanism so that it runs a single instance of
     the "fossil" executable on the remote side, obviating the need for a shell





>
|
















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







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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<title>Change Log</title>

<h2>Changes For Version 1.29 (as yet unreleased)</h2>
  *  Add the ability to display content, diffs and annotations for UTF16
     text files in the web interface.
  *  Add the "SaveAs..." and "Invert" buttons
     to the graphical diff display that results
     from using the --tk option with the [/help/diff | fossil diff] command.
  *  Honor timezones in imports from git.
  *  The [/reports] page now requires Read ("o") permissions. The "byweek"
     report now properly propagates the selected year through the event type
     filter links.
  *  The [/help/info | info command] now shows leaf status of the checkout.
  *  Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
  *  Add option --empty to the "[/help?cmd=open | fossil open]" command.
  *  Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter.
  *  Add -w|--ignore-all-space and -Z|--ignore-trailing-space options to
     [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame],
     [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff].
  *  Add --strip-trailing-cr option to [/help?cmd=diff|fossil (g)diff] and
     [/help?cmd=stash|fossil stash diff].
  *  Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff
     and /vdiff UI pages.
  *  Enhance [/reports?view=byweekday|/reports] with a "byweekday" view.
  *  Enhance the [/help?cmd=cat|fossil cat] command so that it works outside
     of a checkout when using the -R command-line option.
  *  Use full-length SHA1 hashes, not abbreviations, in most hyperlinks.
  *  Correctly render the &lt;title&gt; markup on wiki pages in the
     [/help?cmd=/artifact|/artifact] webpage.
  *  Enhance the [/help?cmd=whatis|fossil whatis] command to report on attachments
     and cluster artifacts.  Added the [/help?cmd=test-whatis-all] command for
     testing purposes.
  *  Add support for HTTP Basic Authentication on [/help?cmd=clone|clone] and
     [/help?cmd=sync|sync].
  *  Fix the [/help?cmd=stash|stash] so that it remembers added files and re-adds
     them when the stash is applied.
  *  Fix the server so that it avoids writing to the database (and thus avoids
     database locking issues) on a 
     [/help?cmd=pull|pull] or [/help?cmd=clone|clone].
  *  Add support for [./server.wiki#loadmgmt|server load management].
  *  Add the [/help?cmd=praise|fossil praise] command as an alias for 
     [/help?cmd=blame|fossil blame] for subversion compatibility.
  *  Enhance the [/help?cmd=test-diff|fossil test-diff] command with -y or --tk
     options so that it shows both filenames above their respective columns in
     the side-by-side diff output.
  *  Issue a warning if a [/help?cmd=add|fossil add] command tries to add a file
     that matches the ignore-glob.
  *  Add option -W|--width to "[/help?cmd=stash|fossil stash ls]"
     and "[/help?cmd=leaves|fossil leaves]" commands.

<h2>Changes For Version 1.28 (2014-01-27)</h2>
  *  Enhance [/help?cmd=/reports | /reports] to support event type filtering.
  *  When cloning a repository, the user name passed via the URL (if any)
     is now used as the default local admin user's name.
  *  Enhance the SSH transport mechanism so that it runs a single instance of
     the "fossil" executable on the remote side, obviating the need for a shell