Fossil SCM

Merge trunk

andygoth 2017-10-14 19:28 andygoth-enhanced-symlink merge
Commit 057645a9381434c707228d83396a4b1ebc9867214e37c69d2070c27f33e751dd
+21
--- Makefile.in
+++ Makefile.in
@@ -49,5 +49,26 @@
4949
5050
include $(SRCDIR)/main.mk
5151
5252
distclean: clean
5353
rm -f autoconfig.h config.log Makefile
54
+
55
+reconfig:
56
+ @AUTOREMAKE@
57
+
58
+# Automatically reconfigure whenever an autosetup file or one of the
59
+# make source files change.
60
+#
61
+# The "touch" is necessary to avoid a make loop due to a new upstream
62
+# feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
63
+# if doing so will write different contents; otherwise, it leaves them
64
+# alone so the mtime doesn't change. This means that if you change one
65
+# our depdendencies besides Makefile.in, we'll reconfigure but Makefile
66
+# won't change, so this rule will remain out of date, so we'll reconfig
67
+# but Makefile won't change, so we'll reconfig but... endlessly.
68
+#
69
+# This is also why we repeat the reconfig target's command here instead
70
+# of delegating to it with "$(MAKE) reconfig": having children running
71
+# around interfering makes this failure mode even worse.
72
+Makefile: @srcdir@/Makefile.in $(SRCDIR)/main.mk @AUTODEPS@
73
+ @AUTOREMAKE@
74
+ touch @builddir@/Makefile
5475
--- Makefile.in
+++ Makefile.in
@@ -49,5 +49,26 @@
49
50 include $(SRCDIR)/main.mk
51
52 distclean: clean
53 rm -f autoconfig.h config.log Makefile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
--- Makefile.in
+++ Makefile.in
@@ -49,5 +49,26 @@
49
50 include $(SRCDIR)/main.mk
51
52 distclean: clean
53 rm -f autoconfig.h config.log Makefile
54
55 reconfig:
56 @AUTOREMAKE@
57
58 # Automatically reconfigure whenever an autosetup file or one of the
59 # make source files change.
60 #
61 # The "touch" is necessary to avoid a make loop due to a new upstream
62 # feature in autosetup (GH 0a71e3c3b7) which rewrites *.in outputs only
63 # if doing so will write different contents; otherwise, it leaves them
64 # alone so the mtime doesn't change. This means that if you change one
65 # our depdendencies besides Makefile.in, we'll reconfigure but Makefile
66 # won't change, so this rule will remain out of date, so we'll reconfig
67 # but Makefile won't change, so we'll reconfig but... endlessly.
68 #
69 # This is also why we repeat the reconfig target's command here instead
70 # of delegating to it with "$(MAKE) reconfig": having children running
71 # around interfering makes this failure mode even worse.
72 Makefile: @srcdir@/Makefile.in $(SRCDIR)/main.mk @AUTODEPS@
73 @AUTOREMAKE@
74 touch @builddir@/Makefile
75
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -205,13 +205,13 @@
205205
}
206206
continue
207207
}
208208
lappend result $line
209209
}
210
- writefile $out [string map $mapping [join $result \n]]\n
211
-
212
- msg-result "Created [relative-path $out] from [relative-path $template]"
210
+ write-if-changed $out [string map $mapping [join $result \n]]\n {
211
+ msg-result "Created [relative-path $out] from [relative-path $template]"
212
+ }
213213
}
214214
215215
# build/host tuples and cross-compilation prefix
216216
set build [opt-val build]
217217
define build_alias $build
218218
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -205,13 +205,13 @@
205 }
206 continue
207 }
208 lappend result $line
209 }
210 writefile $out [string map $mapping [join $result \n]]\n
211
212 msg-result "Created [relative-path $out] from [relative-path $template]"
213 }
214
215 # build/host tuples and cross-compilation prefix
216 set build [opt-val build]
217 define build_alias $build
218
--- autosetup/system.tcl
+++ autosetup/system.tcl
@@ -205,13 +205,13 @@
205 }
206 continue
207 }
208 lappend result $line
209 }
210 write-if-changed $out [string map $mapping [join $result \n]]\n {
211 msg-result "Created [relative-path $out] from [relative-path $template]"
212 }
213 }
214
215 # build/host tuples and cross-compilation prefix
216 set build [opt-val build]
217 define build_alias $build
218
+3 -4
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
29282928
** When executing certain external commands (e.g. diff and
29292929
** gdiff), use relative paths.
29302930
*/
29312931
#endif
29322932
/*
2933
-** SETTING; gdiff-command width=40 default=gdiff
2933
+** SETTING: gdiff-command width=40 default=gdiff
29342934
** The value is an external command to run when performing a graphical
29352935
** diff. If undefined, text diff will be used.
29362936
*/
29372937
/*
29382938
** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
30183018
** and "delete" commands will also remove the associated
30193019
** files from within the checkout.
30203020
*/
30213021
#endif
30223022
/*
3023
-** SETTING; pgp-command width=40
3024
-** DEFAULT: gpg --clearsign -o
3025
-**
3023
+** SETTING: pgp-command width=40
30263024
** Command used to clear-sign manifests at check-in.
3025
+** Default value is "gpg --clearsign -o"
30273026
*/
30283027
/*
30293028
** SETTING: proxy width=32 default=off
30303029
** URL of the HTTP proxy. If undefined or "off" then
30313030
** the "http_proxy" environment variable is consulted.
30323031
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
2928 ** When executing certain external commands (e.g. diff and
2929 ** gdiff), use relative paths.
2930 */
2931 #endif
2932 /*
2933 ** SETTING; gdiff-command width=40 default=gdiff
2934 ** The value is an external command to run when performing a graphical
2935 ** diff. If undefined, text diff will be used.
2936 */
2937 /*
2938 ** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
3018 ** and "delete" commands will also remove the associated
3019 ** files from within the checkout.
3020 */
3021 #endif
3022 /*
3023 ** SETTING; pgp-command width=40
3024 ** DEFAULT: gpg --clearsign -o
3025 **
3026 ** Command used to clear-sign manifests at check-in.
 
3027 */
3028 /*
3029 ** SETTING: proxy width=32 default=off
3030 ** URL of the HTTP proxy. If undefined or "off" then
3031 ** the "http_proxy" environment variable is consulted.
3032
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
2928 ** When executing certain external commands (e.g. diff and
2929 ** gdiff), use relative paths.
2930 */
2931 #endif
2932 /*
2933 ** SETTING: gdiff-command width=40 default=gdiff
2934 ** The value is an external command to run when performing a graphical
2935 ** diff. If undefined, text diff will be used.
2936 */
2937 /*
2938 ** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
3018 ** and "delete" commands will also remove the associated
3019 ** files from within the checkout.
3020 */
3021 #endif
3022 /*
3023 ** SETTING: pgp-command width=40
 
 
3024 ** Command used to clear-sign manifests at check-in.
3025 ** Default value is "gpg --clearsign -o"
3026 */
3027 /*
3028 ** SETTING: proxy width=32 default=off
3029 ** URL of the HTTP proxy. If undefined or "off" then
3030 ** the "http_proxy" environment variable is consulted.
3031
+3 -4
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
29282928
** When executing certain external commands (e.g. diff and
29292929
** gdiff), use relative paths.
29302930
*/
29312931
#endif
29322932
/*
2933
-** SETTING; gdiff-command width=40 default=gdiff
2933
+** SETTING: gdiff-command width=40 default=gdiff
29342934
** The value is an external command to run when performing a graphical
29352935
** diff. If undefined, text diff will be used.
29362936
*/
29372937
/*
29382938
** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
30183018
** and "delete" commands will also remove the associated
30193019
** files from within the checkout.
30203020
*/
30213021
#endif
30223022
/*
3023
-** SETTING; pgp-command width=40
3024
-** DEFAULT: gpg --clearsign -o
3025
-**
3023
+** SETTING: pgp-command width=40
30263024
** Command used to clear-sign manifests at check-in.
3025
+** Default value is "gpg --clearsign -o"
30273026
*/
30283027
/*
30293028
** SETTING: proxy width=32 default=off
30303029
** URL of the HTTP proxy. If undefined or "off" then
30313030
** the "http_proxy" environment variable is consulted.
30323031
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
2928 ** When executing certain external commands (e.g. diff and
2929 ** gdiff), use relative paths.
2930 */
2931 #endif
2932 /*
2933 ** SETTING; gdiff-command width=40 default=gdiff
2934 ** The value is an external command to run when performing a graphical
2935 ** diff. If undefined, text diff will be used.
2936 */
2937 /*
2938 ** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
3018 ** and "delete" commands will also remove the associated
3019 ** files from within the checkout.
3020 */
3021 #endif
3022 /*
3023 ** SETTING; pgp-command width=40
3024 ** DEFAULT: gpg --clearsign -o
3025 **
3026 ** Command used to clear-sign manifests at check-in.
 
3027 */
3028 /*
3029 ** SETTING: proxy width=32 default=off
3030 ** URL of the HTTP proxy. If undefined or "off" then
3031 ** the "http_proxy" environment variable is consulted.
3032
--- src/db.c
+++ src/db.c
@@ -2928,11 +2928,11 @@
2928 ** When executing certain external commands (e.g. diff and
2929 ** gdiff), use relative paths.
2930 */
2931 #endif
2932 /*
2933 ** SETTING: gdiff-command width=40 default=gdiff
2934 ** The value is an external command to run when performing a graphical
2935 ** diff. If undefined, text diff will be used.
2936 */
2937 /*
2938 ** SETTING: gmerge-command width=40
@@ -3018,14 +3018,13 @@
3018 ** and "delete" commands will also remove the associated
3019 ** files from within the checkout.
3020 */
3021 #endif
3022 /*
3023 ** SETTING: pgp-command width=40
 
 
3024 ** Command used to clear-sign manifests at check-in.
3025 ** Default value is "gpg --clearsign -o"
3026 */
3027 /*
3028 ** SETTING: proxy width=32 default=off
3029 ** URL of the HTTP proxy. If undefined or "off" then
3030 ** the "http_proxy" environment variable is consulted.
3031
+2 -2
--- src/delta.c
+++ src/delta.c
@@ -571,11 +571,11 @@
571571
int lenDelta, /* Length of the delta */
572572
char *zOut /* Write the output into this preallocated buffer */
573573
){
574574
unsigned int limit;
575575
unsigned int total = 0;
576
-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
576
+#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
577577
char *zOrigOut = zOut;
578578
#endif
579579
580580
limit = getInt(&zDelta, &lenDelta);
581581
if( *zDelta!='\n' ){
@@ -628,11 +628,11 @@
628628
break;
629629
}
630630
case ';': {
631631
zDelta++; lenDelta--;
632632
zOut[0] = 0;
633
-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
633
+#ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
634634
if( cnt!=checksum(zOrigOut, total) ){
635635
/* ERROR: bad checksum */
636636
return -1;
637637
}
638638
#endif
639639
--- src/delta.c
+++ src/delta.c
@@ -571,11 +571,11 @@
571 int lenDelta, /* Length of the delta */
572 char *zOut /* Write the output into this preallocated buffer */
573 ){
574 unsigned int limit;
575 unsigned int total = 0;
576 #ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
577 char *zOrigOut = zOut;
578 #endif
579
580 limit = getInt(&zDelta, &lenDelta);
581 if( *zDelta!='\n' ){
@@ -628,11 +628,11 @@
628 break;
629 }
630 case ';': {
631 zDelta++; lenDelta--;
632 zOut[0] = 0;
633 #ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
634 if( cnt!=checksum(zOrigOut, total) ){
635 /* ERROR: bad checksum */
636 return -1;
637 }
638 #endif
639
--- src/delta.c
+++ src/delta.c
@@ -571,11 +571,11 @@
571 int lenDelta, /* Length of the delta */
572 char *zOut /* Write the output into this preallocated buffer */
573 ){
574 unsigned int limit;
575 unsigned int total = 0;
576 #ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
577 char *zOrigOut = zOut;
578 #endif
579
580 limit = getInt(&zDelta, &lenDelta);
581 if( *zDelta!='\n' ){
@@ -628,11 +628,11 @@
628 break;
629 }
630 case ';': {
631 zDelta++; lenDelta--;
632 zOut[0] = 0;
633 #ifdef FOSSIL_ENABLE_DELTA_CKSUM_TEST
634 if( cnt!=checksum(zOrigOut, total) ){
635 /* ERROR: bad checksum */
636 return -1;
637 }
638 #endif
639
+1 -1
--- src/diff.c
+++ src/diff.c
@@ -2259,11 +2259,11 @@
22592259
file_tree_name(zFilename, &treename, 0, 1);
22602260
zFilename = blob_str(&treename);
22612261
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
22622262
22632263
db_prepare(&q,
2264
- "SELECT"
2264
+ "SELECT DISTINCT"
22652265
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
22662266
" (SELECT uuid FROM blob WHERE rid=mlink.mid),"
22672267
" date(event.mtime),"
22682268
" coalesce(event.euser,event.user),"
22692269
" mlink.fid"
22702270
--- src/diff.c
+++ src/diff.c
@@ -2259,11 +2259,11 @@
2259 file_tree_name(zFilename, &treename, 0, 1);
2260 zFilename = blob_str(&treename);
2261 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2262
2263 db_prepare(&q,
2264 "SELECT"
2265 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2266 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2267 " date(event.mtime),"
2268 " coalesce(event.euser,event.user),"
2269 " mlink.fid"
2270
--- src/diff.c
+++ src/diff.c
@@ -2259,11 +2259,11 @@
2259 file_tree_name(zFilename, &treename, 0, 1);
2260 zFilename = blob_str(&treename);
2261 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2262
2263 db_prepare(&q,
2264 "SELECT DISTINCT"
2265 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
2266 " (SELECT uuid FROM blob WHERE rid=mlink.mid),"
2267 " date(event.mtime),"
2268 " coalesce(event.euser,event.user),"
2269 " mlink.fid"
2270
+15 -9
--- src/finfo.c
+++ src/finfo.c
@@ -596,12 +596,18 @@
596596
** WEBPAGE: mlink
597597
** URL: /mlink?name=FILENAME
598598
** URL: /mlink?ci=NAME
599599
**
600600
** Show all MLINK table entries for a particular file, or for
601
-** a particular check-in. This screen is intended for use by developers
602
-** in debugging Fossil.
601
+** a particular check-in.
602
+**
603
+** This screen is intended for use by Fossil developers to help
604
+** in debugging Fossil itself. Ordinary Fossil users are not
605
+** expected to know what the MLINK table is or why it is important.
606
+**
607
+** To avoid confusing ordinary users, this page is only available
608
+** to adminstrators.
603609
*/
604610
void mlink_page(void){
605611
const char *zFName = P("name");
606612
const char *zCI = P("ci");
607613
Stmt q;
@@ -638,16 +644,16 @@
638644
@ <div class='brlist'>
639645
@ <table id='mlinktable'>
640646
@ <thead><tr>
641647
@ <th>Date</th>
642648
@ <th>Check-in</th>
643
- @ <th>Parent Check-in</th>
649
+ @ <th>Parent<br>Check-in</th>
644650
@ <th>Merge?</th>
645651
@ <th>New</th>
646652
@ <th>Old</th>
647
- @ <th>Exe Bit?</th>
648
- @ <th>Prior Name</th>
653
+ @ <th>Exe<br>Bit?</th>
654
+ @ <th>Prior<br>Name</th>
649655
@ </tr></thead>
650656
@ <tbody>
651657
while( db_step(&q)==SQLITE_ROW ){
652658
const char *zDate = db_column_text(&q,0);
653659
const char *zCkin = db_column_text(&q,1);
@@ -659,11 +665,11 @@
659665
const char *zPrior = db_column_text(&q,8);
660666
@ <tr>
661667
@ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
662668
@ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
663669
if( zParent ){
664
- @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
670
+ @ <td><a href='%R/info/%!S(zParent)'>%S(zParent)</a></td>
665671
}else{
666672
@ <td><i>(New)</i></td>
667673
}
668674
@ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
669675
if( zFid ){
@@ -711,16 +717,16 @@
711717
@ <hr />
712718
@ <div class='brlist'>
713719
@ <table id='mlinktable'>
714720
@ <thead><tr>
715721
@ <th>File</th>
716
- @ <th>From</th>
722
+ @ <th>Parent<br>Check-in</th>
717723
@ <th>Merge?</th>
718724
@ <th>New</th>
719725
@ <th>Old</th>
720
- @ <th>Exe Bit?</th>
721
- @ <th>Prior Name</th>
726
+ @ <th>Exe<br>Bit?</th>
727
+ @ <th>Prior<br>Name</th>
722728
@ </tr></thead>
723729
@ <tbody>
724730
while( db_step(&q)==SQLITE_ROW ){
725731
const char *zName = db_column_text(&q,0);
726732
const char *zFid = db_column_text(&q,1);
727733
--- src/finfo.c
+++ src/finfo.c
@@ -596,12 +596,18 @@
596 ** WEBPAGE: mlink
597 ** URL: /mlink?name=FILENAME
598 ** URL: /mlink?ci=NAME
599 **
600 ** Show all MLINK table entries for a particular file, or for
601 ** a particular check-in. This screen is intended for use by developers
602 ** in debugging Fossil.
 
 
 
 
 
 
603 */
604 void mlink_page(void){
605 const char *zFName = P("name");
606 const char *zCI = P("ci");
607 Stmt q;
@@ -638,16 +644,16 @@
638 @ <div class='brlist'>
639 @ <table id='mlinktable'>
640 @ <thead><tr>
641 @ <th>Date</th>
642 @ <th>Check-in</th>
643 @ <th>Parent Check-in</th>
644 @ <th>Merge?</th>
645 @ <th>New</th>
646 @ <th>Old</th>
647 @ <th>Exe Bit?</th>
648 @ <th>Prior Name</th>
649 @ </tr></thead>
650 @ <tbody>
651 while( db_step(&q)==SQLITE_ROW ){
652 const char *zDate = db_column_text(&q,0);
653 const char *zCkin = db_column_text(&q,1);
@@ -659,11 +665,11 @@
659 const char *zPrior = db_column_text(&q,8);
660 @ <tr>
661 @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
662 @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
663 if( zParent ){
664 @ <td><a href='%R/info/%!S(zPid)'>%S(zParent)</a></td>
665 }else{
666 @ <td><i>(New)</i></td>
667 }
668 @ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
669 if( zFid ){
@@ -711,16 +717,16 @@
711 @ <hr />
712 @ <div class='brlist'>
713 @ <table id='mlinktable'>
714 @ <thead><tr>
715 @ <th>File</th>
716 @ <th>From</th>
717 @ <th>Merge?</th>
718 @ <th>New</th>
719 @ <th>Old</th>
720 @ <th>Exe Bit?</th>
721 @ <th>Prior Name</th>
722 @ </tr></thead>
723 @ <tbody>
724 while( db_step(&q)==SQLITE_ROW ){
725 const char *zName = db_column_text(&q,0);
726 const char *zFid = db_column_text(&q,1);
727
--- src/finfo.c
+++ src/finfo.c
@@ -596,12 +596,18 @@
596 ** WEBPAGE: mlink
597 ** URL: /mlink?name=FILENAME
598 ** URL: /mlink?ci=NAME
599 **
600 ** Show all MLINK table entries for a particular file, or for
601 ** a particular check-in.
602 **
603 ** This screen is intended for use by Fossil developers to help
604 ** in debugging Fossil itself. Ordinary Fossil users are not
605 ** expected to know what the MLINK table is or why it is important.
606 **
607 ** To avoid confusing ordinary users, this page is only available
608 ** to adminstrators.
609 */
610 void mlink_page(void){
611 const char *zFName = P("name");
612 const char *zCI = P("ci");
613 Stmt q;
@@ -638,16 +644,16 @@
644 @ <div class='brlist'>
645 @ <table id='mlinktable'>
646 @ <thead><tr>
647 @ <th>Date</th>
648 @ <th>Check-in</th>
649 @ <th>Parent<br>Check-in</th>
650 @ <th>Merge?</th>
651 @ <th>New</th>
652 @ <th>Old</th>
653 @ <th>Exe<br>Bit?</th>
654 @ <th>Prior<br>Name</th>
655 @ </tr></thead>
656 @ <tbody>
657 while( db_step(&q)==SQLITE_ROW ){
658 const char *zDate = db_column_text(&q,0);
659 const char *zCkin = db_column_text(&q,1);
@@ -659,11 +665,11 @@
665 const char *zPrior = db_column_text(&q,8);
666 @ <tr>
667 @ <td><a href='%R/timeline?c=%!S(zCkin)'>%s(zDate)</a></td>
668 @ <td><a href='%R/info/%!S(zCkin)'>%S(zCkin)</a></td>
669 if( zParent ){
670 @ <td><a href='%R/info/%!S(zParent)'>%S(zParent)</a></td>
671 }else{
672 @ <td><i>(New)</i></td>
673 }
674 @ <td align='center'>%s(isMerge?"&#x2713;":"")</td>
675 if( zFid ){
@@ -711,16 +717,16 @@
717 @ <hr />
718 @ <div class='brlist'>
719 @ <table id='mlinktable'>
720 @ <thead><tr>
721 @ <th>File</th>
722 @ <th>Parent<br>Check-in</th>
723 @ <th>Merge?</th>
724 @ <th>New</th>
725 @ <th>Old</th>
726 @ <th>Exe<br>Bit?</th>
727 @ <th>Prior<br>Name</th>
728 @ </tr></thead>
729 @ <tbody>
730 while( db_step(&q)==SQLITE_ROW ){
731 const char *zName = db_column_text(&q,0);
732 const char *zFid = db_column_text(&q,1);
733
+10 -4
--- src/info.c
+++ src/info.c
@@ -764,10 +764,13 @@
764764
@ <td>
765765
@ %z(href("%R/tree?ci=%!S",zUuid))files</a>
766766
@ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
767767
@ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
768768
@ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
769
+ if( g.perm.Admin ){
770
+ @ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
771
+ }
769772
if( g.anon.Write ){
770773
@ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
771774
}
772775
@ </td>
773776
@ </tr>
@@ -1572,21 +1575,24 @@
15721575
** annotation between those version. */
15731576
db_prepare(&q,
15741577
"SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid),"
15751578
" (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid),"
15761579
" (SELECT name FROM filename WHERE filename.fnid=a.fnid)"
1577
- " FROM mlink a, mlink b"
1580
+ " FROM mlink a, event ea, mlink b, event eb"
15781581
" WHERE a.fid=%d"
15791582
" AND b.fid=%d"
15801583
" AND a.fnid=b.fnid"
15811584
" AND a.fid!=a.pid"
1582
- " AND b.fid!=b.pid",
1585
+ " AND b.fid!=b.pid"
1586
+ " AND ea.objid=a.mid"
1587
+ " AND eb.objid=b.mid"
1588
+ " ORDER BY ea.mtime ASC, eb.mtime ASC",
15831589
v1, v2
15841590
);
15851591
if( db_step(&q)==SQLITE_ROW ){
1586
- const char *zOrig = db_column_text(&q, 0);
1587
- const char *zCkin = db_column_text(&q, 1);
1592
+ const char *zCkin = db_column_text(&q, 0);
1593
+ const char *zOrig = db_column_text(&q, 1);
15881594
const char *zFN = db_column_text(&q, 2);
15891595
style_submenu_element("Annotate",
15901596
"%R/annotate?origin=%s&checkin=%s&filename=%T",
15911597
zOrig, zCkin, zFN);
15921598
}
15931599
--- src/info.c
+++ src/info.c
@@ -764,10 +764,13 @@
764 @ <td>
765 @ %z(href("%R/tree?ci=%!S",zUuid))files</a>
766 @ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
767 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
768 @ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
 
 
 
769 if( g.anon.Write ){
770 @ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
771 }
772 @ </td>
773 @ </tr>
@@ -1572,21 +1575,24 @@
1572 ** annotation between those version. */
1573 db_prepare(&q,
1574 "SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid),"
1575 " (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid),"
1576 " (SELECT name FROM filename WHERE filename.fnid=a.fnid)"
1577 " FROM mlink a, mlink b"
1578 " WHERE a.fid=%d"
1579 " AND b.fid=%d"
1580 " AND a.fnid=b.fnid"
1581 " AND a.fid!=a.pid"
1582 " AND b.fid!=b.pid",
 
 
 
1583 v1, v2
1584 );
1585 if( db_step(&q)==SQLITE_ROW ){
1586 const char *zOrig = db_column_text(&q, 0);
1587 const char *zCkin = db_column_text(&q, 1);
1588 const char *zFN = db_column_text(&q, 2);
1589 style_submenu_element("Annotate",
1590 "%R/annotate?origin=%s&checkin=%s&filename=%T",
1591 zOrig, zCkin, zFN);
1592 }
1593
--- src/info.c
+++ src/info.c
@@ -764,10 +764,13 @@
764 @ <td>
765 @ %z(href("%R/tree?ci=%!S",zUuid))files</a>
766 @ | %z(href("%R/fileage?name=%!S",zUuid))file ages</a>
767 @ | %z(href("%R/tree?nofiles&type=tree&ci=%!S",zUuid))folders</a>
768 @ | %z(href("%R/artifact/%!S",zUuid))manifest</a>
769 if( g.perm.Admin ){
770 @ | %z(href("%R/mlink?ci=%!S",zUuid))mlink table</a>
771 }
772 if( g.anon.Write ){
773 @ | %z(href("%R/ci_edit?r=%!S",zUuid))edit</a>
774 }
775 @ </td>
776 @ </tr>
@@ -1572,21 +1575,24 @@
1575 ** annotation between those version. */
1576 db_prepare(&q,
1577 "SELECT (SELECT substr(uuid,1,20) FROM blob WHERE rid=a.mid),"
1578 " (SELECT substr(uuid,1,20) FROM blob WHERE rid=b.mid),"
1579 " (SELECT name FROM filename WHERE filename.fnid=a.fnid)"
1580 " FROM mlink a, event ea, mlink b, event eb"
1581 " WHERE a.fid=%d"
1582 " AND b.fid=%d"
1583 " AND a.fnid=b.fnid"
1584 " AND a.fid!=a.pid"
1585 " AND b.fid!=b.pid"
1586 " AND ea.objid=a.mid"
1587 " AND eb.objid=b.mid"
1588 " ORDER BY ea.mtime ASC, eb.mtime ASC",
1589 v1, v2
1590 );
1591 if( db_step(&q)==SQLITE_ROW ){
1592 const char *zCkin = db_column_text(&q, 0);
1593 const char *zOrig = db_column_text(&q, 1);
1594 const char *zFN = db_column_text(&q, 2);
1595 style_submenu_element("Annotate",
1596 "%R/annotate?origin=%s&checkin=%s&filename=%T",
1597 zOrig, zCkin, zFN);
1598 }
1599
+4 -4
--- src/main.c
+++ src/main.c
@@ -735,11 +735,11 @@
735735
/*
736736
** The TH1 return codes from the hook will be handled as follows:
737737
**
738738
** TH_OK: The xFunc() and the TH1 notification will both be executed.
739739
**
740
- ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
740
+ ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
741741
** skipped. If the xFunc() is being hooked, the error message
742742
** will be emitted.
743743
**
744744
** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
745745
**
@@ -949,12 +949,12 @@
949949
fusefs_lib_version());
950950
#endif
951951
#if defined(FOSSIL_DEBUG)
952952
blob_append(pOut, "FOSSIL_DEBUG\n", -1);
953953
#endif
954
-#if defined(FOSSIL_OMIT_DELTA_CKSUM_TEST)
955
- blob_append(pOut, "FOSSIL_OMIT_DELTA_CKSUM_TEST\n", -1);
954
+#if defined(FOSSIL_ENABLE_DELTA_CKSUM_TEST)
955
+ blob_append(pOut, "FOSSIL_ENABLE_DELTA_CKSUM_TEST\n", -1);
956956
#endif
957957
#if defined(FOSSIL_ENABLE_LEGACY_MV_RM)
958958
blob_append(pOut, "FOSSIL_ENABLE_LEGACY_MV_RM\n", -1);
959959
#endif
960960
#if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
@@ -1664,11 +1664,11 @@
16641664
/*
16651665
** The TH1 return codes from the hook will be handled as follows:
16661666
**
16671667
** TH_OK: The xFunc() and the TH1 notification will both be executed.
16681668
**
1669
- ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
1669
+ ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
16701670
** skipped. If the xFunc() is being hooked, the error message
16711671
** will be emitted.
16721672
**
16731673
** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
16741674
**
16751675
--- src/main.c
+++ src/main.c
@@ -735,11 +735,11 @@
735 /*
736 ** The TH1 return codes from the hook will be handled as follows:
737 **
738 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
739 **
740 ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
741 ** skipped. If the xFunc() is being hooked, the error message
742 ** will be emitted.
743 **
744 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
745 **
@@ -949,12 +949,12 @@
949 fusefs_lib_version());
950 #endif
951 #if defined(FOSSIL_DEBUG)
952 blob_append(pOut, "FOSSIL_DEBUG\n", -1);
953 #endif
954 #if defined(FOSSIL_OMIT_DELTA_CKSUM_TEST)
955 blob_append(pOut, "FOSSIL_OMIT_DELTA_CKSUM_TEST\n", -1);
956 #endif
957 #if defined(FOSSIL_ENABLE_LEGACY_MV_RM)
958 blob_append(pOut, "FOSSIL_ENABLE_LEGACY_MV_RM\n", -1);
959 #endif
960 #if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
@@ -1664,11 +1664,11 @@
1664 /*
1665 ** The TH1 return codes from the hook will be handled as follows:
1666 **
1667 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
1668 **
1669 ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
1670 ** skipped. If the xFunc() is being hooked, the error message
1671 ** will be emitted.
1672 **
1673 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
1674 **
1675
--- src/main.c
+++ src/main.c
@@ -735,11 +735,11 @@
735 /*
736 ** The TH1 return codes from the hook will be handled as follows:
737 **
738 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
739 **
740 ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
741 ** skipped. If the xFunc() is being hooked, the error message
742 ** will be emitted.
743 **
744 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
745 **
@@ -949,12 +949,12 @@
949 fusefs_lib_version());
950 #endif
951 #if defined(FOSSIL_DEBUG)
952 blob_append(pOut, "FOSSIL_DEBUG\n", -1);
953 #endif
954 #if defined(FOSSIL_ENABLE_DELTA_CKSUM_TEST)
955 blob_append(pOut, "FOSSIL_ENABLE_DELTA_CKSUM_TEST\n", -1);
956 #endif
957 #if defined(FOSSIL_ENABLE_LEGACY_MV_RM)
958 blob_append(pOut, "FOSSIL_ENABLE_LEGACY_MV_RM\n", -1);
959 #endif
960 #if defined(FOSSIL_ENABLE_EXEC_REL_PATHS)
@@ -1664,11 +1664,11 @@
1664 /*
1665 ** The TH1 return codes from the hook will be handled as follows:
1666 **
1667 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
1668 **
1669 ** TH_ERROR: The xFunc() will be skipped, the TH1 notification will be
1670 ** skipped. If the xFunc() is being hooked, the error message
1671 ** will be emitted.
1672 **
1673 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
1674 **
1675
+7 -7
--- src/path.c
+++ src/path.c
@@ -203,30 +203,30 @@
203203
void path_shortest_stored_in_ancestor_table(
204204
int origid, /* RID for check-in at start of the path */
205205
int cid /* RID for check-in at the end of the path */
206206
){
207207
PathNode *pPath;
208
- Blob sql;
209208
int gen = 0;
210
- char *zSep = "VALUES";
209
+ Stmt ins;
211210
pPath = path_shortest(cid, origid, 1, 0);
212211
db_multi_exec(
213212
"CREATE TEMP TABLE IF NOT EXISTS ancestor("
214213
" rid INT UNIQUE,"
215214
" generation INTEGER PRIMARY KEY"
216215
");"
217216
"DELETE FROM ancestor;"
218217
);
219
- blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1);
218
+ db_prepare(&ins, "INSERT INTO ancestor(rid, generation) VALUES(:rid,:gen)");
220219
while( pPath ){
221
- blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, pPath->rid,++gen);
222
- zSep = ",";
220
+ db_bind_int(&ins, ":rid", pPath->rid);
221
+ db_bind_int(&ins, ":gen", ++gen);
222
+ db_step(&ins);
223
+ db_reset(&ins);
223224
pPath = pPath->u.pTo;
224225
}
226
+ db_finalize(&ins);
225227
path_reset();
226
- db_multi_exec("%s", blob_sql_text(&sql));
227
- blob_reset(&sql);
228228
}
229229
230230
/*
231231
** COMMAND: test-shortest-path
232232
**
233233
--- src/path.c
+++ src/path.c
@@ -203,30 +203,30 @@
203 void path_shortest_stored_in_ancestor_table(
204 int origid, /* RID for check-in at start of the path */
205 int cid /* RID for check-in at the end of the path */
206 ){
207 PathNode *pPath;
208 Blob sql;
209 int gen = 0;
210 char *zSep = "VALUES";
211 pPath = path_shortest(cid, origid, 1, 0);
212 db_multi_exec(
213 "CREATE TEMP TABLE IF NOT EXISTS ancestor("
214 " rid INT UNIQUE,"
215 " generation INTEGER PRIMARY KEY"
216 ");"
217 "DELETE FROM ancestor;"
218 );
219 blob_init(&sql, "INSERT INTO ancestor(rid, generation)", -1);
220 while( pPath ){
221 blob_append_sql(&sql, "%s(%d,%d)", zSep/*safe-for-%s*/, pPath->rid,++gen);
222 zSep = ",";
 
 
223 pPath = pPath->u.pTo;
224 }
 
225 path_reset();
226 db_multi_exec("%s", blob_sql_text(&sql));
227 blob_reset(&sql);
228 }
229
230 /*
231 ** COMMAND: test-shortest-path
232 **
233
--- src/path.c
+++ src/path.c
@@ -203,30 +203,30 @@
203 void path_shortest_stored_in_ancestor_table(
204 int origid, /* RID for check-in at start of the path */
205 int cid /* RID for check-in at the end of the path */
206 ){
207 PathNode *pPath;
 
208 int gen = 0;
209 Stmt ins;
210 pPath = path_shortest(cid, origid, 1, 0);
211 db_multi_exec(
212 "CREATE TEMP TABLE IF NOT EXISTS ancestor("
213 " rid INT UNIQUE,"
214 " generation INTEGER PRIMARY KEY"
215 ");"
216 "DELETE FROM ancestor;"
217 );
218 db_prepare(&ins, "INSERT INTO ancestor(rid, generation) VALUES(:rid,:gen)");
219 while( pPath ){
220 db_bind_int(&ins, ":rid", pPath->rid);
221 db_bind_int(&ins, ":gen", ++gen);
222 db_step(&ins);
223 db_reset(&ins);
224 pPath = pPath->u.pTo;
225 }
226 db_finalize(&ins);
227 path_reset();
 
 
228 }
229
230 /*
231 ** COMMAND: test-shortest-path
232 **
233
+276 -211
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1147,11 +1147,11 @@
11471147
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
11481148
** [sqlite_version()] and [sqlite_source_id()].
11491149
*/
11501150
#define SQLITE_VERSION "3.21.0"
11511151
#define SQLITE_VERSION_NUMBER 3021000
1152
-#define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43"
1152
+#define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bf807a"
11531153
11541154
/*
11551155
** CAPI3REF: Run-Time Library Version Numbers
11561156
** KEYWORDS: sqlite3_version sqlite3_sourceid
11571157
**
@@ -15279,20 +15279,19 @@
1527915279
*/
1528015280
#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
1528115281
#define SQLITE_ColumnCache 0x0002 /* Column cache */
1528215282
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
1528315283
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
15284
-/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
15285
-#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
15286
-#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
15287
-#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
15288
-#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
15289
-#define SQLITE_Transitive 0x0200 /* Transitive constraints */
15290
-#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
15284
+#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
15285
+#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
15286
+#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
15287
+#define SQLITE_Transitive 0x0080 /* Transitive constraints */
15288
+#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
15289
+#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
15290
+#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
1529115291
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
15292
-#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */
15293
-#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
15292
+ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
1529415293
#define SQLITE_AllOpts 0xffff /* All optimizations */
1529515294
1529615295
/*
1529715296
** Macros for testing whether or not optimizations are enabled or disabled.
1529815297
*/
@@ -17777,10 +17776,12 @@
1777717776
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
1777817777
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
1777917778
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
1778017779
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
1778117780
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
17781
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
17782
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
1778217783
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
1778317784
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
1778417785
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
1778517786
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
1778617787
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
@@ -43282,18 +43283,23 @@
4328243283
dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
4328343284
extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
4328443285
extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
4328543286
extendedParameters.lpSecurityAttributes = NULL;
4328643287
extendedParameters.hTemplateFile = NULL;
43287
- while( (h = osCreateFile2((LPCWSTR)zConverted,
43288
- dwDesiredAccess,
43289
- dwShareMode,
43290
- dwCreationDisposition,
43291
- &extendedParameters))==INVALID_HANDLE_VALUE &&
43292
- winRetryIoerr(&cnt, &lastErrno) ){
43293
- /* Noop */
43294
- }
43288
+ do{
43289
+ h = osCreateFile2((LPCWSTR)zConverted,
43290
+ dwDesiredAccess,
43291
+ dwShareMode,
43292
+ dwCreationDisposition,
43293
+ &extendedParameters);
43294
+ if( h!=INVALID_HANDLE_VALUE ) break;
43295
+ if( isReadWrite ){
43296
+ int isRO = 0;
43297
+ int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
43298
+ if( rc2==SQLITE_OK && isRO ) break;
43299
+ }
43300
+ }while( winRetryIoerr(&cnt, &lastErrno) );
4329543301
#else
4329643302
do{
4329743303
h = osCreateFileW((LPCWSTR)zConverted,
4329843304
dwDesiredAccess,
4329943305
dwShareMode, NULL,
@@ -43309,19 +43315,24 @@
4330943315
}while( winRetryIoerr(&cnt, &lastErrno) );
4331043316
#endif
4331143317
}
4331243318
#ifdef SQLITE_WIN32_HAS_ANSI
4331343319
else{
43314
- while( (h = osCreateFileA((LPCSTR)zConverted,
43315
- dwDesiredAccess,
43316
- dwShareMode, NULL,
43317
- dwCreationDisposition,
43318
- dwFlagsAndAttributes,
43319
- NULL))==INVALID_HANDLE_VALUE &&
43320
- winRetryIoerr(&cnt, &lastErrno) ){
43321
- /* Noop */
43322
- }
43320
+ do{
43321
+ h = osCreateFileA((LPCSTR)zConverted,
43322
+ dwDesiredAccess,
43323
+ dwShareMode, NULL,
43324
+ dwCreationDisposition,
43325
+ dwFlagsAndAttributes,
43326
+ NULL);
43327
+ if( h!=INVALID_HANDLE_VALUE ) break;
43328
+ if( isReadWrite ){
43329
+ int isRO = 0;
43330
+ int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
43331
+ if( rc2==SQLITE_OK && isRO ) break;
43332
+ }
43333
+ }while( winRetryIoerr(&cnt, &lastErrno) );
4332343334
}
4332443335
#endif
4332543336
winLogIoerr(cnt, __LINE__);
4332643337
4332743338
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
@@ -61031,10 +61042,13 @@
6103161042
u8 *pEnd = &data[cellOffset + nCell*2];
6103261043
u8 *pAddr;
6103361044
int sz2 = 0;
6103461045
int sz = get2byte(&data[iFree+2]);
6103561046
int top = get2byte(&data[hdr+5]);
61047
+ if( top>=iFree ){
61048
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
61049
+ }
6103661050
if( iFree2 ){
6103761051
assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
6103861052
sz2 = get2byte(&data[iFree2+2]);
6103961053
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
6104061054
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
@@ -71383,13 +71397,14 @@
7138371397
u32 amt, /* Number of bytes to return. */
7138471398
Mem *pMem /* OUT: Return data in this Mem structure. */
7138571399
){
7138671400
int rc;
7138771401
pMem->flags = MEM_Null;
71388
- if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt)) ){
71402
+ if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
7138971403
rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
7139071404
if( rc==SQLITE_OK ){
71405
+ pMem->z[amt] = 0; /* Overrun area used when reading malformed records */
7139171406
pMem->flags = MEM_Blob;
7139271407
pMem->n = (int)amt;
7139371408
}else{
7139471409
sqlite3VdbeMemRelease(pMem);
7139571410
}
@@ -91882,10 +91897,15 @@
9188291897
9188391898
/*
9188491899
** Return the collation sequence for the expression pExpr. If
9188591900
** there is no defined collating sequence, return NULL.
9188691901
**
91902
+** See also: sqlite3ExprNNCollSeq()
91903
+**
91904
+** The sqlite3ExprNNCollSeq() works the same exact that it returns the
91905
+** default collation if pExpr has no defined collation.
91906
+**
9188791907
** The collating sequence might be determined by a COLLATE operator
9188891908
** or by the presence of a column with a defined collating sequence.
9188991909
** COLLATE operators take first precedence. Left operands take
9189091910
** precedence over right operands.
9189191911
*/
@@ -91945,10 +91965,36 @@
9194591965
if( sqlite3CheckCollSeq(pParse, pColl) ){
9194691966
pColl = 0;
9194791967
}
9194891968
return pColl;
9194991969
}
91970
+
91971
+/*
91972
+** Return the collation sequence for the expression pExpr. If
91973
+** there is no defined collating sequence, return a pointer to the
91974
+** defautl collation sequence.
91975
+**
91976
+** See also: sqlite3ExprCollSeq()
91977
+**
91978
+** The sqlite3ExprCollSeq() routine works the same except that it
91979
+** returns NULL if there is no defined collation.
91980
+*/
91981
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
91982
+ CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
91983
+ if( p==0 ) p = pParse->db->pDfltColl;
91984
+ assert( p!=0 );
91985
+ return p;
91986
+}
91987
+
91988
+/*
91989
+** Return TRUE if the two expressions have equivalent collating sequences.
91990
+*/
91991
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
91992
+ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
91993
+ CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
91994
+ return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
91995
+}
9195091996
9195191997
/*
9195291998
** pExpr is an operand of a comparison operator. aff2 is the
9195391999
** type affinity of the other operand. This routine returns the
9195492000
** type affinity that should be used for the comparison operator.
@@ -93439,16 +93485,15 @@
9343993485
** ExprList.
9344093486
*/
9344193487
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
9344293488
int i;
9344393489
u32 m = 0;
93444
- if( pList ){
93445
- for(i=0; i<pList->nExpr; i++){
93446
- Expr *pExpr = pList->a[i].pExpr;
93447
- assert( pExpr!=0 );
93448
- m |= pExpr->flags;
93449
- }
93490
+ assert( pList!=0 );
93491
+ for(i=0; i<pList->nExpr; i++){
93492
+ Expr *pExpr = pList->a[i].pExpr;
93493
+ assert( pExpr!=0 );
93494
+ m |= pExpr->flags;
9345093495
}
9345193496
return m;
9345293497
}
9345393498
9345493499
/*
@@ -93601,12 +93646,12 @@
9360193646
/* Check if pExpr is identical to any GROUP BY term. If so, consider
9360293647
** it constant. */
9360393648
for(i=0; i<pGroupBy->nExpr; i++){
9360493649
Expr *p = pGroupBy->a[i].pExpr;
9360593650
if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
93606
- CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
93607
- if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
93651
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
93652
+ if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
9360893653
return WRC_Prune;
9360993654
}
9361093655
}
9361193656
}
9361293657
@@ -117746,11 +117791,12 @@
117746117791
if( pNew==0 ){
117747117792
assert( pParse->db->mallocFailed );
117748117793
pNew = &standin;
117749117794
}
117750117795
if( pEList==0 ){
117751
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0));
117796
+ pEList = sqlite3ExprListAppend(pParse, 0,
117797
+ sqlite3Expr(pParse->db,TK_ASTERISK,0));
117752117798
}
117753117799
pNew->pEList = pEList;
117754117800
pNew->op = TK_SELECT;
117755117801
pNew->selFlags = selFlags;
117756117802
pNew->iLimit = 0;
@@ -117770,11 +117816,12 @@
117770117816
pNew->pPrior = 0;
117771117817
pNew->pNext = 0;
117772117818
pNew->pLimit = pLimit;
117773117819
pNew->pOffset = pOffset;
117774117820
pNew->pWith = 0;
117775
- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 );
117821
+ assert( pOffset==0 || pLimit!=0 || pParse->nErr>0
117822
+ || pParse->db->mallocFailed!=0 );
117776117823
if( pParse->db->mallocFailed ) {
117777117824
clearSelect(pParse->db, pNew, pNew!=&standin);
117778117825
pNew = 0;
117779117826
}else{
117780117827
assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -118387,11 +118434,12 @@
118387118434
}
118388118435
regOrig = 0;
118389118436
assert( eDest==SRT_Set || eDest==SRT_Mem
118390118437
|| eDest==SRT_Coroutine || eDest==SRT_Output );
118391118438
}
118392
- nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,0,ecelFlags);
118439
+ nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,
118440
+ 0,ecelFlags);
118393118441
}
118394118442
118395118443
/* If the DISTINCT keyword was present on the SELECT statement
118396118444
** and this row has been seen before, then do not make this row
118397118445
** part of the result.
@@ -118737,14 +118785,11 @@
118737118785
nExpr = pList->nExpr;
118738118786
pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
118739118787
if( pInfo ){
118740118788
assert( sqlite3KeyInfoIsWriteable(pInfo) );
118741118789
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
118742
- CollSeq *pColl;
118743
- pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
118744
- if( !pColl ) pColl = db->pDfltColl;
118745
- pInfo->aColl[i-iStart] = pColl;
118790
+ pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
118746118791
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
118747118792
}
118748118793
}
118749118794
return pInfo;
118750118795
}
@@ -119201,13 +119246,13 @@
119201119246
** short=OFF, full=OFF: Column name is the text of the expression has it
119202119247
** originally appears in the SELECT statement. In
119203119248
** other words, the zSpan of the result expression.
119204119249
**
119205119250
** short=ON, full=OFF: (This is the default setting). If the result
119206
-** refers directly to a table column, then the result
119207
-** column name is just the table column name: COLUMN.
119208
-** Otherwise use zSpan.
119251
+** refers directly to a table column, then the
119252
+** result column name is just the table column
119253
+** name: COLUMN. Otherwise use zSpan.
119209119254
**
119210119255
** full=ON, short=ANY: If the result refers directly to a table column,
119211119256
** then the result column name with the table name
119212119257
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
119213119258
*/
@@ -119245,11 +119290,11 @@
119245119290
for(i=0; i<pEList->nExpr; i++){
119246119291
Expr *p = pEList->a[i].pExpr;
119247119292
119248119293
assert( p!=0 );
119249119294
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
119250
- assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering indexes not yet coded */
119295
+ assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
119251119296
if( pEList->a[i].zName ){
119252119297
/* An AS clause always takes first priority */
119253119298
char *zName = pEList->a[i].zName;
119254119299
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
119255119300
}else if( srcName && p->op==TK_COLUMN ){
@@ -120809,11 +120854,13 @@
120809120854
static Expr *substExpr(
120810120855
SubstContext *pSubst, /* Description of the substitution */
120811120856
Expr *pExpr /* Expr in which substitution occurs */
120812120857
){
120813120858
if( pExpr==0 ) return 0;
120814
- if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){
120859
+ if( ExprHasProperty(pExpr, EP_FromJoin)
120860
+ && pExpr->iRightJoinTable==pSubst->iTable
120861
+ ){
120815120862
pExpr->iRightJoinTable = pSubst->iNewTable;
120816120863
}
120817120864
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
120818120865
if( pExpr->iColumn<0 ){
120819120866
pExpr->op = TK_NULL;
@@ -120922,72 +120969,78 @@
120922120969
** The code generated for this simplification gives the same result
120923120970
** but only has to scan the data once. And because indices might
120924120971
** exist on the table t1, a complete scan of the data might be
120925120972
** avoided.
120926120973
**
120927
-** Flattening is only attempted if all of the following are true:
120928
-**
120929
-** (1) The subquery and the outer query do not both use aggregates.
120930
-**
120931
-** (2) The subquery is not an aggregate or (2a) the outer query is not a join
120932
-** and (2b) the outer query does not use subqueries other than the one
120933
-** FROM-clause subquery that is a candidate for flattening. (2b is
120934
-** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
120935
-**
120936
-** (3) The subquery is not the right operand of a LEFT JOIN
120937
-** or (a) the subquery is not itself a join and (b) the FROM clause
120938
-** of the subquery does not contain a virtual table and (c) the
120939
-** outer query is not an aggregate.
120940
-**
120941
-** (4) The subquery is not DISTINCT.
120974
+** Flattening is subject to the following constraints:
120975
+**
120976
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
120977
+** The subquery and the outer query cannot both be aggregates.
120978
+**
120979
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
120980
+** (2) If the subquery is an aggregate then
120981
+** (2a) the outer query must not be a join and
120982
+** (2b) the outer query must not use subqueries
120983
+** other than the one FROM-clause subquery that is a candidate
120984
+** for flattening. (This is due to ticket [2f7170d73bf9abf80]
120985
+** from 2015-02-09.)
120986
+**
120987
+** (3) If the subquery is the right operand of a LEFT JOIN then
120988
+** (3a) the subquery may not be a join and
120989
+** (3b) the FROM clause of the subquery may not contain a virtual
120990
+** table and
120991
+** (3c) the outer query may not be an aggregate.
120992
+**
120993
+** (4) The subquery can not be DISTINCT.
120942120994
**
120943120995
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
120944120996
** sub-queries that were excluded from this optimization. Restriction
120945120997
** (4) has since been expanded to exclude all DISTINCT subqueries.
120946120998
**
120947
-** (6) The subquery does not use aggregates or the outer query is not
120948
-** DISTINCT.
120999
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
121000
+** If the subquery is aggregate, the outer query may not be DISTINCT.
120949121001
**
120950
-** (7) The subquery has a FROM clause. TODO: For subqueries without
121002
+** (7) The subquery must have a FROM clause. TODO: For subqueries without
120951121003
** A FROM clause, consider adding a FROM clause with the special
120952121004
** table sqlite_once that consists of a single row containing a
120953121005
** single NULL.
120954121006
**
120955
-** (8) The subquery does not use LIMIT or the outer query is not a join.
121007
+** (8) If the subquery uses LIMIT then the outer query may not be a join.
120956121008
**
120957
-** (9) The subquery does not use LIMIT or the outer query does not use
120958
-** aggregates.
121009
+** (9) If the subquery uses LIMIT then the outer query may not be aggregate.
120959121010
**
120960121011
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
120961121012
** accidently carried the comment forward until 2014-09-15. Original
120962
-** text: "The subquery does not use aggregates or the outer query
120963
-** does not use LIMIT."
121013
+** constraint: "If the subquery is aggregate then the outer query
121014
+** may not use LIMIT."
120964121015
**
120965
-** (11) The subquery and the outer query do not both have ORDER BY clauses.
121016
+** (11) The subquery and the outer query may not both have ORDER BY clauses.
120966121017
**
120967121018
** (**) Not implemented. Subsumed into restriction (3). Was previously
120968121019
** a separate restriction deriving from ticket #350.
120969121020
**
120970
-** (13) The subquery and outer query do not both use LIMIT.
121021
+** (13) The subquery and outer query may not both use LIMIT.
120971121022
**
120972
-** (14) The subquery does not use OFFSET.
121023
+** (14) The subquery may not use OFFSET.
120973121024
**
120974
-** (15) The outer query is not part of a compound select or the
120975
-** subquery does not have a LIMIT clause.
121025
+** (15) If the outer query is part of a compound select, then the
121026
+** subquery may not use LIMIT.
120976121027
** (See ticket #2339 and ticket [02a8e81d44]).
120977121028
**
120978
-** (16) The outer query is not an aggregate or the subquery does
120979
-** not contain ORDER BY. (Ticket #2942) This used to not matter
121029
+** (16) If the outer query is aggregate, then the subquery may not
121030
+** use ORDER BY. (Ticket #2942) This used to not matter
120980121031
** until we introduced the group_concat() function.
120981121032
**
120982
-** (17) The sub-query is not a compound select, or it is a UNION ALL
120983
-** compound clause made up entirely of non-aggregate queries, and
120984
-** the parent query:
120985
-**
120986
-** * is not itself part of a compound select,
120987
-** * is not an aggregate or DISTINCT query, and
120988
-** * is not a join
121033
+** (17) If the subquery is a compound select, then
121034
+** (17a) all compound operators must be a UNION ALL, and
121035
+** (17b) no terms within the subquery compound may be aggregate
121036
+** or DISTINT, and
121037
+** (17c) every term within the subquery compound must have a FROM clause
121038
+** (17d) the outer query may not be
121039
+** (17d1) aggregate, or
121040
+** (17d2) DISTINCT, or
121041
+** (17d3) a join.
120989121042
**
120990121043
** The parent and sub-query may contain WHERE clauses. Subject to
120991121044
** rules (11), (13) and (14), they may also contain ORDER BY,
120992121045
** LIMIT and OFFSET clauses. The subquery cannot use any compound
120993121046
** operator other than UNION ALL because all the other compound
@@ -120999,41 +121052,42 @@
120999121052
** SELECT statement, but all the code here does is make sure that no
121000121053
** such (illegal) sub-query is flattened. The caller will detect the
121001121054
** syntax error and return a detailed message.
121002121055
**
121003121056
** (18) If the sub-query is a compound select, then all terms of the
121004
-** ORDER by clause of the parent must be simple references to
121057
+** ORDER BY clause of the parent must be simple references to
121005121058
** columns of the sub-query.
121006121059
**
121007
-** (19) The subquery does not use LIMIT or the outer query does not
121060
+** (19) If the subquery uses LIMIT then the outer query may not
121008121061
** have a WHERE clause.
121009121062
**
121010121063
** (20) If the sub-query is a compound select, then it must not use
121011121064
** an ORDER BY clause. Ticket #3773. We could relax this constraint
121012121065
** somewhat by saying that the terms of the ORDER BY clause must
121013121066
** appear as unmodified result columns in the outer query. But we
121014121067
** have other optimizations in mind to deal with that case.
121015121068
**
121016
-** (21) The subquery does not use LIMIT or the outer query is not
121069
+** (21) If the subquery uses LIMIT then the outer query may not be
121017121070
** DISTINCT. (See ticket [752e1646fc]).
121018121071
**
121019
-** (22) The subquery is not a recursive CTE.
121072
+** (22) The subquery may not be a recursive CTE.
121020121073
**
121021
-** (23) The parent is not a recursive CTE, or the sub-query is not a
121022
-** compound query. This restriction is because transforming the
121074
+** (23) If the outer query is a recursive CTE, then the sub-query may not be
121075
+** a compound query. This restriction is because transforming the
121023121076
** parent to a compound query confuses the code that handles
121024121077
** recursive queries in multiSelect().
121025121078
**
121026
-** (24) The subquery is not an aggregate that uses the built-in min() or
121079
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
121080
+** The subquery may not be an aggregate that uses the built-in min() or
121027121081
** or max() functions. (Without this restriction, a query like:
121028121082
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
121029121083
** return the value X for which Y was maximal.)
121030121084
**
121031121085
**
121032121086
** In this routine, the "p" parameter is a pointer to the outer query.
121033121087
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
121034
-** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
121088
+** uses aggregates.
121035121089
**
121036121090
** If flattening is not attempted, this routine is a no-op and returns 0.
121037121091
** If flattening is attempted this routine returns 1.
121038121092
**
121039121093
** All of the expression analysis must occur on both the outer query and
@@ -121041,12 +121095,11 @@
121041121095
*/
121042121096
static int flattenSubquery(
121043121097
Parse *pParse, /* Parsing context */
121044121098
Select *p, /* The parent or outer SELECT statement */
121045121099
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
121046
- int isAgg, /* True if outer SELECT uses aggregate functions */
121047
- int subqueryIsAgg /* True if the subquery uses aggregate functions */
121100
+ int isAgg /* True if outer SELECT uses aggregate functions */
121048121101
){
121049121102
const char *zSavedAuthContext = pParse->zAuthContext;
121050121103
Select *pParent; /* Current UNION ALL term of the other query */
121051121104
Select *pSub; /* The inner query or "subquery" */
121052121105
Select *pSub1; /* Pointer to the rightmost select in sub-query */
@@ -121061,28 +121114,18 @@
121061121114
sqlite3 *db = pParse->db;
121062121115
121063121116
/* Check to see if flattening is permitted. Return 0 if not.
121064121117
*/
121065121118
assert( p!=0 );
121066
- assert( p->pPrior==0 ); /* Unable to flatten compound queries */
121119
+ assert( p->pPrior==0 );
121067121120
if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
121068121121
pSrc = p->pSrc;
121069121122
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
121070121123
pSubitem = &pSrc->a[iFrom];
121071121124
iParent = pSubitem->iCursor;
121072121125
pSub = pSubitem->pSelect;
121073121126
assert( pSub!=0 );
121074
- if( subqueryIsAgg ){
121075
- if( isAgg ) return 0; /* Restriction (1) */
121076
- if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */
121077
- if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery))
121078
- || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0
121079
- || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0
121080
- ){
121081
- return 0; /* Restriction (2b) */
121082
- }
121083
- }
121084121127
121085121128
pSubSrc = pSub->pSrc;
121086121129
assert( pSubSrc );
121087121130
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
121088121131
** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
@@ -121093,37 +121136,33 @@
121093121136
if( pSub->pOffset ) return 0; /* Restriction (14) */
121094121137
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
121095121138
return 0; /* Restriction (15) */
121096121139
}
121097121140
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
121098
- if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
121141
+ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
121099121142
if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
121100121143
return 0; /* Restrictions (8)(9) */
121101121144
}
121102
- if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
121103
- return 0; /* Restriction (6) */
121104
- }
121105121145
if( p->pOrderBy && pSub->pOrderBy ){
121106121146
return 0; /* Restriction (11) */
121107121147
}
121108121148
if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
121109121149
if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
121110121150
if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
121111121151
return 0; /* Restriction (21) */
121112121152
}
121113
- testcase( pSub->selFlags & SF_Recursive );
121114
- testcase( pSub->selFlags & SF_MinMaxAgg );
121115
- if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){
121116
- return 0; /* Restrictions (22) and (24) */
121153
+ if( pSub->selFlags & (SF_Recursive) ){
121154
+ return 0; /* Restrictions (22) */
121117121155
}
121118121156
if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
121119121157
return 0; /* Restriction (23) */
121120121158
}
121121121159
121122121160
/*
121123121161
** If the subquery is the right operand of a LEFT JOIN, then the
121124
- ** subquery may not be a join itself. Example of why this is not allowed:
121162
+ ** subquery may not be a join itself (3a). Example of why this is not
121163
+ ** allowed:
121125121164
**
121126121165
** t1 LEFT OUTER JOIN (t2 JOIN t3)
121127121166
**
121128121167
** If we flatten the above, we would get
121129121168
**
@@ -121130,58 +121169,60 @@
121130121169
** (t1 LEFT OUTER JOIN t2) JOIN t3
121131121170
**
121132121171
** which is not at all the same thing.
121133121172
**
121134121173
** If the subquery is the right operand of a LEFT JOIN, then the outer
121135
- ** query cannot be an aggregate. This is an artifact of the way aggregates
121136
- ** are processed - there is no mechanism to determine if the LEFT JOIN
121137
- ** table should be all-NULL.
121174
+ ** query cannot be an aggregate. (3c) This is an artifact of the way
121175
+ ** aggregates are processed - there is no mechanism to determine if
121176
+ ** the LEFT JOIN table should be all-NULL.
121138121177
**
121139121178
** See also tickets #306, #350, and #3300.
121140121179
*/
121141121180
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
121142121181
isLeftJoin = 1;
121143121182
if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
121144
- return 0; /* Restriction (3) */
121183
+ /* (3a) (3c) (3b) */
121184
+ return 0;
121145121185
}
121146121186
}
121147121187
#ifdef SQLITE_EXTRA_IFNULLROW
121148121188
else if( iFrom>0 && !isAgg ){
121149121189
/* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
121150
- ** every reference to any result column from subquery in a join, even though
121151
- ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */
121190
+ ** every reference to any result column from subquery in a join, even
121191
+ ** though they are not necessary. This will stress-test the OP_IfNullRow
121192
+ ** opcode. */
121152121193
isLeftJoin = -1;
121153121194
}
121154121195
#endif
121155121196
121156
- /* Restriction 17: If the sub-query is a compound SELECT, then it must
121197
+ /* Restriction (17): If the sub-query is a compound SELECT, then it must
121157121198
** use only the UNION ALL operator. And none of the simple select queries
121158121199
** that make up the compound SELECT are allowed to be aggregate or distinct
121159121200
** queries.
121160121201
*/
121161121202
if( pSub->pPrior ){
121162121203
if( pSub->pOrderBy ){
121163
- return 0; /* Restriction 20 */
121204
+ return 0; /* Restriction (20) */
121164121205
}
121165121206
if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
121166
- return 0;
121207
+ return 0; /* (17d1), (17d2), or (17d3) */
121167121208
}
121168121209
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
121169121210
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
121170121211
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
121171121212
assert( pSub->pSrc!=0 );
121172121213
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
121173
- if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
121174
- || (pSub1->pPrior && pSub1->op!=TK_ALL)
121175
- || pSub1->pSrc->nSrc<1
121214
+ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
121215
+ || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
121216
+ || pSub1->pSrc->nSrc<1 /* (17c) */
121176121217
){
121177121218
return 0;
121178121219
}
121179121220
testcase( pSub1->pSrc->nSrc>1 );
121180121221
}
121181121222
121182
- /* Restriction 18. */
121223
+ /* Restriction (18). */
121183121224
if( p->pOrderBy ){
121184121225
int ii;
121185121226
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
121186121227
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
121187121228
}
@@ -121398,22 +121439,11 @@
121398121439
}
121399121440
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
121400121441
if( isLeftJoin>0 ){
121401121442
setJoinExpr(pWhere, iNewParent);
121402121443
}
121403
- if( subqueryIsAgg ){
121404
- assert( pParent->pHaving==0 );
121405
- pParent->pHaving = pParent->pWhere;
121406
- pParent->pWhere = pWhere;
121407
- pParent->pHaving = sqlite3ExprAnd(db,
121408
- sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving
121409
- );
121410
- assert( pParent->pGroupBy==0 );
121411
- pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
121412
- }else{
121413
- pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
121414
- }
121444
+ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
121415121445
if( db->mallocFailed==0 ){
121416121446
SubstContext x;
121417121447
x.pParse = pParse;
121418121448
x.iTable = iParent;
121419121449
x.iNewTable = iNewParent;
@@ -121472,13 +121502,17 @@
121472121502
** The hope is that the terms added to the inner query will make it more
121473121503
** efficient.
121474121504
**
121475121505
** Do not attempt this optimization if:
121476121506
**
121477
-** (1) The inner query is an aggregate. (In that case, we'd really want
121478
-** to copy the outer WHERE-clause terms onto the HAVING clause of the
121479
-** inner query. But they probably won't help there so do not bother.)
121507
+** (1) (** This restriction was removed on 2017-09-29. We used to
121508
+** disallow this optimization for aggregate subqueries, but now
121509
+** it is allowed by putting the extra terms on the HAVING clause.
121510
+** The added HAVING clause is pointless if the subquery lacks
121511
+** a GROUP BY clause. But such a HAVING clause is also harmless
121512
+** so there does not appear to be any reason to add extra logic
121513
+** to suppress it. **)
121480121514
**
121481121515
** (2) The inner query is the recursive part of a common table expression.
121482121516
**
121483121517
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
121484121518
** close would change the meaning of the LIMIT).
@@ -121499,28 +121533,34 @@
121499121533
Expr *pWhere, /* The WHERE clause of the outer query */
121500121534
int iCursor /* Cursor number of the subquery */
121501121535
){
121502121536
Expr *pNew;
121503121537
int nChng = 0;
121504
- Select *pX; /* For looping over compound SELECTs in pSubq */
121505121538
if( pWhere==0 ) return 0;
121506
- for(pX=pSubq; pX; pX=pX->pPrior){
121507
- if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
121508
- testcase( pX->selFlags & SF_Aggregate );
121509
- testcase( pX->selFlags & SF_Recursive );
121510
- testcase( pX!=pSubq );
121511
- return 0; /* restrictions (1) and (2) */
121539
+ if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
121540
+
121541
+#ifdef SQLITE_DEBUG
121542
+ /* Only the first term of a compound can have a WITH clause. But make
121543
+ ** sure no other terms are marked SF_Recursive in case something changes
121544
+ ** in the future.
121545
+ */
121546
+ {
121547
+ Select *pX;
121548
+ for(pX=pSubq; pX; pX=pX->pPrior){
121549
+ assert( (pX->selFlags & (SF_Recursive))==0 );
121512121550
}
121513121551
}
121552
+#endif
121553
+
121514121554
if( pSubq->pLimit!=0 ){
121515121555
return 0; /* restriction (3) */
121516121556
}
121517121557
while( pWhere->op==TK_AND ){
121518121558
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
121519121559
pWhere = pWhere->pLeft;
121520121560
}
121521
- if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
121561
+ if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */
121522121562
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
121523121563
nChng++;
121524121564
while( pSubq ){
121525121565
SubstContext x;
121526121566
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -121528,11 +121568,15 @@
121528121568
x.iTable = iCursor;
121529121569
x.iNewTable = iCursor;
121530121570
x.isLeftJoin = 0;
121531121571
x.pEList = pSubq->pEList;
121532121572
pNew = substExpr(&x, pNew);
121533
- pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
121573
+ if( pSubq->selFlags & SF_Aggregate ){
121574
+ pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
121575
+ }else{
121576
+ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
121577
+ }
121534121578
pSubq = pSubq->pPrior;
121535121579
}
121536121580
}
121537121581
return nChng;
121538121582
}
@@ -121856,11 +121900,12 @@
121856121900
sqlite3ErrorMsg(
121857121901
pParse, "multiple references to recursive table: %s", pCte->zName
121858121902
);
121859121903
return SQLITE_ERROR;
121860121904
}
121861
- assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
121905
+ assert( pTab->nTabRef==1 ||
121906
+ ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
121862121907
121863121908
pCte->zCteErr = "circular reference: %s";
121864121909
pSavedWith = pParse->pWith;
121865121910
pParse->pWith = pWith;
121866121911
if( bMayRecursive ){
@@ -122000,11 +122045,15 @@
122000122045
assert( pFrom->pTab==0 );
122001122046
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
122002122047
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
122003122048
if( pTab==0 ) return WRC_Abort;
122004122049
pTab->nTabRef = 1;
122005
- pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
122050
+ if( pFrom->zAlias ){
122051
+ pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias);
122052
+ }else{
122053
+ pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab);
122054
+ }
122006122055
while( pSel->pPrior ){ pSel = pSel->pPrior; }
122007122056
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
122008122057
pTab->iPKey = -1;
122009122058
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
122010122059
pTab->tabFlags |= TF_Ephemeral;
@@ -122660,28 +122709,28 @@
122660122709
static int countOfViewOptimization(Parse *pParse, Select *p){
122661122710
Select *pSub, *pPrior;
122662122711
Expr *pExpr;
122663122712
Expr *pCount;
122664122713
sqlite3 *db;
122665
- if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */
122714
+ if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
122666122715
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
122667122716
pExpr = p->pEList->a[0].pExpr;
122668122717
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
122669
- if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */
122718
+ if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
122670122719
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
122671
- if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */
122720
+ if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
122672122721
pSub = p->pSrc->a[0].pSelect;
122673122722
if( pSub==0 ) return 0; /* The FROM is a subquery */
122674
- if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */
122723
+ if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
122675122724
do{
122676122725
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
122677122726
if( pSub->pWhere ) return 0; /* No WHERE clause */
122678122727
if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
122679
- pSub = pSub->pPrior; /* Repeat over compound terms */
122728
+ pSub = pSub->pPrior; /* Repeat over compound */
122680122729
}while( pSub );
122681122730
122682
- /* If we reach this point, that means it is OK to perform the transformation */
122731
+ /* If we reach this point then it is OK to perform the transformation */
122683122732
122684122733
db = pParse->db;
122685122734
pCount = pExpr;
122686122735
pExpr = 0;
122687122736
pSub = p->pSrc->a[0].pSelect;
@@ -122817,11 +122866,10 @@
122817122866
*/
122818122867
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
122819122868
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
122820122869
struct SrcList_item *pItem = &pTabList->a[i];
122821122870
Select *pSub = pItem->pSelect;
122822
- int isAggSub;
122823122871
Table *pTab = pItem->pTab;
122824122872
if( pSub==0 ) continue;
122825122873
122826122874
/* Catch mismatch in the declared columns of a view and the number of
122827122875
** columns in the SELECT on the RHS */
@@ -122829,17 +122877,40 @@
122829122877
sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d",
122830122878
pTab->nCol, pTab->zName, pSub->pEList->nExpr);
122831122879
goto select_end;
122832122880
}
122833122881
122834
- isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
122835
- if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
122882
+ /* Do not try to flatten an aggregate subquery.
122883
+ **
122884
+ ** Flattening an aggregate subquery is only possible if the outer query
122885
+ ** is not a join. But if the outer query is not a join, then the subquery
122886
+ ** will be implemented as a co-routine and there is no advantage to
122887
+ ** flattening in that case.
122888
+ */
122889
+ if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
122890
+ assert( pSub->pGroupBy==0 );
122891
+
122892
+ /* If the subquery contains an ORDER BY clause and if
122893
+ ** it will be implemented as a co-routine, then do not flatten. This
122894
+ ** restriction allows SQL constructs like this:
122895
+ **
122896
+ ** SELECT expensive_function(x)
122897
+ ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
122898
+ **
122899
+ ** The expensive_function() is only computed on the 10 rows that
122900
+ ** are output, rather than every row of the table.
122901
+ */
122902
+ if( pSub->pOrderBy!=0
122903
+ && i==0
122904
+ && (pTabList->nSrc==1
122905
+ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
122906
+ ){
122907
+ continue;
122908
+ }
122909
+
122910
+ if( flattenSubquery(pParse, p, i, isAgg) ){
122836122911
/* This subquery can be absorbed into its parent. */
122837
- if( isAggSub ){
122838
- isAgg = 1;
122839
- p->selFlags |= SF_Aggregate;
122840
- }
122841122912
i = -1;
122842122913
}
122843122914
pTabList = p->pSrc;
122844122915
if( db->mallocFailed ) goto select_end;
122845122916
if( !IgnorableOrderby(pDest) ){
@@ -122869,25 +122940,29 @@
122869122940
*/
122870122941
for(i=0; i<pTabList->nSrc; i++){
122871122942
struct SrcList_item *pItem = &pTabList->a[i];
122872122943
SelectDest dest;
122873122944
Select *pSub;
122945
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
122946
+ const char *zSavedAuthContext;
122947
+#endif
122874122948
122875
- /* Issue SQLITE_READ authorizations with a fake column name for any tables that
122876
- ** are referenced but from which no values are extracted. Examples of where these
122877
- ** kinds of null SQLITE_READ authorizations would occur:
122949
+ /* Issue SQLITE_READ authorizations with a fake column name for any
122950
+ ** tables that are referenced but from which no values are extracted.
122951
+ ** Examples of where these kinds of null SQLITE_READ authorizations
122952
+ ** would occur:
122878122953
**
122879122954
** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
122880122955
** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
122881122956
**
122882122957
** The fake column name is an empty string. It is possible for a table to
122883122958
** have a column named by the empty string, in which case there is no way to
122884122959
** distinguish between an unreferenced table and an actual reference to the
122885
- ** "" column. The original design was for the fake column name to be a NULL,
122960
+ ** "" column. The original design was for the fake column name to be a NULL,
122886122961
** which would be unambiguous. But legacy authorization callbacks might
122887
- ** assume the column name is non-NULL and segfault. The use of an empty string
122888
- ** for the fake column name seems safer.
122962
+ ** assume the column name is non-NULL and segfault. The use of an empty
122963
+ ** string for the fake column name seems safer.
122889122964
*/
122890122965
if( pItem->colUsed==0 ){
122891122966
sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
122892122967
}
122893122968
@@ -122934,35 +123009,32 @@
122934123009
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
122935123010
sqlite3TreeViewSelect(0, p, 0);
122936123011
}
122937123012
#endif
122938123013
}
123014
+
123015
+ zSavedAuthContext = pParse->zAuthContext;
123016
+ pParse->zAuthContext = pItem->zName;
122939123017
122940123018
/* Generate code to implement the subquery
122941123019
**
122942
- ** The subquery is implemented as a co-routine if all of these are true:
122943
- ** (1) The subquery is guaranteed to be the outer loop (so that it
122944
- ** does not need to be computed more than once)
122945
- ** (2) The ALL keyword after SELECT is omitted. (Applications are
122946
- ** allowed to say "SELECT ALL" instead of just "SELECT" to disable
122947
- ** the use of co-routines.)
122948
- ** (3) Co-routines are not disabled using sqlite3_test_control()
122949
- ** with SQLITE_TESTCTRL_OPTIMIZATIONS.
123020
+ ** The subquery is implemented as a co-routine if the subquery is
123021
+ ** guaranteed to be the outer loop (so that it does not need to be
123022
+ ** computed more than once)
122950123023
**
122951123024
** TODO: Are there other reasons beside (1) to use a co-routine
122952123025
** implementation?
122953123026
*/
122954123027
if( i==0
122955123028
&& (pTabList->nSrc==1
122956123029
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
122957
- && (p->selFlags & SF_All)==0 /* (2) */
122958
- && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
122959123030
){
122960123031
/* Implement a co-routine that will return a single row of the result
122961123032
** set on each invocation.
122962123033
*/
122963123034
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
123035
+
122964123036
pItem->regReturn = ++pParse->nMem;
122965123037
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
122966123038
VdbeComment((v, "%s", pItem->pTab->zName));
122967123039
pItem->addrFillSub = addrTop;
122968123040
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
@@ -123016,10 +123088,11 @@
123016123088
sqlite3VdbeChangeP1(v, topAddr, retAddr);
123017123089
sqlite3ClearTempRegCache(pParse);
123018123090
}
123019123091
if( db->mallocFailed ) goto select_end;
123020123092
pParse->nHeight -= sqlite3SelectExprHeight(p);
123093
+ pParse->zAuthContext = zSavedAuthContext;
123021123094
#endif
123022123095
}
123023123096
123024123097
/* Various elements of the SELECT copied into local variables for
123025123098
** convenience */
@@ -131021,11 +131094,10 @@
131021131094
** returned when it should not be, then incorrect answers might result.
131022131095
*/
131023131096
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
131024131097
char aff1, aff2;
131025131098
CollSeq *pColl;
131026
- const char *zColl1, *zColl2;
131027131099
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
131028131100
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
131029131101
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
131030131102
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
131031131103
aff2 = sqlite3ExprAffinity(pExpr->pRight);
@@ -131034,15 +131106,11 @@
131034131106
){
131035131107
return 0;
131036131108
}
131037131109
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
131038131110
if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
131039
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
131040
- zColl1 = pColl ? pColl->zName : 0;
131041
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
131042
- zColl2 = pColl ? pColl->zName : 0;
131043
- return sqlite3_stricmp(zColl1, zColl2)==0;
131111
+ return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
131044131112
}
131045131113
131046131114
/*
131047131115
** Recursively walk the expressions of a SELECT statement and generate
131048131116
** a bitmask indicating which tables are used in that expression
@@ -132119,12 +132187,12 @@
132119132187
Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
132120132188
if( p->op==TK_COLUMN
132121132189
&& p->iColumn==pIdx->aiColumn[iCol]
132122132190
&& p->iTable==iBase
132123132191
){
132124
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
132125
- if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
132192
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
132193
+ if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
132126132194
return i;
132127132195
}
132128132196
}
132129132197
}
132130132198
@@ -134385,11 +134453,11 @@
134385134453
if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
134386134454
}
134387134455
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
134388134456
for(jj=0; jj<pIndex->nKeyCol; jj++){
134389134457
if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
134390
- if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
134458
+ if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
134391134459
return 1;
134392134460
}
134393134461
}
134394134462
}
134395134463
}
@@ -135295,18 +135363,14 @@
135295135363
assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
135296135364
for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
135297135365
if( j>=pLoop->nLTerm ) continue;
135298135366
}
135299135367
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
135300
- const char *z1, *z2;
135301
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
135302
- if( !pColl ) pColl = db->pDfltColl;
135303
- z1 = pColl->zName;
135304
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
135305
- if( !pColl ) pColl = db->pDfltColl;
135306
- z2 = pColl->zName;
135307
- if( sqlite3StrICmp(z1, z2)!=0 ) continue;
135368
+ if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
135369
+ pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
135370
+ continue;
135371
+ }
135308135372
testcase( pTerm->pExpr->op==TK_IS );
135309135373
}
135310135374
obSat |= MASKBIT(i);
135311135375
}
135312135376
@@ -135374,11 +135438,11 @@
135374135438
** (revIdx) for the j-th column of the index.
135375135439
*/
135376135440
if( pIndex ){
135377135441
iColumn = pIndex->aiColumn[j];
135378135442
revIdx = pIndex->aSortOrder[j];
135379
- if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
135443
+ if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
135380135444
}else{
135381135445
iColumn = XN_ROWID;
135382135446
revIdx = 0;
135383135447
}
135384135448
@@ -135401,23 +135465,22 @@
135401135465
if( MASKBIT(i) & obSat ) continue;
135402135466
pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
135403135467
testcase( wctrlFlags & WHERE_GROUPBY );
135404135468
testcase( wctrlFlags & WHERE_DISTINCTBY );
135405135469
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
135406
- if( iColumn>=(-1) ){
135470
+ if( iColumn>=XN_ROWID ){
135407135471
if( pOBExpr->op!=TK_COLUMN ) continue;
135408135472
if( pOBExpr->iTable!=iCur ) continue;
135409135473
if( pOBExpr->iColumn!=iColumn ) continue;
135410135474
}else{
135411
- if( sqlite3ExprCompare(0,
135412
- pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
135475
+ Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
135476
+ if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
135413135477
continue;
135414135478
}
135415135479
}
135416135480
if( iColumn!=XN_ROWID ){
135417
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
135418
- if( !pColl ) pColl = db->pDfltColl;
135481
+ pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
135419135482
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
135420135483
}
135421135484
pLoop->u.btree.nIdxCol = j+1;
135422135485
isMatch = 1;
135423135486
break;
@@ -137095,11 +137158,12 @@
137095137158
** YYNSTATE the combined number of states.
137096137159
** YYNRULE the number of rules in the grammar
137097137160
** YY_MAX_SHIFT Maximum value for shift actions
137098137161
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
137099137162
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
137100
-** YY_MIN_REDUCE Maximum value for reduce actions
137163
+** YY_MIN_REDUCE Minimum value for reduce actions
137164
+** YY_MAX_REDUCE Maximum value for reduce actions
137101137165
** YY_ERROR_ACTION The yy_action[] code for syntax error
137102137166
** YY_ACCEPT_ACTION The yy_action[] code for accept
137103137167
** YY_NO_ACTION The yy_action[] code for no-op
137104137168
*/
137105137169
#ifndef INTERFACE
@@ -184892,11 +184956,12 @@
184892184956
** fts5YYNSTATE the combined number of states.
184893184957
** fts5YYNRULE the number of rules in the grammar
184894184958
** fts5YY_MAX_SHIFT Maximum value for shift actions
184895184959
** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
184896184960
** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
184897
-** fts5YY_MIN_REDUCE Maximum value for reduce actions
184961
+** fts5YY_MIN_REDUCE Minimum value for reduce actions
184962
+** fts5YY_MAX_REDUCE Maximum value for reduce actions
184898184963
** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error
184899184964
** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept
184900184965
** fts5YY_NO_ACTION The fts5yy_action[] code for no-op
184901184966
*/
184902184967
#ifndef INTERFACE
@@ -200632,11 +200697,11 @@
200632200697
int nArg, /* Number of args */
200633200698
sqlite3_value **apUnused /* Function arguments */
200634200699
){
200635200700
assert( nArg==0 );
200636200701
UNUSED_PARAM2(nArg, apUnused);
200637
- sqlite3_result_text(pCtx, "fts5: 2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43", -1, SQLITE_TRANSIENT);
200702
+ sqlite3_result_text(pCtx, "fts5: 2017-09-29 16:07:56 0840f9f824c16212ce3fd6c859e501176eb0a58924ea1728a54d5bdfd0c25c86", -1, SQLITE_TRANSIENT);
200638200703
}
200639200704
200640200705
static int fts5Init(sqlite3 *db){
200641200706
static const sqlite3_module fts5Mod = {
200642200707
/* iVersion */ 2,
@@ -204901,12 +204966,12 @@
204901204966
}
204902204967
#endif /* SQLITE_CORE */
204903204968
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
204904204969
204905204970
/************** End of stmt.c ************************************************/
204906
-#if __LINE__!=204906
204971
+#if __LINE__!=204971
204907204972
#undef SQLITE_SOURCE_ID
204908
-#define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c14alt2"
204973
+#define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bfalt2"
204909204974
#endif
204910204975
/* Return the source-id for this library */
204911204976
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
204912204977
/************************** End of sqlite3.c ******************************/
204913204978
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1147,11 +1147,11 @@
1147 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1148 ** [sqlite_version()] and [sqlite_source_id()].
1149 */
1150 #define SQLITE_VERSION "3.21.0"
1151 #define SQLITE_VERSION_NUMBER 3021000
1152 #define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43"
1153
1154 /*
1155 ** CAPI3REF: Run-Time Library Version Numbers
1156 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1157 **
@@ -15279,20 +15279,19 @@
15279 */
15280 #define SQLITE_QueryFlattener 0x0001 /* Query flattening */
15281 #define SQLITE_ColumnCache 0x0002 /* Column cache */
15282 #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
15283 #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
15284 /* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
15285 #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
15286 #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
15287 #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
15288 #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
15289 #define SQLITE_Transitive 0x0200 /* Transitive constraints */
15290 #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
15291 #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
15292 #define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */
15293 #define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
15294 #define SQLITE_AllOpts 0xffff /* All optimizations */
15295
15296 /*
15297 ** Macros for testing whether or not optimizations are enabled or disabled.
15298 */
@@ -17777,10 +17776,12 @@
17777 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
17778 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
17779 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
17780 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
17781 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
 
 
17782 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
17783 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
17784 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
17785 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
17786 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
@@ -43282,18 +43283,23 @@
43282 dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
43283 extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
43284 extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
43285 extendedParameters.lpSecurityAttributes = NULL;
43286 extendedParameters.hTemplateFile = NULL;
43287 while( (h = osCreateFile2((LPCWSTR)zConverted,
43288 dwDesiredAccess,
43289 dwShareMode,
43290 dwCreationDisposition,
43291 &extendedParameters))==INVALID_HANDLE_VALUE &&
43292 winRetryIoerr(&cnt, &lastErrno) ){
43293 /* Noop */
43294 }
 
 
 
 
 
43295 #else
43296 do{
43297 h = osCreateFileW((LPCWSTR)zConverted,
43298 dwDesiredAccess,
43299 dwShareMode, NULL,
@@ -43309,19 +43315,24 @@
43309 }while( winRetryIoerr(&cnt, &lastErrno) );
43310 #endif
43311 }
43312 #ifdef SQLITE_WIN32_HAS_ANSI
43313 else{
43314 while( (h = osCreateFileA((LPCSTR)zConverted,
43315 dwDesiredAccess,
43316 dwShareMode, NULL,
43317 dwCreationDisposition,
43318 dwFlagsAndAttributes,
43319 NULL))==INVALID_HANDLE_VALUE &&
43320 winRetryIoerr(&cnt, &lastErrno) ){
43321 /* Noop */
43322 }
 
 
 
 
 
43323 }
43324 #endif
43325 winLogIoerr(cnt, __LINE__);
43326
43327 OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
@@ -61031,10 +61042,13 @@
61031 u8 *pEnd = &data[cellOffset + nCell*2];
61032 u8 *pAddr;
61033 int sz2 = 0;
61034 int sz = get2byte(&data[iFree+2]);
61035 int top = get2byte(&data[hdr+5]);
 
 
 
61036 if( iFree2 ){
61037 assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
61038 sz2 = get2byte(&data[iFree2+2]);
61039 assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
61040 memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
@@ -71383,13 +71397,14 @@
71383 u32 amt, /* Number of bytes to return. */
71384 Mem *pMem /* OUT: Return data in this Mem structure. */
71385 ){
71386 int rc;
71387 pMem->flags = MEM_Null;
71388 if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt)) ){
71389 rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
71390 if( rc==SQLITE_OK ){
 
71391 pMem->flags = MEM_Blob;
71392 pMem->n = (int)amt;
71393 }else{
71394 sqlite3VdbeMemRelease(pMem);
71395 }
@@ -91882,10 +91897,15 @@
91882
91883 /*
91884 ** Return the collation sequence for the expression pExpr. If
91885 ** there is no defined collating sequence, return NULL.
91886 **
 
 
 
 
 
91887 ** The collating sequence might be determined by a COLLATE operator
91888 ** or by the presence of a column with a defined collating sequence.
91889 ** COLLATE operators take first precedence. Left operands take
91890 ** precedence over right operands.
91891 */
@@ -91945,10 +91965,36 @@
91945 if( sqlite3CheckCollSeq(pParse, pColl) ){
91946 pColl = 0;
91947 }
91948 return pColl;
91949 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91950
91951 /*
91952 ** pExpr is an operand of a comparison operator. aff2 is the
91953 ** type affinity of the other operand. This routine returns the
91954 ** type affinity that should be used for the comparison operator.
@@ -93439,16 +93485,15 @@
93439 ** ExprList.
93440 */
93441 SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
93442 int i;
93443 u32 m = 0;
93444 if( pList ){
93445 for(i=0; i<pList->nExpr; i++){
93446 Expr *pExpr = pList->a[i].pExpr;
93447 assert( pExpr!=0 );
93448 m |= pExpr->flags;
93449 }
93450 }
93451 return m;
93452 }
93453
93454 /*
@@ -93601,12 +93646,12 @@
93601 /* Check if pExpr is identical to any GROUP BY term. If so, consider
93602 ** it constant. */
93603 for(i=0; i<pGroupBy->nExpr; i++){
93604 Expr *p = pGroupBy->a[i].pExpr;
93605 if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
93606 CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
93607 if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
93608 return WRC_Prune;
93609 }
93610 }
93611 }
93612
@@ -117746,11 +117791,12 @@
117746 if( pNew==0 ){
117747 assert( pParse->db->mallocFailed );
117748 pNew = &standin;
117749 }
117750 if( pEList==0 ){
117751 pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0));
 
117752 }
117753 pNew->pEList = pEList;
117754 pNew->op = TK_SELECT;
117755 pNew->selFlags = selFlags;
117756 pNew->iLimit = 0;
@@ -117770,11 +117816,12 @@
117770 pNew->pPrior = 0;
117771 pNew->pNext = 0;
117772 pNew->pLimit = pLimit;
117773 pNew->pOffset = pOffset;
117774 pNew->pWith = 0;
117775 assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 );
 
117776 if( pParse->db->mallocFailed ) {
117777 clearSelect(pParse->db, pNew, pNew!=&standin);
117778 pNew = 0;
117779 }else{
117780 assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -118387,11 +118434,12 @@
118387 }
118388 regOrig = 0;
118389 assert( eDest==SRT_Set || eDest==SRT_Mem
118390 || eDest==SRT_Coroutine || eDest==SRT_Output );
118391 }
118392 nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,0,ecelFlags);
 
118393 }
118394
118395 /* If the DISTINCT keyword was present on the SELECT statement
118396 ** and this row has been seen before, then do not make this row
118397 ** part of the result.
@@ -118737,14 +118785,11 @@
118737 nExpr = pList->nExpr;
118738 pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
118739 if( pInfo ){
118740 assert( sqlite3KeyInfoIsWriteable(pInfo) );
118741 for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
118742 CollSeq *pColl;
118743 pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
118744 if( !pColl ) pColl = db->pDfltColl;
118745 pInfo->aColl[i-iStart] = pColl;
118746 pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
118747 }
118748 }
118749 return pInfo;
118750 }
@@ -119201,13 +119246,13 @@
119201 ** short=OFF, full=OFF: Column name is the text of the expression has it
119202 ** originally appears in the SELECT statement. In
119203 ** other words, the zSpan of the result expression.
119204 **
119205 ** short=ON, full=OFF: (This is the default setting). If the result
119206 ** refers directly to a table column, then the result
119207 ** column name is just the table column name: COLUMN.
119208 ** Otherwise use zSpan.
119209 **
119210 ** full=ON, short=ANY: If the result refers directly to a table column,
119211 ** then the result column name with the table name
119212 ** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
119213 */
@@ -119245,11 +119290,11 @@
119245 for(i=0; i<pEList->nExpr; i++){
119246 Expr *p = pEList->a[i].pExpr;
119247
119248 assert( p!=0 );
119249 assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
119250 assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering indexes not yet coded */
119251 if( pEList->a[i].zName ){
119252 /* An AS clause always takes first priority */
119253 char *zName = pEList->a[i].zName;
119254 sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
119255 }else if( srcName && p->op==TK_COLUMN ){
@@ -120809,11 +120854,13 @@
120809 static Expr *substExpr(
120810 SubstContext *pSubst, /* Description of the substitution */
120811 Expr *pExpr /* Expr in which substitution occurs */
120812 ){
120813 if( pExpr==0 ) return 0;
120814 if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){
 
 
120815 pExpr->iRightJoinTable = pSubst->iNewTable;
120816 }
120817 if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
120818 if( pExpr->iColumn<0 ){
120819 pExpr->op = TK_NULL;
@@ -120922,72 +120969,78 @@
120922 ** The code generated for this simplification gives the same result
120923 ** but only has to scan the data once. And because indices might
120924 ** exist on the table t1, a complete scan of the data might be
120925 ** avoided.
120926 **
120927 ** Flattening is only attempted if all of the following are true:
120928 **
120929 ** (1) The subquery and the outer query do not both use aggregates.
120930 **
120931 ** (2) The subquery is not an aggregate or (2a) the outer query is not a join
120932 ** and (2b) the outer query does not use subqueries other than the one
120933 ** FROM-clause subquery that is a candidate for flattening. (2b is
120934 ** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
120935 **
120936 ** (3) The subquery is not the right operand of a LEFT JOIN
120937 ** or (a) the subquery is not itself a join and (b) the FROM clause
120938 ** of the subquery does not contain a virtual table and (c) the
120939 ** outer query is not an aggregate.
120940 **
120941 ** (4) The subquery is not DISTINCT.
 
 
 
 
 
120942 **
120943 ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
120944 ** sub-queries that were excluded from this optimization. Restriction
120945 ** (4) has since been expanded to exclude all DISTINCT subqueries.
120946 **
120947 ** (6) The subquery does not use aggregates or the outer query is not
120948 ** DISTINCT.
120949 **
120950 ** (7) The subquery has a FROM clause. TODO: For subqueries without
120951 ** A FROM clause, consider adding a FROM clause with the special
120952 ** table sqlite_once that consists of a single row containing a
120953 ** single NULL.
120954 **
120955 ** (8) The subquery does not use LIMIT or the outer query is not a join.
120956 **
120957 ** (9) The subquery does not use LIMIT or the outer query does not use
120958 ** aggregates.
120959 **
120960 ** (**) Restriction (10) was removed from the code on 2005-02-05 but we
120961 ** accidently carried the comment forward until 2014-09-15. Original
120962 ** text: "The subquery does not use aggregates or the outer query
120963 ** does not use LIMIT."
120964 **
120965 ** (11) The subquery and the outer query do not both have ORDER BY clauses.
120966 **
120967 ** (**) Not implemented. Subsumed into restriction (3). Was previously
120968 ** a separate restriction deriving from ticket #350.
120969 **
120970 ** (13) The subquery and outer query do not both use LIMIT.
120971 **
120972 ** (14) The subquery does not use OFFSET.
120973 **
120974 ** (15) The outer query is not part of a compound select or the
120975 ** subquery does not have a LIMIT clause.
120976 ** (See ticket #2339 and ticket [02a8e81d44]).
120977 **
120978 ** (16) The outer query is not an aggregate or the subquery does
120979 ** not contain ORDER BY. (Ticket #2942) This used to not matter
120980 ** until we introduced the group_concat() function.
120981 **
120982 ** (17) The sub-query is not a compound select, or it is a UNION ALL
120983 ** compound clause made up entirely of non-aggregate queries, and
120984 ** the parent query:
120985 **
120986 ** * is not itself part of a compound select,
120987 ** * is not an aggregate or DISTINCT query, and
120988 ** * is not a join
 
 
120989 **
120990 ** The parent and sub-query may contain WHERE clauses. Subject to
120991 ** rules (11), (13) and (14), they may also contain ORDER BY,
120992 ** LIMIT and OFFSET clauses. The subquery cannot use any compound
120993 ** operator other than UNION ALL because all the other compound
@@ -120999,41 +121052,42 @@
120999 ** SELECT statement, but all the code here does is make sure that no
121000 ** such (illegal) sub-query is flattened. The caller will detect the
121001 ** syntax error and return a detailed message.
121002 **
121003 ** (18) If the sub-query is a compound select, then all terms of the
121004 ** ORDER by clause of the parent must be simple references to
121005 ** columns of the sub-query.
121006 **
121007 ** (19) The subquery does not use LIMIT or the outer query does not
121008 ** have a WHERE clause.
121009 **
121010 ** (20) If the sub-query is a compound select, then it must not use
121011 ** an ORDER BY clause. Ticket #3773. We could relax this constraint
121012 ** somewhat by saying that the terms of the ORDER BY clause must
121013 ** appear as unmodified result columns in the outer query. But we
121014 ** have other optimizations in mind to deal with that case.
121015 **
121016 ** (21) The subquery does not use LIMIT or the outer query is not
121017 ** DISTINCT. (See ticket [752e1646fc]).
121018 **
121019 ** (22) The subquery is not a recursive CTE.
121020 **
121021 ** (23) The parent is not a recursive CTE, or the sub-query is not a
121022 ** compound query. This restriction is because transforming the
121023 ** parent to a compound query confuses the code that handles
121024 ** recursive queries in multiSelect().
121025 **
121026 ** (24) The subquery is not an aggregate that uses the built-in min() or
 
121027 ** or max() functions. (Without this restriction, a query like:
121028 ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
121029 ** return the value X for which Y was maximal.)
121030 **
121031 **
121032 ** In this routine, the "p" parameter is a pointer to the outer query.
121033 ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
121034 ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
121035 **
121036 ** If flattening is not attempted, this routine is a no-op and returns 0.
121037 ** If flattening is attempted this routine returns 1.
121038 **
121039 ** All of the expression analysis must occur on both the outer query and
@@ -121041,12 +121095,11 @@
121041 */
121042 static int flattenSubquery(
121043 Parse *pParse, /* Parsing context */
121044 Select *p, /* The parent or outer SELECT statement */
121045 int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
121046 int isAgg, /* True if outer SELECT uses aggregate functions */
121047 int subqueryIsAgg /* True if the subquery uses aggregate functions */
121048 ){
121049 const char *zSavedAuthContext = pParse->zAuthContext;
121050 Select *pParent; /* Current UNION ALL term of the other query */
121051 Select *pSub; /* The inner query or "subquery" */
121052 Select *pSub1; /* Pointer to the rightmost select in sub-query */
@@ -121061,28 +121114,18 @@
121061 sqlite3 *db = pParse->db;
121062
121063 /* Check to see if flattening is permitted. Return 0 if not.
121064 */
121065 assert( p!=0 );
121066 assert( p->pPrior==0 ); /* Unable to flatten compound queries */
121067 if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
121068 pSrc = p->pSrc;
121069 assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
121070 pSubitem = &pSrc->a[iFrom];
121071 iParent = pSubitem->iCursor;
121072 pSub = pSubitem->pSelect;
121073 assert( pSub!=0 );
121074 if( subqueryIsAgg ){
121075 if( isAgg ) return 0; /* Restriction (1) */
121076 if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */
121077 if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery))
121078 || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0
121079 || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0
121080 ){
121081 return 0; /* Restriction (2b) */
121082 }
121083 }
121084
121085 pSubSrc = pSub->pSrc;
121086 assert( pSubSrc );
121087 /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
121088 ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
@@ -121093,37 +121136,33 @@
121093 if( pSub->pOffset ) return 0; /* Restriction (14) */
121094 if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
121095 return 0; /* Restriction (15) */
121096 }
121097 if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
121098 if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
121099 if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
121100 return 0; /* Restrictions (8)(9) */
121101 }
121102 if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
121103 return 0; /* Restriction (6) */
121104 }
121105 if( p->pOrderBy && pSub->pOrderBy ){
121106 return 0; /* Restriction (11) */
121107 }
121108 if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
121109 if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
121110 if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
121111 return 0; /* Restriction (21) */
121112 }
121113 testcase( pSub->selFlags & SF_Recursive );
121114 testcase( pSub->selFlags & SF_MinMaxAgg );
121115 if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){
121116 return 0; /* Restrictions (22) and (24) */
121117 }
121118 if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
121119 return 0; /* Restriction (23) */
121120 }
121121
121122 /*
121123 ** If the subquery is the right operand of a LEFT JOIN, then the
121124 ** subquery may not be a join itself. Example of why this is not allowed:
 
121125 **
121126 ** t1 LEFT OUTER JOIN (t2 JOIN t3)
121127 **
121128 ** If we flatten the above, we would get
121129 **
@@ -121130,58 +121169,60 @@
121130 ** (t1 LEFT OUTER JOIN t2) JOIN t3
121131 **
121132 ** which is not at all the same thing.
121133 **
121134 ** If the subquery is the right operand of a LEFT JOIN, then the outer
121135 ** query cannot be an aggregate. This is an artifact of the way aggregates
121136 ** are processed - there is no mechanism to determine if the LEFT JOIN
121137 ** table should be all-NULL.
121138 **
121139 ** See also tickets #306, #350, and #3300.
121140 */
121141 if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
121142 isLeftJoin = 1;
121143 if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
121144 return 0; /* Restriction (3) */
 
121145 }
121146 }
121147 #ifdef SQLITE_EXTRA_IFNULLROW
121148 else if( iFrom>0 && !isAgg ){
121149 /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
121150 ** every reference to any result column from subquery in a join, even though
121151 ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */
 
121152 isLeftJoin = -1;
121153 }
121154 #endif
121155
121156 /* Restriction 17: If the sub-query is a compound SELECT, then it must
121157 ** use only the UNION ALL operator. And none of the simple select queries
121158 ** that make up the compound SELECT are allowed to be aggregate or distinct
121159 ** queries.
121160 */
121161 if( pSub->pPrior ){
121162 if( pSub->pOrderBy ){
121163 return 0; /* Restriction 20 */
121164 }
121165 if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
121166 return 0;
121167 }
121168 for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
121169 testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
121170 testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
121171 assert( pSub->pSrc!=0 );
121172 assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
121173 if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
121174 || (pSub1->pPrior && pSub1->op!=TK_ALL)
121175 || pSub1->pSrc->nSrc<1
121176 ){
121177 return 0;
121178 }
121179 testcase( pSub1->pSrc->nSrc>1 );
121180 }
121181
121182 /* Restriction 18. */
121183 if( p->pOrderBy ){
121184 int ii;
121185 for(ii=0; ii<p->pOrderBy->nExpr; ii++){
121186 if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
121187 }
@@ -121398,22 +121439,11 @@
121398 }
121399 pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
121400 if( isLeftJoin>0 ){
121401 setJoinExpr(pWhere, iNewParent);
121402 }
121403 if( subqueryIsAgg ){
121404 assert( pParent->pHaving==0 );
121405 pParent->pHaving = pParent->pWhere;
121406 pParent->pWhere = pWhere;
121407 pParent->pHaving = sqlite3ExprAnd(db,
121408 sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving
121409 );
121410 assert( pParent->pGroupBy==0 );
121411 pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
121412 }else{
121413 pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
121414 }
121415 if( db->mallocFailed==0 ){
121416 SubstContext x;
121417 x.pParse = pParse;
121418 x.iTable = iParent;
121419 x.iNewTable = iNewParent;
@@ -121472,13 +121502,17 @@
121472 ** The hope is that the terms added to the inner query will make it more
121473 ** efficient.
121474 **
121475 ** Do not attempt this optimization if:
121476 **
121477 ** (1) The inner query is an aggregate. (In that case, we'd really want
121478 ** to copy the outer WHERE-clause terms onto the HAVING clause of the
121479 ** inner query. But they probably won't help there so do not bother.)
 
 
 
 
121480 **
121481 ** (2) The inner query is the recursive part of a common table expression.
121482 **
121483 ** (3) The inner query has a LIMIT clause (since the changes to the WHERE
121484 ** close would change the meaning of the LIMIT).
@@ -121499,28 +121533,34 @@
121499 Expr *pWhere, /* The WHERE clause of the outer query */
121500 int iCursor /* Cursor number of the subquery */
121501 ){
121502 Expr *pNew;
121503 int nChng = 0;
121504 Select *pX; /* For looping over compound SELECTs in pSubq */
121505 if( pWhere==0 ) return 0;
121506 for(pX=pSubq; pX; pX=pX->pPrior){
121507 if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
121508 testcase( pX->selFlags & SF_Aggregate );
121509 testcase( pX->selFlags & SF_Recursive );
121510 testcase( pX!=pSubq );
121511 return 0; /* restrictions (1) and (2) */
 
 
 
 
 
121512 }
121513 }
 
 
121514 if( pSubq->pLimit!=0 ){
121515 return 0; /* restriction (3) */
121516 }
121517 while( pWhere->op==TK_AND ){
121518 nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
121519 pWhere = pWhere->pLeft;
121520 }
121521 if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
121522 if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
121523 nChng++;
121524 while( pSubq ){
121525 SubstContext x;
121526 pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -121528,11 +121568,15 @@
121528 x.iTable = iCursor;
121529 x.iNewTable = iCursor;
121530 x.isLeftJoin = 0;
121531 x.pEList = pSubq->pEList;
121532 pNew = substExpr(&x, pNew);
121533 pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
 
 
 
 
121534 pSubq = pSubq->pPrior;
121535 }
121536 }
121537 return nChng;
121538 }
@@ -121856,11 +121900,12 @@
121856 sqlite3ErrorMsg(
121857 pParse, "multiple references to recursive table: %s", pCte->zName
121858 );
121859 return SQLITE_ERROR;
121860 }
121861 assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
 
121862
121863 pCte->zCteErr = "circular reference: %s";
121864 pSavedWith = pParse->pWith;
121865 pParse->pWith = pWith;
121866 if( bMayRecursive ){
@@ -122000,11 +122045,15 @@
122000 assert( pFrom->pTab==0 );
122001 if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
122002 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
122003 if( pTab==0 ) return WRC_Abort;
122004 pTab->nTabRef = 1;
122005 pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
 
 
 
 
122006 while( pSel->pPrior ){ pSel = pSel->pPrior; }
122007 sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
122008 pTab->iPKey = -1;
122009 pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
122010 pTab->tabFlags |= TF_Ephemeral;
@@ -122660,28 +122709,28 @@
122660 static int countOfViewOptimization(Parse *pParse, Select *p){
122661 Select *pSub, *pPrior;
122662 Expr *pExpr;
122663 Expr *pCount;
122664 sqlite3 *db;
122665 if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */
122666 if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
122667 pExpr = p->pEList->a[0].pExpr;
122668 if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
122669 if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */
122670 if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
122671 if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */
122672 pSub = p->pSrc->a[0].pSelect;
122673 if( pSub==0 ) return 0; /* The FROM is a subquery */
122674 if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */
122675 do{
122676 if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
122677 if( pSub->pWhere ) return 0; /* No WHERE clause */
122678 if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
122679 pSub = pSub->pPrior; /* Repeat over compound terms */
122680 }while( pSub );
122681
122682 /* If we reach this point, that means it is OK to perform the transformation */
122683
122684 db = pParse->db;
122685 pCount = pExpr;
122686 pExpr = 0;
122687 pSub = p->pSrc->a[0].pSelect;
@@ -122817,11 +122866,10 @@
122817 */
122818 #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
122819 for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
122820 struct SrcList_item *pItem = &pTabList->a[i];
122821 Select *pSub = pItem->pSelect;
122822 int isAggSub;
122823 Table *pTab = pItem->pTab;
122824 if( pSub==0 ) continue;
122825
122826 /* Catch mismatch in the declared columns of a view and the number of
122827 ** columns in the SELECT on the RHS */
@@ -122829,17 +122877,40 @@
122829 sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d",
122830 pTab->nCol, pTab->zName, pSub->pEList->nExpr);
122831 goto select_end;
122832 }
122833
122834 isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
122835 if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122836 /* This subquery can be absorbed into its parent. */
122837 if( isAggSub ){
122838 isAgg = 1;
122839 p->selFlags |= SF_Aggregate;
122840 }
122841 i = -1;
122842 }
122843 pTabList = p->pSrc;
122844 if( db->mallocFailed ) goto select_end;
122845 if( !IgnorableOrderby(pDest) ){
@@ -122869,25 +122940,29 @@
122869 */
122870 for(i=0; i<pTabList->nSrc; i++){
122871 struct SrcList_item *pItem = &pTabList->a[i];
122872 SelectDest dest;
122873 Select *pSub;
 
 
 
122874
122875 /* Issue SQLITE_READ authorizations with a fake column name for any tables that
122876 ** are referenced but from which no values are extracted. Examples of where these
122877 ** kinds of null SQLITE_READ authorizations would occur:
 
122878 **
122879 ** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
122880 ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
122881 **
122882 ** The fake column name is an empty string. It is possible for a table to
122883 ** have a column named by the empty string, in which case there is no way to
122884 ** distinguish between an unreferenced table and an actual reference to the
122885 ** "" column. The original design was for the fake column name to be a NULL,
122886 ** which would be unambiguous. But legacy authorization callbacks might
122887 ** assume the column name is non-NULL and segfault. The use of an empty string
122888 ** for the fake column name seems safer.
122889 */
122890 if( pItem->colUsed==0 ){
122891 sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
122892 }
122893
@@ -122934,35 +123009,32 @@
122934 SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
122935 sqlite3TreeViewSelect(0, p, 0);
122936 }
122937 #endif
122938 }
 
 
 
122939
122940 /* Generate code to implement the subquery
122941 **
122942 ** The subquery is implemented as a co-routine if all of these are true:
122943 ** (1) The subquery is guaranteed to be the outer loop (so that it
122944 ** does not need to be computed more than once)
122945 ** (2) The ALL keyword after SELECT is omitted. (Applications are
122946 ** allowed to say "SELECT ALL" instead of just "SELECT" to disable
122947 ** the use of co-routines.)
122948 ** (3) Co-routines are not disabled using sqlite3_test_control()
122949 ** with SQLITE_TESTCTRL_OPTIMIZATIONS.
122950 **
122951 ** TODO: Are there other reasons beside (1) to use a co-routine
122952 ** implementation?
122953 */
122954 if( i==0
122955 && (pTabList->nSrc==1
122956 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
122957 && (p->selFlags & SF_All)==0 /* (2) */
122958 && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
122959 ){
122960 /* Implement a co-routine that will return a single row of the result
122961 ** set on each invocation.
122962 */
122963 int addrTop = sqlite3VdbeCurrentAddr(v)+1;
 
122964 pItem->regReturn = ++pParse->nMem;
122965 sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
122966 VdbeComment((v, "%s", pItem->pTab->zName));
122967 pItem->addrFillSub = addrTop;
122968 sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
@@ -123016,10 +123088,11 @@
123016 sqlite3VdbeChangeP1(v, topAddr, retAddr);
123017 sqlite3ClearTempRegCache(pParse);
123018 }
123019 if( db->mallocFailed ) goto select_end;
123020 pParse->nHeight -= sqlite3SelectExprHeight(p);
 
123021 #endif
123022 }
123023
123024 /* Various elements of the SELECT copied into local variables for
123025 ** convenience */
@@ -131021,11 +131094,10 @@
131021 ** returned when it should not be, then incorrect answers might result.
131022 */
131023 static int termIsEquivalence(Parse *pParse, Expr *pExpr){
131024 char aff1, aff2;
131025 CollSeq *pColl;
131026 const char *zColl1, *zColl2;
131027 if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
131028 if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
131029 if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
131030 aff1 = sqlite3ExprAffinity(pExpr->pLeft);
131031 aff2 = sqlite3ExprAffinity(pExpr->pRight);
@@ -131034,15 +131106,11 @@
131034 ){
131035 return 0;
131036 }
131037 pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
131038 if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
131039 pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
131040 zColl1 = pColl ? pColl->zName : 0;
131041 pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
131042 zColl2 = pColl ? pColl->zName : 0;
131043 return sqlite3_stricmp(zColl1, zColl2)==0;
131044 }
131045
131046 /*
131047 ** Recursively walk the expressions of a SELECT statement and generate
131048 ** a bitmask indicating which tables are used in that expression
@@ -132119,12 +132187,12 @@
132119 Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
132120 if( p->op==TK_COLUMN
132121 && p->iColumn==pIdx->aiColumn[iCol]
132122 && p->iTable==iBase
132123 ){
132124 CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
132125 if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
132126 return i;
132127 }
132128 }
132129 }
132130
@@ -134385,11 +134453,11 @@
134385 if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
134386 }
134387 }else if( (aColExpr = pIndex->aColExpr)!=0 ){
134388 for(jj=0; jj<pIndex->nKeyCol; jj++){
134389 if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
134390 if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
134391 return 1;
134392 }
134393 }
134394 }
134395 }
@@ -135295,18 +135363,14 @@
135295 assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
135296 for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
135297 if( j>=pLoop->nLTerm ) continue;
135298 }
135299 if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
135300 const char *z1, *z2;
135301 pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
135302 if( !pColl ) pColl = db->pDfltColl;
135303 z1 = pColl->zName;
135304 pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
135305 if( !pColl ) pColl = db->pDfltColl;
135306 z2 = pColl->zName;
135307 if( sqlite3StrICmp(z1, z2)!=0 ) continue;
135308 testcase( pTerm->pExpr->op==TK_IS );
135309 }
135310 obSat |= MASKBIT(i);
135311 }
135312
@@ -135374,11 +135438,11 @@
135374 ** (revIdx) for the j-th column of the index.
135375 */
135376 if( pIndex ){
135377 iColumn = pIndex->aiColumn[j];
135378 revIdx = pIndex->aSortOrder[j];
135379 if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
135380 }else{
135381 iColumn = XN_ROWID;
135382 revIdx = 0;
135383 }
135384
@@ -135401,23 +135465,22 @@
135401 if( MASKBIT(i) & obSat ) continue;
135402 pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
135403 testcase( wctrlFlags & WHERE_GROUPBY );
135404 testcase( wctrlFlags & WHERE_DISTINCTBY );
135405 if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
135406 if( iColumn>=(-1) ){
135407 if( pOBExpr->op!=TK_COLUMN ) continue;
135408 if( pOBExpr->iTable!=iCur ) continue;
135409 if( pOBExpr->iColumn!=iColumn ) continue;
135410 }else{
135411 if( sqlite3ExprCompare(0,
135412 pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
135413 continue;
135414 }
135415 }
135416 if( iColumn!=XN_ROWID ){
135417 pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
135418 if( !pColl ) pColl = db->pDfltColl;
135419 if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
135420 }
135421 pLoop->u.btree.nIdxCol = j+1;
135422 isMatch = 1;
135423 break;
@@ -137095,11 +137158,12 @@
137095 ** YYNSTATE the combined number of states.
137096 ** YYNRULE the number of rules in the grammar
137097 ** YY_MAX_SHIFT Maximum value for shift actions
137098 ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
137099 ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
137100 ** YY_MIN_REDUCE Maximum value for reduce actions
 
137101 ** YY_ERROR_ACTION The yy_action[] code for syntax error
137102 ** YY_ACCEPT_ACTION The yy_action[] code for accept
137103 ** YY_NO_ACTION The yy_action[] code for no-op
137104 */
137105 #ifndef INTERFACE
@@ -184892,11 +184956,12 @@
184892 ** fts5YYNSTATE the combined number of states.
184893 ** fts5YYNRULE the number of rules in the grammar
184894 ** fts5YY_MAX_SHIFT Maximum value for shift actions
184895 ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
184896 ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
184897 ** fts5YY_MIN_REDUCE Maximum value for reduce actions
 
184898 ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error
184899 ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept
184900 ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op
184901 */
184902 #ifndef INTERFACE
@@ -200632,11 +200697,11 @@
200632 int nArg, /* Number of args */
200633 sqlite3_value **apUnused /* Function arguments */
200634 ){
200635 assert( nArg==0 );
200636 UNUSED_PARAM2(nArg, apUnused);
200637 sqlite3_result_text(pCtx, "fts5: 2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43", -1, SQLITE_TRANSIENT);
200638 }
200639
200640 static int fts5Init(sqlite3 *db){
200641 static const sqlite3_module fts5Mod = {
200642 /* iVersion */ 2,
@@ -204901,12 +204966,12 @@
204901 }
204902 #endif /* SQLITE_CORE */
204903 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
204904
204905 /************** End of stmt.c ************************************************/
204906 #if __LINE__!=204906
204907 #undef SQLITE_SOURCE_ID
204908 #define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c14alt2"
204909 #endif
204910 /* Return the source-id for this library */
204911 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
204912 /************************** End of sqlite3.c ******************************/
204913
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1147,11 +1147,11 @@
1147 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
1148 ** [sqlite_version()] and [sqlite_source_id()].
1149 */
1150 #define SQLITE_VERSION "3.21.0"
1151 #define SQLITE_VERSION_NUMBER 3021000
1152 #define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bf807a"
1153
1154 /*
1155 ** CAPI3REF: Run-Time Library Version Numbers
1156 ** KEYWORDS: sqlite3_version sqlite3_sourceid
1157 **
@@ -15279,20 +15279,19 @@
15279 */
15280 #define SQLITE_QueryFlattener 0x0001 /* Query flattening */
15281 #define SQLITE_ColumnCache 0x0002 /* Column cache */
15282 #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
15283 #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
15284 #define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
15285 #define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
15286 #define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
15287 #define SQLITE_Transitive 0x0080 /* Transitive constraints */
15288 #define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
15289 #define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
15290 #define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
15291 #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
15292 /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
 
15293 #define SQLITE_AllOpts 0xffff /* All optimizations */
15294
15295 /*
15296 ** Macros for testing whether or not optimizations are enabled or disabled.
15297 */
@@ -17777,10 +17776,12 @@
17776 SQLITE_PRIVATE const char *sqlite3ErrStr(int);
17777 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
17778 SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
17779 SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
17780 SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
17781 SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
17782 SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
17783 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
17784 SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
17785 SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
17786 SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
17787 SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
@@ -43282,18 +43283,23 @@
43283 dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
43284 extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
43285 extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
43286 extendedParameters.lpSecurityAttributes = NULL;
43287 extendedParameters.hTemplateFile = NULL;
43288 do{
43289 h = osCreateFile2((LPCWSTR)zConverted,
43290 dwDesiredAccess,
43291 dwShareMode,
43292 dwCreationDisposition,
43293 &extendedParameters);
43294 if( h!=INVALID_HANDLE_VALUE ) break;
43295 if( isReadWrite ){
43296 int isRO = 0;
43297 int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
43298 if( rc2==SQLITE_OK && isRO ) break;
43299 }
43300 }while( winRetryIoerr(&cnt, &lastErrno) );
43301 #else
43302 do{
43303 h = osCreateFileW((LPCWSTR)zConverted,
43304 dwDesiredAccess,
43305 dwShareMode, NULL,
@@ -43309,19 +43315,24 @@
43315 }while( winRetryIoerr(&cnt, &lastErrno) );
43316 #endif
43317 }
43318 #ifdef SQLITE_WIN32_HAS_ANSI
43319 else{
43320 do{
43321 h = osCreateFileA((LPCSTR)zConverted,
43322 dwDesiredAccess,
43323 dwShareMode, NULL,
43324 dwCreationDisposition,
43325 dwFlagsAndAttributes,
43326 NULL);
43327 if( h!=INVALID_HANDLE_VALUE ) break;
43328 if( isReadWrite ){
43329 int isRO = 0;
43330 int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
43331 if( rc2==SQLITE_OK && isRO ) break;
43332 }
43333 }while( winRetryIoerr(&cnt, &lastErrno) );
43334 }
43335 #endif
43336 winLogIoerr(cnt, __LINE__);
43337
43338 OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
@@ -61031,10 +61042,13 @@
61042 u8 *pEnd = &data[cellOffset + nCell*2];
61043 u8 *pAddr;
61044 int sz2 = 0;
61045 int sz = get2byte(&data[iFree+2]);
61046 int top = get2byte(&data[hdr+5]);
61047 if( top>=iFree ){
61048 return SQLITE_CORRUPT_PGNO(pPage->pgno);
61049 }
61050 if( iFree2 ){
61051 assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
61052 sz2 = get2byte(&data[iFree2+2]);
61053 assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
61054 memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
@@ -71383,13 +71397,14 @@
71397 u32 amt, /* Number of bytes to return. */
71398 Mem *pMem /* OUT: Return data in this Mem structure. */
71399 ){
71400 int rc;
71401 pMem->flags = MEM_Null;
71402 if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
71403 rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
71404 if( rc==SQLITE_OK ){
71405 pMem->z[amt] = 0; /* Overrun area used when reading malformed records */
71406 pMem->flags = MEM_Blob;
71407 pMem->n = (int)amt;
71408 }else{
71409 sqlite3VdbeMemRelease(pMem);
71410 }
@@ -91882,10 +91897,15 @@
91897
91898 /*
91899 ** Return the collation sequence for the expression pExpr. If
91900 ** there is no defined collating sequence, return NULL.
91901 **
91902 ** See also: sqlite3ExprNNCollSeq()
91903 **
91904 ** The sqlite3ExprNNCollSeq() works the same exact that it returns the
91905 ** default collation if pExpr has no defined collation.
91906 **
91907 ** The collating sequence might be determined by a COLLATE operator
91908 ** or by the presence of a column with a defined collating sequence.
91909 ** COLLATE operators take first precedence. Left operands take
91910 ** precedence over right operands.
91911 */
@@ -91945,10 +91965,36 @@
91965 if( sqlite3CheckCollSeq(pParse, pColl) ){
91966 pColl = 0;
91967 }
91968 return pColl;
91969 }
91970
91971 /*
91972 ** Return the collation sequence for the expression pExpr. If
91973 ** there is no defined collating sequence, return a pointer to the
91974 ** defautl collation sequence.
91975 **
91976 ** See also: sqlite3ExprCollSeq()
91977 **
91978 ** The sqlite3ExprCollSeq() routine works the same except that it
91979 ** returns NULL if there is no defined collation.
91980 */
91981 SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
91982 CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
91983 if( p==0 ) p = pParse->db->pDfltColl;
91984 assert( p!=0 );
91985 return p;
91986 }
91987
91988 /*
91989 ** Return TRUE if the two expressions have equivalent collating sequences.
91990 */
91991 SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
91992 CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
91993 CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
91994 return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
91995 }
91996
91997 /*
91998 ** pExpr is an operand of a comparison operator. aff2 is the
91999 ** type affinity of the other operand. This routine returns the
92000 ** type affinity that should be used for the comparison operator.
@@ -93439,16 +93485,15 @@
93485 ** ExprList.
93486 */
93487 SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
93488 int i;
93489 u32 m = 0;
93490 assert( pList!=0 );
93491 for(i=0; i<pList->nExpr; i++){
93492 Expr *pExpr = pList->a[i].pExpr;
93493 assert( pExpr!=0 );
93494 m |= pExpr->flags;
 
93495 }
93496 return m;
93497 }
93498
93499 /*
@@ -93601,12 +93646,12 @@
93646 /* Check if pExpr is identical to any GROUP BY term. If so, consider
93647 ** it constant. */
93648 for(i=0; i<pGroupBy->nExpr; i++){
93649 Expr *p = pGroupBy->a[i].pExpr;
93650 if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
93651 CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
93652 if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
93653 return WRC_Prune;
93654 }
93655 }
93656 }
93657
@@ -117746,11 +117791,12 @@
117791 if( pNew==0 ){
117792 assert( pParse->db->mallocFailed );
117793 pNew = &standin;
117794 }
117795 if( pEList==0 ){
117796 pEList = sqlite3ExprListAppend(pParse, 0,
117797 sqlite3Expr(pParse->db,TK_ASTERISK,0));
117798 }
117799 pNew->pEList = pEList;
117800 pNew->op = TK_SELECT;
117801 pNew->selFlags = selFlags;
117802 pNew->iLimit = 0;
@@ -117770,11 +117816,12 @@
117816 pNew->pPrior = 0;
117817 pNew->pNext = 0;
117818 pNew->pLimit = pLimit;
117819 pNew->pOffset = pOffset;
117820 pNew->pWith = 0;
117821 assert( pOffset==0 || pLimit!=0 || pParse->nErr>0
117822 || pParse->db->mallocFailed!=0 );
117823 if( pParse->db->mallocFailed ) {
117824 clearSelect(pParse->db, pNew, pNew!=&standin);
117825 pNew = 0;
117826 }else{
117827 assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -118387,11 +118434,12 @@
118434 }
118435 regOrig = 0;
118436 assert( eDest==SRT_Set || eDest==SRT_Mem
118437 || eDest==SRT_Coroutine || eDest==SRT_Output );
118438 }
118439 nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,
118440 0,ecelFlags);
118441 }
118442
118443 /* If the DISTINCT keyword was present on the SELECT statement
118444 ** and this row has been seen before, then do not make this row
118445 ** part of the result.
@@ -118737,14 +118785,11 @@
118785 nExpr = pList->nExpr;
118786 pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1);
118787 if( pInfo ){
118788 assert( sqlite3KeyInfoIsWriteable(pInfo) );
118789 for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
118790 pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
 
 
 
118791 pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
118792 }
118793 }
118794 return pInfo;
118795 }
@@ -119201,13 +119246,13 @@
119246 ** short=OFF, full=OFF: Column name is the text of the expression has it
119247 ** originally appears in the SELECT statement. In
119248 ** other words, the zSpan of the result expression.
119249 **
119250 ** short=ON, full=OFF: (This is the default setting). If the result
119251 ** refers directly to a table column, then the
119252 ** result column name is just the table column
119253 ** name: COLUMN. Otherwise use zSpan.
119254 **
119255 ** full=ON, short=ANY: If the result refers directly to a table column,
119256 ** then the result column name with the table name
119257 ** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
119258 */
@@ -119245,11 +119290,11 @@
119290 for(i=0; i<pEList->nExpr; i++){
119291 Expr *p = pEList->a[i].pExpr;
119292
119293 assert( p!=0 );
119294 assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
119295 assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
119296 if( pEList->a[i].zName ){
119297 /* An AS clause always takes first priority */
119298 char *zName = pEList->a[i].zName;
119299 sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
119300 }else if( srcName && p->op==TK_COLUMN ){
@@ -120809,11 +120854,13 @@
120854 static Expr *substExpr(
120855 SubstContext *pSubst, /* Description of the substitution */
120856 Expr *pExpr /* Expr in which substitution occurs */
120857 ){
120858 if( pExpr==0 ) return 0;
120859 if( ExprHasProperty(pExpr, EP_FromJoin)
120860 && pExpr->iRightJoinTable==pSubst->iTable
120861 ){
120862 pExpr->iRightJoinTable = pSubst->iNewTable;
120863 }
120864 if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
120865 if( pExpr->iColumn<0 ){
120866 pExpr->op = TK_NULL;
@@ -120922,72 +120969,78 @@
120969 ** The code generated for this simplification gives the same result
120970 ** but only has to scan the data once. And because indices might
120971 ** exist on the table t1, a complete scan of the data might be
120972 ** avoided.
120973 **
120974 ** Flattening is subject to the following constraints:
120975 **
120976 ** (**) We no longer attempt to flatten aggregate subqueries. Was:
120977 ** The subquery and the outer query cannot both be aggregates.
120978 **
120979 ** (**) We no longer attempt to flatten aggregate subqueries. Was:
120980 ** (2) If the subquery is an aggregate then
120981 ** (2a) the outer query must not be a join and
120982 ** (2b) the outer query must not use subqueries
120983 ** other than the one FROM-clause subquery that is a candidate
120984 ** for flattening. (This is due to ticket [2f7170d73bf9abf80]
120985 ** from 2015-02-09.)
120986 **
120987 ** (3) If the subquery is the right operand of a LEFT JOIN then
120988 ** (3a) the subquery may not be a join and
120989 ** (3b) the FROM clause of the subquery may not contain a virtual
120990 ** table and
120991 ** (3c) the outer query may not be an aggregate.
120992 **
120993 ** (4) The subquery can not be DISTINCT.
120994 **
120995 ** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
120996 ** sub-queries that were excluded from this optimization. Restriction
120997 ** (4) has since been expanded to exclude all DISTINCT subqueries.
120998 **
120999 ** (**) We no longer attempt to flatten aggregate subqueries. Was:
121000 ** If the subquery is aggregate, the outer query may not be DISTINCT.
121001 **
121002 ** (7) The subquery must have a FROM clause. TODO: For subqueries without
121003 ** A FROM clause, consider adding a FROM clause with the special
121004 ** table sqlite_once that consists of a single row containing a
121005 ** single NULL.
121006 **
121007 ** (8) If the subquery uses LIMIT then the outer query may not be a join.
121008 **
121009 ** (9) If the subquery uses LIMIT then the outer query may not be aggregate.
 
121010 **
121011 ** (**) Restriction (10) was removed from the code on 2005-02-05 but we
121012 ** accidently carried the comment forward until 2014-09-15. Original
121013 ** constraint: "If the subquery is aggregate then the outer query
121014 ** may not use LIMIT."
121015 **
121016 ** (11) The subquery and the outer query may not both have ORDER BY clauses.
121017 **
121018 ** (**) Not implemented. Subsumed into restriction (3). Was previously
121019 ** a separate restriction deriving from ticket #350.
121020 **
121021 ** (13) The subquery and outer query may not both use LIMIT.
121022 **
121023 ** (14) The subquery may not use OFFSET.
121024 **
121025 ** (15) If the outer query is part of a compound select, then the
121026 ** subquery may not use LIMIT.
121027 ** (See ticket #2339 and ticket [02a8e81d44]).
121028 **
121029 ** (16) If the outer query is aggregate, then the subquery may not
121030 ** use ORDER BY. (Ticket #2942) This used to not matter
121031 ** until we introduced the group_concat() function.
121032 **
121033 ** (17) If the subquery is a compound select, then
121034 ** (17a) all compound operators must be a UNION ALL, and
121035 ** (17b) no terms within the subquery compound may be aggregate
121036 ** or DISTINT, and
121037 ** (17c) every term within the subquery compound must have a FROM clause
121038 ** (17d) the outer query may not be
121039 ** (17d1) aggregate, or
121040 ** (17d2) DISTINCT, or
121041 ** (17d3) a join.
121042 **
121043 ** The parent and sub-query may contain WHERE clauses. Subject to
121044 ** rules (11), (13) and (14), they may also contain ORDER BY,
121045 ** LIMIT and OFFSET clauses. The subquery cannot use any compound
121046 ** operator other than UNION ALL because all the other compound
@@ -120999,41 +121052,42 @@
121052 ** SELECT statement, but all the code here does is make sure that no
121053 ** such (illegal) sub-query is flattened. The caller will detect the
121054 ** syntax error and return a detailed message.
121055 **
121056 ** (18) If the sub-query is a compound select, then all terms of the
121057 ** ORDER BY clause of the parent must be simple references to
121058 ** columns of the sub-query.
121059 **
121060 ** (19) If the subquery uses LIMIT then the outer query may not
121061 ** have a WHERE clause.
121062 **
121063 ** (20) If the sub-query is a compound select, then it must not use
121064 ** an ORDER BY clause. Ticket #3773. We could relax this constraint
121065 ** somewhat by saying that the terms of the ORDER BY clause must
121066 ** appear as unmodified result columns in the outer query. But we
121067 ** have other optimizations in mind to deal with that case.
121068 **
121069 ** (21) If the subquery uses LIMIT then the outer query may not be
121070 ** DISTINCT. (See ticket [752e1646fc]).
121071 **
121072 ** (22) The subquery may not be a recursive CTE.
121073 **
121074 ** (23) If the outer query is a recursive CTE, then the sub-query may not be
121075 ** a compound query. This restriction is because transforming the
121076 ** parent to a compound query confuses the code that handles
121077 ** recursive queries in multiSelect().
121078 **
121079 ** (**) We no longer attempt to flatten aggregate subqueries. Was:
121080 ** The subquery may not be an aggregate that uses the built-in min() or
121081 ** or max() functions. (Without this restriction, a query like:
121082 ** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
121083 ** return the value X for which Y was maximal.)
121084 **
121085 **
121086 ** In this routine, the "p" parameter is a pointer to the outer query.
121087 ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
121088 ** uses aggregates.
121089 **
121090 ** If flattening is not attempted, this routine is a no-op and returns 0.
121091 ** If flattening is attempted this routine returns 1.
121092 **
121093 ** All of the expression analysis must occur on both the outer query and
@@ -121041,12 +121095,11 @@
121095 */
121096 static int flattenSubquery(
121097 Parse *pParse, /* Parsing context */
121098 Select *p, /* The parent or outer SELECT statement */
121099 int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
121100 int isAgg /* True if outer SELECT uses aggregate functions */
 
121101 ){
121102 const char *zSavedAuthContext = pParse->zAuthContext;
121103 Select *pParent; /* Current UNION ALL term of the other query */
121104 Select *pSub; /* The inner query or "subquery" */
121105 Select *pSub1; /* Pointer to the rightmost select in sub-query */
@@ -121061,28 +121114,18 @@
121114 sqlite3 *db = pParse->db;
121115
121116 /* Check to see if flattening is permitted. Return 0 if not.
121117 */
121118 assert( p!=0 );
121119 assert( p->pPrior==0 );
121120 if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
121121 pSrc = p->pSrc;
121122 assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
121123 pSubitem = &pSrc->a[iFrom];
121124 iParent = pSubitem->iCursor;
121125 pSub = pSubitem->pSelect;
121126 assert( pSub!=0 );
 
 
 
 
 
 
 
 
 
 
121127
121128 pSubSrc = pSub->pSrc;
121129 assert( pSubSrc );
121130 /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
121131 ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
@@ -121093,37 +121136,33 @@
121136 if( pSub->pOffset ) return 0; /* Restriction (14) */
121137 if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
121138 return 0; /* Restriction (15) */
121139 }
121140 if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
121141 if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
121142 if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
121143 return 0; /* Restrictions (8)(9) */
121144 }
 
 
 
121145 if( p->pOrderBy && pSub->pOrderBy ){
121146 return 0; /* Restriction (11) */
121147 }
121148 if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
121149 if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
121150 if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
121151 return 0; /* Restriction (21) */
121152 }
121153 if( pSub->selFlags & (SF_Recursive) ){
121154 return 0; /* Restrictions (22) */
 
 
121155 }
121156 if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
121157 return 0; /* Restriction (23) */
121158 }
121159
121160 /*
121161 ** If the subquery is the right operand of a LEFT JOIN, then the
121162 ** subquery may not be a join itself (3a). Example of why this is not
121163 ** allowed:
121164 **
121165 ** t1 LEFT OUTER JOIN (t2 JOIN t3)
121166 **
121167 ** If we flatten the above, we would get
121168 **
@@ -121130,58 +121169,60 @@
121169 ** (t1 LEFT OUTER JOIN t2) JOIN t3
121170 **
121171 ** which is not at all the same thing.
121172 **
121173 ** If the subquery is the right operand of a LEFT JOIN, then the outer
121174 ** query cannot be an aggregate. (3c) This is an artifact of the way
121175 ** aggregates are processed - there is no mechanism to determine if
121176 ** the LEFT JOIN table should be all-NULL.
121177 **
121178 ** See also tickets #306, #350, and #3300.
121179 */
121180 if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
121181 isLeftJoin = 1;
121182 if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
121183 /* (3a) (3c) (3b) */
121184 return 0;
121185 }
121186 }
121187 #ifdef SQLITE_EXTRA_IFNULLROW
121188 else if( iFrom>0 && !isAgg ){
121189 /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
121190 ** every reference to any result column from subquery in a join, even
121191 ** though they are not necessary. This will stress-test the OP_IfNullRow
121192 ** opcode. */
121193 isLeftJoin = -1;
121194 }
121195 #endif
121196
121197 /* Restriction (17): If the sub-query is a compound SELECT, then it must
121198 ** use only the UNION ALL operator. And none of the simple select queries
121199 ** that make up the compound SELECT are allowed to be aggregate or distinct
121200 ** queries.
121201 */
121202 if( pSub->pPrior ){
121203 if( pSub->pOrderBy ){
121204 return 0; /* Restriction (20) */
121205 }
121206 if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
121207 return 0; /* (17d1), (17d2), or (17d3) */
121208 }
121209 for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
121210 testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
121211 testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
121212 assert( pSub->pSrc!=0 );
121213 assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
121214 if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
121215 || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
121216 || pSub1->pSrc->nSrc<1 /* (17c) */
121217 ){
121218 return 0;
121219 }
121220 testcase( pSub1->pSrc->nSrc>1 );
121221 }
121222
121223 /* Restriction (18). */
121224 if( p->pOrderBy ){
121225 int ii;
121226 for(ii=0; ii<p->pOrderBy->nExpr; ii++){
121227 if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
121228 }
@@ -121398,22 +121439,11 @@
121439 }
121440 pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
121441 if( isLeftJoin>0 ){
121442 setJoinExpr(pWhere, iNewParent);
121443 }
121444 pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
 
 
 
 
 
 
 
 
 
 
 
121445 if( db->mallocFailed==0 ){
121446 SubstContext x;
121447 x.pParse = pParse;
121448 x.iTable = iParent;
121449 x.iNewTable = iNewParent;
@@ -121472,13 +121502,17 @@
121502 ** The hope is that the terms added to the inner query will make it more
121503 ** efficient.
121504 **
121505 ** Do not attempt this optimization if:
121506 **
121507 ** (1) (** This restriction was removed on 2017-09-29. We used to
121508 ** disallow this optimization for aggregate subqueries, but now
121509 ** it is allowed by putting the extra terms on the HAVING clause.
121510 ** The added HAVING clause is pointless if the subquery lacks
121511 ** a GROUP BY clause. But such a HAVING clause is also harmless
121512 ** so there does not appear to be any reason to add extra logic
121513 ** to suppress it. **)
121514 **
121515 ** (2) The inner query is the recursive part of a common table expression.
121516 **
121517 ** (3) The inner query has a LIMIT clause (since the changes to the WHERE
121518 ** close would change the meaning of the LIMIT).
@@ -121499,28 +121533,34 @@
121533 Expr *pWhere, /* The WHERE clause of the outer query */
121534 int iCursor /* Cursor number of the subquery */
121535 ){
121536 Expr *pNew;
121537 int nChng = 0;
 
121538 if( pWhere==0 ) return 0;
121539 if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
121540
121541 #ifdef SQLITE_DEBUG
121542 /* Only the first term of a compound can have a WITH clause. But make
121543 ** sure no other terms are marked SF_Recursive in case something changes
121544 ** in the future.
121545 */
121546 {
121547 Select *pX;
121548 for(pX=pSubq; pX; pX=pX->pPrior){
121549 assert( (pX->selFlags & (SF_Recursive))==0 );
121550 }
121551 }
121552 #endif
121553
121554 if( pSubq->pLimit!=0 ){
121555 return 0; /* restriction (3) */
121556 }
121557 while( pWhere->op==TK_AND ){
121558 nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
121559 pWhere = pWhere->pLeft;
121560 }
121561 if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */
121562 if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
121563 nChng++;
121564 while( pSubq ){
121565 SubstContext x;
121566 pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
@@ -121528,11 +121568,15 @@
121568 x.iTable = iCursor;
121569 x.iNewTable = iCursor;
121570 x.isLeftJoin = 0;
121571 x.pEList = pSubq->pEList;
121572 pNew = substExpr(&x, pNew);
121573 if( pSubq->selFlags & SF_Aggregate ){
121574 pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
121575 }else{
121576 pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
121577 }
121578 pSubq = pSubq->pPrior;
121579 }
121580 }
121581 return nChng;
121582 }
@@ -121856,11 +121900,12 @@
121900 sqlite3ErrorMsg(
121901 pParse, "multiple references to recursive table: %s", pCte->zName
121902 );
121903 return SQLITE_ERROR;
121904 }
121905 assert( pTab->nTabRef==1 ||
121906 ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
121907
121908 pCte->zCteErr = "circular reference: %s";
121909 pSavedWith = pParse->pWith;
121910 pParse->pWith = pWith;
121911 if( bMayRecursive ){
@@ -122000,11 +122045,15 @@
122045 assert( pFrom->pTab==0 );
122046 if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
122047 pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
122048 if( pTab==0 ) return WRC_Abort;
122049 pTab->nTabRef = 1;
122050 if( pFrom->zAlias ){
122051 pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias);
122052 }else{
122053 pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab);
122054 }
122055 while( pSel->pPrior ){ pSel = pSel->pPrior; }
122056 sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
122057 pTab->iPKey = -1;
122058 pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
122059 pTab->tabFlags |= TF_Ephemeral;
@@ -122660,28 +122709,28 @@
122709 static int countOfViewOptimization(Parse *pParse, Select *p){
122710 Select *pSub, *pPrior;
122711 Expr *pExpr;
122712 Expr *pCount;
122713 sqlite3 *db;
122714 if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
122715 if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
122716 pExpr = p->pEList->a[0].pExpr;
122717 if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
122718 if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
122719 if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
122720 if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
122721 pSub = p->pSrc->a[0].pSelect;
122722 if( pSub==0 ) return 0; /* The FROM is a subquery */
122723 if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
122724 do{
122725 if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
122726 if( pSub->pWhere ) return 0; /* No WHERE clause */
122727 if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
122728 pSub = pSub->pPrior; /* Repeat over compound */
122729 }while( pSub );
122730
122731 /* If we reach this point then it is OK to perform the transformation */
122732
122733 db = pParse->db;
122734 pCount = pExpr;
122735 pExpr = 0;
122736 pSub = p->pSrc->a[0].pSelect;
@@ -122817,11 +122866,10 @@
122866 */
122867 #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
122868 for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
122869 struct SrcList_item *pItem = &pTabList->a[i];
122870 Select *pSub = pItem->pSelect;
 
122871 Table *pTab = pItem->pTab;
122872 if( pSub==0 ) continue;
122873
122874 /* Catch mismatch in the declared columns of a view and the number of
122875 ** columns in the SELECT on the RHS */
@@ -122829,17 +122877,40 @@
122877 sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d",
122878 pTab->nCol, pTab->zName, pSub->pEList->nExpr);
122879 goto select_end;
122880 }
122881
122882 /* Do not try to flatten an aggregate subquery.
122883 **
122884 ** Flattening an aggregate subquery is only possible if the outer query
122885 ** is not a join. But if the outer query is not a join, then the subquery
122886 ** will be implemented as a co-routine and there is no advantage to
122887 ** flattening in that case.
122888 */
122889 if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
122890 assert( pSub->pGroupBy==0 );
122891
122892 /* If the subquery contains an ORDER BY clause and if
122893 ** it will be implemented as a co-routine, then do not flatten. This
122894 ** restriction allows SQL constructs like this:
122895 **
122896 ** SELECT expensive_function(x)
122897 ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
122898 **
122899 ** The expensive_function() is only computed on the 10 rows that
122900 ** are output, rather than every row of the table.
122901 */
122902 if( pSub->pOrderBy!=0
122903 && i==0
122904 && (pTabList->nSrc==1
122905 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
122906 ){
122907 continue;
122908 }
122909
122910 if( flattenSubquery(pParse, p, i, isAgg) ){
122911 /* This subquery can be absorbed into its parent. */
 
 
 
 
122912 i = -1;
122913 }
122914 pTabList = p->pSrc;
122915 if( db->mallocFailed ) goto select_end;
122916 if( !IgnorableOrderby(pDest) ){
@@ -122869,25 +122940,29 @@
122940 */
122941 for(i=0; i<pTabList->nSrc; i++){
122942 struct SrcList_item *pItem = &pTabList->a[i];
122943 SelectDest dest;
122944 Select *pSub;
122945 #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
122946 const char *zSavedAuthContext;
122947 #endif
122948
122949 /* Issue SQLITE_READ authorizations with a fake column name for any
122950 ** tables that are referenced but from which no values are extracted.
122951 ** Examples of where these kinds of null SQLITE_READ authorizations
122952 ** would occur:
122953 **
122954 ** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
122955 ** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
122956 **
122957 ** The fake column name is an empty string. It is possible for a table to
122958 ** have a column named by the empty string, in which case there is no way to
122959 ** distinguish between an unreferenced table and an actual reference to the
122960 ** "" column. The original design was for the fake column name to be a NULL,
122961 ** which would be unambiguous. But legacy authorization callbacks might
122962 ** assume the column name is non-NULL and segfault. The use of an empty
122963 ** string for the fake column name seems safer.
122964 */
122965 if( pItem->colUsed==0 ){
122966 sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
122967 }
122968
@@ -122934,35 +123009,32 @@
123009 SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
123010 sqlite3TreeViewSelect(0, p, 0);
123011 }
123012 #endif
123013 }
123014
123015 zSavedAuthContext = pParse->zAuthContext;
123016 pParse->zAuthContext = pItem->zName;
123017
123018 /* Generate code to implement the subquery
123019 **
123020 ** The subquery is implemented as a co-routine if the subquery is
123021 ** guaranteed to be the outer loop (so that it does not need to be
123022 ** computed more than once)
 
 
 
 
 
123023 **
123024 ** TODO: Are there other reasons beside (1) to use a co-routine
123025 ** implementation?
123026 */
123027 if( i==0
123028 && (pTabList->nSrc==1
123029 || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
 
 
123030 ){
123031 /* Implement a co-routine that will return a single row of the result
123032 ** set on each invocation.
123033 */
123034 int addrTop = sqlite3VdbeCurrentAddr(v)+1;
123035
123036 pItem->regReturn = ++pParse->nMem;
123037 sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
123038 VdbeComment((v, "%s", pItem->pTab->zName));
123039 pItem->addrFillSub = addrTop;
123040 sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
@@ -123016,10 +123088,11 @@
123088 sqlite3VdbeChangeP1(v, topAddr, retAddr);
123089 sqlite3ClearTempRegCache(pParse);
123090 }
123091 if( db->mallocFailed ) goto select_end;
123092 pParse->nHeight -= sqlite3SelectExprHeight(p);
123093 pParse->zAuthContext = zSavedAuthContext;
123094 #endif
123095 }
123096
123097 /* Various elements of the SELECT copied into local variables for
123098 ** convenience */
@@ -131021,11 +131094,10 @@
131094 ** returned when it should not be, then incorrect answers might result.
131095 */
131096 static int termIsEquivalence(Parse *pParse, Expr *pExpr){
131097 char aff1, aff2;
131098 CollSeq *pColl;
 
131099 if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
131100 if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
131101 if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
131102 aff1 = sqlite3ExprAffinity(pExpr->pLeft);
131103 aff2 = sqlite3ExprAffinity(pExpr->pRight);
@@ -131034,15 +131106,11 @@
131106 ){
131107 return 0;
131108 }
131109 pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
131110 if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
131111 return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
 
 
 
 
131112 }
131113
131114 /*
131115 ** Recursively walk the expressions of a SELECT statement and generate
131116 ** a bitmask indicating which tables are used in that expression
@@ -132119,12 +132187,12 @@
132187 Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
132188 if( p->op==TK_COLUMN
132189 && p->iColumn==pIdx->aiColumn[iCol]
132190 && p->iTable==iBase
132191 ){
132192 CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
132193 if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
132194 return i;
132195 }
132196 }
132197 }
132198
@@ -134385,11 +134453,11 @@
134453 if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
134454 }
134455 }else if( (aColExpr = pIndex->aColExpr)!=0 ){
134456 for(jj=0; jj<pIndex->nKeyCol; jj++){
134457 if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
134458 if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
134459 return 1;
134460 }
134461 }
134462 }
134463 }
@@ -135295,18 +135363,14 @@
135363 assert( wctrlFlags & WHERE_ORDERBY_LIMIT );
135364 for(j=0; j<pLoop->nLTerm && pTerm!=pLoop->aLTerm[j]; j++){}
135365 if( j>=pLoop->nLTerm ) continue;
135366 }
135367 if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
135368 if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
135369 pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
135370 continue;
135371 }
 
 
 
 
135372 testcase( pTerm->pExpr->op==TK_IS );
135373 }
135374 obSat |= MASKBIT(i);
135375 }
135376
@@ -135374,11 +135438,11 @@
135438 ** (revIdx) for the j-th column of the index.
135439 */
135440 if( pIndex ){
135441 iColumn = pIndex->aiColumn[j];
135442 revIdx = pIndex->aSortOrder[j];
135443 if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
135444 }else{
135445 iColumn = XN_ROWID;
135446 revIdx = 0;
135447 }
135448
@@ -135401,23 +135465,22 @@
135465 if( MASKBIT(i) & obSat ) continue;
135466 pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
135467 testcase( wctrlFlags & WHERE_GROUPBY );
135468 testcase( wctrlFlags & WHERE_DISTINCTBY );
135469 if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
135470 if( iColumn>=XN_ROWID ){
135471 if( pOBExpr->op!=TK_COLUMN ) continue;
135472 if( pOBExpr->iTable!=iCur ) continue;
135473 if( pOBExpr->iColumn!=iColumn ) continue;
135474 }else{
135475 Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
135476 if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
135477 continue;
135478 }
135479 }
135480 if( iColumn!=XN_ROWID ){
135481 pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
 
135482 if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
135483 }
135484 pLoop->u.btree.nIdxCol = j+1;
135485 isMatch = 1;
135486 break;
@@ -137095,11 +137158,12 @@
137158 ** YYNSTATE the combined number of states.
137159 ** YYNRULE the number of rules in the grammar
137160 ** YY_MAX_SHIFT Maximum value for shift actions
137161 ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
137162 ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
137163 ** YY_MIN_REDUCE Minimum value for reduce actions
137164 ** YY_MAX_REDUCE Maximum value for reduce actions
137165 ** YY_ERROR_ACTION The yy_action[] code for syntax error
137166 ** YY_ACCEPT_ACTION The yy_action[] code for accept
137167 ** YY_NO_ACTION The yy_action[] code for no-op
137168 */
137169 #ifndef INTERFACE
@@ -184892,11 +184956,12 @@
184956 ** fts5YYNSTATE the combined number of states.
184957 ** fts5YYNRULE the number of rules in the grammar
184958 ** fts5YY_MAX_SHIFT Maximum value for shift actions
184959 ** fts5YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
184960 ** fts5YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
184961 ** fts5YY_MIN_REDUCE Minimum value for reduce actions
184962 ** fts5YY_MAX_REDUCE Maximum value for reduce actions
184963 ** fts5YY_ERROR_ACTION The fts5yy_action[] code for syntax error
184964 ** fts5YY_ACCEPT_ACTION The fts5yy_action[] code for accept
184965 ** fts5YY_NO_ACTION The fts5yy_action[] code for no-op
184966 */
184967 #ifndef INTERFACE
@@ -200632,11 +200697,11 @@
200697 int nArg, /* Number of args */
200698 sqlite3_value **apUnused /* Function arguments */
200699 ){
200700 assert( nArg==0 );
200701 UNUSED_PARAM2(nArg, apUnused);
200702 sqlite3_result_text(pCtx, "fts5: 2017-09-29 16:07:56 0840f9f824c16212ce3fd6c859e501176eb0a58924ea1728a54d5bdfd0c25c86", -1, SQLITE_TRANSIENT);
200703 }
200704
200705 static int fts5Init(sqlite3 *db){
200706 static const sqlite3_module fts5Mod = {
200707 /* iVersion */ 2,
@@ -204901,12 +204966,12 @@
204966 }
204967 #endif /* SQLITE_CORE */
204968 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
204969
204970 /************** End of stmt.c ************************************************/
204971 #if __LINE__!=204971
204972 #undef SQLITE_SOURCE_ID
204973 #define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bfalt2"
204974 #endif
204975 /* Return the source-id for this library */
204976 SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
204977 /************************** End of sqlite3.c ******************************/
204978
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123123
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124124
** [sqlite_version()] and [sqlite_source_id()].
125125
*/
126126
#define SQLITE_VERSION "3.21.0"
127127
#define SQLITE_VERSION_NUMBER 3021000
128
-#define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43"
128
+#define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bf807a"
129129
130130
/*
131131
** CAPI3REF: Run-Time Library Version Numbers
132132
** KEYWORDS: sqlite3_version sqlite3_sourceid
133133
**
134134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.21.0"
127 #define SQLITE_VERSION_NUMBER 3021000
128 #define SQLITE_SOURCE_ID "2017-09-21 20:43:48 5d03c738e93d36815248991d9ed3d62297ba1bb966e602e7874410076c144f43"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -123,11 +123,11 @@
123 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
124 ** [sqlite_version()] and [sqlite_source_id()].
125 */
126 #define SQLITE_VERSION "3.21.0"
127 #define SQLITE_VERSION_NUMBER 3021000
128 #define SQLITE_SOURCE_ID "2017-10-02 02:52:54 c9104b59c7ed360291f7f6fc8caae938e9840c77620d598e4096f78183bf807a"
129
130 /*
131 ** CAPI3REF: Run-Time Library Version Numbers
132 ** KEYWORDS: sqlite3_version sqlite3_sourceid
133 **
134
+3 -3
--- src/stat.c
+++ src/stat.c
@@ -113,15 +113,15 @@
113113
@ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) total
114114
@ </td></tr>
115115
@ <tr><th>Compression&nbsp;Ratio:</th><td>
116116
if( t/fsize < 5 ){
117117
b = 10;
118
- fsize /= 10;
118
+ a = t/(fsize/10);
119119
}else{
120120
b = 1;
121
+ a = t/fsize;
121122
}
122
- a = t/fsize;
123123
@ %d(a):%d(b)
124124
@ </td></tr>
125125
}
126126
if( db_table_exists("repository","unversioned") ){
127127
Stmt q;
@@ -132,11 +132,11 @@
132132
" WHERE length(hash)>1"
133133
);
134134
if( db_step(&q)==SQLITE_ROW && (n = db_column_int(&q,0))>0 ){
135135
sqlite3_int64 iStored, pct;
136136
iStored = db_column_int64(&q,2);
137
- pct = (iStored*100 + fsize - 1)/fsize;
137
+ pct = (iStored*100 + fsize/2)/fsize;
138138
approxSizeName(sizeof(zStored), zStored, iStored);
139139
@ <tr><th>Unversioned&nbsp;Files:</th><td>
140140
@ %z(href("%R/uvlist"))%d(n) files</a>,
141141
@ %s(zStored) compressed, %d(pct)%% of total repository space
142142
@ </td></tr>
143143
--- src/stat.c
+++ src/stat.c
@@ -113,15 +113,15 @@
113 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) total
114 @ </td></tr>
115 @ <tr><th>Compression&nbsp;Ratio:</th><td>
116 if( t/fsize < 5 ){
117 b = 10;
118 fsize /= 10;
119 }else{
120 b = 1;
 
121 }
122 a = t/fsize;
123 @ %d(a):%d(b)
124 @ </td></tr>
125 }
126 if( db_table_exists("repository","unversioned") ){
127 Stmt q;
@@ -132,11 +132,11 @@
132 " WHERE length(hash)>1"
133 );
134 if( db_step(&q)==SQLITE_ROW && (n = db_column_int(&q,0))>0 ){
135 sqlite3_int64 iStored, pct;
136 iStored = db_column_int64(&q,2);
137 pct = (iStored*100 + fsize - 1)/fsize;
138 approxSizeName(sizeof(zStored), zStored, iStored);
139 @ <tr><th>Unversioned&nbsp;Files:</th><td>
140 @ %z(href("%R/uvlist"))%d(n) files</a>,
141 @ %s(zStored) compressed, %d(pct)%% of total repository space
142 @ </td></tr>
143
--- src/stat.c
+++ src/stat.c
@@ -113,15 +113,15 @@
113 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) total
114 @ </td></tr>
115 @ <tr><th>Compression&nbsp;Ratio:</th><td>
116 if( t/fsize < 5 ){
117 b = 10;
118 a = t/(fsize/10);
119 }else{
120 b = 1;
121 a = t/fsize;
122 }
 
123 @ %d(a):%d(b)
124 @ </td></tr>
125 }
126 if( db_table_exists("repository","unversioned") ){
127 Stmt q;
@@ -132,11 +132,11 @@
132 " WHERE length(hash)>1"
133 );
134 if( db_step(&q)==SQLITE_ROW && (n = db_column_int(&q,0))>0 ){
135 sqlite3_int64 iStored, pct;
136 iStored = db_column_int64(&q,2);
137 pct = (iStored*100 + fsize/2)/fsize;
138 approxSizeName(sizeof(zStored), zStored, iStored);
139 @ <tr><th>Unversioned&nbsp;Files:</th><td>
140 @ %z(href("%R/uvlist"))%d(n) files</a>,
141 @ %s(zStored) compressed, %d(pct)%% of total repository space
142 @ </td></tr>
143
--- src/style.c
+++ src/style.c
@@ -1425,10 +1425,11 @@
14251425
@ border-spacing: 0;
14261426
},
14271427
{ ".brlist table th", "Branch list table headers",
14281428
@ text-align: left;
14291429
@ padding: 0px 1em 0.5ex 0px;
1430
+ @ vertical-align: bottom;
14301431
},
14311432
{ ".brlist table td", "Branch list table headers",
14321433
@ padding: 0px 2em 0px 0px;
14331434
@ white-space: nowrap;
14341435
},
14351436
--- src/style.c
+++ src/style.c
@@ -1425,10 +1425,11 @@
1425 @ border-spacing: 0;
1426 },
1427 { ".brlist table th", "Branch list table headers",
1428 @ text-align: left;
1429 @ padding: 0px 1em 0.5ex 0px;
 
1430 },
1431 { ".brlist table td", "Branch list table headers",
1432 @ padding: 0px 2em 0px 0px;
1433 @ white-space: nowrap;
1434 },
1435
--- src/style.c
+++ src/style.c
@@ -1425,10 +1425,11 @@
1425 @ border-spacing: 0;
1426 },
1427 { ".brlist table th", "Branch list table headers",
1428 @ text-align: left;
1429 @ padding: 0px 1em 0.5ex 0px;
1430 @ vertical-align: bottom;
1431 },
1432 { ".brlist table td", "Branch list table headers",
1433 @ padding: 0px 2em 0px 0px;
1434 @ white-space: nowrap;
1435 },
1436
+1
--- src/th.h
+++ src/th.h
@@ -102,10 +102,11 @@
102102
#define TH_OK 0
103103
#define TH_ERROR 1
104104
#define TH_BREAK 2
105105
#define TH_RETURN 3
106106
#define TH_CONTINUE 4
107
+#define TH_RETURN2 5
107108
108109
/*
109110
** Set and get the interpreter result.
110111
*/
111112
int Th_SetResult(Th_Interp *, const char *, int);
112113
--- src/th.h
+++ src/th.h
@@ -102,10 +102,11 @@
102 #define TH_OK 0
103 #define TH_ERROR 1
104 #define TH_BREAK 2
105 #define TH_RETURN 3
106 #define TH_CONTINUE 4
 
107
108 /*
109 ** Set and get the interpreter result.
110 */
111 int Th_SetResult(Th_Interp *, const char *, int);
112
--- src/th.h
+++ src/th.h
@@ -102,10 +102,11 @@
102 #define TH_OK 0
103 #define TH_ERROR 1
104 #define TH_BREAK 2
105 #define TH_RETURN 3
106 #define TH_CONTINUE 4
107 #define TH_RETURN2 5
108
109 /*
110 ** Set and get the interpreter result.
111 */
112 int Th_SetResult(Th_Interp *, const char *, int);
113
+51 -14
--- src/th_lang.c
+++ src/th_lang.c
@@ -433,10 +433,13 @@
433433
rc = Th_InFrame(interp, proc_call2, (void *)p, (void *)&procargs);
434434
435435
if( rc==TH_RETURN ){
436436
rc = TH_OK;
437437
}
438
+ if( rc==TH_RETURN2 ){
439
+ rc = TH_RETURN;
440
+ }
438441
return rc;
439442
}
440443
441444
/*
442445
** This function is registered as the delete callback for all commands
@@ -715,10 +718,39 @@
715718
}
716719
}
717720
718721
return Th_SetResultInt(interp, iRes);
719722
}
723
+
724
+/*
725
+** TH Syntax:
726
+**
727
+** string index STRING INDEX
728
+*/
729
+static int string_index_command(
730
+ Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
731
+){
732
+ int iIndex;
733
+
734
+ if( argc!=4 ){
735
+ return Th_WrongNumArgs(interp, "string index string index");
736
+ }
737
+
738
+ if( argl[3]==3 && 0==memcmp("end", argv[3], 3) ){
739
+ iIndex = argl[2]-1;
740
+ }else if( Th_ToInt(interp, argv[3], argl[3], &iIndex) ){
741
+ Th_ErrorMessage(
742
+ interp, "Expected \"end\" or integer, got:", argv[3], argl[3]);
743
+ return TH_ERROR;
744
+ }
745
+
746
+ if( iIndex>=0 && iIndex<argl[2] ){
747
+ return Th_SetResult(interp, &argv[2][iIndex], 1);
748
+ }else{
749
+ return Th_SetResult(interp, 0, 0);
750
+ }
751
+}
720752
721753
/*
722754
** TH Syntax:
723755
**
724756
** string is CLASS STRING
@@ -1057,33 +1089,38 @@
10571089
}
10581090
10591091
/*
10601092
** TH Syntax:
10611093
**
1062
-** string compare STR1 STR2
1063
-** string first NEEDLE HAYSTACK ?STARTINDEX?
1064
-** string is CLASS STRING
1065
-** string last NEEDLE HAYSTACK ?STARTINDEX?
1066
-** string length STRING
1067
-** string range STRING FIRST LAST
1068
-** string repeat STRING COUNT
1094
+** string compare STR1 STR2
1095
+** string first NEEDLE HAYSTACK ?STARTINDEX?
1096
+** string index STRING INDEX
1097
+** string is CLASS STRING
1098
+** string last NEEDLE HAYSTACK ?STARTINDEX?
1099
+** string length STRING
1100
+** string range STRING FIRST LAST
1101
+** string repeat STRING COUNT
1102
+** string trim STRING
1103
+** string trimleft STRING
1104
+** string trimright STRING
10691105
*/
10701106
static int string_command(
10711107
Th_Interp *interp,
10721108
void *ctx,
10731109
int argc,
10741110
const char **argv,
10751111
int *argl
10761112
){
10771113
static const Th_SubCommand aSub[] = {
1078
- { "compare", string_compare_command },
1079
- { "first", string_first_command },
1080
- { "is", string_is_command },
1081
- { "last", string_last_command },
1082
- { "length", string_length_command },
1083
- { "range", string_range_command },
1084
- { "repeat", string_repeat_command },
1114
+ { "compare", string_compare_command },
1115
+ { "first", string_first_command },
1116
+ { "index", string_index_command },
1117
+ { "is", string_is_command },
1118
+ { "last", string_last_command },
1119
+ { "length", string_length_command },
1120
+ { "range", string_range_command },
1121
+ { "repeat", string_repeat_command },
10851122
{ "trim", string_trim_command },
10861123
{ "trimleft", string_trim_command },
10871124
{ "trimright", string_trim_command },
10881125
{ 0, 0 }
10891126
};
10901127
--- src/th_lang.c
+++ src/th_lang.c
@@ -433,10 +433,13 @@
433 rc = Th_InFrame(interp, proc_call2, (void *)p, (void *)&procargs);
434
435 if( rc==TH_RETURN ){
436 rc = TH_OK;
437 }
 
 
 
438 return rc;
439 }
440
441 /*
442 ** This function is registered as the delete callback for all commands
@@ -715,10 +718,39 @@
715 }
716 }
717
718 return Th_SetResultInt(interp, iRes);
719 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
720
721 /*
722 ** TH Syntax:
723 **
724 ** string is CLASS STRING
@@ -1057,33 +1089,38 @@
1057 }
1058
1059 /*
1060 ** TH Syntax:
1061 **
1062 ** string compare STR1 STR2
1063 ** string first NEEDLE HAYSTACK ?STARTINDEX?
1064 ** string is CLASS STRING
1065 ** string last NEEDLE HAYSTACK ?STARTINDEX?
1066 ** string length STRING
1067 ** string range STRING FIRST LAST
1068 ** string repeat STRING COUNT
 
 
 
 
1069 */
1070 static int string_command(
1071 Th_Interp *interp,
1072 void *ctx,
1073 int argc,
1074 const char **argv,
1075 int *argl
1076 ){
1077 static const Th_SubCommand aSub[] = {
1078 { "compare", string_compare_command },
1079 { "first", string_first_command },
1080 { "is", string_is_command },
1081 { "last", string_last_command },
1082 { "length", string_length_command },
1083 { "range", string_range_command },
1084 { "repeat", string_repeat_command },
 
1085 { "trim", string_trim_command },
1086 { "trimleft", string_trim_command },
1087 { "trimright", string_trim_command },
1088 { 0, 0 }
1089 };
1090
--- src/th_lang.c
+++ src/th_lang.c
@@ -433,10 +433,13 @@
433 rc = Th_InFrame(interp, proc_call2, (void *)p, (void *)&procargs);
434
435 if( rc==TH_RETURN ){
436 rc = TH_OK;
437 }
438 if( rc==TH_RETURN2 ){
439 rc = TH_RETURN;
440 }
441 return rc;
442 }
443
444 /*
445 ** This function is registered as the delete callback for all commands
@@ -715,10 +718,39 @@
718 }
719 }
720
721 return Th_SetResultInt(interp, iRes);
722 }
723
724 /*
725 ** TH Syntax:
726 **
727 ** string index STRING INDEX
728 */
729 static int string_index_command(
730 Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
731 ){
732 int iIndex;
733
734 if( argc!=4 ){
735 return Th_WrongNumArgs(interp, "string index string index");
736 }
737
738 if( argl[3]==3 && 0==memcmp("end", argv[3], 3) ){
739 iIndex = argl[2]-1;
740 }else if( Th_ToInt(interp, argv[3], argl[3], &iIndex) ){
741 Th_ErrorMessage(
742 interp, "Expected \"end\" or integer, got:", argv[3], argl[3]);
743 return TH_ERROR;
744 }
745
746 if( iIndex>=0 && iIndex<argl[2] ){
747 return Th_SetResult(interp, &argv[2][iIndex], 1);
748 }else{
749 return Th_SetResult(interp, 0, 0);
750 }
751 }
752
753 /*
754 ** TH Syntax:
755 **
756 ** string is CLASS STRING
@@ -1057,33 +1089,38 @@
1089 }
1090
1091 /*
1092 ** TH Syntax:
1093 **
1094 ** string compare STR1 STR2
1095 ** string first NEEDLE HAYSTACK ?STARTINDEX?
1096 ** string index STRING INDEX
1097 ** string is CLASS STRING
1098 ** string last NEEDLE HAYSTACK ?STARTINDEX?
1099 ** string length STRING
1100 ** string range STRING FIRST LAST
1101 ** string repeat STRING COUNT
1102 ** string trim STRING
1103 ** string trimleft STRING
1104 ** string trimright STRING
1105 */
1106 static int string_command(
1107 Th_Interp *interp,
1108 void *ctx,
1109 int argc,
1110 const char **argv,
1111 int *argl
1112 ){
1113 static const Th_SubCommand aSub[] = {
1114 { "compare", string_compare_command },
1115 { "first", string_first_command },
1116 { "index", string_index_command },
1117 { "is", string_is_command },
1118 { "last", string_last_command },
1119 { "length", string_length_command },
1120 { "range", string_range_command },
1121 { "repeat", string_repeat_command },
1122 { "trim", string_trim_command },
1123 { "trimleft", string_trim_command },
1124 { "trimright", string_trim_command },
1125 { 0, 0 }
1126 };
1127
--- src/th_main.c
+++ src/th_main.c
@@ -299,10 +299,11 @@
299299
case TH_OK: return nullIfOk ? 0 : "TH_OK";
300300
case TH_ERROR: return "TH_ERROR";
301301
case TH_BREAK: return "TH_BREAK";
302302
case TH_RETURN: return "TH_RETURN";
303303
case TH_CONTINUE: return "TH_CONTINUE";
304
+ case TH_RETURN2: return "TH_RETURN2";
304305
default: {
305306
sqlite3_snprintf(sizeof(zRc), zRc, "TH1 return code %d", rc);
306307
}
307308
}
308309
return zRc;
309310
--- src/th_main.c
+++ src/th_main.c
@@ -299,10 +299,11 @@
299 case TH_OK: return nullIfOk ? 0 : "TH_OK";
300 case TH_ERROR: return "TH_ERROR";
301 case TH_BREAK: return "TH_BREAK";
302 case TH_RETURN: return "TH_RETURN";
303 case TH_CONTINUE: return "TH_CONTINUE";
 
304 default: {
305 sqlite3_snprintf(sizeof(zRc), zRc, "TH1 return code %d", rc);
306 }
307 }
308 return zRc;
309
--- src/th_main.c
+++ src/th_main.c
@@ -299,10 +299,11 @@
299 case TH_OK: return nullIfOk ? 0 : "TH_OK";
300 case TH_ERROR: return "TH_ERROR";
301 case TH_BREAK: return "TH_BREAK";
302 case TH_RETURN: return "TH_RETURN";
303 case TH_CONTINUE: return "TH_CONTINUE";
304 case TH_RETURN2: return "TH_RETURN2";
305 default: {
306 sqlite3_snprintf(sizeof(zRc), zRc, "TH1 return code %d", rc);
307 }
308 }
309 return zRc;
310
+80 -76
--- src/unversioned.c
+++ src/unversioned.c
@@ -484,86 +484,90 @@
484484
return;
485485
}
486486
if( PB("byage") ) zOrderBy = "mtime DESC";
487487
if( PB("showdel") ) showDel = 1;
488488
db_prepare(&q,
489
- "SELECT"
490
- " name,"
491
- " mtime,"
492
- " hash,"
493
- " sz,"
494
- " (SELECT login FROM rcvfrom, user"
495
- " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
496
- " rcvid"
497
- " FROM unversioned %s ORDER BY %s",
498
- showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
499
- zOrderBy/*safe-for-%s*/
500
- );
501
- iNow = db_int64(0, "SELECT strftime('%%s','now');");
502
- while( db_step(&q)==SQLITE_ROW ){
503
- const char *zName = db_column_text(&q, 0);
504
- sqlite3_int64 mtime = db_column_int(&q, 1);
505
- const char *zHash = db_column_text(&q, 2);
506
- int isDeleted = zHash==0;
507
- int fullSize = db_column_int(&q, 3);
508
- char *zAge = human_readable_age((iNow - mtime)/86400.0);
509
- const char *zLogin = db_column_text(&q, 4);
510
- int rcvid = db_column_int(&q,5);
511
- if( zLogin==0 ) zLogin = "";
512
- if( (n++)==0 ){
513
- @ <div class="uvlist">
514
- @ <table cellpadding="2" cellspacing="0" border="1" id="uvtab">
515
- @ <thead><tr>
516
- @ <th> Name
517
- @ <th> Age
518
- @ <th> Size
519
- @ <th> User
520
- @ <th> SHA1
521
- if( g.perm.Admin ){
522
- @ <th> rcvid
523
- }
524
- @ </tr></thead>
525
- @ <tbody>
526
- }
527
- @ <tr>
528
- if( isDeleted ){
529
- sqlite3_snprintf(sizeof(zSzName), zSzName, "<i>Deleted</i>");
530
- zHash = "";
531
- fullSize = 0;
532
- @ <td> %h(zName) </td>
533
- }else{
534
- approxSizeName(sizeof(zSzName), zSzName, fullSize);
535
- iTotalSz += fullSize;
536
- cnt++;
537
- @ <td> <a href='%R/uv/%T(zName)'>%h(zName)</a> </td>
538
- }
539
- @ <td data-sortkey='%016llx(-mtime)'> %s(zAge) </td>
540
- @ <td data-sortkey='%08x(fullSize)'> %s(zSzName) </td>
541
- @ <td> %h(zLogin) </td>
542
- @ <td> %h(zHash) </td>
543
- if( g.perm.Admin ){
544
- if( rcvid ){
545
- @ <td> <a href="%R/rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a>
546
- }else{
547
- @ <td>
548
- }
549
- }
550
- @ </tr>
551
- fossil_free(zAge);
552
- }
553
- db_finalize(&q);
554
- if( n ){
555
- approxSizeName(sizeof(zSzName), zSzName, iTotalSz);
556
- @ </tbody>
557
- @ <tfoot><tr><td><b>Total over %d(cnt) files</b><td><td>%s(zSzName)
558
- @ <td><td><td></tfoot>
559
- @ </table></div>
560
- output_table_sorting_javascript("uvtab","tkKttN",1);
561
- }else{
562
- @ No unversioned files on this server.
563
- }
564
- style_footer();
489
+ "SELECT"
490
+ " name,"
491
+ " mtime,"
492
+ " hash,"
493
+ " sz,"
494
+ " (SELECT login FROM rcvfrom, user"
495
+ " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
496
+ " rcvid"
497
+ " FROM unversioned %s ORDER BY %s",
498
+ showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
499
+ zOrderBy/*safe-for-%s*/
500
+ );
501
+ iNow = db_int64(0, "SELECT strftime('%%s','now');");
502
+ while( db_step(&q)==SQLITE_ROW ){
503
+ const char *zName = db_column_text(&q, 0);
504
+ sqlite3_int64 mtime = db_column_int(&q, 1);
505
+ const char *zHash = db_column_text(&q, 2);
506
+ int isDeleted = zHash==0;
507
+ int fullSize = db_column_int(&q, 3);
508
+ char *zAge = human_readable_age((iNow - mtime)/86400.0);
509
+ const char *zLogin = db_column_text(&q, 4);
510
+ int rcvid = db_column_int(&q,5);
511
+ if( zLogin==0 ) zLogin = "";
512
+ if( (n++)==0 ){
513
+ @ <div class="uvlist">
514
+ @ <table cellpadding="2" cellspacing="0" border="1" id="uvtab">
515
+ @ <thead><tr>
516
+ @ <th> Name
517
+ @ <th> Age
518
+ @ <th> Size
519
+ @ <th> User
520
+ @ <th> SHA1
521
+ if( g.perm.Admin ){
522
+ @ <th> rcvid
523
+ }
524
+ @ </tr></thead>
525
+ @ <tbody>
526
+ }
527
+ @ <tr>
528
+ if( isDeleted ){
529
+ sqlite3_snprintf(sizeof(zSzName), zSzName, "<i>Deleted</i>");
530
+ zHash = "";
531
+ fullSize = 0;
532
+ @ <td> %h(zName) </td>
533
+ }else{
534
+ approxSizeName(sizeof(zSzName), zSzName, fullSize);
535
+ iTotalSz += fullSize;
536
+ cnt++;
537
+ @ <td> <a href='%R/uv/%T(zName)'>%h(zName)</a> </td>
538
+ }
539
+ @ <td data-sortkey='%016llx(-mtime)'> %s(zAge) </td>
540
+ @ <td data-sortkey='%08x(fullSize)'> %s(zSzName) </td>
541
+ @ <td> %h(zLogin) </td>
542
+ @ <td> %h(zHash) </td>
543
+ if( g.perm.Admin ){
544
+ if( rcvid ){
545
+ @ <td> <a href="%R/rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a>
546
+ }else{
547
+ @ <td>
548
+ }
549
+ }
550
+ @ </tr>
551
+ fossil_free(zAge);
552
+ }
553
+ db_finalize(&q);
554
+ if( n ){
555
+ approxSizeName(sizeof(zSzName), zSzName, iTotalSz);
556
+ @ </tbody>
557
+ @ <tfoot><tr><td><b>Total over %d(cnt) files</b><td><td>%s(zSzName)
558
+ @ <td><td>
559
+ if( g.perm.Admin ){
560
+ @ <td>
561
+ }
562
+ @ </tfoot>
563
+ @ </table></div>
564
+ output_table_sorting_javascript("uvtab","tkKttN",1);
565
+ }else{
566
+ @ No unversioned files on this server.
567
+ }
568
+ style_footer();
565569
}
566570
567571
/*
568572
** WEBPAGE: juvlist
569573
**
570574
--- src/unversioned.c
+++ src/unversioned.c
@@ -484,86 +484,90 @@
484 return;
485 }
486 if( PB("byage") ) zOrderBy = "mtime DESC";
487 if( PB("showdel") ) showDel = 1;
488 db_prepare(&q,
489 "SELECT"
490 " name,"
491 " mtime,"
492 " hash,"
493 " sz,"
494 " (SELECT login FROM rcvfrom, user"
495 " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
496 " rcvid"
497 " FROM unversioned %s ORDER BY %s",
498 showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
499 zOrderBy/*safe-for-%s*/
500 );
501 iNow = db_int64(0, "SELECT strftime('%%s','now');");
502 while( db_step(&q)==SQLITE_ROW ){
503 const char *zName = db_column_text(&q, 0);
504 sqlite3_int64 mtime = db_column_int(&q, 1);
505 const char *zHash = db_column_text(&q, 2);
506 int isDeleted = zHash==0;
507 int fullSize = db_column_int(&q, 3);
508 char *zAge = human_readable_age((iNow - mtime)/86400.0);
509 const char *zLogin = db_column_text(&q, 4);
510 int rcvid = db_column_int(&q,5);
511 if( zLogin==0 ) zLogin = "";
512 if( (n++)==0 ){
513 @ <div class="uvlist">
514 @ <table cellpadding="2" cellspacing="0" border="1" id="uvtab">
515 @ <thead><tr>
516 @ <th> Name
517 @ <th> Age
518 @ <th> Size
519 @ <th> User
520 @ <th> SHA1
521 if( g.perm.Admin ){
522 @ <th> rcvid
523 }
524 @ </tr></thead>
525 @ <tbody>
526 }
527 @ <tr>
528 if( isDeleted ){
529 sqlite3_snprintf(sizeof(zSzName), zSzName, "<i>Deleted</i>");
530 zHash = "";
531 fullSize = 0;
532 @ <td> %h(zName) </td>
533 }else{
534 approxSizeName(sizeof(zSzName), zSzName, fullSize);
535 iTotalSz += fullSize;
536 cnt++;
537 @ <td> <a href='%R/uv/%T(zName)'>%h(zName)</a> </td>
538 }
539 @ <td data-sortkey='%016llx(-mtime)'> %s(zAge) </td>
540 @ <td data-sortkey='%08x(fullSize)'> %s(zSzName) </td>
541 @ <td> %h(zLogin) </td>
542 @ <td> %h(zHash) </td>
543 if( g.perm.Admin ){
544 if( rcvid ){
545 @ <td> <a href="%R/rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a>
546 }else{
547 @ <td>
548 }
549 }
550 @ </tr>
551 fossil_free(zAge);
552 }
553 db_finalize(&q);
554 if( n ){
555 approxSizeName(sizeof(zSzName), zSzName, iTotalSz);
556 @ </tbody>
557 @ <tfoot><tr><td><b>Total over %d(cnt) files</b><td><td>%s(zSzName)
558 @ <td><td><td></tfoot>
559 @ </table></div>
560 output_table_sorting_javascript("uvtab","tkKttN",1);
561 }else{
562 @ No unversioned files on this server.
563 }
564 style_footer();
 
 
 
 
565 }
566
567 /*
568 ** WEBPAGE: juvlist
569 **
570
--- src/unversioned.c
+++ src/unversioned.c
@@ -484,86 +484,90 @@
484 return;
485 }
486 if( PB("byage") ) zOrderBy = "mtime DESC";
487 if( PB("showdel") ) showDel = 1;
488 db_prepare(&q,
489 "SELECT"
490 " name,"
491 " mtime,"
492 " hash,"
493 " sz,"
494 " (SELECT login FROM rcvfrom, user"
495 " WHERE user.uid=rcvfrom.uid AND rcvfrom.rcvid=unversioned.rcvid),"
496 " rcvid"
497 " FROM unversioned %s ORDER BY %s",
498 showDel ? "" : "WHERE hash IS NOT NULL" /*safe-for-%s*/,
499 zOrderBy/*safe-for-%s*/
500 );
501 iNow = db_int64(0, "SELECT strftime('%%s','now');");
502 while( db_step(&q)==SQLITE_ROW ){
503 const char *zName = db_column_text(&q, 0);
504 sqlite3_int64 mtime = db_column_int(&q, 1);
505 const char *zHash = db_column_text(&q, 2);
506 int isDeleted = zHash==0;
507 int fullSize = db_column_int(&q, 3);
508 char *zAge = human_readable_age((iNow - mtime)/86400.0);
509 const char *zLogin = db_column_text(&q, 4);
510 int rcvid = db_column_int(&q,5);
511 if( zLogin==0 ) zLogin = "";
512 if( (n++)==0 ){
513 @ <div class="uvlist">
514 @ <table cellpadding="2" cellspacing="0" border="1" id="uvtab">
515 @ <thead><tr>
516 @ <th> Name
517 @ <th> Age
518 @ <th> Size
519 @ <th> User
520 @ <th> SHA1
521 if( g.perm.Admin ){
522 @ <th> rcvid
523 }
524 @ </tr></thead>
525 @ <tbody>
526 }
527 @ <tr>
528 if( isDeleted ){
529 sqlite3_snprintf(sizeof(zSzName), zSzName, "<i>Deleted</i>");
530 zHash = "";
531 fullSize = 0;
532 @ <td> %h(zName) </td>
533 }else{
534 approxSizeName(sizeof(zSzName), zSzName, fullSize);
535 iTotalSz += fullSize;
536 cnt++;
537 @ <td> <a href='%R/uv/%T(zName)'>%h(zName)</a> </td>
538 }
539 @ <td data-sortkey='%016llx(-mtime)'> %s(zAge) </td>
540 @ <td data-sortkey='%08x(fullSize)'> %s(zSzName) </td>
541 @ <td> %h(zLogin) </td>
542 @ <td> %h(zHash) </td>
543 if( g.perm.Admin ){
544 if( rcvid ){
545 @ <td> <a href="%R/rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a>
546 }else{
547 @ <td>
548 }
549 }
550 @ </tr>
551 fossil_free(zAge);
552 }
553 db_finalize(&q);
554 if( n ){
555 approxSizeName(sizeof(zSzName), zSzName, iTotalSz);
556 @ </tbody>
557 @ <tfoot><tr><td><b>Total over %d(cnt) files</b><td><td>%s(zSzName)
558 @ <td><td>
559 if( g.perm.Admin ){
560 @ <td>
561 }
562 @ </tfoot>
563 @ </table></div>
564 output_table_sorting_javascript("uvtab","tkKttN",1);
565 }else{
566 @ No unversioned files on this server.
567 }
568 style_footer();
569 }
570
571 /*
572 ** WEBPAGE: juvlist
573 **
574
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -70,11 +70,11 @@
7070
} elseif {$::cmd_name eq "test3"} {
7171
emit_hook_log
7272
break "TH_BREAK return code"
7373
} elseif {$::cmd_name eq "test4"} {
7474
emit_hook_log
75
- return -code 2 "TH_RETURN return code"
75
+ return -code 5 "TH_RETURN return code"
7676
} elseif {$::cmd_name eq "timeline"} {
7777
set length [llength $::cmd_args]
7878
set length [expr {$length - 1}]
7979
if {[lindex $::cmd_args $length] eq "custom"} {
8080
append_hook_log "CUSTOM TIMELINE"
@@ -82,10 +82,13 @@
8282
return "custom timeline"
8383
} elseif {[lindex $::cmd_args $length] eq "custom2"} {
8484
emit_hook_log
8585
puts "+++ some stuff here +++"
8686
continue "custom2 timeline"
87
+ } elseif {[lindex $::cmd_args $length] eq "custom3"} {
88
+ emit_hook_log
89
+ return -code 5 "TH_RETURN return code"
8790
} elseif {[lindex $::cmd_args $length] eq "now"} {
8891
emit_hook_log
8992
return "now timeline"
9093
} else {
9194
emit_hook_log
@@ -142,10 +145,18 @@
142145
+++ some stuff here +++
143146
<h1><b>command_hook timeline command_notify timeline</b></h1>}}
144147
145148
###############################################################################
146149
150
+fossil timeline custom3; # NOTE: Bad "WHEN" argument.
151
+
152
+test th1-cmd-hooks-1c {[normalize_result] eq \
153
+{<h1><b>command_hook timeline</b></h1>
154
+unknown check-in or invalid date: custom3}}
155
+
156
+###############################################################################
157
+
147158
fossil timeline
148159
test th1-cmd-hooks-2a {[first_data_line] eq \
149160
{<h1><b>command_hook timeline</b></h1>}}
150161
151162
test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
@@ -185,13 +196,20 @@
185196
{<h1><b>command_hook test3</b></h1>}}
186197
187198
###############################################################################
188199
189200
fossil test4
190
-test th1-custom-cmd-4a {[string trim $RESULT] eq \
201
+
202
+test th1-custom-cmd-4a {[first_data_line] eq \
191203
{<h1><b>command_hook test4</b></h1>}}
192204
205
+test th1-custom-cmd-4b {[regexp -- \
206
+ {: unknown command: test4$} [second_data_line]]}
207
+
208
+test th1-custom-cmd-4d {[regexp -- \
209
+ {: use "help" for more information$} [third_data_line]]}
210
+
193211
###############################################################################
194212
195213
set RESULT [test_fossil_http $repository $dataFileName /timeline]
196214
197215
test th1-web-hooks-1a {[regexp \
198216
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -70,11 +70,11 @@
70 } elseif {$::cmd_name eq "test3"} {
71 emit_hook_log
72 break "TH_BREAK return code"
73 } elseif {$::cmd_name eq "test4"} {
74 emit_hook_log
75 return -code 2 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
80 append_hook_log "CUSTOM TIMELINE"
@@ -82,10 +82,13 @@
82 return "custom timeline"
83 } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84 emit_hook_log
85 puts "+++ some stuff here +++"
86 continue "custom2 timeline"
 
 
 
87 } elseif {[lindex $::cmd_args $length] eq "now"} {
88 emit_hook_log
89 return "now timeline"
90 } else {
91 emit_hook_log
@@ -142,10 +145,18 @@
142 +++ some stuff here +++
143 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
144
145 ###############################################################################
146
 
 
 
 
 
 
 
 
147 fossil timeline
148 test th1-cmd-hooks-2a {[first_data_line] eq \
149 {<h1><b>command_hook timeline</b></h1>}}
150
151 test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
@@ -185,13 +196,20 @@
185 {<h1><b>command_hook test3</b></h1>}}
186
187 ###############################################################################
188
189 fossil test4
190 test th1-custom-cmd-4a {[string trim $RESULT] eq \
 
191 {<h1><b>command_hook test4</b></h1>}}
192
 
 
 
 
 
 
193 ###############################################################################
194
195 set RESULT [test_fossil_http $repository $dataFileName /timeline]
196
197 test th1-web-hooks-1a {[regexp \
198
--- test/th1-hooks.test
+++ test/th1-hooks.test
@@ -70,11 +70,11 @@
70 } elseif {$::cmd_name eq "test3"} {
71 emit_hook_log
72 break "TH_BREAK return code"
73 } elseif {$::cmd_name eq "test4"} {
74 emit_hook_log
75 return -code 5 "TH_RETURN return code"
76 } elseif {$::cmd_name eq "timeline"} {
77 set length [llength $::cmd_args]
78 set length [expr {$length - 1}]
79 if {[lindex $::cmd_args $length] eq "custom"} {
80 append_hook_log "CUSTOM TIMELINE"
@@ -82,10 +82,13 @@
82 return "custom timeline"
83 } elseif {[lindex $::cmd_args $length] eq "custom2"} {
84 emit_hook_log
85 puts "+++ some stuff here +++"
86 continue "custom2 timeline"
87 } elseif {[lindex $::cmd_args $length] eq "custom3"} {
88 emit_hook_log
89 return -code 5 "TH_RETURN return code"
90 } elseif {[lindex $::cmd_args $length] eq "now"} {
91 emit_hook_log
92 return "now timeline"
93 } else {
94 emit_hook_log
@@ -142,10 +145,18 @@
145 +++ some stuff here +++
146 <h1><b>command_hook timeline command_notify timeline</b></h1>}}
147
148 ###############################################################################
149
150 fossil timeline custom3; # NOTE: Bad "WHEN" argument.
151
152 test th1-cmd-hooks-1c {[normalize_result] eq \
153 {<h1><b>command_hook timeline</b></h1>
154 unknown check-in or invalid date: custom3}}
155
156 ###############################################################################
157
158 fossil timeline
159 test th1-cmd-hooks-2a {[first_data_line] eq \
160 {<h1><b>command_hook timeline</b></h1>}}
161
162 test th1-cmd-hooks-2b {[second_data_line] eq {ERROR: unsupported timeline}}
@@ -185,13 +196,20 @@
196 {<h1><b>command_hook test3</b></h1>}}
197
198 ###############################################################################
199
200 fossil test4
201
202 test th1-custom-cmd-4a {[first_data_line] eq \
203 {<h1><b>command_hook test4</b></h1>}}
204
205 test th1-custom-cmd-4b {[regexp -- \
206 {: unknown command: test4$} [second_data_line]]}
207
208 test th1-custom-cmd-4d {[regexp -- \
209 {: use "help" for more information$} [third_data_line]]}
210
211 ###############################################################################
212
213 set RESULT [test_fossil_http $repository $dataFileName /timeline]
214
215 test th1-web-hooks-1a {[regexp \
216
--- test/th1.test
+++ test/th1.test
@@ -1433,10 +1433,85 @@
14331433
14341434
###############################################################################
14351435
14361436
fossil test-th-eval {string is integer 0xC0DEF00Z}
14371437
test th1-string-is-31 {$RESULT eq "0"}
1438
+
1439
+###############################################################################
1440
+
1441
+fossil test-th-eval {string index "" -1}
1442
+test th1-string-index-1 {$RESULT eq ""}
1443
+
1444
+###############################################################################
1445
+
1446
+fossil test-th-eval {string index "" 0}
1447
+test th1-string-index-2 {$RESULT eq ""}
1448
+
1449
+###############################################################################
1450
+
1451
+fossil test-th-eval {string index "" 1}
1452
+test th1-string-index-3 {$RESULT eq ""}
1453
+
1454
+###############################################################################
1455
+
1456
+fossil test-th-eval {string index "" 2}
1457
+test th1-string-index-4 {$RESULT eq ""}
1458
+
1459
+###############################################################################
1460
+
1461
+fossil test-th-eval {string index "" end}
1462
+test th1-string-index-5 {$RESULT eq ""}
1463
+
1464
+###############################################################################
1465
+
1466
+fossil test-th-eval {string index A -1}
1467
+test th1-string-index-6 {$RESULT eq ""}
1468
+
1469
+###############################################################################
1470
+
1471
+fossil test-th-eval {string index A 0}
1472
+test th1-string-index-7 {$RESULT eq "A"}
1473
+
1474
+###############################################################################
1475
+
1476
+fossil test-th-eval {string index A 1}
1477
+test th1-string-index-8 {$RESULT eq ""}
1478
+
1479
+###############################################################################
1480
+
1481
+fossil test-th-eval {string index A 2}
1482
+test th1-string-index-9 {$RESULT eq ""}
1483
+
1484
+###############################################################################
1485
+
1486
+fossil test-th-eval {string index A end}
1487
+test th1-string-index-10 {$RESULT eq "A"}
1488
+
1489
+###############################################################################
1490
+
1491
+fossil test-th-eval {string index ABC -1}
1492
+test th1-string-index-11 {$RESULT eq ""}
1493
+
1494
+###############################################################################
1495
+
1496
+fossil test-th-eval {string index ABC 0}
1497
+test th1-string-index-12 {$RESULT eq "A"}
1498
+
1499
+###############################################################################
1500
+
1501
+fossil test-th-eval {string index ABC 1}
1502
+test th1-string-index-13 {$RESULT eq "B"}
1503
+
1504
+###############################################################################
1505
+
1506
+fossil test-th-eval {string index ABC 2}
1507
+test th1-string-index-14 {$RESULT eq "C"}
1508
+
1509
+###############################################################################
1510
+
1511
+fossil test-th-eval {string index ABC end}
1512
+test th1-string-index-15 {$RESULT eq "C"}
14381513
14391514
###############################################################################
14401515
14411516
fossil test-th-eval {markdown}
14421517
test th1-markdown-1 {$RESULT eq \
14431518
--- test/th1.test
+++ test/th1.test
@@ -1433,10 +1433,85 @@
1433
1434 ###############################################################################
1435
1436 fossil test-th-eval {string is integer 0xC0DEF00Z}
1437 test th1-string-is-31 {$RESULT eq "0"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1438
1439 ###############################################################################
1440
1441 fossil test-th-eval {markdown}
1442 test th1-markdown-1 {$RESULT eq \
1443
--- test/th1.test
+++ test/th1.test
@@ -1433,10 +1433,85 @@
1433
1434 ###############################################################################
1435
1436 fossil test-th-eval {string is integer 0xC0DEF00Z}
1437 test th1-string-is-31 {$RESULT eq "0"}
1438
1439 ###############################################################################
1440
1441 fossil test-th-eval {string index "" -1}
1442 test th1-string-index-1 {$RESULT eq ""}
1443
1444 ###############################################################################
1445
1446 fossil test-th-eval {string index "" 0}
1447 test th1-string-index-2 {$RESULT eq ""}
1448
1449 ###############################################################################
1450
1451 fossil test-th-eval {string index "" 1}
1452 test th1-string-index-3 {$RESULT eq ""}
1453
1454 ###############################################################################
1455
1456 fossil test-th-eval {string index "" 2}
1457 test th1-string-index-4 {$RESULT eq ""}
1458
1459 ###############################################################################
1460
1461 fossil test-th-eval {string index "" end}
1462 test th1-string-index-5 {$RESULT eq ""}
1463
1464 ###############################################################################
1465
1466 fossil test-th-eval {string index A -1}
1467 test th1-string-index-6 {$RESULT eq ""}
1468
1469 ###############################################################################
1470
1471 fossil test-th-eval {string index A 0}
1472 test th1-string-index-7 {$RESULT eq "A"}
1473
1474 ###############################################################################
1475
1476 fossil test-th-eval {string index A 1}
1477 test th1-string-index-8 {$RESULT eq ""}
1478
1479 ###############################################################################
1480
1481 fossil test-th-eval {string index A 2}
1482 test th1-string-index-9 {$RESULT eq ""}
1483
1484 ###############################################################################
1485
1486 fossil test-th-eval {string index A end}
1487 test th1-string-index-10 {$RESULT eq "A"}
1488
1489 ###############################################################################
1490
1491 fossil test-th-eval {string index ABC -1}
1492 test th1-string-index-11 {$RESULT eq ""}
1493
1494 ###############################################################################
1495
1496 fossil test-th-eval {string index ABC 0}
1497 test th1-string-index-12 {$RESULT eq "A"}
1498
1499 ###############################################################################
1500
1501 fossil test-th-eval {string index ABC 1}
1502 test th1-string-index-13 {$RESULT eq "B"}
1503
1504 ###############################################################################
1505
1506 fossil test-th-eval {string index ABC 2}
1507 test th1-string-index-14 {$RESULT eq "C"}
1508
1509 ###############################################################################
1510
1511 fossil test-th-eval {string index ABC end}
1512 test th1-string-index-15 {$RESULT eq "C"}
1513
1514 ###############################################################################
1515
1516 fossil test-th-eval {markdown}
1517 test th1-markdown-1 {$RESULT eq \
1518
--- www/index.wiki
+++ www/index.wiki
@@ -127,10 +127,12 @@
127127
[http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language],
128128
used to customize [./custom_ticket.wiki | ticketing], and several other
129129
subsystems, including [./customskin.md | theming].
130130
* List of [./th1.md | TH1 commands provided by Fossil itself] that expose
131131
its key functionality to TH1 scripts.
132
+ * List of [./th1-hooks.md | TH1 hooks exposed by Fossil] that enable
133
+ customization of commands and web pages.
132134
* A free hosting server for Fossil repositories is available at
133135
[http://chiselapp.com/].
134136
* How to [./server.wiki | set up a server] for your repository.
135137
* Customizing the [./custom_ticket.wiki | ticket system].
136138
* Methods to [./checkin_names.wiki | identify a specific check-in].
137139
138140
ADDED www/th1-hooks.md
--- www/index.wiki
+++ www/index.wiki
@@ -127,10 +127,12 @@
127 [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language],
128 used to customize [./custom_ticket.wiki | ticketing], and several other
129 subsystems, including [./customskin.md | theming].
130 * List of [./th1.md | TH1 commands provided by Fossil itself] that expose
131 its key functionality to TH1 scripts.
 
 
132 * A free hosting server for Fossil repositories is available at
133 [http://chiselapp.com/].
134 * How to [./server.wiki | set up a server] for your repository.
135 * Customizing the [./custom_ticket.wiki | ticket system].
136 * Methods to [./checkin_names.wiki | identify a specific check-in].
137
138 DDED www/th1-hooks.md
--- www/index.wiki
+++ www/index.wiki
@@ -127,10 +127,12 @@
127 [http://www.sqliteconcepts.org/THManual.pdf | TH1 scripting language],
128 used to customize [./custom_ticket.wiki | ticketing], and several other
129 subsystems, including [./customskin.md | theming].
130 * List of [./th1.md | TH1 commands provided by Fossil itself] that expose
131 its key functionality to TH1 scripts.
132 * List of [./th1-hooks.md | TH1 hooks exposed by Fossil] that enable
133 customization of commands and web pages.
134 * A free hosting server for Fossil repositories is available at
135 [http://chiselapp.com/].
136 * How to [./server.wiki | set up a server] for your repository.
137 * Customizing the [./custom_ticket.wiki | ticket system].
138 * Methods to [./checkin_names.wiki | identify a specific check-in].
139
140 DDED www/th1-hooks.md
--- a/www/th1-hooks.md
+++ b/www/th1-hooks.md
@@ -0,0 +1,6 @@
1
+TH1 Hooks
2
+=========
3
+
4
+<big><big><big><font color="red">** DRAFT **</font></big></big></big>
5
+
6
+The **
--- a/www/th1-hooks.md
+++ b/www/th1-hooks.md
@@ -0,0 +1,6 @@
 
 
 
 
 
 
--- a/www/th1-hooks.md
+++ b/www/th1-hooks.md
@@ -0,0 +1,6 @@
1 TH1 Hooks
2 =========
3
4 <big><big><big><font color="red">** DRAFT **</font></big></big></big>
5
6 The **
+1
--- www/th1.md
+++ www/th1.md
@@ -105,10 +105,11 @@
105105
* rename OLD NEW
106106
* return ?-code CODE? ?VALUE?
107107
* set VARNAME VALUE
108108
* string compare STR1 STR2
109109
* string first NEEDLE HAYSTACK ?START-INDEX?
110
+ * string index STRING INDEX
110111
* string is CLASS STRING
111112
* string last NEEDLE HAYSTACK ?START-INDEX?
112113
* string length STRING
113114
* string range STRING FIRST LAST
114115
* string repeat STRING COUNT
115116
--- www/th1.md
+++ www/th1.md
@@ -105,10 +105,11 @@
105 * rename OLD NEW
106 * return ?-code CODE? ?VALUE?
107 * set VARNAME VALUE
108 * string compare STR1 STR2
109 * string first NEEDLE HAYSTACK ?START-INDEX?
 
110 * string is CLASS STRING
111 * string last NEEDLE HAYSTACK ?START-INDEX?
112 * string length STRING
113 * string range STRING FIRST LAST
114 * string repeat STRING COUNT
115
--- www/th1.md
+++ www/th1.md
@@ -105,10 +105,11 @@
105 * rename OLD NEW
106 * return ?-code CODE? ?VALUE?
107 * set VARNAME VALUE
108 * string compare STR1 STR2
109 * string first NEEDLE HAYSTACK ?START-INDEX?
110 * string index STRING INDEX
111 * string is CLASS STRING
112 * string last NEEDLE HAYSTACK ?START-INDEX?
113 * string length STRING
114 * string range STRING FIRST LAST
115 * string repeat STRING COUNT
116

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button