Fossil SCM

Bring up-to-date with latest features/fixes from trunk.

andybradford 2014-03-06 14:54 http-auth merge
Commit d6259b7582d57f4e5d68feb06282b1605f2ce02e
+7 -38
--- src/blob.c
+++ src/blob.c
@@ -786,48 +786,17 @@
786786
return nWrote;
787787
}
788788
#endif
789789
fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
790790
}else{
791
- int i, nName;
792
- char *zName, zBuf[1000];
793
-
794
- nName = strlen(zFilename);
795
- if( nName>=sizeof(zBuf) ){
796
- zName = mprintf("%s", zFilename);
797
- }else{
798
- zName = zBuf;
799
- memcpy(zName, zFilename, nName+1);
800
- }
801
- nName = file_simplify_name(zName, nName, 0);
802
- for(i=1; i<nName; i++){
803
- if( zName[i]=='/' ){
804
- zName[i] = 0;
805
-#if defined(_WIN32) || defined(__CYGWIN__)
806
- /*
807
- ** On Windows, local path looks like: C:/develop/project/file.txt
808
- ** The if stops us from trying to create a directory of a drive letter
809
- ** C: in this example.
810
- */
811
- if( !(i==2 && zName[1]==':') ){
812
-#endif
813
- if( file_mkdir(zName, 1) && file_isdir(zName)!=1 ){
814
- fossil_fatal_recursive("unable to create directory %s", zName);
815
- return 0;
816
- }
817
-#if defined(_WIN32) || defined(__CYGWIN__)
818
- }
819
-#endif
820
- zName[i] = '/';
821
- }
822
- }
823
- out = fossil_fopen(zName, "wb");
824
- if( out==0 ){
825
- fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
826
- return 0;
827
- }
828
- if( zName!=zBuf ) free(zName);
791
+ file_mkfolder(zFilename, 1);
792
+ out = fossil_fopen(zFilename, "wb");
793
+ if( out==0 ){
794
+ fossil_fatal_recursive("unable to open file \"%s\" for writing",
795
+ zFilename);
796
+ return 0;
797
+ }
829798
blob_is_init(pBlob);
830799
nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
831800
fclose(out);
832801
if( nWrote!=blob_size(pBlob) ){
833802
fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
834803
--- src/blob.c
+++ src/blob.c
@@ -786,48 +786,17 @@
786 return nWrote;
787 }
788 #endif
789 fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
790 }else{
791 int i, nName;
792 char *zName, zBuf[1000];
793
794 nName = strlen(zFilename);
795 if( nName>=sizeof(zBuf) ){
796 zName = mprintf("%s", zFilename);
797 }else{
798 zName = zBuf;
799 memcpy(zName, zFilename, nName+1);
800 }
801 nName = file_simplify_name(zName, nName, 0);
802 for(i=1; i<nName; i++){
803 if( zName[i]=='/' ){
804 zName[i] = 0;
805 #if defined(_WIN32) || defined(__CYGWIN__)
806 /*
807 ** On Windows, local path looks like: C:/develop/project/file.txt
808 ** The if stops us from trying to create a directory of a drive letter
809 ** C: in this example.
810 */
811 if( !(i==2 && zName[1]==':') ){
812 #endif
813 if( file_mkdir(zName, 1) && file_isdir(zName)!=1 ){
814 fossil_fatal_recursive("unable to create directory %s", zName);
815 return 0;
816 }
817 #if defined(_WIN32) || defined(__CYGWIN__)
818 }
819 #endif
820 zName[i] = '/';
821 }
822 }
823 out = fossil_fopen(zName, "wb");
824 if( out==0 ){
825 fossil_fatal_recursive("unable to open file \"%s\" for writing", zName);
826 return 0;
827 }
828 if( zName!=zBuf ) free(zName);
829 blob_is_init(pBlob);
830 nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
831 fclose(out);
832 if( nWrote!=blob_size(pBlob) ){
833 fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
834
--- src/blob.c
+++ src/blob.c
@@ -786,48 +786,17 @@
786 return nWrote;
787 }
788 #endif
789 fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
790 }else{
791 file_mkfolder(zFilename, 1);
792 out = fossil_fopen(zFilename, "wb");
793 if( out==0 ){
794 fossil_fatal_recursive("unable to open file \"%s\" for writing",
795 zFilename);
796 return 0;
797 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
798 blob_is_init(pBlob);
799 nWrote = fwrite(blob_buffer(pBlob), 1, blob_size(pBlob), out);
800 fclose(out);
801 if( nWrote!=blob_size(pBlob) ){
802 fossil_fatal_recursive("short write: %d of %d bytes to %s", nWrote,
803
+11 -5
--- src/browse.c
+++ src/browse.c
@@ -732,20 +732,22 @@
732732
733733
/*
734734
** Look at all file containing in the version "vid". Construct a
735735
** temporary table named "fileage" that contains the file-id for each
736736
** files, the pathname, the check-in where the file was added, and the
737
-** mtime on that checkin.
737
+** mtime on that checkin. If zGlob and *zGlob then only files matching
738
+** the given glob are computed.
738739
*/
739
-int compute_fileage(int vid){
740
+int compute_fileage(int vid, char const * zGlob){
740741
Manifest *pManifest;
741742
ManifestFile *pFile;
742743
int nFile = 0;
743744
double vmtime;
744745
Stmt ins;
745746
Stmt q1, q2, q3;
746747
Stmt upd;
748
+ if(zGlob && !*zGlob) zGlob = NULL;
747749
db_multi_exec(
748750
/*"DROP TABLE IF EXISTS temp.fileage;"*/
749751
"CREATE TEMP TABLE fileage("
750752
" fid INTEGER,"
751753
" mid INTEGER,"
@@ -760,10 +762,11 @@
760762
db_prepare(&ins,
761763
"INSERT INTO temp.fileage(fid, pathname)"
762764
" SELECT rid, :path FROM blob WHERE uuid=:uuid"
763765
);
764766
while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
767
+ if(zGlob && !strglob(zGlob, pFile->zName)) continue;
765768
db_bind_text(&ins, ":uuid", pFile->zUuid);
766769
db_bind_text(&ins, ":path", pFile->zName);
767770
db_step(&ins);
768771
db_reset(&ins);
769772
nFile++;
@@ -807,20 +810,22 @@
807810
808811
/*
809812
** WEBPAGE: fileage
810813
**
811814
** Parameters:
812
-** name=VERSION
815
+** name=VERSION Selects the checkin version (default=tip).
816
+** glob=STRING Only shows files matching this glob pattern
817
+** (e.g. *.c or *.txt).
813818
*/
814819
void fileage_page(void){
815820
int rid;
816821
const char *zName;
817822
char *zBaseTime;
823
+ char const * zGlob;
818824
Stmt q;
819825
double baseTime;
820826
int lastMid = -1;
821
-
822827
login_check_credentials();
823828
if( !g.perm.Read ){ login_needed(); return; }
824829
zName = P("name");
825830
if( zName==0 ) zName = "tip";
826831
rid = symbolic_name_to_rid(zName, "ci");
@@ -827,11 +832,12 @@
827832
if( rid==0 ){
828833
fossil_fatal("not a valid check-in: %s", zName);
829834
}
830835
style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
831836
style_header("File Ages", zName);
832
- compute_fileage(rid);
837
+ zGlob = P("glob");
838
+ compute_fileage(rid,zGlob);
833839
baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
834840
zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
835841
@ <h2>File Ages For Check-in
836842
@ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
837843
@
838844
--- src/browse.c
+++ src/browse.c
@@ -732,20 +732,22 @@
732
733 /*
734 ** Look at all file containing in the version "vid". Construct a
735 ** temporary table named "fileage" that contains the file-id for each
736 ** files, the pathname, the check-in where the file was added, and the
737 ** mtime on that checkin.
 
738 */
739 int compute_fileage(int vid){
740 Manifest *pManifest;
741 ManifestFile *pFile;
742 int nFile = 0;
743 double vmtime;
744 Stmt ins;
745 Stmt q1, q2, q3;
746 Stmt upd;
 
747 db_multi_exec(
748 /*"DROP TABLE IF EXISTS temp.fileage;"*/
749 "CREATE TEMP TABLE fileage("
750 " fid INTEGER,"
751 " mid INTEGER,"
@@ -760,10 +762,11 @@
760 db_prepare(&ins,
761 "INSERT INTO temp.fileage(fid, pathname)"
762 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
763 );
764 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
 
765 db_bind_text(&ins, ":uuid", pFile->zUuid);
766 db_bind_text(&ins, ":path", pFile->zName);
767 db_step(&ins);
768 db_reset(&ins);
769 nFile++;
@@ -807,20 +810,22 @@
807
808 /*
809 ** WEBPAGE: fileage
810 **
811 ** Parameters:
812 ** name=VERSION
 
 
813 */
814 void fileage_page(void){
815 int rid;
816 const char *zName;
817 char *zBaseTime;
 
818 Stmt q;
819 double baseTime;
820 int lastMid = -1;
821
822 login_check_credentials();
823 if( !g.perm.Read ){ login_needed(); return; }
824 zName = P("name");
825 if( zName==0 ) zName = "tip";
826 rid = symbolic_name_to_rid(zName, "ci");
@@ -827,11 +832,12 @@
827 if( rid==0 ){
828 fossil_fatal("not a valid check-in: %s", zName);
829 }
830 style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
831 style_header("File Ages", zName);
832 compute_fileage(rid);
 
833 baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
834 zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
835 @ <h2>File Ages For Check-in
836 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
837 @
838
--- src/browse.c
+++ src/browse.c
@@ -732,20 +732,22 @@
732
733 /*
734 ** Look at all file containing in the version "vid". Construct a
735 ** temporary table named "fileage" that contains the file-id for each
736 ** files, the pathname, the check-in where the file was added, and the
737 ** mtime on that checkin. If zGlob and *zGlob then only files matching
738 ** the given glob are computed.
739 */
740 int compute_fileage(int vid, char const * zGlob){
741 Manifest *pManifest;
742 ManifestFile *pFile;
743 int nFile = 0;
744 double vmtime;
745 Stmt ins;
746 Stmt q1, q2, q3;
747 Stmt upd;
748 if(zGlob && !*zGlob) zGlob = NULL;
749 db_multi_exec(
750 /*"DROP TABLE IF EXISTS temp.fileage;"*/
751 "CREATE TEMP TABLE fileage("
752 " fid INTEGER,"
753 " mid INTEGER,"
@@ -760,10 +762,11 @@
762 db_prepare(&ins,
763 "INSERT INTO temp.fileage(fid, pathname)"
764 " SELECT rid, :path FROM blob WHERE uuid=:uuid"
765 );
766 while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
767 if(zGlob && !strglob(zGlob, pFile->zName)) continue;
768 db_bind_text(&ins, ":uuid", pFile->zUuid);
769 db_bind_text(&ins, ":path", pFile->zName);
770 db_step(&ins);
771 db_reset(&ins);
772 nFile++;
@@ -807,20 +810,22 @@
810
811 /*
812 ** WEBPAGE: fileage
813 **
814 ** Parameters:
815 ** name=VERSION Selects the checkin version (default=tip).
816 ** glob=STRING Only shows files matching this glob pattern
817 ** (e.g. *.c or *.txt).
818 */
819 void fileage_page(void){
820 int rid;
821 const char *zName;
822 char *zBaseTime;
823 char const * zGlob;
824 Stmt q;
825 double baseTime;
826 int lastMid = -1;
 
827 login_check_credentials();
828 if( !g.perm.Read ){ login_needed(); return; }
829 zName = P("name");
830 if( zName==0 ) zName = "tip";
831 rid = symbolic_name_to_rid(zName, "ci");
@@ -827,11 +832,12 @@
832 if( rid==0 ){
833 fossil_fatal("not a valid check-in: %s", zName);
834 }
835 style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName);
836 style_header("File Ages", zName);
837 zGlob = P("glob");
838 compute_fileage(rid,zGlob);
839 baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
840 zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc());
841 @ <h2>File Ages For Check-in
842 @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2>
843 @
844
+2 -2
--- src/checkin.c
+++ src/checkin.c
@@ -1560,11 +1560,11 @@
15601560
** should be committed.
15611561
*/
15621562
if( select_commit_files() ){
15631563
prompt_user("continue (y/N)? ", &ans);
15641564
cReply = blob_str(&ans)[0];
1565
- if( cReply!='y' && cReply!='Y' ) fossil_exit(1);;
1565
+ if( cReply!='y' && cReply!='Y' ) fossil_exit(1);
15661566
}
15671567
isAMerge = db_exists("SELECT 1 FROM vmerge WHERE id=0 OR id<-2");
15681568
if( g.aCommitFile && isAMerge ){
15691569
fossil_fatal("cannot do a partial commit of a merge");
15701570
}
@@ -1660,11 +1660,11 @@
16601660
char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
16611661
prepare_commit_comment(&comment, zInit, &sCiInfo, vid);
16621662
if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
16631663
prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
16641664
cReply = blob_str(&ans)[0];
1665
- if( cReply!='y' && cReply!='Y' ) fossil_exit(1);;
1665
+ if( cReply!='y' && cReply!='Y' ) fossil_exit(1);
16661666
}
16671667
free(zInit);
16681668
}
16691669
if( blob_size(&comment)==0 ){
16701670
if( !dryRunFlag ){
16711671
--- src/checkin.c
+++ src/checkin.c
@@ -1560,11 +1560,11 @@
1560 ** should be committed.
1561 */
1562 if( select_commit_files() ){
1563 prompt_user("continue (y/N)? ", &ans);
1564 cReply = blob_str(&ans)[0];
1565 if( cReply!='y' && cReply!='Y' ) fossil_exit(1);;
1566 }
1567 isAMerge = db_exists("SELECT 1 FROM vmerge WHERE id=0 OR id<-2");
1568 if( g.aCommitFile && isAMerge ){
1569 fossil_fatal("cannot do a partial commit of a merge");
1570 }
@@ -1660,11 +1660,11 @@
1660 char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
1661 prepare_commit_comment(&comment, zInit, &sCiInfo, vid);
1662 if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
1663 prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
1664 cReply = blob_str(&ans)[0];
1665 if( cReply!='y' && cReply!='Y' ) fossil_exit(1);;
1666 }
1667 free(zInit);
1668 }
1669 if( blob_size(&comment)==0 ){
1670 if( !dryRunFlag ){
1671
--- src/checkin.c
+++ src/checkin.c
@@ -1560,11 +1560,11 @@
1560 ** should be committed.
1561 */
1562 if( select_commit_files() ){
1563 prompt_user("continue (y/N)? ", &ans);
1564 cReply = blob_str(&ans)[0];
1565 if( cReply!='y' && cReply!='Y' ) fossil_exit(1);
1566 }
1567 isAMerge = db_exists("SELECT 1 FROM vmerge WHERE id=0 OR id<-2");
1568 if( g.aCommitFile && isAMerge ){
1569 fossil_fatal("cannot do a partial commit of a merge");
1570 }
@@ -1660,11 +1660,11 @@
1660 char *zInit = db_text(0, "SELECT value FROM vvar WHERE name='ci-comment'");
1661 prepare_commit_comment(&comment, zInit, &sCiInfo, vid);
1662 if( zInit && zInit[0] && fossil_strcmp(zInit, blob_str(&comment))==0 ){
1663 prompt_user("unchanged check-in comment. continue (y/N)? ", &ans);
1664 cReply = blob_str(&ans)[0];
1665 if( cReply!='y' && cReply!='Y' ) fossil_exit(1);
1666 }
1667 free(zInit);
1668 }
1669 if( blob_size(&comment)==0 ){
1670 if( !dryRunFlag ){
1671
+3 -3
--- src/checkout.c
+++ src/checkout.c
@@ -157,11 +157,11 @@
157157
zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
158158
file_delete(zManFile);
159159
free(zManFile);
160160
}
161161
}
162
-
162
+
163163
}
164164
165165
/*
166166
** COMMAND: checkout*
167167
** COMMAND: co*
@@ -175,11 +175,11 @@
175175
** leaves files on disk unchanged, except the manifest and manifest.uuid
176176
** files.
177177
**
178178
** The --latest flag can be used in place of VERSION to checkout the
179179
** latest version in the repository.
180
-**
180
+**
181181
** Options:
182182
** --force Ignore edited files in the current checkout
183183
** --keep Only update the manifest and manifest.uuid files
184184
**
185185
** See also: update
@@ -190,11 +190,11 @@
190190
int latestFlag; /* Checkout the latest version */
191191
char *zVers; /* Version to checkout */
192192
int promptFlag; /* True to prompt before overwriting */
193193
int vid, prior;
194194
Blob cksum1, cksum1b, cksum2;
195
-
195
+
196196
db_must_be_within_tree();
197197
db_begin_transaction();
198198
forceFlag = find_option("force","f",0)!=0;
199199
keepFlag = find_option("keep",0,0)!=0;
200200
latestFlag = find_option("latest",0,0)!=0;
201201
--- src/checkout.c
+++ src/checkout.c
@@ -157,11 +157,11 @@
157 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
158 file_delete(zManFile);
159 free(zManFile);
160 }
161 }
162
163 }
164
165 /*
166 ** COMMAND: checkout*
167 ** COMMAND: co*
@@ -175,11 +175,11 @@
175 ** leaves files on disk unchanged, except the manifest and manifest.uuid
176 ** files.
177 **
178 ** The --latest flag can be used in place of VERSION to checkout the
179 ** latest version in the repository.
180 **
181 ** Options:
182 ** --force Ignore edited files in the current checkout
183 ** --keep Only update the manifest and manifest.uuid files
184 **
185 ** See also: update
@@ -190,11 +190,11 @@
190 int latestFlag; /* Checkout the latest version */
191 char *zVers; /* Version to checkout */
192 int promptFlag; /* True to prompt before overwriting */
193 int vid, prior;
194 Blob cksum1, cksum1b, cksum2;
195
196 db_must_be_within_tree();
197 db_begin_transaction();
198 forceFlag = find_option("force","f",0)!=0;
199 keepFlag = find_option("keep",0,0)!=0;
200 latestFlag = find_option("latest",0,0)!=0;
201
--- src/checkout.c
+++ src/checkout.c
@@ -157,11 +157,11 @@
157 zManFile = mprintf("%smanifest.uuid", g.zLocalRoot);
158 file_delete(zManFile);
159 free(zManFile);
160 }
161 }
162
163 }
164
165 /*
166 ** COMMAND: checkout*
167 ** COMMAND: co*
@@ -175,11 +175,11 @@
175 ** leaves files on disk unchanged, except the manifest and manifest.uuid
176 ** files.
177 **
178 ** The --latest flag can be used in place of VERSION to checkout the
179 ** latest version in the repository.
180 **
181 ** Options:
182 ** --force Ignore edited files in the current checkout
183 ** --keep Only update the manifest and manifest.uuid files
184 **
185 ** See also: update
@@ -190,11 +190,11 @@
190 int latestFlag; /* Checkout the latest version */
191 char *zVers; /* Version to checkout */
192 int promptFlag; /* True to prompt before overwriting */
193 int vid, prior;
194 Blob cksum1, cksum1b, cksum2;
195
196 db_must_be_within_tree();
197 db_begin_transaction();
198 forceFlag = find_option("force","f",0)!=0;
199 keepFlag = find_option("keep",0,0)!=0;
200 latestFlag = find_option("latest",0,0)!=0;
201
+11 -1
--- src/config.h
+++ src/config.h
@@ -105,11 +105,21 @@
105105
# else
106106
# define COMPILER_NAME "msc"
107107
# endif
108108
# elif defined(__MINGW32__)
109109
# if !defined(COMPILER_VERSION)
110
-# if defined(__MINGW32_VERSION)
110
+# if defined(__MINGW_VERSION)
111
+# if defined(__GNUC__)
112
+# if defined(__VERSION__)
113
+# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc-" __VERSION__
114
+# else
115
+# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc"
116
+# endif
117
+# else
118
+# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION)
119
+# endif
120
+# elif defined(__MINGW32_VERSION)
111121
# if defined(__GNUC__)
112122
# if defined(__VERSION__)
113123
# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__
114124
# else
115125
# define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc"
116126
--- src/config.h
+++ src/config.h
@@ -105,11 +105,21 @@
105 # else
106 # define COMPILER_NAME "msc"
107 # endif
108 # elif defined(__MINGW32__)
109 # if !defined(COMPILER_VERSION)
110 # if defined(__MINGW32_VERSION)
 
 
 
 
 
 
 
 
 
 
111 # if defined(__GNUC__)
112 # if defined(__VERSION__)
113 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__
114 # else
115 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc"
116
--- src/config.h
+++ src/config.h
@@ -105,11 +105,21 @@
105 # else
106 # define COMPILER_NAME "msc"
107 # endif
108 # elif defined(__MINGW32__)
109 # if !defined(COMPILER_VERSION)
110 # if defined(__MINGW_VERSION)
111 # if defined(__GNUC__)
112 # if defined(__VERSION__)
113 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc-" __VERSION__
114 # else
115 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION) "-gcc"
116 # endif
117 # else
118 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW_VERSION)
119 # endif
120 # elif defined(__MINGW32_VERSION)
121 # if defined(__GNUC__)
122 # if defined(__VERSION__)
123 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc-" __VERSION__
124 # else
125 # define COMPILER_VERSION COMPILER_STRINGIFY(__MINGW32_VERSION) "-gcc"
126
+128 -54
--- src/diff.c
+++ src/diff.c
@@ -28,18 +28,18 @@
2828
** Flag parameters to the text_diff() routine used to control the formatting
2929
** of the diff output.
3030
*/
3131
#define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
3232
#define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
33
-#define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */
34
-#define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */
35
-#define DIFF_VERBOSE ((u64)0x04000000) /* Missing shown as empty files */
36
-#define DIFF_BRIEF ((u64)0x08000000) /* Show filenames only */
33
+#define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */
34
+#define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */
35
+#define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */
36
+#define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */
3737
#define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */
38
-#define DIFF_HTML ((u64)0x10000000) /* Render for HTML */
39
-#define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */
40
-#define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */
38
+#define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */
39
+#define DIFF_HTML ((u64)0x20000000) /* Render for HTML */
40
+#define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */
4141
#define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
4242
#define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
4343
#define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */
4444
#define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */
4545
@@ -54,10 +54,13 @@
5454
"cannot compute difference between symlink and regular file\n"
5555
5656
#define DIFF_TOO_MANY_CHANGES \
5757
"more than 10,000 changes\n"
5858
59
+#define DIFF_WHITESPACE_ONLY \
60
+ "whitespace changes only\n"
61
+
5962
/*
6063
** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
6164
*/
6265
#define LENGTH_MASK_SZ 13
6366
#define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
@@ -73,10 +76,11 @@
7376
*/
7477
typedef struct DLine DLine;
7578
struct DLine {
7679
const char *z; /* The text of the line */
7780
unsigned int h; /* Hash of the line */
81
+ unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */
7882
unsigned int iNext; /* 1+(Index of next line with same the same hash) */
7983
8084
/* an array of DLine elements serves two purposes. The fields
8185
** above are one per line of input text. But each entry is also
8286
** a bucket in a hash table, as follows: */
@@ -125,12 +129,12 @@
125129
** too long.
126130
**
127131
** Profiling show that in most cases this routine consumes the bulk of
128132
** the CPU time on a diff.
129133
*/
130
-static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){
131
- int nLine, i, j, k, x;
134
+static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){
135
+ int nLine, i, j, k, s, indent, x;
132136
unsigned int h, h2;
133137
DLine *a;
134138
135139
/* Count the number of lines. Allocate space to hold
136140
** the returned array.
@@ -158,18 +162,33 @@
158162
return a;
159163
}
160164
161165
/* Fill in the array */
162166
for(i=0; i<nLine; i++){
163
- a[i].z = z;
164167
for(j=0; z[j] && z[j]!='\n'; j++){}
165168
k = j;
166
- while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; }
167
- for(h=0, x=0; x<=k; x++){
169
+ s = 0;
170
+ indent = 0;
171
+ if( diffFlags & DIFF_IGNORE_EOLWS ){
172
+ while( k>0 && fossil_isspace(z[k-1]) ){ k--; }
173
+ }
174
+ if( diffFlags & DIFF_IGNORE_SOLWS ){
175
+ while( s<k && fossil_isspace(z[s]) ){
176
+ if( z[s]=='\t' ){
177
+ indent = ((indent+9)/8)*8;
178
+ }else if( z[s]==' ' ){
179
+ indent++;
180
+ }
181
+ s++;
182
+ }
183
+ }
184
+ a[i].z = z+s;
185
+ a[i].indent = s;
186
+ for(h=0, x=s; x<k; x++){
168187
h = h ^ (h<<2) ^ z[x];
169188
}
170
- a[i].h = h = (h<<LENGTH_MASK_SZ) | k;;
189
+ a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
171190
h2 = h % nLine;
172191
a[i].iNext = a[h2].iHash;
173192
a[h2].iHash = i+1;
174193
z += j+1;
175194
}
@@ -221,15 +240,21 @@
221240
}else if( cPrefix=='+' ){
222241
blob_append(pOut, "<span class=\"diffadd\">", -1);
223242
}else if( cPrefix=='-' ){
224243
blob_append(pOut, "<span class=\"diffrm\">", -1);
225244
}
245
+ if( pLine->indent ){
246
+ blob_appendf(pOut, "%*s", pLine->indent, " ");
247
+ }
226248
htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK));
227249
if( cPrefix!=' ' ){
228250
blob_append(pOut, "</span>", -1);
229251
}
230252
}else{
253
+ if( pLine->indent ){
254
+ blob_appendf(pOut, "%*s", pLine->indent, " ");
255
+ }
231256
blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);
232257
}
233258
blob_append(pOut, "\n", 1);
234259
}
235260
@@ -507,10 +532,13 @@
507532
p->iEnd = p->iEnd2;
508533
p->iEnd2 = 0;
509534
}
510535
}
511536
}
537
+ if( pLine->indent && i==0 ){
538
+ blob_appendf(pCol, "%*s", pLine->indent, " ");
539
+ }
512540
if( c=='\t' && !p->escHtml ){
513541
blob_append(pCol, " ", 1);
514542
while( (k&7)!=7 && (p->escHtml || k<w) ){
515543
blob_append(pCol, " ", 1);
516544
k++;
@@ -534,11 +562,11 @@
534562
blob_append(pCol, "</span>", 7);
535563
}
536564
if( col==SBS_TXTB ){
537565
sbsWriteNewlines(p);
538566
}else if( !p->escHtml ){
539
- sbsWriteSpace(p, w-k, SBS_TXTA);
567
+ sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA);
540568
}
541569
}
542570
543571
/*
544572
** Append a column to the final output blob.
@@ -1305,11 +1333,11 @@
13051333
sbsWriteMarker(&s, " ", "");
13061334
sbsWriteLineno(&s, b+j, SBS_LNB);
13071335
sbsWriteText(&s, &B[b+j], SBS_TXTB);
13081336
}
13091337
}
1310
-
1338
+
13111339
if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){
13121340
blob_append(pOut, "<table class=\"sbsdiffcols\"><tr>\n", -1);
13131341
for(i=SBS_LNA; i<=SBS_TXTB; i++){
13141342
sbsWriteColumn(pOut, s.apCols[i], i);
13151343
blob_reset(s.apCols[i]);
@@ -1753,28 +1781,28 @@
17531781
Blob *pB_Blob, /* TO file */
17541782
Blob *pOut, /* Write diff here if not NULL */
17551783
ReCompiled *pRe, /* Only output changes where this Regexp matches */
17561784
u64 diffFlags /* DIFF_* flags defined above */
17571785
){
1758
- int ignoreEolWs; /* Ignore whitespace at the end of lines */
1786
+ int ignoreWs; /* Ignore whitespace */
17591787
DContext c;
17601788
17611789
if( diffFlags & DIFF_INVERT ){
17621790
Blob *pTemp = pA_Blob;
17631791
pA_Blob = pB_Blob;
17641792
pB_Blob = pTemp;
17651793
}
1766
- ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
1794
+ ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0;
17671795
blob_to_utf8_no_bom(pA_Blob, 0);
17681796
blob_to_utf8_no_bom(pB_Blob, 0);
17691797
17701798
/* Prepare the input files */
17711799
memset(&c, 0, sizeof(c));
17721800
c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
1773
- &c.nFrom, ignoreEolWs);
1801
+ &c.nFrom, diffFlags);
17741802
c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
1775
- &c.nTo, ignoreEolWs);
1803
+ &c.nTo, diffFlags);
17761804
if( c.aFrom==0 || c.aTo==0 ){
17771805
fossil_free(c.aFrom);
17781806
fossil_free(c.aTo);
17791807
if( pOut ){
17801808
diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags);
@@ -1782,20 +1810,27 @@
17821810
return 0;
17831811
}
17841812
17851813
/* Compute the difference */
17861814
diff_all(&c);
1815
+ if( ignoreWs && c.nEdit==6 && c.aEdit[1]==0 && c.aEdit[2]==0 ){
1816
+ fossil_free(c.aFrom);
1817
+ fossil_free(c.aTo);
1818
+ fossil_free(c.aEdit);
1819
+ if( pOut ) diff_errmsg(pOut, DIFF_WHITESPACE_ONLY, diffFlags);
1820
+ return 0;
1821
+ }
17871822
if( (diffFlags & DIFF_NOTTOOBIG)!=0 ){
17881823
int i, m, n;
17891824
int *a = c.aEdit;
17901825
int mx = c.nEdit;
17911826
for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; }
17921827
if( n>10000 ){
17931828
fossil_free(c.aFrom);
17941829
fossil_free(c.aTo);
17951830
fossil_free(c.aEdit);
1796
- diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags);
1831
+ if( pOut ) diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags);
17971832
return 0;
17981833
}
17991834
}
18001835
if( (diffFlags & DIFF_NOOPT)==0 ){
18011836
diff_optimize(&c);
@@ -1828,14 +1863,17 @@
18281863
**
18291864
** --brief Show filenames only DIFF_BRIEF
18301865
** --context|-c N N lines of context. DIFF_CONTEXT_MASK
18311866
** --html Format for HTML DIFF_HTML
18321867
** --invert Invert the diff DIFF_INVERT
1868
+** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS
1869
+** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS
18331870
** --linenum|-n Show line numbers DIFF_LINENO
18341871
** --noopt Disable optimization DIFF_NOOPT
18351872
** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
18361873
** --unified Unified diff. ~DIFF_SIDEBYSIDE
1874
+** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS
18371875
** --width|-W N N character lines. DIFF_WIDTH_MASK
18381876
*/
18391877
u64 diff_options(void){
18401878
u64 diffFlags = 0;
18411879
const char *z;
@@ -1850,10 +1888,13 @@
18501888
f *= DIFF_CONTEXT_MASK+1;
18511889
if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
18521890
diffFlags |= f;
18531891
}
18541892
if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
1893
+ if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS;
1894
+ if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS;
1895
+ if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
18551896
if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
18561897
if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
18571898
if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
18581899
if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF;
18591900
return diffFlags;
@@ -1930,11 +1971,14 @@
19301971
typedef struct Annotator Annotator;
19311972
struct Annotator {
19321973
DContext c; /* The diff-engine context */
19331974
struct AnnLine { /* Lines of the original files... */
19341975
const char *z; /* The text of the line */
1935
- short int n; /* Number of bytes (omitting trailing space and \n) */
1976
+ short int n; /* Number of bytes. Whether this omits sol/eol spacing
1977
+ depends on the diffFlags) */
1978
+ unsigned short indent; /* Indenting (number of initial spaces, only used
1979
+ if sol-spacing is ignored in the diffFlags) */
19361980
short int iVers; /* Level at which tag was set */
19371981
} *aOrig;
19381982
int nOrig; /* Number of elements in aOrig[] */
19391983
int nVers; /* Number of versions analyzed */
19401984
int bLimit; /* True if the iLimit was reached */
@@ -1952,22 +1996,24 @@
19521996
/*
19531997
** Initialize the annotation process by specifying the file that is
19541998
** to be annotated. The annotator takes control of the input Blob and
19551999
** will release it when it is finished with it.
19562000
*/
1957
-static int annotation_start(Annotator *p, Blob *pInput){
2001
+static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){
19582002
int i;
19592003
19602004
memset(p, 0, sizeof(*p));
1961
- p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1);
2005
+ p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,
2006
+ diffFlags);
19622007
if( p->c.aTo==0 ){
19632008
return 1;
19642009
}
19652010
p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
19662011
for(i=0; i<p->c.nTo; i++){
19672012
p->aOrig[i].z = p->c.aTo[i].z;
19682013
p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
2014
+ p->aOrig[i].indent = p->c.aTo[i].indent;
19692015
p->aOrig[i].iVers = -1;
19702016
}
19712017
p->nOrig = p->c.nTo;
19722018
return 0;
19732019
}
@@ -1977,17 +2023,17 @@
19772023
** being annotated. Do another step of the annotation. Return true
19782024
** if additional annotation is required. zPName is the tag to insert
19792025
** on each line of the file being annotated that was contributed by
19802026
** pParent. Memory to hold zPName is leaked.
19812027
*/
1982
-static int annotation_step(Annotator *p, Blob *pParent, int iVers){
2028
+static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){
19832029
int i, j;
19842030
int lnTo;
19852031
19862032
/* Prepare the parent file to be diffed */
19872033
p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
1988
- &p->c.nFrom, 1);
2034
+ &p->c.nFrom, diffFlags);
19892035
if( p->c.aFrom==0 ){
19902036
return 1;
19912037
}
19922038
19932039
/* Compute the differences going from pParent to the file being
@@ -2034,11 +2080,12 @@
20342080
static void annotate_file(
20352081
Annotator *p, /* The annotator */
20362082
int fnid, /* The name of the file to be annotated */
20372083
int mid, /* Use the version of the file in this check-in */
20382084
int iLimit, /* Limit the number of levels if greater than zero */
2039
- int annFlags /* Flags to alter the annotation */
2085
+ int annFlags, /* Flags to alter the annotation */
2086
+ u64 diffFlags /* Flags to alter the whitespace handling */
20402087
){
20412088
Blob toAnnotate; /* Text of the final (mid) version of the file */
20422089
Blob step; /* Text of previous revision */
20432090
int rid; /* Artifact ID of the file being annotated */
20442091
Stmt q; /* Query returning all ancestor versions */
@@ -2052,11 +2099,11 @@
20522099
}
20532100
if( !content_get(rid, &toAnnotate) ){
20542101
fossil_fatal("unable to retrieve content of artifact #%d", rid);
20552102
}
20562103
if( iLimit<=0 ) iLimit = 1000000000;
2057
- annotation_start(p, &toAnnotate);
2104
+ annotation_start(p, &toAnnotate, diffFlags);
20582105
db_begin_transaction();
20592106
db_multi_exec(
20602107
"CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);"
20612108
"DELETE FROM vseen;"
20622109
);
@@ -2086,11 +2133,11 @@
20862133
p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
20872134
p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
20882135
p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
20892136
if( p->nVers ){
20902137
content_get(rid, &step);
2091
- annotation_step(p, &step, p->nVers-1);
2138
+ annotation_step(p, &step, p->nVers-1, diffFlags);
20922139
blob_reset(&step);
20932140
}
20942141
p->nVers++;
20952142
db_bind_int(&ins, ":rid", rid);
20962143
db_step(&ins);
@@ -2126,10 +2173,11 @@
21262173
}
21272174
21282175
/*
21292176
** WEBPAGE: annotate
21302177
** WEBPAGE: blame
2178
+** WEBPAGE: praise
21312179
**
21322180
** Query parameters:
21332181
**
21342182
** checkin=ID The manifest ID at which to start the annotation
21352183
** filename=FILENAME The filename.
@@ -2140,19 +2188,21 @@
21402188
void annotation_page(void){
21412189
int mid;
21422190
int fnid;
21432191
int i;
21442192
int iLimit; /* Depth limit */
2145
- int annFlags = ANN_FILE_ANCEST;
2193
+ int annFlags = ANN_FILE_ANCEST;
21462194
int showLog = 0; /* True to display the log */
2195
+ int ignoreWs = 0; /* Ignore whitespace */
2196
+ u64 diffFlags = 0; /* diff flags for ignore whitespace */
21472197
const char *zFilename; /* Name of file to annotate */
21482198
const char *zCI; /* The check-in containing zFilename */
21492199
Annotator ann;
21502200
HQuery url;
21512201
struct AnnVers *p;
21522202
unsigned clr1, clr2, clr;
2153
- int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */
2203
+ int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
21542204
21552205
/* Gather query parameters */
21562206
showLog = atoi(PD("log","1"));
21572207
login_check_credentials();
21582208
if( !g.perm.Read ){ login_needed(); return; }
@@ -2161,28 +2211,42 @@
21612211
zFilename = P("filename");
21622212
fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
21632213
if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
21642214
iLimit = atoi(PD("limit","20"));
21652215
if( P("filevers") ) annFlags |= ANN_FILE_VERS;
2216
+ ignoreWs = P("w")!=0;
2217
+ if( ignoreWs ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
21662218
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
21672219
fossil_redirect_home();
21682220
}
21692221
21702222
/* compute the annotation */
21712223
compute_direct_ancestors(mid, 10000000);
2172
- annotate_file(&ann, fnid, mid, iLimit, annFlags);
2224
+ annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags);
21732225
zCI = ann.aVers[0].zMUuid;
21742226
21752227
/* generate the web page */
21762228
style_header("Annotation For %h", zFilename);
2177
- url_initialize(&url, "annotate");
2229
+ if( bBlame ){
2230
+ url_initialize(&url, "blame");
2231
+ }else{
2232
+ url_initialize(&url, "annotate");
2233
+ }
21782234
url_add_parameter(&url, "checkin", P("checkin"));
21792235
url_add_parameter(&url, "filename", zFilename);
21802236
if( iLimit!=20 ){
21812237
url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit));
21822238
}
21832239
url_add_parameter(&url, "log", showLog ? "1" : "0");
2240
+ if( ignoreWs ){
2241
+ url_add_parameter(&url, "w", "");
2242
+ style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes",
2243
+ "%s", url_render(&url, "w", 0, 0, 0));
2244
+ }else{
2245
+ style_submenu_element("Ignore Whitespace", "Ignore Whitespace",
2246
+ "%s", url_render(&url, "w", "", 0, 0));
2247
+ }
21842248
if( showLog ){
21852249
style_submenu_element("Hide Log", "Hide Log",
21862250
"%s", url_render(&url, "log", "0", 0, 0));
21872251
}else{
21882252
style_submenu_element("Show Log", "Show Log",
@@ -2208,11 +2272,11 @@
22082272
clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
22092273
}
22102274
for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
22112275
clr = gradient_color(clr1, clr2, ann.nVers-1, i);
22122276
ann.aVers[i].zBgColor = mprintf("#%06x", clr);
2213
- }
2277
+ }
22142278
22152279
if( showLog ){
22162280
char *zLink = href("%R/finfo?name=%t&ci=%S",zFilename,zCI);
22172281
@ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
22182282
@ <ol>
@@ -2238,11 +2302,11 @@
22382302
}
22392303
@ </ol>
22402304
@ <hr>
22412305
}
22422306
if( !ann.bLimit ){
2243
- @ <h2>Origin for each line in
2307
+ @ <h2>Origin for each line in
22442308
@ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename)</a>
22452309
@ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
22462310
iLimit = ann.nVers+10;
22472311
}else{
22482312
@ <h2>Lines added by the %d(iLimit) most recent ancestors of
@@ -2252,10 +2316,11 @@
22522316
@ <pre>
22532317
for(i=0; i<ann.nOrig; i++){
22542318
int iVers = ann.aOrig[i].iVers;
22552319
char *z = (char*)ann.aOrig[i].z;
22562320
int n = ann.aOrig[i].n;
2321
+ int indent = ann.aOrig[i].indent+1;
22572322
char zPrefix[300];
22582323
z[n] = 0;
22592324
if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
22602325
22612326
if( bBlame ){
@@ -2266,47 +2331,51 @@
22662331
"<span style='background-color:%s'>"
22672332
"%s%.10s</a> %s</span> %13.13s:",
22682333
p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
22692334
fossil_free(zLink);
22702335
}else{
2271
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
2336
+ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " ");
22722337
}
22732338
}else{
22742339
if( iVers>=0 ){
22752340
struct AnnVers *p = ann.aVers+iVers;
22762341
char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
22772342
sqlite3_snprintf(sizeof(zPrefix), zPrefix,
22782343
"<span style='background-color:%s'>"
2279
- "%s%.10s</a> %s</span> %4d:",
2280
- p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
2344
+ "%s%.10s</a> %s</span> %4d:%*s",
2345
+ p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " ");
22812346
fossil_free(zLink);
22822347
}else{
2283
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1);
2348
+ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " ");
22842349
}
22852350
}
2286
- @ %s(zPrefix) %h(z)
2351
+ @ %s(zPrefix)%h(z)
22872352
22882353
}
22892354
@ </pre>
22902355
style_footer();
22912356
}
22922357
22932358
/*
22942359
** COMMAND: annotate
22952360
** COMMAND: blame
2361
+** COMMAND: praise
22962362
**
2297
-** %fossil (annotate|blame) ?OPTIONS? FILENAME
2363
+** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME
22982364
**
22992365
** Output the text of a file with markings to show when each line of
23002366
** the file was last modified. The "annotate" command shows line numbers
2301
-** and omits the username. The "blame" command shows the user who made each
2302
-** checkin and omits the line number.
2367
+** and omits the username. The "blame" and "praise" commands show the user
2368
+** who made each checkin and omits the line number.
23032369
**
23042370
** Options:
2305
-** --filevers Show file version numbers rather than check-in versions
2306
-** -l|--log List all versions analyzed
2307
-** -n|--limit N Only look backwards in time by N versions
2371
+** --filevers Show file version numbers rather than check-in versions
2372
+** -l|--log List all versions analyzed
2373
+** -n|--limit N Only look backwards in time by N versions
2374
+** --ignore-space-at-eol Ignore eol-whitespaces
2375
+** --ignore-space-at-sol Ignore sol-whitespaces
2376
+** -w Ignore all whitespaces
23082377
**
23092378
** See also: info, finfo, timeline
23102379
*/
23112380
void annotate_cmd(void){
23122381
int fnid; /* Filename ID */
@@ -2318,19 +2387,23 @@
23182387
Annotator ann; /* The annotation of the file */
23192388
int i; /* Loop counter */
23202389
const char *zLimit; /* The value to the -n|--limit option */
23212390
int iLimit; /* How far back in time to look */
23222391
int showLog; /* True to show the log */
2392
+ u64 diffFlags = 0;/* Flags to control whitespace handling */
23232393
int fileVers; /* Show file version instead of check-in versions */
23242394
int annFlags = 0; /* Flags to control annotation properties */
23252395
int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
23262396
2327
- bBlame = g.argv[1][0]=='b';
2397
+ bBlame = g.argv[1][0]!='a';
23282398
zLimit = find_option("limit","n",1);
23292399
if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
23302400
iLimit = atoi(zLimit);
23312401
showLog = find_option("log","l",0)!=0;
2402
+ if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS;
2403
+ if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS;
2404
+ if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
23322405
fileVers = find_option("filevers",0,0)!=0;
23332406
db_must_be_within_tree();
23342407
if( g.argc<3 ) {
23352408
usage("FILENAME");
23362409
}
@@ -2356,11 +2429,11 @@
23562429
fid, fnid);
23572430
if( mid==0 ){
23582431
fossil_fatal("unable to find manifest");
23592432
}
23602433
annFlags |= ANN_FILE_ANCEST;
2361
- annotate_file(&ann, fnid, mid, iLimit, annFlags);
2434
+ annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags);
23622435
if( showLog ){
23632436
struct AnnVers *p;
23642437
for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
23652438
fossil_print("version %3d: %s %.10s file %.10s\n",
23662439
i+1, p->zDate, p->zMUuid, p->zFUuid);
@@ -2368,27 +2441,28 @@
23682441
fossil_print("---------------------------------------------------\n");
23692442
}
23702443
for(i=0; i<ann.nOrig; i++){
23712444
int iVers = ann.aOrig[i].iVers;
23722445
char *z = (char*)ann.aOrig[i].z;
2446
+ int indent = ann.aOrig[i].indent + 1;
23732447
int n = ann.aOrig[i].n;
23742448
struct AnnVers *p;
23752449
if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
23762450
p = ann.aVers + iVers;
23772451
if( bBlame ){
23782452
if( iVers>=0 ){
2379
- fossil_print("%.10s %s %13.13s: %.*s\n",
2380
- fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2453
+ fossil_print("%.10s %s %13.13s:%*s%.*s\n",
2454
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z);
23812455
}else{
2382
- fossil_print("%35s %.*s\n", "", n, z);
2456
+ fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z);
23832457
}
23842458
}else{
23852459
if( iVers>=0 ){
2386
- fossil_print("%.10s %s %5d: %.*s\n",
2387
- fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2460
+ fossil_print("%.10s %s %5d:%*s%.*s\n",
2461
+ fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z);
23882462
}else{
2389
- fossil_print("%21s %5d: %.*s\n",
2390
- "", i+1, n, z);
2463
+ fossil_print("%21s %5d:%*s%.*s\n",
2464
+ "", i+1, indent, " ", n, z);
23912465
}
23922466
}
23932467
}
23942468
}
23952469
--- src/diff.c
+++ src/diff.c
@@ -28,18 +28,18 @@
28 ** Flag parameters to the text_diff() routine used to control the formatting
29 ** of the diff output.
30 */
31 #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
32 #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
33 #define DIFF_IGNORE_EOLWS ((u64)0x01000000) /* Ignore end-of-line whitespace */
34 #define DIFF_SIDEBYSIDE ((u64)0x02000000) /* Generate a side-by-side diff */
35 #define DIFF_VERBOSE ((u64)0x04000000) /* Missing shown as empty files */
36 #define DIFF_BRIEF ((u64)0x08000000) /* Show filenames only */
37 #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */
38 #define DIFF_HTML ((u64)0x10000000) /* Render for HTML */
39 #define DIFF_LINENO ((u64)0x20000000) /* Show line numbers */
40 #define DIFF_WS_WARNING ((u64)0x40000000) /* Warn about whitespace */
41 #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
42 #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
43 #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */
44 #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */
45
@@ -54,10 +54,13 @@
54 "cannot compute difference between symlink and regular file\n"
55
56 #define DIFF_TOO_MANY_CHANGES \
57 "more than 10,000 changes\n"
58
 
 
 
59 /*
60 ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
61 */
62 #define LENGTH_MASK_SZ 13
63 #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
@@ -73,10 +76,11 @@
73 */
74 typedef struct DLine DLine;
75 struct DLine {
76 const char *z; /* The text of the line */
77 unsigned int h; /* Hash of the line */
 
78 unsigned int iNext; /* 1+(Index of next line with same the same hash) */
79
80 /* an array of DLine elements serves two purposes. The fields
81 ** above are one per line of input text. But each entry is also
82 ** a bucket in a hash table, as follows: */
@@ -125,12 +129,12 @@
125 ** too long.
126 **
127 ** Profiling show that in most cases this routine consumes the bulk of
128 ** the CPU time on a diff.
129 */
130 static DLine *break_into_lines(const char *z, int n, int *pnLine, int ignoreWS){
131 int nLine, i, j, k, x;
132 unsigned int h, h2;
133 DLine *a;
134
135 /* Count the number of lines. Allocate space to hold
136 ** the returned array.
@@ -158,18 +162,33 @@
158 return a;
159 }
160
161 /* Fill in the array */
162 for(i=0; i<nLine; i++){
163 a[i].z = z;
164 for(j=0; z[j] && z[j]!='\n'; j++){}
165 k = j;
166 while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; }
167 for(h=0, x=0; x<=k; x++){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168 h = h ^ (h<<2) ^ z[x];
169 }
170 a[i].h = h = (h<<LENGTH_MASK_SZ) | k;;
171 h2 = h % nLine;
172 a[i].iNext = a[h2].iHash;
173 a[h2].iHash = i+1;
174 z += j+1;
175 }
@@ -221,15 +240,21 @@
221 }else if( cPrefix=='+' ){
222 blob_append(pOut, "<span class=\"diffadd\">", -1);
223 }else if( cPrefix=='-' ){
224 blob_append(pOut, "<span class=\"diffrm\">", -1);
225 }
 
 
 
226 htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK));
227 if( cPrefix!=' ' ){
228 blob_append(pOut, "</span>", -1);
229 }
230 }else{
 
 
 
231 blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);
232 }
233 blob_append(pOut, "\n", 1);
234 }
235
@@ -507,10 +532,13 @@
507 p->iEnd = p->iEnd2;
508 p->iEnd2 = 0;
509 }
510 }
511 }
 
 
 
512 if( c=='\t' && !p->escHtml ){
513 blob_append(pCol, " ", 1);
514 while( (k&7)!=7 && (p->escHtml || k<w) ){
515 blob_append(pCol, " ", 1);
516 k++;
@@ -534,11 +562,11 @@
534 blob_append(pCol, "</span>", 7);
535 }
536 if( col==SBS_TXTB ){
537 sbsWriteNewlines(p);
538 }else if( !p->escHtml ){
539 sbsWriteSpace(p, w-k, SBS_TXTA);
540 }
541 }
542
543 /*
544 ** Append a column to the final output blob.
@@ -1305,11 +1333,11 @@
1305 sbsWriteMarker(&s, " ", "");
1306 sbsWriteLineno(&s, b+j, SBS_LNB);
1307 sbsWriteText(&s, &B[b+j], SBS_TXTB);
1308 }
1309 }
1310
1311 if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){
1312 blob_append(pOut, "<table class=\"sbsdiffcols\"><tr>\n", -1);
1313 for(i=SBS_LNA; i<=SBS_TXTB; i++){
1314 sbsWriteColumn(pOut, s.apCols[i], i);
1315 blob_reset(s.apCols[i]);
@@ -1753,28 +1781,28 @@
1753 Blob *pB_Blob, /* TO file */
1754 Blob *pOut, /* Write diff here if not NULL */
1755 ReCompiled *pRe, /* Only output changes where this Regexp matches */
1756 u64 diffFlags /* DIFF_* flags defined above */
1757 ){
1758 int ignoreEolWs; /* Ignore whitespace at the end of lines */
1759 DContext c;
1760
1761 if( diffFlags & DIFF_INVERT ){
1762 Blob *pTemp = pA_Blob;
1763 pA_Blob = pB_Blob;
1764 pB_Blob = pTemp;
1765 }
1766 ignoreEolWs = (diffFlags & DIFF_IGNORE_EOLWS)!=0;
1767 blob_to_utf8_no_bom(pA_Blob, 0);
1768 blob_to_utf8_no_bom(pB_Blob, 0);
1769
1770 /* Prepare the input files */
1771 memset(&c, 0, sizeof(c));
1772 c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
1773 &c.nFrom, ignoreEolWs);
1774 c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
1775 &c.nTo, ignoreEolWs);
1776 if( c.aFrom==0 || c.aTo==0 ){
1777 fossil_free(c.aFrom);
1778 fossil_free(c.aTo);
1779 if( pOut ){
1780 diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags);
@@ -1782,20 +1810,27 @@
1782 return 0;
1783 }
1784
1785 /* Compute the difference */
1786 diff_all(&c);
 
 
 
 
 
 
 
1787 if( (diffFlags & DIFF_NOTTOOBIG)!=0 ){
1788 int i, m, n;
1789 int *a = c.aEdit;
1790 int mx = c.nEdit;
1791 for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; }
1792 if( n>10000 ){
1793 fossil_free(c.aFrom);
1794 fossil_free(c.aTo);
1795 fossil_free(c.aEdit);
1796 diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags);
1797 return 0;
1798 }
1799 }
1800 if( (diffFlags & DIFF_NOOPT)==0 ){
1801 diff_optimize(&c);
@@ -1828,14 +1863,17 @@
1828 **
1829 ** --brief Show filenames only DIFF_BRIEF
1830 ** --context|-c N N lines of context. DIFF_CONTEXT_MASK
1831 ** --html Format for HTML DIFF_HTML
1832 ** --invert Invert the diff DIFF_INVERT
 
 
1833 ** --linenum|-n Show line numbers DIFF_LINENO
1834 ** --noopt Disable optimization DIFF_NOOPT
1835 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
1836 ** --unified Unified diff. ~DIFF_SIDEBYSIDE
 
1837 ** --width|-W N N character lines. DIFF_WIDTH_MASK
1838 */
1839 u64 diff_options(void){
1840 u64 diffFlags = 0;
1841 const char *z;
@@ -1850,10 +1888,13 @@
1850 f *= DIFF_CONTEXT_MASK+1;
1851 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
1852 diffFlags |= f;
1853 }
1854 if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
 
 
 
1855 if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
1856 if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
1857 if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
1858 if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF;
1859 return diffFlags;
@@ -1930,11 +1971,14 @@
1930 typedef struct Annotator Annotator;
1931 struct Annotator {
1932 DContext c; /* The diff-engine context */
1933 struct AnnLine { /* Lines of the original files... */
1934 const char *z; /* The text of the line */
1935 short int n; /* Number of bytes (omitting trailing space and \n) */
 
 
 
1936 short int iVers; /* Level at which tag was set */
1937 } *aOrig;
1938 int nOrig; /* Number of elements in aOrig[] */
1939 int nVers; /* Number of versions analyzed */
1940 int bLimit; /* True if the iLimit was reached */
@@ -1952,22 +1996,24 @@
1952 /*
1953 ** Initialize the annotation process by specifying the file that is
1954 ** to be annotated. The annotator takes control of the input Blob and
1955 ** will release it when it is finished with it.
1956 */
1957 static int annotation_start(Annotator *p, Blob *pInput){
1958 int i;
1959
1960 memset(p, 0, sizeof(*p));
1961 p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1);
 
1962 if( p->c.aTo==0 ){
1963 return 1;
1964 }
1965 p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
1966 for(i=0; i<p->c.nTo; i++){
1967 p->aOrig[i].z = p->c.aTo[i].z;
1968 p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
 
1969 p->aOrig[i].iVers = -1;
1970 }
1971 p->nOrig = p->c.nTo;
1972 return 0;
1973 }
@@ -1977,17 +2023,17 @@
1977 ** being annotated. Do another step of the annotation. Return true
1978 ** if additional annotation is required. zPName is the tag to insert
1979 ** on each line of the file being annotated that was contributed by
1980 ** pParent. Memory to hold zPName is leaked.
1981 */
1982 static int annotation_step(Annotator *p, Blob *pParent, int iVers){
1983 int i, j;
1984 int lnTo;
1985
1986 /* Prepare the parent file to be diffed */
1987 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
1988 &p->c.nFrom, 1);
1989 if( p->c.aFrom==0 ){
1990 return 1;
1991 }
1992
1993 /* Compute the differences going from pParent to the file being
@@ -2034,11 +2080,12 @@
2034 static void annotate_file(
2035 Annotator *p, /* The annotator */
2036 int fnid, /* The name of the file to be annotated */
2037 int mid, /* Use the version of the file in this check-in */
2038 int iLimit, /* Limit the number of levels if greater than zero */
2039 int annFlags /* Flags to alter the annotation */
 
2040 ){
2041 Blob toAnnotate; /* Text of the final (mid) version of the file */
2042 Blob step; /* Text of previous revision */
2043 int rid; /* Artifact ID of the file being annotated */
2044 Stmt q; /* Query returning all ancestor versions */
@@ -2052,11 +2099,11 @@
2052 }
2053 if( !content_get(rid, &toAnnotate) ){
2054 fossil_fatal("unable to retrieve content of artifact #%d", rid);
2055 }
2056 if( iLimit<=0 ) iLimit = 1000000000;
2057 annotation_start(p, &toAnnotate);
2058 db_begin_transaction();
2059 db_multi_exec(
2060 "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);"
2061 "DELETE FROM vseen;"
2062 );
@@ -2086,11 +2133,11 @@
2086 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2087 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2088 p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
2089 if( p->nVers ){
2090 content_get(rid, &step);
2091 annotation_step(p, &step, p->nVers-1);
2092 blob_reset(&step);
2093 }
2094 p->nVers++;
2095 db_bind_int(&ins, ":rid", rid);
2096 db_step(&ins);
@@ -2126,10 +2173,11 @@
2126 }
2127
2128 /*
2129 ** WEBPAGE: annotate
2130 ** WEBPAGE: blame
 
2131 **
2132 ** Query parameters:
2133 **
2134 ** checkin=ID The manifest ID at which to start the annotation
2135 ** filename=FILENAME The filename.
@@ -2140,19 +2188,21 @@
2140 void annotation_page(void){
2141 int mid;
2142 int fnid;
2143 int i;
2144 int iLimit; /* Depth limit */
2145 int annFlags = ANN_FILE_ANCEST;
2146 int showLog = 0; /* True to display the log */
 
 
2147 const char *zFilename; /* Name of file to annotate */
2148 const char *zCI; /* The check-in containing zFilename */
2149 Annotator ann;
2150 HQuery url;
2151 struct AnnVers *p;
2152 unsigned clr1, clr2, clr;
2153 int bBlame = g.zPath[0]=='b';/* True for BLAME output. False for ANNOTATE. */
2154
2155 /* Gather query parameters */
2156 showLog = atoi(PD("log","1"));
2157 login_check_credentials();
2158 if( !g.perm.Read ){ login_needed(); return; }
@@ -2161,28 +2211,42 @@
2161 zFilename = P("filename");
2162 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2163 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
2164 iLimit = atoi(PD("limit","20"));
2165 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
 
 
2166 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
2167 fossil_redirect_home();
2168 }
2169
2170 /* compute the annotation */
2171 compute_direct_ancestors(mid, 10000000);
2172 annotate_file(&ann, fnid, mid, iLimit, annFlags);
2173 zCI = ann.aVers[0].zMUuid;
2174
2175 /* generate the web page */
2176 style_header("Annotation For %h", zFilename);
2177 url_initialize(&url, "annotate");
 
 
 
 
2178 url_add_parameter(&url, "checkin", P("checkin"));
2179 url_add_parameter(&url, "filename", zFilename);
2180 if( iLimit!=20 ){
2181 url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit));
2182 }
2183 url_add_parameter(&url, "log", showLog ? "1" : "0");
 
 
 
 
 
 
 
 
2184 if( showLog ){
2185 style_submenu_element("Hide Log", "Hide Log",
2186 "%s", url_render(&url, "log", "0", 0, 0));
2187 }else{
2188 style_submenu_element("Show Log", "Show Log",
@@ -2208,11 +2272,11 @@
2208 clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
2209 }
2210 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2211 clr = gradient_color(clr1, clr2, ann.nVers-1, i);
2212 ann.aVers[i].zBgColor = mprintf("#%06x", clr);
2213 }
2214
2215 if( showLog ){
2216 char *zLink = href("%R/finfo?name=%t&ci=%S",zFilename,zCI);
2217 @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
2218 @ <ol>
@@ -2238,11 +2302,11 @@
2238 }
2239 @ </ol>
2240 @ <hr>
2241 }
2242 if( !ann.bLimit ){
2243 @ <h2>Origin for each line in
2244 @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename)</a>
2245 @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
2246 iLimit = ann.nVers+10;
2247 }else{
2248 @ <h2>Lines added by the %d(iLimit) most recent ancestors of
@@ -2252,10 +2316,11 @@
2252 @ <pre>
2253 for(i=0; i<ann.nOrig; i++){
2254 int iVers = ann.aOrig[i].iVers;
2255 char *z = (char*)ann.aOrig[i].z;
2256 int n = ann.aOrig[i].n;
 
2257 char zPrefix[300];
2258 z[n] = 0;
2259 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2260
2261 if( bBlame ){
@@ -2266,47 +2331,51 @@
2266 "<span style='background-color:%s'>"
2267 "%s%.10s</a> %s</span> %13.13s:",
2268 p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
2269 fossil_free(zLink);
2270 }else{
2271 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", "");
2272 }
2273 }else{
2274 if( iVers>=0 ){
2275 struct AnnVers *p = ann.aVers+iVers;
2276 char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
2277 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
2278 "<span style='background-color:%s'>"
2279 "%s%.10s</a> %s</span> %4d:",
2280 p->zBgColor, zLink, p->zMUuid, p->zDate, i+1);
2281 fossil_free(zLink);
2282 }else{
2283 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1);
2284 }
2285 }
2286 @ %s(zPrefix) %h(z)
2287
2288 }
2289 @ </pre>
2290 style_footer();
2291 }
2292
2293 /*
2294 ** COMMAND: annotate
2295 ** COMMAND: blame
 
2296 **
2297 ** %fossil (annotate|blame) ?OPTIONS? FILENAME
2298 **
2299 ** Output the text of a file with markings to show when each line of
2300 ** the file was last modified. The "annotate" command shows line numbers
2301 ** and omits the username. The "blame" command shows the user who made each
2302 ** checkin and omits the line number.
2303 **
2304 ** Options:
2305 ** --filevers Show file version numbers rather than check-in versions
2306 ** -l|--log List all versions analyzed
2307 ** -n|--limit N Only look backwards in time by N versions
 
 
 
2308 **
2309 ** See also: info, finfo, timeline
2310 */
2311 void annotate_cmd(void){
2312 int fnid; /* Filename ID */
@@ -2318,19 +2387,23 @@
2318 Annotator ann; /* The annotation of the file */
2319 int i; /* Loop counter */
2320 const char *zLimit; /* The value to the -n|--limit option */
2321 int iLimit; /* How far back in time to look */
2322 int showLog; /* True to show the log */
 
2323 int fileVers; /* Show file version instead of check-in versions */
2324 int annFlags = 0; /* Flags to control annotation properties */
2325 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2326
2327 bBlame = g.argv[1][0]=='b';
2328 zLimit = find_option("limit","n",1);
2329 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2330 iLimit = atoi(zLimit);
2331 showLog = find_option("log","l",0)!=0;
 
 
 
2332 fileVers = find_option("filevers",0,0)!=0;
2333 db_must_be_within_tree();
2334 if( g.argc<3 ) {
2335 usage("FILENAME");
2336 }
@@ -2356,11 +2429,11 @@
2356 fid, fnid);
2357 if( mid==0 ){
2358 fossil_fatal("unable to find manifest");
2359 }
2360 annFlags |= ANN_FILE_ANCEST;
2361 annotate_file(&ann, fnid, mid, iLimit, annFlags);
2362 if( showLog ){
2363 struct AnnVers *p;
2364 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2365 fossil_print("version %3d: %s %.10s file %.10s\n",
2366 i+1, p->zDate, p->zMUuid, p->zFUuid);
@@ -2368,27 +2441,28 @@
2368 fossil_print("---------------------------------------------------\n");
2369 }
2370 for(i=0; i<ann.nOrig; i++){
2371 int iVers = ann.aOrig[i].iVers;
2372 char *z = (char*)ann.aOrig[i].z;
 
2373 int n = ann.aOrig[i].n;
2374 struct AnnVers *p;
2375 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2376 p = ann.aVers + iVers;
2377 if( bBlame ){
2378 if( iVers>=0 ){
2379 fossil_print("%.10s %s %13.13s: %.*s\n",
2380 fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, n, z);
2381 }else{
2382 fossil_print("%35s %.*s\n", "", n, z);
2383 }
2384 }else{
2385 if( iVers>=0 ){
2386 fossil_print("%.10s %s %5d: %.*s\n",
2387 fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, n, z);
2388 }else{
2389 fossil_print("%21s %5d: %.*s\n",
2390 "", i+1, n, z);
2391 }
2392 }
2393 }
2394 }
2395
--- src/diff.c
+++ src/diff.c
@@ -28,18 +28,18 @@
28 ** Flag parameters to the text_diff() routine used to control the formatting
29 ** of the diff output.
30 */
31 #define DIFF_CONTEXT_MASK ((u64)0x0000ffff) /* Lines of context. Default if 0 */
32 #define DIFF_WIDTH_MASK ((u64)0x00ff0000) /* side-by-side column width */
33 #define DIFF_IGNORE_SOLWS ((u64)0x01000000) /* Ignore start-of-line whitespace */
34 #define DIFF_IGNORE_EOLWS ((u64)0x02000000) /* Ignore end-of-line whitespace */
35 #define DIFF_SIDEBYSIDE ((u64)0x04000000) /* Generate a side-by-side diff */
36 #define DIFF_VERBOSE ((u64)0x08000000) /* Missing shown as empty files */
37 #define DIFF_INLINE ((u64)0x00000000) /* Inline (not side-by-side) diff */
38 #define DIFF_BRIEF ((u64)0x10000000) /* Show filenames only */
39 #define DIFF_HTML ((u64)0x20000000) /* Render for HTML */
40 #define DIFF_LINENO ((u64)0x40000000) /* Show line numbers */
41 #define DIFF_NOOPT (((u64)0x01)<<32) /* Suppress optimizations (debug) */
42 #define DIFF_INVERT (((u64)0x02)<<32) /* Invert the diff (debug) */
43 #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */
44 #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */
45
@@ -54,10 +54,13 @@
54 "cannot compute difference between symlink and regular file\n"
55
56 #define DIFF_TOO_MANY_CHANGES \
57 "more than 10,000 changes\n"
58
59 #define DIFF_WHITESPACE_ONLY \
60 "whitespace changes only\n"
61
62 /*
63 ** Maximum length of a line in a text file, in bytes. (2**13 = 8192 bytes)
64 */
65 #define LENGTH_MASK_SZ 13
66 #define LENGTH_MASK ((1<<LENGTH_MASK_SZ)-1)
@@ -73,10 +76,11 @@
76 */
77 typedef struct DLine DLine;
78 struct DLine {
79 const char *z; /* The text of the line */
80 unsigned int h; /* Hash of the line */
81 unsigned short indent; /* Indent of the line. Only !=0 with --ignore-space-at sol option */
82 unsigned int iNext; /* 1+(Index of next line with same the same hash) */
83
84 /* an array of DLine elements serves two purposes. The fields
85 ** above are one per line of input text. But each entry is also
86 ** a bucket in a hash table, as follows: */
@@ -125,12 +129,12 @@
129 ** too long.
130 **
131 ** Profiling show that in most cases this routine consumes the bulk of
132 ** the CPU time on a diff.
133 */
134 static DLine *break_into_lines(const char *z, int n, int *pnLine, u64 diffFlags){
135 int nLine, i, j, k, s, indent, x;
136 unsigned int h, h2;
137 DLine *a;
138
139 /* Count the number of lines. Allocate space to hold
140 ** the returned array.
@@ -158,18 +162,33 @@
162 return a;
163 }
164
165 /* Fill in the array */
166 for(i=0; i<nLine; i++){
 
167 for(j=0; z[j] && z[j]!='\n'; j++){}
168 k = j;
169 s = 0;
170 indent = 0;
171 if( diffFlags & DIFF_IGNORE_EOLWS ){
172 while( k>0 && fossil_isspace(z[k-1]) ){ k--; }
173 }
174 if( diffFlags & DIFF_IGNORE_SOLWS ){
175 while( s<k && fossil_isspace(z[s]) ){
176 if( z[s]=='\t' ){
177 indent = ((indent+9)/8)*8;
178 }else if( z[s]==' ' ){
179 indent++;
180 }
181 s++;
182 }
183 }
184 a[i].z = z+s;
185 a[i].indent = s;
186 for(h=0, x=s; x<k; x++){
187 h = h ^ (h<<2) ^ z[x];
188 }
189 a[i].h = h = (h<<LENGTH_MASK_SZ) | (k-s);
190 h2 = h % nLine;
191 a[i].iNext = a[h2].iHash;
192 a[h2].iHash = i+1;
193 z += j+1;
194 }
@@ -221,15 +240,21 @@
240 }else if( cPrefix=='+' ){
241 blob_append(pOut, "<span class=\"diffadd\">", -1);
242 }else if( cPrefix=='-' ){
243 blob_append(pOut, "<span class=\"diffrm\">", -1);
244 }
245 if( pLine->indent ){
246 blob_appendf(pOut, "%*s", pLine->indent, " ");
247 }
248 htmlize_to_blob(pOut, pLine->z, (pLine->h & LENGTH_MASK));
249 if( cPrefix!=' ' ){
250 blob_append(pOut, "</span>", -1);
251 }
252 }else{
253 if( pLine->indent ){
254 blob_appendf(pOut, "%*s", pLine->indent, " ");
255 }
256 blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK);
257 }
258 blob_append(pOut, "\n", 1);
259 }
260
@@ -507,10 +532,13 @@
532 p->iEnd = p->iEnd2;
533 p->iEnd2 = 0;
534 }
535 }
536 }
537 if( pLine->indent && i==0 ){
538 blob_appendf(pCol, "%*s", pLine->indent, " ");
539 }
540 if( c=='\t' && !p->escHtml ){
541 blob_append(pCol, " ", 1);
542 while( (k&7)!=7 && (p->escHtml || k<w) ){
543 blob_append(pCol, " ", 1);
544 k++;
@@ -534,11 +562,11 @@
562 blob_append(pCol, "</span>", 7);
563 }
564 if( col==SBS_TXTB ){
565 sbsWriteNewlines(p);
566 }else if( !p->escHtml ){
567 sbsWriteSpace(p, w-k-pLine->indent, SBS_TXTA);
568 }
569 }
570
571 /*
572 ** Append a column to the final output blob.
@@ -1305,11 +1333,11 @@
1333 sbsWriteMarker(&s, " ", "");
1334 sbsWriteLineno(&s, b+j, SBS_LNB);
1335 sbsWriteText(&s, &B[b+j], SBS_TXTB);
1336 }
1337 }
1338
1339 if( s.escHtml && blob_size(s.apCols[SBS_LNA])>0 ){
1340 blob_append(pOut, "<table class=\"sbsdiffcols\"><tr>\n", -1);
1341 for(i=SBS_LNA; i<=SBS_TXTB; i++){
1342 sbsWriteColumn(pOut, s.apCols[i], i);
1343 blob_reset(s.apCols[i]);
@@ -1753,28 +1781,28 @@
1781 Blob *pB_Blob, /* TO file */
1782 Blob *pOut, /* Write diff here if not NULL */
1783 ReCompiled *pRe, /* Only output changes where this Regexp matches */
1784 u64 diffFlags /* DIFF_* flags defined above */
1785 ){
1786 int ignoreWs; /* Ignore whitespace */
1787 DContext c;
1788
1789 if( diffFlags & DIFF_INVERT ){
1790 Blob *pTemp = pA_Blob;
1791 pA_Blob = pB_Blob;
1792 pB_Blob = pTemp;
1793 }
1794 ignoreWs = (diffFlags & (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))!=0;
1795 blob_to_utf8_no_bom(pA_Blob, 0);
1796 blob_to_utf8_no_bom(pB_Blob, 0);
1797
1798 /* Prepare the input files */
1799 memset(&c, 0, sizeof(c));
1800 c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob),
1801 &c.nFrom, diffFlags);
1802 c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob),
1803 &c.nTo, diffFlags);
1804 if( c.aFrom==0 || c.aTo==0 ){
1805 fossil_free(c.aFrom);
1806 fossil_free(c.aTo);
1807 if( pOut ){
1808 diff_errmsg(pOut, DIFF_CANNOT_COMPUTE_BINARY, diffFlags);
@@ -1782,20 +1810,27 @@
1810 return 0;
1811 }
1812
1813 /* Compute the difference */
1814 diff_all(&c);
1815 if( ignoreWs && c.nEdit==6 && c.aEdit[1]==0 && c.aEdit[2]==0 ){
1816 fossil_free(c.aFrom);
1817 fossil_free(c.aTo);
1818 fossil_free(c.aEdit);
1819 if( pOut ) diff_errmsg(pOut, DIFF_WHITESPACE_ONLY, diffFlags);
1820 return 0;
1821 }
1822 if( (diffFlags & DIFF_NOTTOOBIG)!=0 ){
1823 int i, m, n;
1824 int *a = c.aEdit;
1825 int mx = c.nEdit;
1826 for(i=m=n=0; i<mx; i+=3){ m += a[i]; n += a[i+1]+a[i+2]; }
1827 if( n>10000 ){
1828 fossil_free(c.aFrom);
1829 fossil_free(c.aTo);
1830 fossil_free(c.aEdit);
1831 if( pOut ) diff_errmsg(pOut, DIFF_TOO_MANY_CHANGES, diffFlags);
1832 return 0;
1833 }
1834 }
1835 if( (diffFlags & DIFF_NOOPT)==0 ){
1836 diff_optimize(&c);
@@ -1828,14 +1863,17 @@
1863 **
1864 ** --brief Show filenames only DIFF_BRIEF
1865 ** --context|-c N N lines of context. DIFF_CONTEXT_MASK
1866 ** --html Format for HTML DIFF_HTML
1867 ** --invert Invert the diff DIFF_INVERT
1868 ** --ignore-space-at-eol Ignore eol-whitespaces DIFF_IGNORE_EOLWS
1869 ** --ignore-space-at-sol Ignore sol-whitespaces DIFF_IGNORE_SOLWS
1870 ** --linenum|-n Show line numbers DIFF_LINENO
1871 ** --noopt Disable optimization DIFF_NOOPT
1872 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE
1873 ** --unified Unified diff. ~DIFF_SIDEBYSIDE
1874 ** -w Ignore all whitespaces DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS
1875 ** --width|-W N N character lines. DIFF_WIDTH_MASK
1876 */
1877 u64 diff_options(void){
1878 u64 diffFlags = 0;
1879 const char *z;
@@ -1850,10 +1888,13 @@
1888 f *= DIFF_CONTEXT_MASK+1;
1889 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK;
1890 diffFlags |= f;
1891 }
1892 if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML;
1893 if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS;
1894 if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS;
1895 if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
1896 if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO;
1897 if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT;
1898 if( find_option("invert",0,0)!=0 ) diffFlags |= DIFF_INVERT;
1899 if( find_option("brief",0,0)!=0 ) diffFlags |= DIFF_BRIEF;
1900 return diffFlags;
@@ -1930,11 +1971,14 @@
1971 typedef struct Annotator Annotator;
1972 struct Annotator {
1973 DContext c; /* The diff-engine context */
1974 struct AnnLine { /* Lines of the original files... */
1975 const char *z; /* The text of the line */
1976 short int n; /* Number of bytes. Whether this omits sol/eol spacing
1977 depends on the diffFlags) */
1978 unsigned short indent; /* Indenting (number of initial spaces, only used
1979 if sol-spacing is ignored in the diffFlags) */
1980 short int iVers; /* Level at which tag was set */
1981 } *aOrig;
1982 int nOrig; /* Number of elements in aOrig[] */
1983 int nVers; /* Number of versions analyzed */
1984 int bLimit; /* True if the iLimit was reached */
@@ -1952,22 +1996,24 @@
1996 /*
1997 ** Initialize the annotation process by specifying the file that is
1998 ** to be annotated. The annotator takes control of the input Blob and
1999 ** will release it when it is finished with it.
2000 */
2001 static int annotation_start(Annotator *p, Blob *pInput, u64 diffFlags){
2002 int i;
2003
2004 memset(p, 0, sizeof(*p));
2005 p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,
2006 diffFlags);
2007 if( p->c.aTo==0 ){
2008 return 1;
2009 }
2010 p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo );
2011 for(i=0; i<p->c.nTo; i++){
2012 p->aOrig[i].z = p->c.aTo[i].z;
2013 p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
2014 p->aOrig[i].indent = p->c.aTo[i].indent;
2015 p->aOrig[i].iVers = -1;
2016 }
2017 p->nOrig = p->c.nTo;
2018 return 0;
2019 }
@@ -1977,17 +2023,17 @@
2023 ** being annotated. Do another step of the annotation. Return true
2024 ** if additional annotation is required. zPName is the tag to insert
2025 ** on each line of the file being annotated that was contributed by
2026 ** pParent. Memory to hold zPName is leaked.
2027 */
2028 static int annotation_step(Annotator *p, Blob *pParent, int iVers, u64 diffFlags){
2029 int i, j;
2030 int lnTo;
2031
2032 /* Prepare the parent file to be diffed */
2033 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent),
2034 &p->c.nFrom, diffFlags);
2035 if( p->c.aFrom==0 ){
2036 return 1;
2037 }
2038
2039 /* Compute the differences going from pParent to the file being
@@ -2034,11 +2080,12 @@
2080 static void annotate_file(
2081 Annotator *p, /* The annotator */
2082 int fnid, /* The name of the file to be annotated */
2083 int mid, /* Use the version of the file in this check-in */
2084 int iLimit, /* Limit the number of levels if greater than zero */
2085 int annFlags, /* Flags to alter the annotation */
2086 u64 diffFlags /* Flags to alter the whitespace handling */
2087 ){
2088 Blob toAnnotate; /* Text of the final (mid) version of the file */
2089 Blob step; /* Text of previous revision */
2090 int rid; /* Artifact ID of the file being annotated */
2091 Stmt q; /* Query returning all ancestor versions */
@@ -2052,11 +2099,11 @@
2099 }
2100 if( !content_get(rid, &toAnnotate) ){
2101 fossil_fatal("unable to retrieve content of artifact #%d", rid);
2102 }
2103 if( iLimit<=0 ) iLimit = 1000000000;
2104 annotation_start(p, &toAnnotate, diffFlags);
2105 db_begin_transaction();
2106 db_multi_exec(
2107 "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);"
2108 "DELETE FROM vseen;"
2109 );
@@ -2086,11 +2133,11 @@
2133 p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1));
2134 p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2));
2135 p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3));
2136 if( p->nVers ){
2137 content_get(rid, &step);
2138 annotation_step(p, &step, p->nVers-1, diffFlags);
2139 blob_reset(&step);
2140 }
2141 p->nVers++;
2142 db_bind_int(&ins, ":rid", rid);
2143 db_step(&ins);
@@ -2126,10 +2173,11 @@
2173 }
2174
2175 /*
2176 ** WEBPAGE: annotate
2177 ** WEBPAGE: blame
2178 ** WEBPAGE: praise
2179 **
2180 ** Query parameters:
2181 **
2182 ** checkin=ID The manifest ID at which to start the annotation
2183 ** filename=FILENAME The filename.
@@ -2140,19 +2188,21 @@
2188 void annotation_page(void){
2189 int mid;
2190 int fnid;
2191 int i;
2192 int iLimit; /* Depth limit */
2193 int annFlags = ANN_FILE_ANCEST;
2194 int showLog = 0; /* True to display the log */
2195 int ignoreWs = 0; /* Ignore whitespace */
2196 u64 diffFlags = 0; /* diff flags for ignore whitespace */
2197 const char *zFilename; /* Name of file to annotate */
2198 const char *zCI; /* The check-in containing zFilename */
2199 Annotator ann;
2200 HQuery url;
2201 struct AnnVers *p;
2202 unsigned clr1, clr2, clr;
2203 int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */
2204
2205 /* Gather query parameters */
2206 showLog = atoi(PD("log","1"));
2207 login_check_credentials();
2208 if( !g.perm.Read ){ login_needed(); return; }
@@ -2161,28 +2211,42 @@
2211 zFilename = P("filename");
2212 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
2213 if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
2214 iLimit = atoi(PD("limit","20"));
2215 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
2216 ignoreWs = P("w")!=0;
2217 if( ignoreWs ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
2218 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
2219 fossil_redirect_home();
2220 }
2221
2222 /* compute the annotation */
2223 compute_direct_ancestors(mid, 10000000);
2224 annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags);
2225 zCI = ann.aVers[0].zMUuid;
2226
2227 /* generate the web page */
2228 style_header("Annotation For %h", zFilename);
2229 if( bBlame ){
2230 url_initialize(&url, "blame");
2231 }else{
2232 url_initialize(&url, "annotate");
2233 }
2234 url_add_parameter(&url, "checkin", P("checkin"));
2235 url_add_parameter(&url, "filename", zFilename);
2236 if( iLimit!=20 ){
2237 url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit));
2238 }
2239 url_add_parameter(&url, "log", showLog ? "1" : "0");
2240 if( ignoreWs ){
2241 url_add_parameter(&url, "w", "");
2242 style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes",
2243 "%s", url_render(&url, "w", 0, 0, 0));
2244 }else{
2245 style_submenu_element("Ignore Whitespace", "Ignore Whitespace",
2246 "%s", url_render(&url, "w", "", 0, 0));
2247 }
2248 if( showLog ){
2249 style_submenu_element("Hide Log", "Hide Log",
2250 "%s", url_render(&url, "log", "0", 0, 0));
2251 }else{
2252 style_submenu_element("Show Log", "Show Log",
@@ -2208,11 +2272,11 @@
2272 clr2 = 0xb5e0ff; /* Older changes: blue (cold) */
2273 }
2274 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2275 clr = gradient_color(clr1, clr2, ann.nVers-1, i);
2276 ann.aVers[i].zBgColor = mprintf("#%06x", clr);
2277 }
2278
2279 if( showLog ){
2280 char *zLink = href("%R/finfo?name=%t&ci=%S",zFilename,zCI);
2281 @ <h2>Ancestors of %z(zLink)%h(zFilename)</a> analyzed:</h2>
2282 @ <ol>
@@ -2238,11 +2302,11 @@
2302 }
2303 @ </ol>
2304 @ <hr>
2305 }
2306 if( !ann.bLimit ){
2307 @ <h2>Origin for each line in
2308 @ %z(href("%R/finfo?name=%h&ci=%S", zFilename, zCI))%h(zFilename)</a>
2309 @ from check-in %z(href("%R/info/%S",zCI))%S(zCI)</a>:</h2>
2310 iLimit = ann.nVers+10;
2311 }else{
2312 @ <h2>Lines added by the %d(iLimit) most recent ancestors of
@@ -2252,10 +2316,11 @@
2316 @ <pre>
2317 for(i=0; i<ann.nOrig; i++){
2318 int iVers = ann.aOrig[i].iVers;
2319 char *z = (char*)ann.aOrig[i].z;
2320 int n = ann.aOrig[i].n;
2321 int indent = ann.aOrig[i].indent+1;
2322 char zPrefix[300];
2323 z[n] = 0;
2324 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2325
2326 if( bBlame ){
@@ -2266,47 +2331,51 @@
2331 "<span style='background-color:%s'>"
2332 "%s%.10s</a> %s</span> %13.13s:",
2333 p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser);
2334 fossil_free(zLink);
2335 }else{
2336 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s%*s", indent, " ");
2337 }
2338 }else{
2339 if( iVers>=0 ){
2340 struct AnnVers *p = ann.aVers+iVers;
2341 char *zLink = xhref("target='infowindow'", "%R/info/%S", p->zMUuid);
2342 sqlite3_snprintf(sizeof(zPrefix), zPrefix,
2343 "<span style='background-color:%s'>"
2344 "%s%.10s</a> %s</span> %4d:%*s",
2345 p->zBgColor, zLink, p->zMUuid, p->zDate, i+1, indent, " ");
2346 fossil_free(zLink);
2347 }else{
2348 sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:%*s", "", i+1, indent, " ");
2349 }
2350 }
2351 @ %s(zPrefix)%h(z)
2352
2353 }
2354 @ </pre>
2355 style_footer();
2356 }
2357
2358 /*
2359 ** COMMAND: annotate
2360 ** COMMAND: blame
2361 ** COMMAND: praise
2362 **
2363 ** %fossil (annotate|blame|praise) ?OPTIONS? FILENAME
2364 **
2365 ** Output the text of a file with markings to show when each line of
2366 ** the file was last modified. The "annotate" command shows line numbers
2367 ** and omits the username. The "blame" and "praise" commands show the user
2368 ** who made each checkin and omits the line number.
2369 **
2370 ** Options:
2371 ** --filevers Show file version numbers rather than check-in versions
2372 ** -l|--log List all versions analyzed
2373 ** -n|--limit N Only look backwards in time by N versions
2374 ** --ignore-space-at-eol Ignore eol-whitespaces
2375 ** --ignore-space-at-sol Ignore sol-whitespaces
2376 ** -w Ignore all whitespaces
2377 **
2378 ** See also: info, finfo, timeline
2379 */
2380 void annotate_cmd(void){
2381 int fnid; /* Filename ID */
@@ -2318,19 +2387,23 @@
2387 Annotator ann; /* The annotation of the file */
2388 int i; /* Loop counter */
2389 const char *zLimit; /* The value to the -n|--limit option */
2390 int iLimit; /* How far back in time to look */
2391 int showLog; /* True to show the log */
2392 u64 diffFlags = 0;/* Flags to control whitespace handling */
2393 int fileVers; /* Show file version instead of check-in versions */
2394 int annFlags = 0; /* Flags to control annotation properties */
2395 int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */
2396
2397 bBlame = g.argv[1][0]!='a';
2398 zLimit = find_option("limit","n",1);
2399 if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
2400 iLimit = atoi(zLimit);
2401 showLog = find_option("log","l",0)!=0;
2402 if( find_option("ignore-space-at-sol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_SOLWS;
2403 if( find_option("ignore-space-at-eol",0,0)!=0 ) diffFlags |= DIFF_IGNORE_EOLWS;
2404 if( find_option("w",0,0)!=0 ) diffFlags |= (DIFF_IGNORE_EOLWS|DIFF_IGNORE_SOLWS);
2405 fileVers = find_option("filevers",0,0)!=0;
2406 db_must_be_within_tree();
2407 if( g.argc<3 ) {
2408 usage("FILENAME");
2409 }
@@ -2356,11 +2429,11 @@
2429 fid, fnid);
2430 if( mid==0 ){
2431 fossil_fatal("unable to find manifest");
2432 }
2433 annFlags |= ANN_FILE_ANCEST;
2434 annotate_file(&ann, fnid, mid, iLimit, annFlags, diffFlags);
2435 if( showLog ){
2436 struct AnnVers *p;
2437 for(p=ann.aVers, i=0; i<ann.nVers; i++, p++){
2438 fossil_print("version %3d: %s %.10s file %.10s\n",
2439 i+1, p->zDate, p->zMUuid, p->zFUuid);
@@ -2368,27 +2441,28 @@
2441 fossil_print("---------------------------------------------------\n");
2442 }
2443 for(i=0; i<ann.nOrig; i++){
2444 int iVers = ann.aOrig[i].iVers;
2445 char *z = (char*)ann.aOrig[i].z;
2446 int indent = ann.aOrig[i].indent + 1;
2447 int n = ann.aOrig[i].n;
2448 struct AnnVers *p;
2449 if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1;
2450 p = ann.aVers + iVers;
2451 if( bBlame ){
2452 if( iVers>=0 ){
2453 fossil_print("%.10s %s %13.13s:%*s%.*s\n",
2454 fileVers ? p->zFUuid : p->zMUuid, p->zDate, p->zUser, indent, " ", n, z);
2455 }else{
2456 fossil_print("%35s %*s%.*s\n", "", indent, " ", n, z);
2457 }
2458 }else{
2459 if( iVers>=0 ){
2460 fossil_print("%.10s %s %5d:%*s%.*s\n",
2461 fileVers ? p->zFUuid : p->zMUuid, p->zDate, i+1, indent, " ", n, z);
2462 }else{
2463 fossil_print("%21s %5d:%*s%.*s\n",
2464 "", i+1, indent, " ", n, z);
2465 }
2466 }
2467 }
2468 }
2469
+95 -32
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -49,15 +49,25 @@
4949
if( diffFlags & DIFF_BRIEF ){
5050
/* no-op */
5151
}else if( diffFlags & DIFF_SIDEBYSIDE ){
5252
int w = diff_width(diffFlags);
5353
int n1 = strlen(zLeft);
54
+ int n2 = strlen(zRight);
5455
int x;
55
- if( n1>w*2 ) n1 = w*2;
56
- x = w*2+17 - (n1+2);
57
- z = mprintf("%.*c %.*s %.*c\n",
58
- x/2, '=', n1, zLeft, (x+1)/2, '=');
56
+ if( n1==n2 && fossil_strcmp(zLeft,zRight)==0 ){
57
+ if( n1>w*2 ) n1 = w*2;
58
+ x = w*2+17 - (n1+2);
59
+ z = mprintf("%.*c %.*s %.*c\n",
60
+ x/2, '=', n1, zLeft, (x+1)/2, '=');
61
+ }else{
62
+ if( w<20 ) w = 20;
63
+ if( n1>w-10 ) n1 = w - 10;
64
+ if( n2>w-10 ) n2 = w - 10;
65
+ z = mprintf("%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
66
+ (w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
67
+ (w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
68
+ }
5969
}else{
6070
z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
6171
}
6272
fossil_print("%s", z);
6373
fossil_free(z);
@@ -598,10 +608,11 @@
598608
}
599609
600610
/* A Tcl/Tk script used to render diff output.
601611
*/
602612
static const char zDiffScript[] =
613
+@ set prog {
603614
@ package require Tk
604615
@
605616
@ array set CFG {
606617
@ TITLE {Fossil Diff}
607618
@ LN_COL_BG #dddddd
@@ -617,10 +628,11 @@
617628
@ HR_PAD_TOP 4
618629
@ HR_PAD_BTM 8
619630
@ FN_BG #444444
620631
@ FN_FG #ffffff
621632
@ FN_PAD 5
633
+@ ERR_FG #ee0000
622634
@ PADX 5
623635
@ WIDTH 80
624636
@ HEIGHT 45
625637
@ LB_HEIGHT 25
626638
@ }
@@ -641,43 +653,65 @@
641653
@
642654
@ proc colType {c} {
643655
@ regexp {[a-z]+} $c type
644656
@ return $type
645657
@ }
658
+@
659
+@ proc getLine {difftxt N iivar} {
660
+@ upvar $iivar ii
661
+@ if {$ii>=$N} {return -1}
662
+@ set x [lindex $difftxt $ii]
663
+@ incr ii
664
+@ return $x
665
+@ }
646666
@
647667
@ proc readDiffs {fossilcmd} {
648
-@ set in [open $fossilcmd r]
649
-@ fconfigure $in -encoding utf-8
668
+@ global difftxt
669
+@ if {![info exists difftxt]} {
670
+@ set in [open $fossilcmd r]
671
+@ fconfigure $in -encoding utf-8
672
+@ set difftxt [split [read $in] \n]
673
+@ close $in
674
+@ }
675
+@ set N [llength $difftxt]
676
+@ set ii 0
650677
@ set nDiffs 0
651678
@ array set widths {txt 0 ln 0 mkr 0}
652
-@ while {[gets $in line] != -1} {
653
-@ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} {
679
+@ while {[set line [getLine $difftxt $N ii]] != -1} {
680
+@ set fn2 {}
681
+@ if {![regexp {^=+ (.*?) =+ versus =+ (.*?) =+$} $line all fn fn2]
682
+@ && ![regexp {^=+ (.*?) =+$} $line all fn]
683
+@ } {
654684
@ continue
655685
@ }
656
-@ if {[string compare -length 6 [gets $in] "<table"]} {
686
+@ set errMsg ""
687
+@ set line [getLine $difftxt $N ii]
688
+@ if {[string compare -length 6 $line "<table"]
689
+@ && ![regexp {<p[^>]*>(.+)} $line - errMsg]} {
657690
@ continue
658691
@ }
659692
@ incr nDiffs
660693
@ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
661694
@ .wfiles.lb insert end $fn
662695
@
663696
@ foreach c [cols] {
664
-@ while {[gets $in] ne "<pre>"} continue
665
-@
666697
@ if {$nDiffs > 1} {
667698
@ $c insert end \n -
668699
@ }
669700
@ if {[colType $c] eq "txt"} {
670701
@ $c insert end $fn\n fn
702
+@ if {$fn2!=""} {set fn $fn2}
671703
@ } else {
672704
@ $c insert end \n fn
673705
@ }
674706
@ $c insert end \n -
675707
@
708
+@ if {$errMsg ne ""} continue
709
+@ while {[getLine $difftxt $N ii] ne "<pre>"} continue
676710
@ set type [colType $c]
677711
@ set str {}
678
-@ while {[set line [gets $in]] ne "</pre>"} {
712
+@ while {[set line [getLine $difftxt $N ii]] ne "</pre>"} {
679713
@ set len [string length [dehtml $line]]
680714
@ if {$len > $widths($type)} {
681715
@ set widths($type) $len
682716
@ }
683717
@ append str $line\n
@@ -693,12 +727,16 @@
693727
@ } else {
694728
@ $c insert end [dehtml $pre] -
695729
@ }
696730
@ }
697731
@ }
732
+@
733
+@ if {$errMsg ne ""} {
734
+@ foreach c {.txtA .txtB} {$c insert end [string trim $errMsg] err}
735
+@ foreach c [cols] {$c insert end \n -}
736
+@ }
698737
@ }
699
-@ close $in
700738
@
701739
@ foreach c [cols] {
702740
@ set type [colType $c]
703741
@ if {$type ne "txt"} {
704742
@ $c config -width $widths($type)
@@ -797,12 +835,12 @@
797835
@ bind . <q> exit
798836
@ bind . <Destroy> {after 0 exit}
799837
@ bind . <Tab> {cycleDiffs; break}
800838
@ bind . <<PrevWindow>> {cycleDiffs 1; break}
801839
@ bind . <Return> {
802
-@ event generate .files <1>
803
-@ event generate .files <ButtonRelease-1>
840
+@ event generate .bb.files <1>
841
+@ event generate .bb.files <ButtonRelease-1>
804842
@ break
805843
@ }
806844
@ foreach {key axis args} {
807845
@ Up y {scroll -5 units}
808846
@ Down y {scroll 5 units}
@@ -815,21 +853,22 @@
815853
@ } {
816854
@ bind . <$key> "scroll-$axis $args; break"
817855
@ bind . <Shift-$key> continue
818856
@ }
819857
@
820
-@ ::ttk::menubutton .files -text "Files"
858
+@ frame .bb
859
+@ ::ttk::menubutton .bb.files -text "Files"
821860
@ toplevel .wfiles
822861
@ wm withdraw .wfiles
823862
@ update idletasks
824863
@ wm transient .wfiles .
825864
@ wm overrideredirect .wfiles 1
826865
@ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
827866
@ -yscroll {.wfiles.sb set}
828867
@ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview}
829868
@ grid .wfiles.lb .wfiles.sb -sticky ns
830
-@ bind .files <1> {
869
+@ bind .bb.files <1> {
831870
@ set x [winfo rootx %W]
832871
@ set y [expr {[winfo rooty %W]+[winfo height %W]}]
833872
@ wm geometry .wfiles +$x+$y
834873
@ wm deiconify .wfiles
835874
@ focus .wfiles.lb
@@ -864,10 +903,11 @@
864903
@ $txt tag config $tag -background $CFG([string toupper $tag]_BG)
865904
@ $txt tag lower $tag
866905
@ }
867906
@ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
868907
@ -justify center
908
+@ $txt tag config err -foreground $CFG(ERR_FG)
869909
@ }
870910
@ text .mkr
871911
@
872912
@ foreach c [cols] {
873913
@ set keyPrefix [string toupper [colType $c]]_COL_
@@ -890,22 +930,42 @@
890930
@ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
891931
@ exit
892932
@ }
893933
@ update idletasks
894934
@
935
+@ proc saveDiff {} {
936
+@ set fn [tk_getSaveFile]
937
+@ set out [open $fn wb]
938
+@ puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
939
+@ puts $out "# to see the graphical diff.\n#"
940
+@ puts $out "set fossilcmd {}"
941
+@ puts $out "set prog [list $::prog]"
942
+@ puts $out "set difftxt \173"
943
+@ foreach e $::difftxt {puts $out [list $e]}
944
+@ puts $out "\175"
945
+@ puts $out "eval \$prog"
946
+@ close $out
947
+@ }
948
+@ ::ttk::button .bb.quit -text {Quit} -command exit
949
+@ ::ttk::button .bb.save -text {Save As...} -command saveDiff
950
+@ pack .bb.quit -side left
951
+@ if {$fossilcmd!=""} {pack .bb.save -side left}
952
+@ pack .bb.files -side left
895953
@ grid rowconfigure . 1 -weight 1
896954
@ grid columnconfigure . 1 -weight 1
897955
@ grid columnconfigure . 4 -weight 1
898
-@ grid .files -row 0 -columnspan 6
956
+@ grid .bb -row 0 -columnspan 6
899957
@ eval grid [cols] -row 1 -sticky nsew
900958
@ grid .sby -row 1 -column 5 -sticky ns
901959
@ grid .sbxA -row 2 -columnspan 2 -sticky ew
902960
@ grid .spacer -row 2 -column 2
903961
@ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew
904962
@
905963
@ .spacer config -height [winfo height .sbxA]
906964
@ wm deiconify .
965
+@ }
966
+@ eval $prog
907967
;
908968
909969
/*
910970
** Show diff output in a Tcl/Tk window, in response to the --tk option
911971
** to the diff command.
@@ -1029,23 +1089,27 @@
10291089
** The "--binary" option causes files matching the glob PATTERN to be treated
10301090
** as binary when considering if they should be used with external diff program.
10311091
** This option overrides the "binary-glob" setting.
10321092
**
10331093
** Options:
1034
-** --binary PATTERN Treat files that match the glob PATTERN as binary
1035
-** --branch BRANCH Show diff of all changes on BRANCH
1036
-** --brief Show filenames only
1037
-** --context|-c N Use N lines of context
1038
-** --diff-binary BOOL Include binary files when using external commands
1039
-** --from|-r VERSION select VERSION as source for the diff
1040
-** --internal|-i use internal diff logic
1041
-** --side-by-side|-y side-by-side diff
1042
-** --tk Launch a Tcl/Tk GUI for display
1043
-** --to VERSION select VERSION as target for the diff
1044
-** --unified unified diff
1045
-** -v|--verbose output complete text of added or deleted files
1046
-** -W|--width Width of lines in side-by-side diff
1094
+** --binary PATTERN Treat files that match the glob PATTERN as binary
1095
+** --branch BRANCH Show diff of all changes on BRANCH
1096
+** --brief Show filenames only
1097
+** --context|-c N Use N lines of context
1098
+** --diff-binary BOOL Include binary files when using external commands
1099
+** --from|-r VERSION select VERSION as source for the diff
1100
+** --ignore-space-at-eol Ignore changes to end-of-line whitespace
1101
+** --ignore-space-at-sol Ignore changes to start-of-line whitespace
1102
+** --internal|-i use internal diff logic
1103
+** --side-by-side|-y side-by-side diff
1104
+** --tk Launch a Tcl/Tk GUI for display
1105
+** --to VERSION select VERSION as target for the diff
1106
+** --unified unified diff
1107
+** -v|--verbose output complete text of added or deleted files
1108
+** -w Ignore changes to start-of-line and end-of-line
1109
+** whitespace
1110
+** -W|--width Width of lines in side-by-side diff
10471111
*/
10481112
void diff_cmd(void){
10491113
int isGDiff; /* True for gdiff. False for normal diff */
10501114
int isInternDiff; /* True for internal diff */
10511115
int verboseFlag; /* True if -v or --verbose flag is used */
@@ -1071,11 +1135,10 @@
10711135
verboseFlag = find_option("verbose","v",0)!=0;
10721136
if( !verboseFlag ){
10731137
verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */
10741138
}
10751139
if( verboseFlag ) diffFlags |= DIFF_VERBOSE;
1076
-
10771140
if( zBranch ){
10781141
if( zTo || zFrom ){
10791142
fossil_fatal("cannot use --from or --to with --branch");
10801143
}
10811144
zTo = zBranch;
10821145
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -49,15 +49,25 @@
49 if( diffFlags & DIFF_BRIEF ){
50 /* no-op */
51 }else if( diffFlags & DIFF_SIDEBYSIDE ){
52 int w = diff_width(diffFlags);
53 int n1 = strlen(zLeft);
 
54 int x;
55 if( n1>w*2 ) n1 = w*2;
56 x = w*2+17 - (n1+2);
57 z = mprintf("%.*c %.*s %.*c\n",
58 x/2, '=', n1, zLeft, (x+1)/2, '=');
 
 
 
 
 
 
 
 
 
59 }else{
60 z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
61 }
62 fossil_print("%s", z);
63 fossil_free(z);
@@ -598,10 +608,11 @@
598 }
599
600 /* A Tcl/Tk script used to render diff output.
601 */
602 static const char zDiffScript[] =
 
603 @ package require Tk
604 @
605 @ array set CFG {
606 @ TITLE {Fossil Diff}
607 @ LN_COL_BG #dddddd
@@ -617,10 +628,11 @@
617 @ HR_PAD_TOP 4
618 @ HR_PAD_BTM 8
619 @ FN_BG #444444
620 @ FN_FG #ffffff
621 @ FN_PAD 5
 
622 @ PADX 5
623 @ WIDTH 80
624 @ HEIGHT 45
625 @ LB_HEIGHT 25
626 @ }
@@ -641,43 +653,65 @@
641 @
642 @ proc colType {c} {
643 @ regexp {[a-z]+} $c type
644 @ return $type
645 @ }
 
 
 
 
 
 
 
 
646 @
647 @ proc readDiffs {fossilcmd} {
648 @ set in [open $fossilcmd r]
649 @ fconfigure $in -encoding utf-8
 
 
 
 
 
 
 
650 @ set nDiffs 0
651 @ array set widths {txt 0 ln 0 mkr 0}
652 @ while {[gets $in line] != -1} {
653 @ if {![regexp {^=+\s+(.*?)\s+=+$} $line all fn]} {
 
 
 
654 @ continue
655 @ }
656 @ if {[string compare -length 6 [gets $in] "<table"]} {
 
 
 
657 @ continue
658 @ }
659 @ incr nDiffs
660 @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
661 @ .wfiles.lb insert end $fn
662 @
663 @ foreach c [cols] {
664 @ while {[gets $in] ne "<pre>"} continue
665 @
666 @ if {$nDiffs > 1} {
667 @ $c insert end \n -
668 @ }
669 @ if {[colType $c] eq "txt"} {
670 @ $c insert end $fn\n fn
 
671 @ } else {
672 @ $c insert end \n fn
673 @ }
674 @ $c insert end \n -
675 @
 
 
676 @ set type [colType $c]
677 @ set str {}
678 @ while {[set line [gets $in]] ne "</pre>"} {
679 @ set len [string length [dehtml $line]]
680 @ if {$len > $widths($type)} {
681 @ set widths($type) $len
682 @ }
683 @ append str $line\n
@@ -693,12 +727,16 @@
693 @ } else {
694 @ $c insert end [dehtml $pre] -
695 @ }
696 @ }
697 @ }
 
 
 
 
 
698 @ }
699 @ close $in
700 @
701 @ foreach c [cols] {
702 @ set type [colType $c]
703 @ if {$type ne "txt"} {
704 @ $c config -width $widths($type)
@@ -797,12 +835,12 @@
797 @ bind . <q> exit
798 @ bind . <Destroy> {after 0 exit}
799 @ bind . <Tab> {cycleDiffs; break}
800 @ bind . <<PrevWindow>> {cycleDiffs 1; break}
801 @ bind . <Return> {
802 @ event generate .files <1>
803 @ event generate .files <ButtonRelease-1>
804 @ break
805 @ }
806 @ foreach {key axis args} {
807 @ Up y {scroll -5 units}
808 @ Down y {scroll 5 units}
@@ -815,21 +853,22 @@
815 @ } {
816 @ bind . <$key> "scroll-$axis $args; break"
817 @ bind . <Shift-$key> continue
818 @ }
819 @
820 @ ::ttk::menubutton .files -text "Files"
 
821 @ toplevel .wfiles
822 @ wm withdraw .wfiles
823 @ update idletasks
824 @ wm transient .wfiles .
825 @ wm overrideredirect .wfiles 1
826 @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
827 @ -yscroll {.wfiles.sb set}
828 @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview}
829 @ grid .wfiles.lb .wfiles.sb -sticky ns
830 @ bind .files <1> {
831 @ set x [winfo rootx %W]
832 @ set y [expr {[winfo rooty %W]+[winfo height %W]}]
833 @ wm geometry .wfiles +$x+$y
834 @ wm deiconify .wfiles
835 @ focus .wfiles.lb
@@ -864,10 +903,11 @@
864 @ $txt tag config $tag -background $CFG([string toupper $tag]_BG)
865 @ $txt tag lower $tag
866 @ }
867 @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
868 @ -justify center
 
869 @ }
870 @ text .mkr
871 @
872 @ foreach c [cols] {
873 @ set keyPrefix [string toupper [colType $c]]_COL_
@@ -890,22 +930,42 @@
890 @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
891 @ exit
892 @ }
893 @ update idletasks
894 @
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
895 @ grid rowconfigure . 1 -weight 1
896 @ grid columnconfigure . 1 -weight 1
897 @ grid columnconfigure . 4 -weight 1
898 @ grid .files -row 0 -columnspan 6
899 @ eval grid [cols] -row 1 -sticky nsew
900 @ grid .sby -row 1 -column 5 -sticky ns
901 @ grid .sbxA -row 2 -columnspan 2 -sticky ew
902 @ grid .spacer -row 2 -column 2
903 @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew
904 @
905 @ .spacer config -height [winfo height .sbxA]
906 @ wm deiconify .
 
 
907 ;
908
909 /*
910 ** Show diff output in a Tcl/Tk window, in response to the --tk option
911 ** to the diff command.
@@ -1029,23 +1089,27 @@
1029 ** The "--binary" option causes files matching the glob PATTERN to be treated
1030 ** as binary when considering if they should be used with external diff program.
1031 ** This option overrides the "binary-glob" setting.
1032 **
1033 ** Options:
1034 ** --binary PATTERN Treat files that match the glob PATTERN as binary
1035 ** --branch BRANCH Show diff of all changes on BRANCH
1036 ** --brief Show filenames only
1037 ** --context|-c N Use N lines of context
1038 ** --diff-binary BOOL Include binary files when using external commands
1039 ** --from|-r VERSION select VERSION as source for the diff
1040 ** --internal|-i use internal diff logic
1041 ** --side-by-side|-y side-by-side diff
1042 ** --tk Launch a Tcl/Tk GUI for display
1043 ** --to VERSION select VERSION as target for the diff
1044 ** --unified unified diff
1045 ** -v|--verbose output complete text of added or deleted files
1046 ** -W|--width Width of lines in side-by-side diff
 
 
 
 
1047 */
1048 void diff_cmd(void){
1049 int isGDiff; /* True for gdiff. False for normal diff */
1050 int isInternDiff; /* True for internal diff */
1051 int verboseFlag; /* True if -v or --verbose flag is used */
@@ -1071,11 +1135,10 @@
1071 verboseFlag = find_option("verbose","v",0)!=0;
1072 if( !verboseFlag ){
1073 verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */
1074 }
1075 if( verboseFlag ) diffFlags |= DIFF_VERBOSE;
1076
1077 if( zBranch ){
1078 if( zTo || zFrom ){
1079 fossil_fatal("cannot use --from or --to with --branch");
1080 }
1081 zTo = zBranch;
1082
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -49,15 +49,25 @@
49 if( diffFlags & DIFF_BRIEF ){
50 /* no-op */
51 }else if( diffFlags & DIFF_SIDEBYSIDE ){
52 int w = diff_width(diffFlags);
53 int n1 = strlen(zLeft);
54 int n2 = strlen(zRight);
55 int x;
56 if( n1==n2 && fossil_strcmp(zLeft,zRight)==0 ){
57 if( n1>w*2 ) n1 = w*2;
58 x = w*2+17 - (n1+2);
59 z = mprintf("%.*c %.*s %.*c\n",
60 x/2, '=', n1, zLeft, (x+1)/2, '=');
61 }else{
62 if( w<20 ) w = 20;
63 if( n1>w-10 ) n1 = w - 10;
64 if( n2>w-10 ) n2 = w - 10;
65 z = mprintf("%.*c %.*s %.*c versus %.*c %.*s %.*c\n",
66 (w-n1+10)/2, '=', n1, zLeft, (w-n1+1)/2, '=',
67 (w-n2)/2, '=', n2, zRight, (w-n2+1)/2, '=');
68 }
69 }else{
70 z = mprintf("--- %s\n+++ %s\n", zLeft, zRight);
71 }
72 fossil_print("%s", z);
73 fossil_free(z);
@@ -598,10 +608,11 @@
608 }
609
610 /* A Tcl/Tk script used to render diff output.
611 */
612 static const char zDiffScript[] =
613 @ set prog {
614 @ package require Tk
615 @
616 @ array set CFG {
617 @ TITLE {Fossil Diff}
618 @ LN_COL_BG #dddddd
@@ -617,10 +628,11 @@
628 @ HR_PAD_TOP 4
629 @ HR_PAD_BTM 8
630 @ FN_BG #444444
631 @ FN_FG #ffffff
632 @ FN_PAD 5
633 @ ERR_FG #ee0000
634 @ PADX 5
635 @ WIDTH 80
636 @ HEIGHT 45
637 @ LB_HEIGHT 25
638 @ }
@@ -641,43 +653,65 @@
653 @
654 @ proc colType {c} {
655 @ regexp {[a-z]+} $c type
656 @ return $type
657 @ }
658 @
659 @ proc getLine {difftxt N iivar} {
660 @ upvar $iivar ii
661 @ if {$ii>=$N} {return -1}
662 @ set x [lindex $difftxt $ii]
663 @ incr ii
664 @ return $x
665 @ }
666 @
667 @ proc readDiffs {fossilcmd} {
668 @ global difftxt
669 @ if {![info exists difftxt]} {
670 @ set in [open $fossilcmd r]
671 @ fconfigure $in -encoding utf-8
672 @ set difftxt [split [read $in] \n]
673 @ close $in
674 @ }
675 @ set N [llength $difftxt]
676 @ set ii 0
677 @ set nDiffs 0
678 @ array set widths {txt 0 ln 0 mkr 0}
679 @ while {[set line [getLine $difftxt $N ii]] != -1} {
680 @ set fn2 {}
681 @ if {![regexp {^=+ (.*?) =+ versus =+ (.*?) =+$} $line all fn fn2]
682 @ && ![regexp {^=+ (.*?) =+$} $line all fn]
683 @ } {
684 @ continue
685 @ }
686 @ set errMsg ""
687 @ set line [getLine $difftxt $N ii]
688 @ if {[string compare -length 6 $line "<table"]
689 @ && ![regexp {<p[^>]*>(.+)} $line - errMsg]} {
690 @ continue
691 @ }
692 @ incr nDiffs
693 @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
694 @ .wfiles.lb insert end $fn
695 @
696 @ foreach c [cols] {
 
 
697 @ if {$nDiffs > 1} {
698 @ $c insert end \n -
699 @ }
700 @ if {[colType $c] eq "txt"} {
701 @ $c insert end $fn\n fn
702 @ if {$fn2!=""} {set fn $fn2}
703 @ } else {
704 @ $c insert end \n fn
705 @ }
706 @ $c insert end \n -
707 @
708 @ if {$errMsg ne ""} continue
709 @ while {[getLine $difftxt $N ii] ne "<pre>"} continue
710 @ set type [colType $c]
711 @ set str {}
712 @ while {[set line [getLine $difftxt $N ii]] ne "</pre>"} {
713 @ set len [string length [dehtml $line]]
714 @ if {$len > $widths($type)} {
715 @ set widths($type) $len
716 @ }
717 @ append str $line\n
@@ -693,12 +727,16 @@
727 @ } else {
728 @ $c insert end [dehtml $pre] -
729 @ }
730 @ }
731 @ }
732 @
733 @ if {$errMsg ne ""} {
734 @ foreach c {.txtA .txtB} {$c insert end [string trim $errMsg] err}
735 @ foreach c [cols] {$c insert end \n -}
736 @ }
737 @ }
 
738 @
739 @ foreach c [cols] {
740 @ set type [colType $c]
741 @ if {$type ne "txt"} {
742 @ $c config -width $widths($type)
@@ -797,12 +835,12 @@
835 @ bind . <q> exit
836 @ bind . <Destroy> {after 0 exit}
837 @ bind . <Tab> {cycleDiffs; break}
838 @ bind . <<PrevWindow>> {cycleDiffs 1; break}
839 @ bind . <Return> {
840 @ event generate .bb.files <1>
841 @ event generate .bb.files <ButtonRelease-1>
842 @ break
843 @ }
844 @ foreach {key axis args} {
845 @ Up y {scroll -5 units}
846 @ Down y {scroll 5 units}
@@ -815,21 +853,22 @@
853 @ } {
854 @ bind . <$key> "scroll-$axis $args; break"
855 @ bind . <Shift-$key> continue
856 @ }
857 @
858 @ frame .bb
859 @ ::ttk::menubutton .bb.files -text "Files"
860 @ toplevel .wfiles
861 @ wm withdraw .wfiles
862 @ update idletasks
863 @ wm transient .wfiles .
864 @ wm overrideredirect .wfiles 1
865 @ listbox .wfiles.lb -width 0 -height $CFG(LB_HEIGHT) -activestyle none \
866 @ -yscroll {.wfiles.sb set}
867 @ ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview}
868 @ grid .wfiles.lb .wfiles.sb -sticky ns
869 @ bind .bb.files <1> {
870 @ set x [winfo rootx %W]
871 @ set y [expr {[winfo rooty %W]+[winfo height %W]}]
872 @ wm geometry .wfiles +$x+$y
873 @ wm deiconify .wfiles
874 @ focus .wfiles.lb
@@ -864,10 +903,11 @@
903 @ $txt tag config $tag -background $CFG([string toupper $tag]_BG)
904 @ $txt tag lower $tag
905 @ }
906 @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
907 @ -justify center
908 @ $txt tag config err -foreground $CFG(ERR_FG)
909 @ }
910 @ text .mkr
911 @
912 @ foreach c [cols] {
913 @ set keyPrefix [string toupper [colType $c]]_COL_
@@ -890,22 +930,42 @@
930 @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
931 @ exit
932 @ }
933 @ update idletasks
934 @
935 @ proc saveDiff {} {
936 @ set fn [tk_getSaveFile]
937 @ set out [open $fn wb]
938 @ puts $out "#!/usr/bin/tclsh\n#\n# Run this script using 'tclsh' or 'wish'"
939 @ puts $out "# to see the graphical diff.\n#"
940 @ puts $out "set fossilcmd {}"
941 @ puts $out "set prog [list $::prog]"
942 @ puts $out "set difftxt \173"
943 @ foreach e $::difftxt {puts $out [list $e]}
944 @ puts $out "\175"
945 @ puts $out "eval \$prog"
946 @ close $out
947 @ }
948 @ ::ttk::button .bb.quit -text {Quit} -command exit
949 @ ::ttk::button .bb.save -text {Save As...} -command saveDiff
950 @ pack .bb.quit -side left
951 @ if {$fossilcmd!=""} {pack .bb.save -side left}
952 @ pack .bb.files -side left
953 @ grid rowconfigure . 1 -weight 1
954 @ grid columnconfigure . 1 -weight 1
955 @ grid columnconfigure . 4 -weight 1
956 @ grid .bb -row 0 -columnspan 6
957 @ eval grid [cols] -row 1 -sticky nsew
958 @ grid .sby -row 1 -column 5 -sticky ns
959 @ grid .sbxA -row 2 -columnspan 2 -sticky ew
960 @ grid .spacer -row 2 -column 2
961 @ grid .sbxB -row 2 -column 3 -columnspan 2 -sticky ew
962 @
963 @ .spacer config -height [winfo height .sbxA]
964 @ wm deiconify .
965 @ }
966 @ eval $prog
967 ;
968
969 /*
970 ** Show diff output in a Tcl/Tk window, in response to the --tk option
971 ** to the diff command.
@@ -1029,23 +1089,27 @@
1089 ** The "--binary" option causes files matching the glob PATTERN to be treated
1090 ** as binary when considering if they should be used with external diff program.
1091 ** This option overrides the "binary-glob" setting.
1092 **
1093 ** Options:
1094 ** --binary PATTERN Treat files that match the glob PATTERN as binary
1095 ** --branch BRANCH Show diff of all changes on BRANCH
1096 ** --brief Show filenames only
1097 ** --context|-c N Use N lines of context
1098 ** --diff-binary BOOL Include binary files when using external commands
1099 ** --from|-r VERSION select VERSION as source for the diff
1100 ** --ignore-space-at-eol Ignore changes to end-of-line whitespace
1101 ** --ignore-space-at-sol Ignore changes to start-of-line whitespace
1102 ** --internal|-i use internal diff logic
1103 ** --side-by-side|-y side-by-side diff
1104 ** --tk Launch a Tcl/Tk GUI for display
1105 ** --to VERSION select VERSION as target for the diff
1106 ** --unified unified diff
1107 ** -v|--verbose output complete text of added or deleted files
1108 ** -w Ignore changes to start-of-line and end-of-line
1109 ** whitespace
1110 ** -W|--width Width of lines in side-by-side diff
1111 */
1112 void diff_cmd(void){
1113 int isGDiff; /* True for gdiff. False for normal diff */
1114 int isInternDiff; /* True for internal diff */
1115 int verboseFlag; /* True if -v or --verbose flag is used */
@@ -1071,11 +1135,10 @@
1135 verboseFlag = find_option("verbose","v",0)!=0;
1136 if( !verboseFlag ){
1137 verboseFlag = find_option("new-file","N",0)!=0; /* deprecated */
1138 }
1139 if( verboseFlag ) diffFlags |= DIFF_VERBOSE;
 
1140 if( zBranch ){
1141 if( zTo || zFrom ){
1142 fossil_fatal("cannot use --from or --to with --branch");
1143 }
1144 zTo = zBranch;
1145
+8 -8
--- src/event.c
+++ src/event.c
@@ -185,11 +185,11 @@
185185
blob_init(&comment, pEvent->zComment, -1);
186186
wiki_convert(&comment, 0, WIKI_INLINE);
187187
blob_reset(&comment);
188188
@ </div>
189189
@ </blockquote><hr />
190
- }
190
+ }
191191
192192
wiki_convert(&tail, 0, 0);
193193
style_footer();
194194
manifest_destroy(pEvent);
195195
}
@@ -227,11 +227,11 @@
227227
fossil_redirect_home();
228228
return;
229229
}
230230
}
231231
zTag = mprintf("event-%s", zEventId);
232
- rid = db_int(0,
232
+ rid = db_int(0,
233233
"SELECT rid FROM tagxref"
234234
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
235235
" ORDER BY mtime DESC", zTag
236236
);
237237
free(zTag);
@@ -312,11 +312,11 @@
312312
Stmt q;
313313
char *zBlob;
314314
315315
/* Load the tags string into a blob */
316316
blob_zero(&tags);
317
- blob_append(&tags, zTags, -1);
317
+ blob_append(&tags, zTags, -1);
318318
319319
/* Collapse all sequences of whitespace and "," characters into
320320
** a single space character */
321321
zBlob = blob_str(&tags);
322322
for(i=j=0; zBlob[i]; i++, j++){
@@ -341,11 +341,11 @@
341341
db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
342342
while( db_step(&q)==SQLITE_ROW ){
343343
blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
344344
}
345345
db_finalize(&q);
346
- }
346
+ }
347347
if( g.zLogin ){
348348
blob_appendf(&event, "U %F\n", g.zLogin);
349349
}
350350
blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
351351
md5sum_blob(&event, &cksum);
@@ -411,27 +411,27 @@
411411
@ <input type="text" name="t" size="25" value="%h(zETime)" />
412412
@ </td></tr>
413413
414414
@ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
415415
@ <td valign="top">
416
- @ <textarea name="c" class="eventedit" cols="80"
416
+ @ <textarea name="c" class="eventedit" cols="80"
417417
@ rows="3" wrap="virtual">%h(zComment)</textarea>
418418
@ </td></tr>
419419
420420
@ <tr><th align="right" valign="top">Background&nbsp;Color:</th>
421421
@ <td valign="top">
422422
render_color_chooser(0, zClr, 0, "clr", "cclr");
423423
@ </td></tr>
424
-
424
+
425425
@ <tr><th align="right" valign="top">Tags:</th>
426426
@ <td valign="top">
427427
@ <input type="text" name="g" size="40" value="%h(zTags)" />
428428
@ </td></tr>
429
-
429
+
430430
@ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
431431
@ <td valign="top">
432
- @ <textarea name="w" class="eventedit" cols="80"
432
+ @ <textarea name="w" class="eventedit" cols="80"
433433
@ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
434434
@ </td></tr>
435435
436436
@ <tr><td colspan="2">
437437
@ <input type="submit" name="preview" value="Preview Your Changes" />
438438
--- src/event.c
+++ src/event.c
@@ -185,11 +185,11 @@
185 blob_init(&comment, pEvent->zComment, -1);
186 wiki_convert(&comment, 0, WIKI_INLINE);
187 blob_reset(&comment);
188 @ </div>
189 @ </blockquote><hr />
190 }
191
192 wiki_convert(&tail, 0, 0);
193 style_footer();
194 manifest_destroy(pEvent);
195 }
@@ -227,11 +227,11 @@
227 fossil_redirect_home();
228 return;
229 }
230 }
231 zTag = mprintf("event-%s", zEventId);
232 rid = db_int(0,
233 "SELECT rid FROM tagxref"
234 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
235 " ORDER BY mtime DESC", zTag
236 );
237 free(zTag);
@@ -312,11 +312,11 @@
312 Stmt q;
313 char *zBlob;
314
315 /* Load the tags string into a blob */
316 blob_zero(&tags);
317 blob_append(&tags, zTags, -1);
318
319 /* Collapse all sequences of whitespace and "," characters into
320 ** a single space character */
321 zBlob = blob_str(&tags);
322 for(i=j=0; zBlob[i]; i++, j++){
@@ -341,11 +341,11 @@
341 db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
342 while( db_step(&q)==SQLITE_ROW ){
343 blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
344 }
345 db_finalize(&q);
346 }
347 if( g.zLogin ){
348 blob_appendf(&event, "U %F\n", g.zLogin);
349 }
350 blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
351 md5sum_blob(&event, &cksum);
@@ -411,27 +411,27 @@
411 @ <input type="text" name="t" size="25" value="%h(zETime)" />
412 @ </td></tr>
413
414 @ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
415 @ <td valign="top">
416 @ <textarea name="c" class="eventedit" cols="80"
417 @ rows="3" wrap="virtual">%h(zComment)</textarea>
418 @ </td></tr>
419
420 @ <tr><th align="right" valign="top">Background&nbsp;Color:</th>
421 @ <td valign="top">
422 render_color_chooser(0, zClr, 0, "clr", "cclr");
423 @ </td></tr>
424
425 @ <tr><th align="right" valign="top">Tags:</th>
426 @ <td valign="top">
427 @ <input type="text" name="g" size="40" value="%h(zTags)" />
428 @ </td></tr>
429
430 @ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
431 @ <td valign="top">
432 @ <textarea name="w" class="eventedit" cols="80"
433 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
434 @ </td></tr>
435
436 @ <tr><td colspan="2">
437 @ <input type="submit" name="preview" value="Preview Your Changes" />
438
--- src/event.c
+++ src/event.c
@@ -185,11 +185,11 @@
185 blob_init(&comment, pEvent->zComment, -1);
186 wiki_convert(&comment, 0, WIKI_INLINE);
187 blob_reset(&comment);
188 @ </div>
189 @ </blockquote><hr />
190 }
191
192 wiki_convert(&tail, 0, 0);
193 style_footer();
194 manifest_destroy(pEvent);
195 }
@@ -227,11 +227,11 @@
227 fossil_redirect_home();
228 return;
229 }
230 }
231 zTag = mprintf("event-%s", zEventId);
232 rid = db_int(0,
233 "SELECT rid FROM tagxref"
234 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
235 " ORDER BY mtime DESC", zTag
236 );
237 free(zTag);
@@ -312,11 +312,11 @@
312 Stmt q;
313 char *zBlob;
314
315 /* Load the tags string into a blob */
316 blob_zero(&tags);
317 blob_append(&tags, zTags, -1);
318
319 /* Collapse all sequences of whitespace and "," characters into
320 ** a single space character */
321 zBlob = blob_str(&tags);
322 for(i=j=0; zBlob[i]; i++, j++){
@@ -341,11 +341,11 @@
341 db_prepare(&q, "SELECT x FROM newtags ORDER BY x");
342 while( db_step(&q)==SQLITE_ROW ){
343 blob_appendf(&event, "T +sym-%F *\n", db_column_text(&q, 0));
344 }
345 db_finalize(&q);
346 }
347 if( g.zLogin ){
348 blob_appendf(&event, "U %F\n", g.zLogin);
349 }
350 blob_appendf(&event, "W %d\n%s\n", strlen(zBody), zBody);
351 md5sum_blob(&event, &cksum);
@@ -411,27 +411,27 @@
411 @ <input type="text" name="t" size="25" value="%h(zETime)" />
412 @ </td></tr>
413
414 @ <tr><th align="right" valign="top">Timeline&nbsp;Comment:</th>
415 @ <td valign="top">
416 @ <textarea name="c" class="eventedit" cols="80"
417 @ rows="3" wrap="virtual">%h(zComment)</textarea>
418 @ </td></tr>
419
420 @ <tr><th align="right" valign="top">Background&nbsp;Color:</th>
421 @ <td valign="top">
422 render_color_chooser(0, zClr, 0, "clr", "cclr");
423 @ </td></tr>
424
425 @ <tr><th align="right" valign="top">Tags:</th>
426 @ <td valign="top">
427 @ <input type="text" name="g" size="40" value="%h(zTags)" />
428 @ </td></tr>
429
430 @ <tr><th align="right" valign="top">Page&nbsp;Content:</th>
431 @ <td valign="top">
432 @ <textarea name="w" class="eventedit" cols="80"
433 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
434 @ </td></tr>
435
436 @ <tr><td colspan="2">
437 @ <input type="submit" name="preview" value="Preview Your Changes" />
438
+68 -5
--- src/file.c
+++ src/file.c
@@ -393,18 +393,35 @@
393393
FILE *in, *out;
394394
int got;
395395
char zBuf[8192];
396396
in = fossil_fopen(zFrom, "rb");
397397
if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
398
+ file_mkfolder(zTo, 0);
398399
out = fossil_fopen(zTo, "wb");
399400
if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
400401
while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
401402
fwrite(zBuf, 1, got, out);
402403
}
403404
fclose(in);
404405
fclose(out);
405406
}
407
+
408
+/*
409
+** COMMAND: test-file-copy
410
+**
411
+** Usage: %fossil test-file-copy SOURCE DESTINATION
412
+**
413
+** Make a copy of the file at SOURCE into a new name DESTINATION. Any
414
+** directories in the path leading up to DESTINATION that do not already
415
+** exist are created automatically.
416
+*/
417
+void test_file_copy(void){
418
+ if( g.argc!=4 ){
419
+ fossil_fatal("Usage: %s test-file-copy SOURCE DESTINATION", g.argv[0]);
420
+ }
421
+ file_copy(g.argv[2], g.argv[3]);
422
+}
406423
407424
/*
408425
** Set or clear the execute bit on a file. Return true if a change
409426
** occurred and false if this routine is a no-op.
410427
*/
@@ -516,10 +533,45 @@
516533
fossil_filename_free(zMbcs);
517534
return rc;
518535
}
519536
return 0;
520537
}
538
+
539
+/*
540
+** Create the tree of directories in which zFilename belongs, if that sequence
541
+** of directories does not already exist.
542
+*/
543
+void file_mkfolder(const char *zFilename, int forceFlag){
544
+ int i, nName;
545
+ char *zName;
546
+
547
+ nName = strlen(zFilename);
548
+ zName = mprintf("%s", zFilename);
549
+ nName = file_simplify_name(zName, nName, 0);
550
+ for(i=1; i<nName; i++){
551
+ if( zName[i]=='/' ){
552
+ zName[i] = 0;
553
+#if defined(_WIN32) || defined(__CYGWIN__)
554
+ /*
555
+ ** On Windows, local path looks like: C:/develop/project/file.txt
556
+ ** The if stops us from trying to create a directory of a drive letter
557
+ ** C: in this example.
558
+ */
559
+ if( !(i==2 && zName[1]==':') ){
560
+#endif
561
+ if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){
562
+ fossil_fatal_recursive("unable to create directory %s", zName);
563
+ return;
564
+ }
565
+#if defined(_WIN32) || defined(__CYGWIN__)
566
+ }
567
+#endif
568
+ zName[i] = '/';
569
+ }
570
+ }
571
+ free(zName);
572
+}
521573
522574
/*
523575
** Removes the directory named in the argument, if it exists. The directory
524576
** must be empty and cannot be the current directory or the root directory.
525577
**
@@ -644,10 +696,11 @@
644696
}
645697
646698
/*
647699
** Simplify a filename by
648700
**
701
+** * Remove extended path prefix on windows and cygwin
649702
** * Convert all \ into / on windows and cygwin
650703
** * removing any trailing and duplicate /
651704
** * removing /./
652705
** * removing /A/../
653706
**
@@ -654,17 +707,27 @@
654707
** Changes are made in-place. Return the new name length.
655708
** If the slash parameter is non-zero, the trailing slash, if any,
656709
** is retained.
657710
*/
658711
int file_simplify_name(char *z, int n, int slash){
659
- int i, j;
712
+ int i = 1, j;
660713
if( n<0 ) n = strlen(z);
661714
662
- /* On windows and cygwin convert all \ characters to / */
715
+ /* On windows and cygwin convert all \ characters to /
716
+ * and remove extended path prefix if present */
663717
#if defined(_WIN32) || defined(__CYGWIN__)
664
- for(i=0; i<n; i++){
665
- if( z[i]=='\\' ) z[i] = '/';
718
+ for(j=0; j<n; j++){
719
+ if( z[j]=='\\' ) z[j] = '/';
720
+ }
721
+ if( n>3 && !memcmp(z, "//?/", 4) ){
722
+ if( fossil_strnicmp(z+4,"UNC", 3) ){
723
+ i += 4;
724
+ z[0] = z[4];
725
+ }else{
726
+ i += 6;
727
+ z[0] = '/';
728
+ }
666729
}
667730
#endif
668731
669732
/* Removing trailing "/" characters */
670733
if( !slash ){
@@ -671,11 +734,11 @@
671734
while( n>1 && z[n-1]=='/' ){ n--; }
672735
}
673736
674737
/* Remove duplicate '/' characters. Except, two // at the beginning
675738
** of a pathname is allowed since this is important on windows. */
676
- for(i=j=1; i<n; i++){
739
+ for(j=1; i<n; i++){
677740
z[j++] = z[i];
678741
while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++;
679742
}
680743
n = j;
681744
682745
--- src/file.c
+++ src/file.c
@@ -393,18 +393,35 @@
393 FILE *in, *out;
394 int got;
395 char zBuf[8192];
396 in = fossil_fopen(zFrom, "rb");
397 if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
 
398 out = fossil_fopen(zTo, "wb");
399 if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
400 while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
401 fwrite(zBuf, 1, got, out);
402 }
403 fclose(in);
404 fclose(out);
405 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
407 /*
408 ** Set or clear the execute bit on a file. Return true if a change
409 ** occurred and false if this routine is a no-op.
410 */
@@ -516,10 +533,45 @@
516 fossil_filename_free(zMbcs);
517 return rc;
518 }
519 return 0;
520 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
522 /*
523 ** Removes the directory named in the argument, if it exists. The directory
524 ** must be empty and cannot be the current directory or the root directory.
525 **
@@ -644,10 +696,11 @@
644 }
645
646 /*
647 ** Simplify a filename by
648 **
 
649 ** * Convert all \ into / on windows and cygwin
650 ** * removing any trailing and duplicate /
651 ** * removing /./
652 ** * removing /A/../
653 **
@@ -654,17 +707,27 @@
654 ** Changes are made in-place. Return the new name length.
655 ** If the slash parameter is non-zero, the trailing slash, if any,
656 ** is retained.
657 */
658 int file_simplify_name(char *z, int n, int slash){
659 int i, j;
660 if( n<0 ) n = strlen(z);
661
662 /* On windows and cygwin convert all \ characters to / */
 
663 #if defined(_WIN32) || defined(__CYGWIN__)
664 for(i=0; i<n; i++){
665 if( z[i]=='\\' ) z[i] = '/';
 
 
 
 
 
 
 
 
 
666 }
667 #endif
668
669 /* Removing trailing "/" characters */
670 if( !slash ){
@@ -671,11 +734,11 @@
671 while( n>1 && z[n-1]=='/' ){ n--; }
672 }
673
674 /* Remove duplicate '/' characters. Except, two // at the beginning
675 ** of a pathname is allowed since this is important on windows. */
676 for(i=j=1; i<n; i++){
677 z[j++] = z[i];
678 while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++;
679 }
680 n = j;
681
682
--- src/file.c
+++ src/file.c
@@ -393,18 +393,35 @@
393 FILE *in, *out;
394 int got;
395 char zBuf[8192];
396 in = fossil_fopen(zFrom, "rb");
397 if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
398 file_mkfolder(zTo, 0);
399 out = fossil_fopen(zTo, "wb");
400 if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
401 while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
402 fwrite(zBuf, 1, got, out);
403 }
404 fclose(in);
405 fclose(out);
406 }
407
408 /*
409 ** COMMAND: test-file-copy
410 **
411 ** Usage: %fossil test-file-copy SOURCE DESTINATION
412 **
413 ** Make a copy of the file at SOURCE into a new name DESTINATION. Any
414 ** directories in the path leading up to DESTINATION that do not already
415 ** exist are created automatically.
416 */
417 void test_file_copy(void){
418 if( g.argc!=4 ){
419 fossil_fatal("Usage: %s test-file-copy SOURCE DESTINATION", g.argv[0]);
420 }
421 file_copy(g.argv[2], g.argv[3]);
422 }
423
424 /*
425 ** Set or clear the execute bit on a file. Return true if a change
426 ** occurred and false if this routine is a no-op.
427 */
@@ -516,10 +533,45 @@
533 fossil_filename_free(zMbcs);
534 return rc;
535 }
536 return 0;
537 }
538
539 /*
540 ** Create the tree of directories in which zFilename belongs, if that sequence
541 ** of directories does not already exist.
542 */
543 void file_mkfolder(const char *zFilename, int forceFlag){
544 int i, nName;
545 char *zName;
546
547 nName = strlen(zFilename);
548 zName = mprintf("%s", zFilename);
549 nName = file_simplify_name(zName, nName, 0);
550 for(i=1; i<nName; i++){
551 if( zName[i]=='/' ){
552 zName[i] = 0;
553 #if defined(_WIN32) || defined(__CYGWIN__)
554 /*
555 ** On Windows, local path looks like: C:/develop/project/file.txt
556 ** The if stops us from trying to create a directory of a drive letter
557 ** C: in this example.
558 */
559 if( !(i==2 && zName[1]==':') ){
560 #endif
561 if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){
562 fossil_fatal_recursive("unable to create directory %s", zName);
563 return;
564 }
565 #if defined(_WIN32) || defined(__CYGWIN__)
566 }
567 #endif
568 zName[i] = '/';
569 }
570 }
571 free(zName);
572 }
573
574 /*
575 ** Removes the directory named in the argument, if it exists. The directory
576 ** must be empty and cannot be the current directory or the root directory.
577 **
@@ -644,10 +696,11 @@
696 }
697
698 /*
699 ** Simplify a filename by
700 **
701 ** * Remove extended path prefix on windows and cygwin
702 ** * Convert all \ into / on windows and cygwin
703 ** * removing any trailing and duplicate /
704 ** * removing /./
705 ** * removing /A/../
706 **
@@ -654,17 +707,27 @@
707 ** Changes are made in-place. Return the new name length.
708 ** If the slash parameter is non-zero, the trailing slash, if any,
709 ** is retained.
710 */
711 int file_simplify_name(char *z, int n, int slash){
712 int i = 1, j;
713 if( n<0 ) n = strlen(z);
714
715 /* On windows and cygwin convert all \ characters to /
716 * and remove extended path prefix if present */
717 #if defined(_WIN32) || defined(__CYGWIN__)
718 for(j=0; j<n; j++){
719 if( z[j]=='\\' ) z[j] = '/';
720 }
721 if( n>3 && !memcmp(z, "//?/", 4) ){
722 if( fossil_strnicmp(z+4,"UNC", 3) ){
723 i += 4;
724 z[0] = z[4];
725 }else{
726 i += 6;
727 z[0] = '/';
728 }
729 }
730 #endif
731
732 /* Removing trailing "/" characters */
733 if( !slash ){
@@ -671,11 +734,11 @@
734 while( n>1 && z[n-1]=='/' ){ n--; }
735 }
736
737 /* Remove duplicate '/' characters. Except, two // at the beginning
738 ** of a pathname is allowed since this is important on windows. */
739 for(j=1; i<n; i++){
740 z[j++] = z[i];
741 while( z[i]=='/' && i<n-1 && z[i+1]=='/' ) i++;
742 }
743 n = j;
744
745
+81 -55
--- src/info.c
+++ src/info.c
@@ -449,20 +449,23 @@
449449
if( verboseFlag==0 ){
450450
diffFlags = 0; /* Zero means do not show any diff */
451451
}else{
452452
int x;
453453
if( sideBySide ){
454
- diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS;
454
+ diffFlags = DIFF_SIDEBYSIDE;
455455
456456
/* "dw" query parameter determines width of each column */
457457
x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1);
458458
if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK;
459459
diffFlags += x;
460460
}else{
461
- diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS;
461
+ diffFlags = DIFF_INLINE;
462462
}
463463
464
+ if( P("w") ){
465
+ diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS);
466
+ }
464467
/* "dc" query parameter determines lines of context */
465468
x = atoi(PD("dc","7"));
466469
if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
467470
diffFlags += x;
468471
@@ -469,11 +472,10 @@
469472
/* The "noopt" parameter disables diff optimization */
470473
if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
471474
}
472475
return diffFlags;
473476
}
474
-
475477
476478
/*
477479
** WEBPAGE: vinfo
478480
** WEBPAGE: ci
479481
** URL: /ci?name=RID|ARTIFACTID
@@ -664,50 +666,48 @@
664666
login_anonymous_available();
665667
}
666668
db_finalize(&q1);
667669
showTags(rid, "");
668670
if( zParent ){
671
+ const char *zW; /* URL param for ignoring whitespace */
672
+ const char *zPage = "vinfo"; /* Page that shows diffs */
673
+ const char *zPageHide = "ci"; /* Page that hides diffs */
669674
@ <div class="section">Changes</div>
670675
@ <div class="sectionmenu">
671676
verboseFlag = g.zPath[0]!='c';
672677
if( db_get_boolean("show-version-diffs", 0)==0 ){
673678
verboseFlag = !verboseFlag;
674
- if( verboseFlag ){
675
- @ %z(xhref("class='button'","%R/vinfo/%T",zName))
676
- @ hide&nbsp;diffs</a>
677
- if( sideBySide ){
678
- @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
679
- @ unified&nbsp;diffs</a>
680
- }else{
681
- @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
682
- @ side-by-side&nbsp;diffs</a>
683
- }
684
- }else{
685
- @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
686
- @ show&nbsp;unified&nbsp;diffs</a>
687
- @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
688
- @ show&nbsp;side-by-side&nbsp;diffs</a>
689
- }
690
- }else{
691
- if( verboseFlag ){
692
- @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a>
693
- if( sideBySide ){
694
- @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName))
695
- @ unified&nbsp;diffs</a>
696
- }else{
697
- @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName))
698
- @ side-by-side&nbsp;diffs</a>
699
- }
700
- }else{
701
- @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName))
702
- @ show&nbsp;unified&nbsp;diffs</a>
703
- @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
704
- @ show&nbsp;side-by-side&nbsp;diffs</a>
705
- }
679
+ zPage = "ci";
680
+ zPageHide = "vinfo";
681
+ }
682
+ diffFlags = construct_diff_flags(verboseFlag, sideBySide);
683
+ zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
684
+ if( verboseFlag ){
685
+ @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName))
686
+ @ Hide&nbsp;Diffs</a>
687
+ if( sideBySide ){
688
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW))
689
+ @ Unified&nbsp;Diffs</a>
690
+ }else{
691
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=1%s",zPage,zName,zW))
692
+ @ Side-by-Side&nbsp;Diffs</a>
693
+ }
694
+ if( *zW ){
695
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=%d",zPage,zName,sideBySide))
696
+ @ Show&nbsp;Whitespace&nbsp;Changes</a>
697
+ }else{
698
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=%d&w",zPage,zName,sideBySide))
699
+ @ Ignore&nbsp;Whitespace</a>
700
+ }
701
+ }else{
702
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=0",zPage,zName))
703
+ @ Show&nbsp;Unified&nbsp;Diffs</a>
704
+ @ %z(xhref("class='button'","%R/%s/%T?sbs=1",zPage,zName))
705
+ @ Show&nbsp;Side-by-Side&nbsp;Diffs</a>
706706
}
707707
@ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
708
- @ patch</a></div>
708
+ @ Patch</a></div>
709709
if( pRe ){
710710
@ <p><b>Only differences that match regular expression "%h(zRe)"
711711
@ are shown.</b></p>
712712
}
713713
db_prepare(&q3,
@@ -721,11 +721,10 @@
721721
" AND (mlink.fid>0"
722722
" OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
723723
" ORDER BY name /*sort*/",
724724
rid, rid
725725
);
726
- diffFlags = construct_diff_flags(verboseFlag, sideBySide);
727726
while( db_step(&q3)==SQLITE_ROW ){
728727
const char *zName = db_column_text(&q3,0);
729728
int mperm = db_column_int(&q3, 1);
730729
const char *zOld = db_column_text(&q3,2);
731730
const char *zNew = db_column_text(&q3,3);
@@ -954,10 +953,11 @@
954953
ManifestFile *pFileFrom, *pFileTo;
955954
const char *zBranch;
956955
const char *zFrom;
957956
const char *zTo;
958957
const char *zRe;
958
+ const char *zW;
959959
const char *zVerbose;
960960
const char *zGlob;
961961
ReCompiled *pRe = 0;
962962
login_check_credentials();
963963
if( !g.perm.Read ){ login_needed(); return; }
@@ -987,39 +987,54 @@
987987
zFrom = P("from");
988988
zTo = P("to");
989989
if(zGlob && !*zGlob){
990990
zGlob = NULL;
991991
}
992
+ diffFlags = construct_diff_flags(verboseFlag, sideBySide);
993
+ zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
992994
if( sideBySide || verboseFlag ){
993995
style_submenu_element("Hide Diff", "hidediff",
994
- "%R/vdiff?from=%T&to=%T&sbs=0%s%T",
996
+ "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
995997
zFrom, zTo,
996
- zGlob ? "&glob=" : "", zGlob ? zGlob : "");
998
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
997999
}
9981000
if( !sideBySide ){
999
- style_submenu_element("Side-by-side Diff", "sbsdiff",
1000
- "%R/vdiff?from=%T&to=%T&sbs=1%s%T",
1001
+ style_submenu_element("Side-by-Side Diff", "sbsdiff",
1002
+ "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s",
10011003
zFrom, zTo,
1002
- zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1004
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10031005
}
10041006
if( sideBySide || !verboseFlag ) {
10051007
style_submenu_element("Unified Diff", "udiff",
1006
- "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T",
1008
+ "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s",
10071009
zFrom, zTo,
1008
- zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1010
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10091011
}
10101012
style_submenu_element("Invert", "invert",
1011
- "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zTo, zFrom,
1013
+ "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom,
10121014
sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1013
- zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1015
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
10141016
if( zGlob ){
10151017
style_submenu_element("Clear glob", "clearglob",
1016
- "%R/vdiff?from=%T&to=%T&sbs=%d%s", zFrom, zTo,
1017
- sideBySide, (verboseFlag && !sideBySide)?"&v":"");
1018
+ "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo,
1019
+ sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW);
10181020
}else{
10191021
style_submenu_element("Patch", "patch",
1020
- "%R/vpatch?from=%T&to=%T", zFrom, zTo);
1022
+ "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1023
+ }
1024
+ if( sideBySide || verboseFlag ){
1025
+ if( *zW ){
1026
+ style_submenu_element("Show Whitespace Differences", "whitespace",
1027
+ "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo,
1028
+ sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1029
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1030
+ }else{
1031
+ style_submenu_element("Ignore Whitespace", "ignorews",
1032
+ "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo,
1033
+ sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1034
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1035
+ }
10211036
}
10221037
style_header("Check-in Differences");
10231038
@ <h2>Difference From:</h2><blockquote>
10241039
checkin_description(ridFrom);
10251040
@ </blockquote><h2>To:</h2><blockquote>
@@ -1036,11 +1051,10 @@
10361051
10371052
manifest_file_rewind(pFrom);
10381053
pFileFrom = manifest_file_next(pFrom, 0);
10391054
manifest_file_rewind(pTo);
10401055
pFileTo = manifest_file_next(pTo, 0);
1041
- diffFlags = construct_diff_flags(verboseFlag, sideBySide);
10421056
while( pFileFrom || pFileTo ){
10431057
int cmp;
10441058
if( pFileFrom==0 ){
10451059
cmp = +1;
10461060
}else if( pFileTo==0 ){
@@ -1337,10 +1351,11 @@
13371351
int isPatch;
13381352
int sideBySide;
13391353
char *zV1;
13401354
char *zV2;
13411355
const char *zRe;
1356
+ const char *zW; /* URL param for ignoring whitespace */
13421357
ReCompiled *pRe = 0;
13431358
u64 diffFlags;
13441359
13451360
login_check_credentials();
13461361
if( !g.perm.Read ){ login_needed(); return; }
@@ -1367,20 +1382,31 @@
13671382
zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
13681383
zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
13691384
diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
13701385
13711386
style_header("Diff");
1387
+ zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
1388
+ if( *zW ){
1389
+ diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS);
1390
+ style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes",
1391
+ "%s/fdiff?v1=%T&v2=%T&sbs=%d",
1392
+ g.zTop, P("v1"), P("v2"), sideBySide);
1393
+ }else{
1394
+ style_submenu_element("Ignore Whitespace", "Ignore Whitespace",
1395
+ "%s/fdiff?v1=%T&v2=%T&sbs=%d&w",
1396
+ g.zTop, P("v1"), P("v2"), sideBySide);
1397
+ }
13721398
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
13731399
g.zTop, P("v1"), P("v2"));
13741400
if( !sideBySide ){
1375
- style_submenu_element("Side-by-side Diff", "sbsdiff",
1376
- "%s/fdiff?v1=%T&v2=%T&sbs=1",
1377
- g.zTop, P("v1"), P("v2"));
1401
+ style_submenu_element("Side-by-Side Diff", "sbsdiff",
1402
+ "%s/fdiff?v1=%T&v2=%T&sbs=1%s",
1403
+ g.zTop, P("v1"), P("v2"), zW);
13781404
}else{
13791405
style_submenu_element("Unified Diff", "udiff",
1380
- "%s/fdiff?v1=%T&v2=%T&sbs=0",
1381
- g.zTop, P("v1"), P("v2"));
1406
+ "%s/fdiff?v1=%T&v2=%T&sbs=0%s",
1407
+ g.zTop, P("v1"), P("v2"), zW);
13821408
}
13831409
13841410
if( P("smhdr")!=0 ){
13851411
@ <h2>Differences From Artifact
13861412
@ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
13871413
--- src/info.c
+++ src/info.c
@@ -449,20 +449,23 @@
449 if( verboseFlag==0 ){
450 diffFlags = 0; /* Zero means do not show any diff */
451 }else{
452 int x;
453 if( sideBySide ){
454 diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS;
455
456 /* "dw" query parameter determines width of each column */
457 x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1);
458 if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK;
459 diffFlags += x;
460 }else{
461 diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS;
462 }
463
 
 
 
464 /* "dc" query parameter determines lines of context */
465 x = atoi(PD("dc","7"));
466 if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
467 diffFlags += x;
468
@@ -469,11 +472,10 @@
469 /* The "noopt" parameter disables diff optimization */
470 if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
471 }
472 return diffFlags;
473 }
474
475
476 /*
477 ** WEBPAGE: vinfo
478 ** WEBPAGE: ci
479 ** URL: /ci?name=RID|ARTIFACTID
@@ -664,50 +666,48 @@
664 login_anonymous_available();
665 }
666 db_finalize(&q1);
667 showTags(rid, "");
668 if( zParent ){
 
 
 
669 @ <div class="section">Changes</div>
670 @ <div class="sectionmenu">
671 verboseFlag = g.zPath[0]!='c';
672 if( db_get_boolean("show-version-diffs", 0)==0 ){
673 verboseFlag = !verboseFlag;
674 if( verboseFlag ){
675 @ %z(xhref("class='button'","%R/vinfo/%T",zName))
676 @ hide&nbsp;diffs</a>
677 if( sideBySide ){
678 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
679 @ unified&nbsp;diffs</a>
680 }else{
681 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
682 @ side-by-side&nbsp;diffs</a>
683 }
684 }else{
685 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
686 @ show&nbsp;unified&nbsp;diffs</a>
687 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
688 @ show&nbsp;side-by-side&nbsp;diffs</a>
689 }
690 }else{
691 if( verboseFlag ){
692 @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a>
693 if( sideBySide ){
694 @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName))
695 @ unified&nbsp;diffs</a>
696 }else{
697 @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName))
698 @ side-by-side&nbsp;diffs</a>
699 }
700 }else{
701 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName))
702 @ show&nbsp;unified&nbsp;diffs</a>
703 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
704 @ show&nbsp;side-by-side&nbsp;diffs</a>
705 }
706 }
707 @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
708 @ patch</a></div>
709 if( pRe ){
710 @ <p><b>Only differences that match regular expression "%h(zRe)"
711 @ are shown.</b></p>
712 }
713 db_prepare(&q3,
@@ -721,11 +721,10 @@
721 " AND (mlink.fid>0"
722 " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
723 " ORDER BY name /*sort*/",
724 rid, rid
725 );
726 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
727 while( db_step(&q3)==SQLITE_ROW ){
728 const char *zName = db_column_text(&q3,0);
729 int mperm = db_column_int(&q3, 1);
730 const char *zOld = db_column_text(&q3,2);
731 const char *zNew = db_column_text(&q3,3);
@@ -954,10 +953,11 @@
954 ManifestFile *pFileFrom, *pFileTo;
955 const char *zBranch;
956 const char *zFrom;
957 const char *zTo;
958 const char *zRe;
 
959 const char *zVerbose;
960 const char *zGlob;
961 ReCompiled *pRe = 0;
962 login_check_credentials();
963 if( !g.perm.Read ){ login_needed(); return; }
@@ -987,39 +987,54 @@
987 zFrom = P("from");
988 zTo = P("to");
989 if(zGlob && !*zGlob){
990 zGlob = NULL;
991 }
 
 
992 if( sideBySide || verboseFlag ){
993 style_submenu_element("Hide Diff", "hidediff",
994 "%R/vdiff?from=%T&to=%T&sbs=0%s%T",
995 zFrom, zTo,
996 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
997 }
998 if( !sideBySide ){
999 style_submenu_element("Side-by-side Diff", "sbsdiff",
1000 "%R/vdiff?from=%T&to=%T&sbs=1%s%T",
1001 zFrom, zTo,
1002 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1003 }
1004 if( sideBySide || !verboseFlag ) {
1005 style_submenu_element("Unified Diff", "udiff",
1006 "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T",
1007 zFrom, zTo,
1008 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1009 }
1010 style_submenu_element("Invert", "invert",
1011 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zTo, zFrom,
1012 sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1013 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1014 if( zGlob ){
1015 style_submenu_element("Clear glob", "clearglob",
1016 "%R/vdiff?from=%T&to=%T&sbs=%d%s", zFrom, zTo,
1017 sideBySide, (verboseFlag && !sideBySide)?"&v":"");
1018 }else{
1019 style_submenu_element("Patch", "patch",
1020 "%R/vpatch?from=%T&to=%T", zFrom, zTo);
 
 
 
 
 
 
 
 
 
 
 
 
 
1021 }
1022 style_header("Check-in Differences");
1023 @ <h2>Difference From:</h2><blockquote>
1024 checkin_description(ridFrom);
1025 @ </blockquote><h2>To:</h2><blockquote>
@@ -1036,11 +1051,10 @@
1036
1037 manifest_file_rewind(pFrom);
1038 pFileFrom = manifest_file_next(pFrom, 0);
1039 manifest_file_rewind(pTo);
1040 pFileTo = manifest_file_next(pTo, 0);
1041 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
1042 while( pFileFrom || pFileTo ){
1043 int cmp;
1044 if( pFileFrom==0 ){
1045 cmp = +1;
1046 }else if( pFileTo==0 ){
@@ -1337,10 +1351,11 @@
1337 int isPatch;
1338 int sideBySide;
1339 char *zV1;
1340 char *zV2;
1341 const char *zRe;
 
1342 ReCompiled *pRe = 0;
1343 u64 diffFlags;
1344
1345 login_check_credentials();
1346 if( !g.perm.Read ){ login_needed(); return; }
@@ -1367,20 +1382,31 @@
1367 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1368 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
1369 diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
1370
1371 style_header("Diff");
 
 
 
 
 
 
 
 
 
 
 
1372 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
1373 g.zTop, P("v1"), P("v2"));
1374 if( !sideBySide ){
1375 style_submenu_element("Side-by-side Diff", "sbsdiff",
1376 "%s/fdiff?v1=%T&v2=%T&sbs=1",
1377 g.zTop, P("v1"), P("v2"));
1378 }else{
1379 style_submenu_element("Unified Diff", "udiff",
1380 "%s/fdiff?v1=%T&v2=%T&sbs=0",
1381 g.zTop, P("v1"), P("v2"));
1382 }
1383
1384 if( P("smhdr")!=0 ){
1385 @ <h2>Differences From Artifact
1386 @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
1387
--- src/info.c
+++ src/info.c
@@ -449,20 +449,23 @@
449 if( verboseFlag==0 ){
450 diffFlags = 0; /* Zero means do not show any diff */
451 }else{
452 int x;
453 if( sideBySide ){
454 diffFlags = DIFF_SIDEBYSIDE;
455
456 /* "dw" query parameter determines width of each column */
457 x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1);
458 if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK;
459 diffFlags += x;
460 }else{
461 diffFlags = DIFF_INLINE;
462 }
463
464 if( P("w") ){
465 diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS);
466 }
467 /* "dc" query parameter determines lines of context */
468 x = atoi(PD("dc","7"));
469 if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK;
470 diffFlags += x;
471
@@ -469,11 +472,10 @@
472 /* The "noopt" parameter disables diff optimization */
473 if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
474 }
475 return diffFlags;
476 }
 
477
478 /*
479 ** WEBPAGE: vinfo
480 ** WEBPAGE: ci
481 ** URL: /ci?name=RID|ARTIFACTID
@@ -664,50 +666,48 @@
666 login_anonymous_available();
667 }
668 db_finalize(&q1);
669 showTags(rid, "");
670 if( zParent ){
671 const char *zW; /* URL param for ignoring whitespace */
672 const char *zPage = "vinfo"; /* Page that shows diffs */
673 const char *zPageHide = "ci"; /* Page that hides diffs */
674 @ <div class="section">Changes</div>
675 @ <div class="sectionmenu">
676 verboseFlag = g.zPath[0]!='c';
677 if( db_get_boolean("show-version-diffs", 0)==0 ){
678 verboseFlag = !verboseFlag;
679 zPage = "ci";
680 zPageHide = "vinfo";
681 }
682 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
683 zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
684 if( verboseFlag ){
685 @ %z(xhref("class='button'","%R/%s/%T",zPageHide,zName))
686 @ Hide&nbsp;Diffs</a>
687 if( sideBySide ){
688 @ %z(xhref("class='button'","%R/%s/%T?sbs=0%s",zPage,zName,zW))
689 @ Unified&nbsp;Diffs</a>
690 }else{
691 @ %z(xhref("class='button'","%R/%s/%T?sbs=1%s",zPage,zName,zW))
692 @ Side-by-Side&nbsp;Diffs</a>
693 }
694 if( *zW ){
695 @ %z(xhref("class='button'","%R/%s/%T?sbs=%d",zPage,zName,sideBySide))
696 @ Show&nbsp;Whitespace&nbsp;Changes</a>
697 }else{
698 @ %z(xhref("class='button'","%R/%s/%T?sbs=%d&w",zPage,zName,sideBySide))
699 @ Ignore&nbsp;Whitespace</a>
700 }
701 }else{
702 @ %z(xhref("class='button'","%R/%s/%T?sbs=0",zPage,zName))
703 @ Show&nbsp;Unified&nbsp;Diffs</a>
704 @ %z(xhref("class='button'","%R/%s/%T?sbs=1",zPage,zName))
705 @ Show&nbsp;Side-by-Side&nbsp;Diffs</a>
 
 
 
 
 
706 }
707 @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
708 @ Patch</a></div>
709 if( pRe ){
710 @ <p><b>Only differences that match regular expression "%h(zRe)"
711 @ are shown.</b></p>
712 }
713 db_prepare(&q3,
@@ -721,11 +721,10 @@
721 " AND (mlink.fid>0"
722 " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
723 " ORDER BY name /*sort*/",
724 rid, rid
725 );
 
726 while( db_step(&q3)==SQLITE_ROW ){
727 const char *zName = db_column_text(&q3,0);
728 int mperm = db_column_int(&q3, 1);
729 const char *zOld = db_column_text(&q3,2);
730 const char *zNew = db_column_text(&q3,3);
@@ -954,10 +953,11 @@
953 ManifestFile *pFileFrom, *pFileTo;
954 const char *zBranch;
955 const char *zFrom;
956 const char *zTo;
957 const char *zRe;
958 const char *zW;
959 const char *zVerbose;
960 const char *zGlob;
961 ReCompiled *pRe = 0;
962 login_check_credentials();
963 if( !g.perm.Read ){ login_needed(); return; }
@@ -987,39 +987,54 @@
987 zFrom = P("from");
988 zTo = P("to");
989 if(zGlob && !*zGlob){
990 zGlob = NULL;
991 }
992 diffFlags = construct_diff_flags(verboseFlag, sideBySide);
993 zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
994 if( sideBySide || verboseFlag ){
995 style_submenu_element("Hide Diff", "hidediff",
996 "%R/vdiff?from=%T&to=%T&sbs=0%s%T%s",
997 zFrom, zTo,
998 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
999 }
1000 if( !sideBySide ){
1001 style_submenu_element("Side-by-Side Diff", "sbsdiff",
1002 "%R/vdiff?from=%T&to=%T&sbs=1%s%T%s",
1003 zFrom, zTo,
1004 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1005 }
1006 if( sideBySide || !verboseFlag ) {
1007 style_submenu_element("Unified Diff", "udiff",
1008 "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T%s",
1009 zFrom, zTo,
1010 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1011 }
1012 style_submenu_element("Invert", "invert",
1013 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T%s", zTo, zFrom,
1014 sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1015 zGlob ? "&glob=" : "", zGlob ? zGlob : "", zW);
1016 if( zGlob ){
1017 style_submenu_element("Clear glob", "clearglob",
1018 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s", zFrom, zTo,
1019 sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW);
1020 }else{
1021 style_submenu_element("Patch", "patch",
1022 "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW);
1023 }
1024 if( sideBySide || verboseFlag ){
1025 if( *zW ){
1026 style_submenu_element("Show Whitespace Differences", "whitespace",
1027 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo,
1028 sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1029 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1030 }else{
1031 style_submenu_element("Ignore Whitespace", "ignorews",
1032 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo,
1033 sideBySide, (verboseFlag && !sideBySide)?"&v":"",
1034 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1035 }
1036 }
1037 style_header("Check-in Differences");
1038 @ <h2>Difference From:</h2><blockquote>
1039 checkin_description(ridFrom);
1040 @ </blockquote><h2>To:</h2><blockquote>
@@ -1036,11 +1051,10 @@
1051
1052 manifest_file_rewind(pFrom);
1053 pFileFrom = manifest_file_next(pFrom, 0);
1054 manifest_file_rewind(pTo);
1055 pFileTo = manifest_file_next(pTo, 0);
 
1056 while( pFileFrom || pFileTo ){
1057 int cmp;
1058 if( pFileFrom==0 ){
1059 cmp = +1;
1060 }else if( pFileTo==0 ){
@@ -1337,10 +1351,11 @@
1351 int isPatch;
1352 int sideBySide;
1353 char *zV1;
1354 char *zV2;
1355 const char *zRe;
1356 const char *zW; /* URL param for ignoring whitespace */
1357 ReCompiled *pRe = 0;
1358 u64 diffFlags;
1359
1360 login_check_credentials();
1361 if( !g.perm.Read ){ login_needed(); return; }
@@ -1367,20 +1382,31 @@
1382 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1);
1383 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2);
1384 diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML;
1385
1386 style_header("Diff");
1387 zW = (diffFlags&(DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS))?"&w":"";
1388 if( *zW ){
1389 diffFlags |= (DIFF_IGNORE_SOLWS|DIFF_IGNORE_EOLWS);
1390 style_submenu_element("Show Whitespace Changes", "Show Whitespace Changes",
1391 "%s/fdiff?v1=%T&v2=%T&sbs=%d",
1392 g.zTop, P("v1"), P("v2"), sideBySide);
1393 }else{
1394 style_submenu_element("Ignore Whitespace", "Ignore Whitespace",
1395 "%s/fdiff?v1=%T&v2=%T&sbs=%d&w",
1396 g.zTop, P("v1"), P("v2"), sideBySide);
1397 }
1398 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
1399 g.zTop, P("v1"), P("v2"));
1400 if( !sideBySide ){
1401 style_submenu_element("Side-by-Side Diff", "sbsdiff",
1402 "%s/fdiff?v1=%T&v2=%T&sbs=1%s",
1403 g.zTop, P("v1"), P("v2"), zW);
1404 }else{
1405 style_submenu_element("Unified Diff", "udiff",
1406 "%s/fdiff?v1=%T&v2=%T&sbs=0%s",
1407 g.zTop, P("v1"), P("v2"), zW);
1408 }
1409
1410 if( P("smhdr")!=0 ){
1411 @ <h2>Differences From Artifact
1412 @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
1413
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -66,11 +66,11 @@
6666
/*
6767
** Create a temporary table suitable for storing timeline data.
6868
*/
6969
static void json_timeline_temp_table(void){
7070
/* Field order MUST match that from json_timeline_query()!!! */
71
- static const char zSql[] =
71
+ static const char zSql[] =
7272
@ CREATE TEMP TABLE IF NOT EXISTS json_timeline(
7373
@ sortId INTEGER PRIMARY KEY,
7474
@ rid INTEGER,
7575
@ uuid TEXT,
7676
@ mtime INTEGER,
@@ -109,11 +109,11 @@
109109
@ (SELECT group_concat(substr(tagname,5), ',') FROM tag, tagxref
110110
@ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
111111
@ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) as tags,
112112
@ tagid as tagId,
113113
@ brief as brief
114
- @ FROM event JOIN blob
114
+ @ FROM event JOIN blob
115115
@ WHERE blob.rid=event.objid
116116
;
117117
return zBaseSql;
118118
}
119119
@@ -316,11 +316,11 @@
316316
*/
317317
cson_value * json_get_changed_files(int rid, int flags){
318318
cson_value * rowsV = NULL;
319319
cson_array * rows = NULL;
320320
Stmt q = empty_Stmt;
321
- db_prepare(&q,
321
+ db_prepare(&q,
322322
"SELECT (pid==0) AS isnew,"
323323
" (fid==0) AS isdel,"
324324
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
325325
" blob.uuid as uuid,"
326326
" (SELECT uuid FROM blob WHERE rid=pid) as parent,"
327327
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -66,11 +66,11 @@
66 /*
67 ** Create a temporary table suitable for storing timeline data.
68 */
69 static void json_timeline_temp_table(void){
70 /* Field order MUST match that from json_timeline_query()!!! */
71 static const char zSql[] =
72 @ CREATE TEMP TABLE IF NOT EXISTS json_timeline(
73 @ sortId INTEGER PRIMARY KEY,
74 @ rid INTEGER,
75 @ uuid TEXT,
76 @ mtime INTEGER,
@@ -109,11 +109,11 @@
109 @ (SELECT group_concat(substr(tagname,5), ',') FROM tag, tagxref
110 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
111 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) as tags,
112 @ tagid as tagId,
113 @ brief as brief
114 @ FROM event JOIN blob
115 @ WHERE blob.rid=event.objid
116 ;
117 return zBaseSql;
118 }
119
@@ -316,11 +316,11 @@
316 */
317 cson_value * json_get_changed_files(int rid, int flags){
318 cson_value * rowsV = NULL;
319 cson_array * rows = NULL;
320 Stmt q = empty_Stmt;
321 db_prepare(&q,
322 "SELECT (pid==0) AS isnew,"
323 " (fid==0) AS isdel,"
324 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
325 " blob.uuid as uuid,"
326 " (SELECT uuid FROM blob WHERE rid=pid) as parent,"
327
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -66,11 +66,11 @@
66 /*
67 ** Create a temporary table suitable for storing timeline data.
68 */
69 static void json_timeline_temp_table(void){
70 /* Field order MUST match that from json_timeline_query()!!! */
71 static const char zSql[] =
72 @ CREATE TEMP TABLE IF NOT EXISTS json_timeline(
73 @ sortId INTEGER PRIMARY KEY,
74 @ rid INTEGER,
75 @ uuid TEXT,
76 @ mtime INTEGER,
@@ -109,11 +109,11 @@
109 @ (SELECT group_concat(substr(tagname,5), ',') FROM tag, tagxref
110 @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
111 @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) as tags,
112 @ tagid as tagId,
113 @ brief as brief
114 @ FROM event JOIN blob
115 @ WHERE blob.rid=event.objid
116 ;
117 return zBaseSql;
118 }
119
@@ -316,11 +316,11 @@
316 */
317 cson_value * json_get_changed_files(int rid, int flags){
318 cson_value * rowsV = NULL;
319 cson_array * rows = NULL;
320 Stmt q = empty_Stmt;
321 db_prepare(&q,
322 "SELECT (pid==0) AS isnew,"
323 " (fid==0) AS isdel,"
324 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
325 " blob.uuid as uuid,"
326 " (SELECT uuid FROM blob WHERE rid=pid) as parent,"
327
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -153,10 +153,11 @@
153153
}
154154
155155
# Options used to compile the included SQLite shell on Windows.
156156
#
157157
set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
158
+lappend SHELL_WIN32_OPTIONS -Daccess=win32_access
158159
lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
159160
lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen
160161
161162
# Name of the final application
162163
#
@@ -797,11 +798,11 @@
797798
writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
798799
writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
799800
}
800801
801802
set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
802
-lappend MINGW_SQLITE_OPTIONS -D_HAVE_SQLITE_CONFIG_H
803
+lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
803804
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
804805
lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
805806
806807
set j " \\\n "
807808
writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
808809
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -153,10 +153,11 @@
153 }
154
155 # Options used to compile the included SQLite shell on Windows.
156 #
157 set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
 
158 lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
159 lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen
160
161 # Name of the final application
162 #
@@ -797,11 +798,11 @@
797 writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
798 writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
799 }
800
801 set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
802 lappend MINGW_SQLITE_OPTIONS -D_HAVE_SQLITE_CONFIG_H
803 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
804 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
805
806 set j " \\\n "
807 writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
808
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -153,10 +153,11 @@
153 }
154
155 # Options used to compile the included SQLite shell on Windows.
156 #
157 set SHELL_WIN32_OPTIONS $SHELL_OPTIONS
158 lappend SHELL_WIN32_OPTIONS -Daccess=win32_access
159 lappend SHELL_WIN32_OPTIONS -Dgetenv=fossil_getenv
160 lappend SHELL_WIN32_OPTIONS -Dfopen=fossil_fopen
161
162 # Name of the final application
163 #
@@ -797,11 +798,11 @@
798 writeln "\t\$(XTCC) -o \$(OBJDIR)/$s.o -c \$(OBJDIR)/${s}_.c\n"
799 writeln "\$(OBJDIR)/${s}.h:\t\$(OBJDIR)/headers\n"
800 }
801
802 set MINGW_SQLITE_OPTIONS $SQLITE_OPTIONS
803 lappend MINGW_SQLITE_OPTIONS -D_HAVE__MINGW_H
804 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MALLOC_H
805 lappend MINGW_SQLITE_OPTIONS -DSQLITE_USE_MSIZE
806
807 set j " \\\n "
808 writeln "SQLITE_OPTIONS = [join $MINGW_SQLITE_OPTIONS $j]\n"
809
+9 -9
--- src/schema.c
+++ src/schema.c
@@ -21,11 +21,11 @@
2121
#include "schema.h"
2222
2323
/*
2424
** The database schema for the ~/.fossil configuration database.
2525
*/
26
-const char zConfigSchema[] =
26
+const char zConfigSchema[] =
2727
@ -- This file contains the schema for the database that is kept in the
2828
@ -- ~/.fossil file and that stores information about the users setup.
2929
@ --
3030
@ CREATE TABLE global_config(
3131
@ name TEXT PRIMARY KEY,
@@ -50,19 +50,19 @@
5050
5151
#endif /* INTERFACE */
5252
5353
5454
/*
55
-** The schema for a repository database.
55
+** The schema for a repository database.
5656
**
5757
** Schema1[] contains parts of the schema that are fixed and unchanging
5858
** across versions. Schema2[] contains parts of the schema that can
5959
** change from one version to the next. The information in Schema2[]
6060
** is reconstructed from the information in Schema1[] by the "rebuild"
6161
** operation.
6262
*/
63
-const char zRepositorySchema1[] =
63
+const char zRepositorySchema1[] =
6464
@ -- The BLOB and DELTA tables contain all records held in the repository.
6565
@ --
6666
@ -- The BLOB.CONTENT column is always compressed using zlib. This
6767
@ -- column might hold the full text of the record or it might hold
6868
@ -- a delta that is able to reconstruct the record from some other
@@ -69,11 +69,11 @@
6969
@ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
7070
@ -- will exist for the record and that entry will point to another
7171
@ -- entry that holds the source of the delta. Deltas can be chained.
7272
@ --
7373
@ -- The blob and delta tables collectively hold the "global state" of
74
-@ -- a Fossil repository.
74
+@ -- a Fossil repository.
7575
@ --
7676
@ CREATE TABLE blob(
7777
@ rid INTEGER PRIMARY KEY, -- Record ID
7878
@ rcvid INTEGER, -- Origin of this record
7979
@ size INTEGER, -- Size of content. -1 for a phantom.
@@ -89,11 +89,11 @@
8989
@
9090
@ -------------------------------------------------------------------------
9191
@ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
9292
@ -- project; the stuff that is normally exchanged during "sync". The
9393
@ -- "local state" of a repository is contained in the remaining tables of
94
-@ -- the zRepositorySchema1 string.
94
+@ -- the zRepositorySchema1 string.
9595
@ -------------------------------------------------------------------------
9696
@
9797
@ -- Whenever new blobs are received into the repository, an entry
9898
@ -- in this table records the source of the blob.
9999
@ --
@@ -172,11 +172,11 @@
172172
@ );
173173
@
174174
@ -- Some ticket content (such as the originators email address or contact
175175
@ -- information) needs to be obscured to protect privacy. This is achieved
176176
@ -- by storing an SHA1 hash of the content. For display, the hash is
177
-@ -- mapped back into the original text using this table.
177
+@ -- mapped back into the original text using this table.
178178
@ --
179179
@ -- This table contains sensitive information and should not be shared
180180
@ -- with unauthorized users.
181181
@ --
182182
@ CREATE TABLE concealed(
@@ -193,11 +193,11 @@
193193
/*
194194
** The default reportfmt entry for the schema. This is in an extra
195195
** script so that (configure reset) can install the default report.
196196
*/
197197
const char zRepositorySchemaDefaultReports[] =
198
-@ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
198
+@ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
199199
@ VALUES('All Tickets',julianday('1970-01-01'),'#ffffff Key:
200200
@ #f2dcdc Active
201201
@ #e8e8e8 Review
202202
@ #cfe8bd Fixed
203203
@ #bde5d6 Tested
@@ -321,13 +321,13 @@
321321
@ rid INTEGER PRIMARY KEY -- Record ID of the phantom
322322
@ );
323323
@
324324
@ -- Each baseline or manifest can have one or more tags. A tag
325325
@ -- is defined by a row in the next table.
326
-@ --
326
+@ --
327327
@ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
328
-@ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
328
+@ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
329329
@ -- UUID is the indentifier of the ticket. Tags used to assign symbolic
330330
@ -- names to baselines are branches are of the form "sym-NAME" where
331331
@ -- NAME is the symbolic name.
332332
@ --
333333
@ CREATE TABLE tag(
334334
--- src/schema.c
+++ src/schema.c
@@ -21,11 +21,11 @@
21 #include "schema.h"
22
23 /*
24 ** The database schema for the ~/.fossil configuration database.
25 */
26 const char zConfigSchema[] =
27 @ -- This file contains the schema for the database that is kept in the
28 @ -- ~/.fossil file and that stores information about the users setup.
29 @ --
30 @ CREATE TABLE global_config(
31 @ name TEXT PRIMARY KEY,
@@ -50,19 +50,19 @@
50
51 #endif /* INTERFACE */
52
53
54 /*
55 ** The schema for a repository database.
56 **
57 ** Schema1[] contains parts of the schema that are fixed and unchanging
58 ** across versions. Schema2[] contains parts of the schema that can
59 ** change from one version to the next. The information in Schema2[]
60 ** is reconstructed from the information in Schema1[] by the "rebuild"
61 ** operation.
62 */
63 const char zRepositorySchema1[] =
64 @ -- The BLOB and DELTA tables contain all records held in the repository.
65 @ --
66 @ -- The BLOB.CONTENT column is always compressed using zlib. This
67 @ -- column might hold the full text of the record or it might hold
68 @ -- a delta that is able to reconstruct the record from some other
@@ -69,11 +69,11 @@
69 @ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
70 @ -- will exist for the record and that entry will point to another
71 @ -- entry that holds the source of the delta. Deltas can be chained.
72 @ --
73 @ -- The blob and delta tables collectively hold the "global state" of
74 @ -- a Fossil repository.
75 @ --
76 @ CREATE TABLE blob(
77 @ rid INTEGER PRIMARY KEY, -- Record ID
78 @ rcvid INTEGER, -- Origin of this record
79 @ size INTEGER, -- Size of content. -1 for a phantom.
@@ -89,11 +89,11 @@
89 @
90 @ -------------------------------------------------------------------------
91 @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
92 @ -- project; the stuff that is normally exchanged during "sync". The
93 @ -- "local state" of a repository is contained in the remaining tables of
94 @ -- the zRepositorySchema1 string.
95 @ -------------------------------------------------------------------------
96 @
97 @ -- Whenever new blobs are received into the repository, an entry
98 @ -- in this table records the source of the blob.
99 @ --
@@ -172,11 +172,11 @@
172 @ );
173 @
174 @ -- Some ticket content (such as the originators email address or contact
175 @ -- information) needs to be obscured to protect privacy. This is achieved
176 @ -- by storing an SHA1 hash of the content. For display, the hash is
177 @ -- mapped back into the original text using this table.
178 @ --
179 @ -- This table contains sensitive information and should not be shared
180 @ -- with unauthorized users.
181 @ --
182 @ CREATE TABLE concealed(
@@ -193,11 +193,11 @@
193 /*
194 ** The default reportfmt entry for the schema. This is in an extra
195 ** script so that (configure reset) can install the default report.
196 */
197 const char zRepositorySchemaDefaultReports[] =
198 @ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
199 @ VALUES('All Tickets',julianday('1970-01-01'),'#ffffff Key:
200 @ #f2dcdc Active
201 @ #e8e8e8 Review
202 @ #cfe8bd Fixed
203 @ #bde5d6 Tested
@@ -321,13 +321,13 @@
321 @ rid INTEGER PRIMARY KEY -- Record ID of the phantom
322 @ );
323 @
324 @ -- Each baseline or manifest can have one or more tags. A tag
325 @ -- is defined by a row in the next table.
326 @ --
327 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
328 @ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
329 @ -- UUID is the indentifier of the ticket. Tags used to assign symbolic
330 @ -- names to baselines are branches are of the form "sym-NAME" where
331 @ -- NAME is the symbolic name.
332 @ --
333 @ CREATE TABLE tag(
334
--- src/schema.c
+++ src/schema.c
@@ -21,11 +21,11 @@
21 #include "schema.h"
22
23 /*
24 ** The database schema for the ~/.fossil configuration database.
25 */
26 const char zConfigSchema[] =
27 @ -- This file contains the schema for the database that is kept in the
28 @ -- ~/.fossil file and that stores information about the users setup.
29 @ --
30 @ CREATE TABLE global_config(
31 @ name TEXT PRIMARY KEY,
@@ -50,19 +50,19 @@
50
51 #endif /* INTERFACE */
52
53
54 /*
55 ** The schema for a repository database.
56 **
57 ** Schema1[] contains parts of the schema that are fixed and unchanging
58 ** across versions. Schema2[] contains parts of the schema that can
59 ** change from one version to the next. The information in Schema2[]
60 ** is reconstructed from the information in Schema1[] by the "rebuild"
61 ** operation.
62 */
63 const char zRepositorySchema1[] =
64 @ -- The BLOB and DELTA tables contain all records held in the repository.
65 @ --
66 @ -- The BLOB.CONTENT column is always compressed using zlib. This
67 @ -- column might hold the full text of the record or it might hold
68 @ -- a delta that is able to reconstruct the record from some other
@@ -69,11 +69,11 @@
69 @ -- record. If BLOB.CONTENT holds a delta, then a DELTA table entry
70 @ -- will exist for the record and that entry will point to another
71 @ -- entry that holds the source of the delta. Deltas can be chained.
72 @ --
73 @ -- The blob and delta tables collectively hold the "global state" of
74 @ -- a Fossil repository.
75 @ --
76 @ CREATE TABLE blob(
77 @ rid INTEGER PRIMARY KEY, -- Record ID
78 @ rcvid INTEGER, -- Origin of this record
79 @ size INTEGER, -- Size of content. -1 for a phantom.
@@ -89,11 +89,11 @@
89 @
90 @ -------------------------------------------------------------------------
91 @ -- The BLOB and DELTA tables above hold the "global state" of a Fossil
92 @ -- project; the stuff that is normally exchanged during "sync". The
93 @ -- "local state" of a repository is contained in the remaining tables of
94 @ -- the zRepositorySchema1 string.
95 @ -------------------------------------------------------------------------
96 @
97 @ -- Whenever new blobs are received into the repository, an entry
98 @ -- in this table records the source of the blob.
99 @ --
@@ -172,11 +172,11 @@
172 @ );
173 @
174 @ -- Some ticket content (such as the originators email address or contact
175 @ -- information) needs to be obscured to protect privacy. This is achieved
176 @ -- by storing an SHA1 hash of the content. For display, the hash is
177 @ -- mapped back into the original text using this table.
178 @ --
179 @ -- This table contains sensitive information and should not be shared
180 @ -- with unauthorized users.
181 @ --
182 @ CREATE TABLE concealed(
@@ -193,11 +193,11 @@
193 /*
194 ** The default reportfmt entry for the schema. This is in an extra
195 ** script so that (configure reset) can install the default report.
196 */
197 const char zRepositorySchemaDefaultReports[] =
198 @ INSERT INTO reportfmt(title,mtime,cols,sqlcode)
199 @ VALUES('All Tickets',julianday('1970-01-01'),'#ffffff Key:
200 @ #f2dcdc Active
201 @ #e8e8e8 Review
202 @ #cfe8bd Fixed
203 @ #bde5d6 Tested
@@ -321,13 +321,13 @@
321 @ rid INTEGER PRIMARY KEY -- Record ID of the phantom
322 @ );
323 @
324 @ -- Each baseline or manifest can have one or more tags. A tag
325 @ -- is defined by a row in the next table.
326 @ --
327 @ -- Wiki pages are tagged with "wiki-NAME" where NAME is the name of
328 @ -- the wiki page. Tickets changes are tagged with "ticket-UUID" where
329 @ -- UUID is the indentifier of the ticket. Tags used to assign symbolic
330 @ -- names to baselines are branches are of the form "sym-NAME" where
331 @ -- NAME is the symbolic name.
332 @ --
333 @ CREATE TABLE tag(
334
+28 -1
--- src/shell.c
+++ src/shell.c
@@ -63,11 +63,13 @@
6363
#endif
6464
6565
#if defined(_WIN32) || defined(WIN32)
6666
# include <io.h>
6767
#define isatty(h) _isatty(h)
68
-#define access(f,m) _access((f),(m))
68
+#ifndef access
69
+# define access(f,m) _access((f),(m))
70
+#endif
6971
#undef popen
7072
#define popen _popen
7173
#undef pclose
7274
#define pclose _pclose
7375
#else
@@ -442,10 +444,11 @@
442444
** state and mode information.
443445
*/
444446
struct callback_data {
445447
sqlite3 *db; /* The database */
446448
int echoOn; /* True to echo input commands */
449
+ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
447450
int statsOn; /* True to display memory stats before each finalize */
448451
int cnt; /* Number of records displayed so far */
449452
FILE *out; /* Write results here */
450453
FILE *traceOut; /* Output for sqlite3_trace() */
451454
int nErr; /* Number of errors seen */
@@ -1297,10 +1300,27 @@
12971300
/* echo the sql statement if echo on */
12981301
if( pArg && pArg->echoOn ){
12991302
const char *zStmtSql = sqlite3_sql(pStmt);
13001303
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
13011304
}
1305
+
1306
+ /* Show the EXPLAIN QUERY PLAN if .eqp is on */
1307
+ if( pArg && pArg->autoEQP ){
1308
+ sqlite3_stmt *pExplain;
1309
+ char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt));
1310
+ rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
1311
+ if( rc==SQLITE_OK ){
1312
+ while( sqlite3_step(pExplain)==SQLITE_ROW ){
1313
+ fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
1314
+ fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1315
+ fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1316
+ fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
1317
+ }
1318
+ }
1319
+ sqlite3_finalize(pExplain);
1320
+ sqlite3_free(zEQP);
1321
+ }
13021322
13031323
/* Output TESTCTRL_EXPLAIN text of requested */
13041324
if( pArg && pArg->mode==MODE_Explain ){
13051325
const char *zExplain = 0;
13061326
sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
@@ -2296,10 +2316,14 @@
22962316
}else
22972317
22982318
if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
22992319
p->echoOn = booleanValue(azArg[1]);
23002320
}else
2321
+
2322
+ if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
2323
+ p->autoEQP = booleanValue(azArg[1]);
2324
+ }else
23012325
23022326
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
23032327
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
23042328
rc = 2;
23052329
}else
@@ -2869,10 +2893,11 @@
28692893
}else
28702894
28712895
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
28722896
int i;
28732897
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
2898
+ fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
28742899
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
28752900
fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
28762901
fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
28772902
fprintf(p->out,"%9.9s: ", "nullvalue");
28782903
output_c_string(p->out, p->nullvalue);
@@ -3706,10 +3731,12 @@
37063731
data.showHeader = 1;
37073732
}else if( strcmp(z,"-noheader")==0 ){
37083733
data.showHeader = 0;
37093734
}else if( strcmp(z,"-echo")==0 ){
37103735
data.echoOn = 1;
3736
+ }else if( strcmp(z,"-eqp")==0 ){
3737
+ data.autoEQP = 1;
37113738
}else if( strcmp(z,"-stats")==0 ){
37123739
data.statsOn = 1;
37133740
}else if( strcmp(z,"-bail")==0 ){
37143741
bail_on_error = 1;
37153742
}else if( strcmp(z,"-version")==0 ){
37163743
--- src/shell.c
+++ src/shell.c
@@ -63,11 +63,13 @@
63 #endif
64
65 #if defined(_WIN32) || defined(WIN32)
66 # include <io.h>
67 #define isatty(h) _isatty(h)
68 #define access(f,m) _access((f),(m))
 
 
69 #undef popen
70 #define popen _popen
71 #undef pclose
72 #define pclose _pclose
73 #else
@@ -442,10 +444,11 @@
442 ** state and mode information.
443 */
444 struct callback_data {
445 sqlite3 *db; /* The database */
446 int echoOn; /* True to echo input commands */
 
447 int statsOn; /* True to display memory stats before each finalize */
448 int cnt; /* Number of records displayed so far */
449 FILE *out; /* Write results here */
450 FILE *traceOut; /* Output for sqlite3_trace() */
451 int nErr; /* Number of errors seen */
@@ -1297,10 +1300,27 @@
1297 /* echo the sql statement if echo on */
1298 if( pArg && pArg->echoOn ){
1299 const char *zStmtSql = sqlite3_sql(pStmt);
1300 fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1301 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1302
1303 /* Output TESTCTRL_EXPLAIN text of requested */
1304 if( pArg && pArg->mode==MODE_Explain ){
1305 const char *zExplain = 0;
1306 sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
@@ -2296,10 +2316,14 @@
2296 }else
2297
2298 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
2299 p->echoOn = booleanValue(azArg[1]);
2300 }else
 
 
 
 
2301
2302 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
2303 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
2304 rc = 2;
2305 }else
@@ -2869,10 +2893,11 @@
2869 }else
2870
2871 if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
2872 int i;
2873 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
 
2874 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
2875 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
2876 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
2877 fprintf(p->out,"%9.9s: ", "nullvalue");
2878 output_c_string(p->out, p->nullvalue);
@@ -3706,10 +3731,12 @@
3706 data.showHeader = 1;
3707 }else if( strcmp(z,"-noheader")==0 ){
3708 data.showHeader = 0;
3709 }else if( strcmp(z,"-echo")==0 ){
3710 data.echoOn = 1;
 
 
3711 }else if( strcmp(z,"-stats")==0 ){
3712 data.statsOn = 1;
3713 }else if( strcmp(z,"-bail")==0 ){
3714 bail_on_error = 1;
3715 }else if( strcmp(z,"-version")==0 ){
3716
--- src/shell.c
+++ src/shell.c
@@ -63,11 +63,13 @@
63 #endif
64
65 #if defined(_WIN32) || defined(WIN32)
66 # include <io.h>
67 #define isatty(h) _isatty(h)
68 #ifndef access
69 # define access(f,m) _access((f),(m))
70 #endif
71 #undef popen
72 #define popen _popen
73 #undef pclose
74 #define pclose _pclose
75 #else
@@ -442,10 +444,11 @@
444 ** state and mode information.
445 */
446 struct callback_data {
447 sqlite3 *db; /* The database */
448 int echoOn; /* True to echo input commands */
449 int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
450 int statsOn; /* True to display memory stats before each finalize */
451 int cnt; /* Number of records displayed so far */
452 FILE *out; /* Write results here */
453 FILE *traceOut; /* Output for sqlite3_trace() */
454 int nErr; /* Number of errors seen */
@@ -1297,10 +1300,27 @@
1300 /* echo the sql statement if echo on */
1301 if( pArg && pArg->echoOn ){
1302 const char *zStmtSql = sqlite3_sql(pStmt);
1303 fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
1304 }
1305
1306 /* Show the EXPLAIN QUERY PLAN if .eqp is on */
1307 if( pArg && pArg->autoEQP ){
1308 sqlite3_stmt *pExplain;
1309 char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt));
1310 rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
1311 if( rc==SQLITE_OK ){
1312 while( sqlite3_step(pExplain)==SQLITE_ROW ){
1313 fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
1314 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
1315 fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
1316 fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
1317 }
1318 }
1319 sqlite3_finalize(pExplain);
1320 sqlite3_free(zEQP);
1321 }
1322
1323 /* Output TESTCTRL_EXPLAIN text of requested */
1324 if( pArg && pArg->mode==MODE_Explain ){
1325 const char *zExplain = 0;
1326 sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain);
@@ -2296,10 +2316,14 @@
2316 }else
2317
2318 if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
2319 p->echoOn = booleanValue(azArg[1]);
2320 }else
2321
2322 if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
2323 p->autoEQP = booleanValue(azArg[1]);
2324 }else
2325
2326 if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
2327 if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
2328 rc = 2;
2329 }else
@@ -2869,10 +2893,11 @@
2893 }else
2894
2895 if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
2896 int i;
2897 fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
2898 fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
2899 fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
2900 fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
2901 fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
2902 fprintf(p->out,"%9.9s: ", "nullvalue");
2903 output_c_string(p->out, p->nullvalue);
@@ -3706,10 +3731,12 @@
3731 data.showHeader = 1;
3732 }else if( strcmp(z,"-noheader")==0 ){
3733 data.showHeader = 0;
3734 }else if( strcmp(z,"-echo")==0 ){
3735 data.echoOn = 1;
3736 }else if( strcmp(z,"-eqp")==0 ){
3737 data.autoEQP = 1;
3738 }else if( strcmp(z,"-stats")==0 ){
3739 data.statsOn = 1;
3740 }else if( strcmp(z,"-bail")==0 ){
3741 bail_on_error = 1;
3742 }else if( strcmp(z,"-version")==0 ){
3743
+7 -7
--- src/shun.c
+++ src/shun.c
@@ -69,11 +69,11 @@
6969
style_header("Shunned Artifacts");
7070
if( zUuid && P("sub") ){
7171
login_verify_csrf_secret();
7272
db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid);
7373
if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){
74
- @ <p class="noMoreShun">Artifact
74
+ @ <p class="noMoreShun">Artifact
7575
@ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> is no
7676
@ longer being shunned.</p>
7777
}else{
7878
@ <p class="noMoreShun">Artifact %s(zUuid) will no longer
7979
@ be shunned. But it does not exist in the repository. It
@@ -107,11 +107,11 @@
107107
}
108108
@ <p>A shunned artifact will not be pushed nor accepted in a pull and the
109109
@ artifact content will be purged from the repository the next time the
110110
@ repository is rebuilt. A list of shunned artifacts can be seen at the
111111
@ bottom of this page.</p>
112
- @
112
+ @
113113
@ <a name="addshun"></a>
114114
@ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1
115115
@ hash of the artifact) in the
116116
@ following box and press the "Shun" button. This will cause the artifact
117117
@ to be removed from the repository and will prevent the artifact from being
@@ -124,11 +124,11 @@
124124
@ from the repository. Inappropriate content includes such things as
125125
@ spam added to Wiki, files that violate copyright or patent agreements,
126126
@ or artifacts that by design or accident interfere with the processing
127127
@ of the repository. Do not shun artifacts merely to remove them from
128128
@ sight - set the "hidden" tag on such artifacts instead.</p>
129
- @
129
+ @
130130
@ <blockquote>
131131
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
132132
login_insert_csrf_secret();
133133
@ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
134134
@ <input type="submit" name="add" value="Shun" />
@@ -159,14 +159,14 @@
159159
@ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
160160
login_insert_csrf_secret();
161161
@ <input type="submit" name="rebuild" value="Rebuild" />
162162
@ </div></form>
163163
@ </blockquote>
164
- @
164
+ @
165165
@ <hr /><p>Shunned Artifacts:</p>
166166
@ <blockquote><p>
167
- db_prepare(&q,
167
+ db_prepare(&q,
168168
"SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
169169
" FROM shun ORDER BY uuid");
170170
while( db_step(&q)==SQLITE_ROW ){
171171
const char *zUuid = db_column_text(&q, 0);
172172
int stillExists = db_column_int(&q, 1);
@@ -228,11 +228,11 @@
228228
style_header("Content Sources");
229229
if( ofst>0 ){
230230
style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
231231
ofst>30 ? ofst-30 : 0);
232232
}
233
- db_prepare(&q,
233
+ db_prepare(&q,
234234
"SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
235235
" FROM rcvfrom LEFT JOIN user USING(uid)"
236236
" ORDER BY rcvid DESC LIMIT 31 OFFSET %d",
237237
ofst
238238
);
@@ -287,11 +287,11 @@
287287
login_check_credentials();
288288
if( !g.perm.Admin ){
289289
login_needed();
290290
}
291291
style_header("Content Source %d", rcvid);
292
- db_prepare(&q,
292
+ db_prepare(&q,
293293
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
294294
" FROM rcvfrom LEFT JOIN user USING(uid)"
295295
" WHERE rcvid=%d",
296296
rcvid
297297
);
298298
--- src/shun.c
+++ src/shun.c
@@ -69,11 +69,11 @@
69 style_header("Shunned Artifacts");
70 if( zUuid && P("sub") ){
71 login_verify_csrf_secret();
72 db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid);
73 if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){
74 @ <p class="noMoreShun">Artifact
75 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> is no
76 @ longer being shunned.</p>
77 }else{
78 @ <p class="noMoreShun">Artifact %s(zUuid) will no longer
79 @ be shunned. But it does not exist in the repository. It
@@ -107,11 +107,11 @@
107 }
108 @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
109 @ artifact content will be purged from the repository the next time the
110 @ repository is rebuilt. A list of shunned artifacts can be seen at the
111 @ bottom of this page.</p>
112 @
113 @ <a name="addshun"></a>
114 @ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1
115 @ hash of the artifact) in the
116 @ following box and press the "Shun" button. This will cause the artifact
117 @ to be removed from the repository and will prevent the artifact from being
@@ -124,11 +124,11 @@
124 @ from the repository. Inappropriate content includes such things as
125 @ spam added to Wiki, files that violate copyright or patent agreements,
126 @ or artifacts that by design or accident interfere with the processing
127 @ of the repository. Do not shun artifacts merely to remove them from
128 @ sight - set the "hidden" tag on such artifacts instead.</p>
129 @
130 @ <blockquote>
131 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
132 login_insert_csrf_secret();
133 @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
134 @ <input type="submit" name="add" value="Shun" />
@@ -159,14 +159,14 @@
159 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
160 login_insert_csrf_secret();
161 @ <input type="submit" name="rebuild" value="Rebuild" />
162 @ </div></form>
163 @ </blockquote>
164 @
165 @ <hr /><p>Shunned Artifacts:</p>
166 @ <blockquote><p>
167 db_prepare(&q,
168 "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
169 " FROM shun ORDER BY uuid");
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zUuid = db_column_text(&q, 0);
172 int stillExists = db_column_int(&q, 1);
@@ -228,11 +228,11 @@
228 style_header("Content Sources");
229 if( ofst>0 ){
230 style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
231 ofst>30 ? ofst-30 : 0);
232 }
233 db_prepare(&q,
234 "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
235 " FROM rcvfrom LEFT JOIN user USING(uid)"
236 " ORDER BY rcvid DESC LIMIT 31 OFFSET %d",
237 ofst
238 );
@@ -287,11 +287,11 @@
287 login_check_credentials();
288 if( !g.perm.Admin ){
289 login_needed();
290 }
291 style_header("Content Source %d", rcvid);
292 db_prepare(&q,
293 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
294 " FROM rcvfrom LEFT JOIN user USING(uid)"
295 " WHERE rcvid=%d",
296 rcvid
297 );
298
--- src/shun.c
+++ src/shun.c
@@ -69,11 +69,11 @@
69 style_header("Shunned Artifacts");
70 if( zUuid && P("sub") ){
71 login_verify_csrf_secret();
72 db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid);
73 if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){
74 @ <p class="noMoreShun">Artifact
75 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">%s(zUuid)</a> is no
76 @ longer being shunned.</p>
77 }else{
78 @ <p class="noMoreShun">Artifact %s(zUuid) will no longer
79 @ be shunned. But it does not exist in the repository. It
@@ -107,11 +107,11 @@
107 }
108 @ <p>A shunned artifact will not be pushed nor accepted in a pull and the
109 @ artifact content will be purged from the repository the next time the
110 @ repository is rebuilt. A list of shunned artifacts can be seen at the
111 @ bottom of this page.</p>
112 @
113 @ <a name="addshun"></a>
114 @ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1
115 @ hash of the artifact) in the
116 @ following box and press the "Shun" button. This will cause the artifact
117 @ to be removed from the repository and will prevent the artifact from being
@@ -124,11 +124,11 @@
124 @ from the repository. Inappropriate content includes such things as
125 @ spam added to Wiki, files that violate copyright or patent agreements,
126 @ or artifacts that by design or accident interfere with the processing
127 @ of the repository. Do not shun artifacts merely to remove them from
128 @ sight - set the "hidden" tag on such artifacts instead.</p>
129 @
130 @ <blockquote>
131 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
132 login_insert_csrf_secret();
133 @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
134 @ <input type="submit" name="add" value="Shun" />
@@ -159,14 +159,14 @@
159 @ <form method="post" action="%s(g.zTop)/%s(g.zPath)"><div>
160 login_insert_csrf_secret();
161 @ <input type="submit" name="rebuild" value="Rebuild" />
162 @ </div></form>
163 @ </blockquote>
164 @
165 @ <hr /><p>Shunned Artifacts:</p>
166 @ <blockquote><p>
167 db_prepare(&q,
168 "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
169 " FROM shun ORDER BY uuid");
170 while( db_step(&q)==SQLITE_ROW ){
171 const char *zUuid = db_column_text(&q, 0);
172 int stillExists = db_column_int(&q, 1);
@@ -228,11 +228,11 @@
228 style_header("Content Sources");
229 if( ofst>0 ){
230 style_submenu_element("Newer", "Newer", "rcvfromlist?ofst=%d",
231 ofst>30 ? ofst-30 : 0);
232 }
233 db_prepare(&q,
234 "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
235 " FROM rcvfrom LEFT JOIN user USING(uid)"
236 " ORDER BY rcvid DESC LIMIT 31 OFFSET %d",
237 ofst
238 );
@@ -287,11 +287,11 @@
287 login_check_credentials();
288 if( !g.perm.Admin ){
289 login_needed();
290 }
291 style_header("Content Source %d", rcvid);
292 db_prepare(&q,
293 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
294 " FROM rcvfrom LEFT JOIN user USING(uid)"
295 " WHERE rcvid=%d",
296 rcvid
297 );
298
+776 -303
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -73,12 +73,45 @@
7373
# define _FILE_OFFSET_BITS 64
7474
# endif
7575
# define _LARGEFILE_SOURCE 1
7676
#endif
7777
78
+/*
79
+** For MinGW, check to see if we can include the header file containing its
80
+** version information, among other things. Normally, this internal MinGW
81
+** header file would [only] be included automatically by other MinGW header
82
+** files; however, the contained version information is now required by this
83
+** header file to work around binary compatibility issues (see below) and
84
+** this is the only known way to reliably obtain it. This entire #if block
85
+** would be completely unnecessary if there was any other way of detecting
86
+** MinGW via their preprocessor (e.g. if they customized their GCC to define
87
+** some MinGW-specific macros). When compiling for MinGW, either the
88
+** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
89
+** defined; otherwise, detection of conditions specific to MinGW will be
90
+** disabled.
91
+*/
92
+#if defined(_HAVE_MINGW_H)
93
+# include "mingw.h"
94
+#elif defined(_HAVE__MINGW_H)
95
+# include "_mingw.h"
96
+#endif
97
+
98
+/*
99
+** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
100
+** define is required to maintain binary compatibility with the MSVC runtime
101
+** library in use (e.g. for Windows XP).
102
+*/
103
+#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
104
+ defined(_WIN32) && !defined(_WIN64) && \
105
+ defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
106
+ defined(__MSVCRT__)
107
+# define _USE_32BIT_TIME_T
108
+#endif
109
+
78110
/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
79
-** first in QNX.
111
+** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
112
+** MinGW.
80113
*/
81114
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
82115
/************** Begin file sqlite3.h *****************************************/
83116
/*
84117
** 2001 September 15
@@ -189,11 +222,11 @@
189222
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
190223
** [sqlite_version()] and [sqlite_source_id()].
191224
*/
192225
#define SQLITE_VERSION "3.8.4"
193226
#define SQLITE_VERSION_NUMBER 3008004
194
-#define SQLITE_SOURCE_ID "2014-02-27 15:04:13 a6690400235705ecc0d1a60dacff6ad5fb1f944a"
227
+#define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042"
195228
196229
/*
197230
** CAPI3REF: Run-Time Library Version Numbers
198231
** KEYWORDS: sqlite3_version, sqlite3_sourceid
199232
**
@@ -9334,12 +9367,15 @@
93349367
#ifndef SQLITE_OMIT_TRACE
93359368
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
93369369
#endif
93379370
93389371
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
9339
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
9372
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
93409373
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
9374
+
9375
+typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
9376
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
93419377
93429378
#ifndef SQLITE_OMIT_TRIGGER
93439379
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
93449380
#endif
93459381
@@ -10950,23 +10986,23 @@
1095010986
** the OP_MakeRecord opcode of the VDBE and is disassembled by the
1095110987
** OP_Column opcode.
1095210988
**
1095310989
** This structure holds a record that has already been disassembled
1095410990
** into its constituent fields.
10991
+**
10992
+** The r1 and r2 member variables are only used by the optimized comparison
10993
+** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
1095510994
*/
1095610995
struct UnpackedRecord {
1095710996
KeyInfo *pKeyInfo; /* Collation and sort-order information */
1095810997
u16 nField; /* Number of entries in apMem[] */
10959
- u8 flags; /* Boolean settings. UNPACKED_... below */
10998
+ i8 default_rc; /* Comparison result if keys are equal */
1096010999
Mem *aMem; /* Values */
11000
+ int r1; /* Value to return if (lhs > rhs) */
11001
+ int r2; /* Value to return if (rhs < lhs) */
1096111002
};
1096211003
10963
-/*
10964
-** Allowed values of UnpackedRecord.flags
10965
-*/
10966
-#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
10967
-#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
1096811004
1096911005
/*
1097011006
** Each SQL index is represented in memory by an
1097111007
** instance of the following structure.
1097211008
**
@@ -11382,12 +11418,12 @@
1138211418
**
1138311419
** In the colUsed field, the high-order bit (bit 63) is set if the table
1138411420
** contains more than 63 columns and the 64-th or later column is used.
1138511421
*/
1138611422
struct SrcList {
11387
- u8 nSrc; /* Number of tables or subqueries in the FROM clause */
11388
- u8 nAlloc; /* Number of entries allocated in a[] below */
11423
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
11424
+ u32 nAlloc; /* Number of entries allocated in a[] below */
1138911425
struct SrcList_item {
1139011426
Schema *pSchema; /* Schema to which this item is fixed */
1139111427
char *zDatabase; /* Name of database holding this table */
1139211428
char *zName; /* Name of the table */
1139311429
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
@@ -13415,10 +13451,13 @@
1341513451
#ifdef SQLITE_OMIT_COMPLETE
1341613452
"OMIT_COMPLETE",
1341713453
#endif
1341813454
#ifdef SQLITE_OMIT_COMPOUND_SELECT
1341913455
"OMIT_COMPOUND_SELECT",
13456
+#endif
13457
+#ifdef SQLITE_OMIT_CTE
13458
+ "OMIT_CTE",
1342013459
#endif
1342113460
#ifdef SQLITE_OMIT_DATETIME_FUNCS
1342213461
"OMIT_DATETIME_FUNCS",
1342313462
#endif
1342413463
#ifdef SQLITE_OMIT_DECLTYPE
@@ -13800,11 +13839,10 @@
1380013839
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
1380113840
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
1380213841
} u;
1380313842
int n; /* Number of characters in string value, excluding '\0' */
1380413843
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
13805
- u8 memType; /* Lower 5 bits of flags */
1380613844
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
1380713845
#ifdef SQLITE_DEBUG
1380813846
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
1380913847
void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
1381013848
#endif
@@ -13827,10 +13865,11 @@
1382713865
#define MEM_Null 0x0001 /* Value is NULL */
1382813866
#define MEM_Str 0x0002 /* Value is a string */
1382913867
#define MEM_Int 0x0004 /* Value is an integer */
1383013868
#define MEM_Real 0x0008 /* Value is a real number */
1383113869
#define MEM_Blob 0x0010 /* Value is a BLOB */
13870
+#define MEM_AffMask 0x001f /* Mask of affinity bits */
1383213871
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
1383313872
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
1383413873
#define MEM_Undefined 0x0080 /* Value is undefined */
1383513874
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
1383613875
#define MEM_TypeMask 0x01ff /* Mask of type bits */
@@ -13840,11 +13879,11 @@
1384013879
** the following flags must be set to determine the memory management
1384113880
** policy for Mem.z. The MEM_Term flag tells us whether or not the
1384213881
** string is \000 or \u0000 terminated
1384313882
*/
1384413883
#define MEM_Term 0x0200 /* String rep is nul terminated */
13845
-#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
13884
+#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
1384613885
#define MEM_Static 0x0800 /* Mem.z points to a static string */
1384713886
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
1384813887
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
1384913888
#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
1385013889
#ifdef SQLITE_OMIT_INCRBLOB
@@ -14023,11 +14062,11 @@
1402314062
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
1402414063
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
1402514064
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
1402614065
1402714066
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
14028
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
14067
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
1402914068
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
1403014069
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
1403114070
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
1403214071
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
1403314072
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -14066,12 +14105,10 @@
1406614105
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
1406714106
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
1406814107
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
1406914108
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
1407014109
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
14071
-#define sqlite3VdbeMemStoreType(X) (X)->memType = (u8)((X)->flags&0x1f)
14072
-/* void sqlite3VdbeMemStoreType(Mem *pMem); */
1407314110
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
1407414111
1407514112
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
1407614113
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
1407714114
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -14088,10 +14125,11 @@
1408814125
# define sqlite3VdbeLeave(X)
1408914126
#endif
1409014127
1409114128
#ifdef SQLITE_DEBUG
1409214129
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
14130
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
1409314131
#endif
1409414132
1409514133
#ifndef SQLITE_OMIT_FOREIGN_KEY
1409614134
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
1409714135
#else
@@ -21471,11 +21509,11 @@
2147121509
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
2147221510
2147321511
sqlite3VdbeMemRelease(pMem);
2147421512
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
2147521513
pMem->enc = desiredEnc;
21476
- pMem->flags |= (MEM_Term|MEM_Dyn);
21514
+ pMem->flags |= (MEM_Term);
2147721515
pMem->z = (char*)zOut;
2147821516
pMem->zMalloc = pMem->z;
2147921517
2148021518
translate_out:
2148121519
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
@@ -21599,11 +21637,10 @@
2159921637
sqlite3VdbeMemRelease(&m);
2160021638
m.z = 0;
2160121639
}
2160221640
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
2160321641
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
21604
- assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
2160521642
assert( m.z || db->mallocFailed );
2160621643
return m.z;
2160721644
}
2160821645
2160921646
/*
@@ -55305,10 +55342,11 @@
5530555342
i64 intKey, /* The table key */
5530655343
int biasRight, /* If true, bias the search to the high end */
5530755344
int *pRes /* Write search results here */
5530855345
){
5530955346
int rc;
55347
+ RecordCompare xRecordCompare;
5531055348
5531155349
assert( cursorHoldsMutex(pCur) );
5531255350
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
5531355351
assert( pRes );
5531455352
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
@@ -55325,10 +55363,20 @@
5532555363
if( pCur->atLast && pCur->info.nKey<intKey ){
5532655364
*pRes = -1;
5532755365
return SQLITE_OK;
5532855366
}
5532955367
}
55368
+
55369
+ if( pIdxKey ){
55370
+ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
55371
+ assert( pIdxKey->default_rc==1
55372
+ || pIdxKey->default_rc==0
55373
+ || pIdxKey->default_rc==-1
55374
+ );
55375
+ }else{
55376
+ xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */
55377
+ }
5533055378
5533155379
rc = moveToRoot(pCur);
5533255380
if( rc ){
5533355381
return rc;
5533455382
}
@@ -55358,11 +55406,11 @@
5535855406
lwr = 0;
5535955407
upr = pPage->nCell-1;
5536055408
assert( biasRight==0 || biasRight==1 );
5536155409
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
5536255410
pCur->aiIdx[pCur->iPage] = (u16)idx;
55363
- if( pPage->intKey ){
55411
+ if( xRecordCompare==0 ){
5536455412
for(;;){
5536555413
i64 nCellKey;
5536655414
pCell = findCell(pPage, idx) + pPage->childPtrSize;
5536755415
if( pPage->hasData ){
5536855416
while( 0x80 <= *(pCell++) ){
@@ -55410,18 +55458,18 @@
5541055458
if( nCell<=pPage->max1bytePayload ){
5541155459
/* This branch runs if the record-size field of the cell is a
5541255460
** single byte varint and the record fits entirely on the main
5541355461
** b-tree page. */
5541455462
testcase( pCell+nCell+1==pPage->aDataEnd );
55415
- c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
55463
+ c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
5541655464
}else if( !(pCell[1] & 0x80)
5541755465
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
5541855466
){
5541955467
/* The record-size field is a 2 byte varint and the record
5542055468
** fits entirely on the main b-tree page. */
5542155469
testcase( pCell+nCell+2==pPage->aDataEnd );
55422
- c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
55470
+ c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
5542355471
}else{
5542455472
/* The record flows over onto one or more overflow pages. In
5542555473
** this case the whole cell needs to be parsed, a buffer allocated
5542655474
** and accessPayload() used to retrieve the record into the
5542755475
** buffer before VdbeRecordCompare() can be called. */
@@ -55438,11 +55486,11 @@
5543855486
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
5543955487
if( rc ){
5544055488
sqlite3_free(pCellKey);
5544155489
goto moveto_finish;
5544255490
}
55443
- c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
55491
+ c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
5544455492
sqlite3_free(pCellKey);
5544555493
}
5544655494
if( c<0 ){
5544755495
lwr = idx+1;
5544855496
}else if( c>0 ){
@@ -60001,10 +60049,46 @@
6000160049
** This file contains code use to manipulate "Mem" structure. A "Mem"
6000260050
** stores a single value in the VDBE. Mem is an opaque structure visible
6000360051
** only within the VDBE. Interface routines refer to a Mem using the
6000460052
** name sqlite_value
6000560053
*/
60054
+
60055
+#ifdef SQLITE_DEBUG
60056
+/*
60057
+** Check invariants on a Mem object.
60058
+**
60059
+** This routine is intended for use inside of assert() statements, like
60060
+** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
60061
+*/
60062
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
60063
+ /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
60064
+ ** function for Mem.z
60065
+ */
60066
+ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
60067
+ assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
60068
+
60069
+ /* If p holds a string or blob, the Mem.z must point to exactly
60070
+ ** one of the following:
60071
+ **
60072
+ ** (1) Memory in Mem.zMalloc and managed by the Mem object
60073
+ ** (2) Memory to be freed using Mem.xDel
60074
+ ** (3) An ephermal string or blob
60075
+ ** (4) A static string or blob
60076
+ */
60077
+ if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
60078
+ assert(
60079
+ ((p->z==p->zMalloc)? 1 : 0) +
60080
+ ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
60081
+ ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
60082
+ ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
60083
+ );
60084
+ }
60085
+
60086
+ return 1;
60087
+}
60088
+#endif
60089
+
6000660090
6000760091
/*
6000860092
** If pMem is an object with a valid string representation, this routine
6000960093
** ensures the internal encoding for the string representation is
6001060094
** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
@@ -60051,16 +60135,11 @@
6005160135
** pMem->z into the new allocation. pMem must be either a string or
6005260136
** blob if bPreserve is true. If bPreserve is false, any prior content
6005360137
** in pMem->z is discarded.
6005460138
*/
6005560139
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
60056
- assert( 1 >=
60057
- ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
60058
- (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
60059
- ((pMem->flags&MEM_Ephem) ? 1 : 0) +
60060
- ((pMem->flags&MEM_Static) ? 1 : 0)
60061
- );
60140
+ assert( sqlite3VdbeCheckMemInvariants(pMem) );
6006260141
assert( (pMem->flags&MEM_RowSet)==0 );
6006360142
6006460143
/* If the bPreserve flag is set to true, then the memory cell must already
6006560144
** contain a valid string or blob value. */
6006660145
assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
@@ -60074,26 +60153,27 @@
6007460153
}else{
6007560154
sqlite3DbFree(pMem->db, pMem->zMalloc);
6007660155
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
6007760156
}
6007860157
if( pMem->zMalloc==0 ){
60079
- sqlite3VdbeMemRelease(pMem);
60158
+ VdbeMemRelease(pMem);
60159
+ pMem->z = 0;
6008060160
pMem->flags = MEM_Null;
6008160161
return SQLITE_NOMEM;
6008260162
}
6008360163
}
6008460164
6008560165
if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
6008660166
memcpy(pMem->zMalloc, pMem->z, pMem->n);
6008760167
}
60088
- if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
60089
- assert( pMem->xDel!=SQLITE_DYNAMIC );
60168
+ if( (pMem->flags&MEM_Dyn)!=0 ){
60169
+ assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
6009060170
pMem->xDel((void *)(pMem->z));
6009160171
}
6009260172
6009360173
pMem->z = pMem->zMalloc;
60094
- pMem->flags &= ~(MEM_Ephem|MEM_Static);
60174
+ pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
6009560175
pMem->xDel = 0;
6009660176
return SQLITE_OK;
6009760177
}
6009860178
6009960179
/*
@@ -60258,13 +60338,13 @@
6025860338
assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
6025960339
if( p->flags&MEM_Agg ){
6026060340
sqlite3VdbeMemFinalize(p, p->u.pDef);
6026160341
assert( (p->flags & MEM_Agg)==0 );
6026260342
sqlite3VdbeMemRelease(p);
60263
- }else if( p->flags&MEM_Dyn && p->xDel ){
60343
+ }else if( p->flags&MEM_Dyn ){
6026460344
assert( (p->flags&MEM_RowSet)==0 );
60265
- assert( p->xDel!=SQLITE_DYNAMIC );
60345
+ assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
6026660346
p->xDel((void *)p->z);
6026760347
p->xDel = 0;
6026860348
}else if( p->flags&MEM_RowSet ){
6026960349
sqlite3RowSetClear(p->u.pRowSet);
6027060350
}else if( p->flags&MEM_Frame ){
@@ -60273,13 +60353,14 @@
6027360353
}
6027460354
6027560355
/*
6027660356
** Release any memory held by the Mem. This may leave the Mem in an
6027760357
** inconsistent state, for example with (Mem.z==0) and
60278
-** (Mem.memType==MEM_Str).
60358
+** (Mem.flags==MEM_Str).
6027960359
*/
6028060360
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
60361
+ assert( sqlite3VdbeCheckMemInvariants(p) );
6028160362
VdbeMemRelease(p);
6028260363
if( p->zMalloc ){
6028360364
sqlite3DbFree(p->db, p->zMalloc);
6028460365
p->zMalloc = 0;
6028560366
}
@@ -60464,11 +60545,10 @@
6046460545
}
6046560546
if( pMem->flags & MEM_RowSet ){
6046660547
sqlite3RowSetClear(pMem->u.pRowSet);
6046760548
}
6046860549
MemSetTypeFlag(pMem, MEM_Null);
60469
- pMem->memType = MEM_Null;
6047060550
}
6047160551
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
6047260552
sqlite3VdbeMemSetNull((Mem*)p);
6047360553
}
6047460554
@@ -60477,11 +60557,10 @@
6047760557
** n containing all zeros.
6047860558
*/
6047960559
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
6048060560
sqlite3VdbeMemRelease(pMem);
6048160561
pMem->flags = MEM_Blob|MEM_Zero;
60482
- pMem->memType = MEM_Blob;
6048360562
pMem->n = 0;
6048460563
if( n<0 ) n = 0;
6048560564
pMem->u.nZero = n;
6048660565
pMem->enc = SQLITE_UTF8;
6048760566
@@ -60500,11 +60579,10 @@
6050060579
*/
6050160580
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
6050260581
sqlite3VdbeMemRelease(pMem);
6050360582
pMem->u.i = val;
6050460583
pMem->flags = MEM_Int;
60505
- pMem->memType = MEM_Int;
6050660584
}
6050760585
6050860586
#ifndef SQLITE_OMIT_FLOATING_POINT
6050960587
/*
6051060588
** Delete any previous value and set the value stored in *pMem to val,
@@ -60515,11 +60593,10 @@
6051560593
sqlite3VdbeMemSetNull(pMem);
6051660594
}else{
6051760595
sqlite3VdbeMemRelease(pMem);
6051860596
pMem->r = val;
6051960597
pMem->flags = MEM_Real;
60520
- pMem->memType = MEM_Real;
6052160598
}
6052260599
}
6052360600
#endif
6052460601
6052560602
/*
@@ -60613,10 +60690,11 @@
6061360690
6061460691
assert( (pFrom->flags & MEM_RowSet)==0 );
6061560692
VdbeMemRelease(pTo);
6061660693
memcpy(pTo, pFrom, MEMCELLSIZE);
6061760694
pTo->flags &= ~MEM_Dyn;
60695
+ pTo->xDel = 0;
6061860696
6061960697
if( pTo->flags&(MEM_Str|MEM_Blob) ){
6062060698
if( 0==(pFrom->flags&MEM_Static) ){
6062160699
pTo->flags |= MEM_Ephem;
6062260700
rc = sqlite3VdbeMemMakeWriteable(pTo);
@@ -60723,11 +60801,10 @@
6072360801
}
6072460802
6072560803
pMem->n = nByte;
6072660804
pMem->flags = flags;
6072760805
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
60728
- pMem->memType = flags&0x1f;
6072960806
6073060807
#ifndef SQLITE_OMIT_UTF16
6073160808
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
6073260809
return SQLITE_NOMEM;
6073360810
}
@@ -60738,123 +60815,10 @@
6073860815
}
6073960816
6074060817
return SQLITE_OK;
6074160818
}
6074260819
60743
-/*
60744
-** Compare the values contained by the two memory cells, returning
60745
-** negative, zero or positive if pMem1 is less than, equal to, or greater
60746
-** than pMem2. Sorting order is NULL's first, followed by numbers (integers
60747
-** and reals) sorted numerically, followed by text ordered by the collating
60748
-** sequence pColl and finally blob's ordered by memcmp().
60749
-**
60750
-** Two NULL values are considered equal by this function.
60751
-*/
60752
-SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
60753
- int rc;
60754
- int f1, f2;
60755
- int combined_flags;
60756
-
60757
- f1 = pMem1->flags;
60758
- f2 = pMem2->flags;
60759
- combined_flags = f1|f2;
60760
- assert( (combined_flags & MEM_RowSet)==0 );
60761
-
60762
- /* If one value is NULL, it is less than the other. If both values
60763
- ** are NULL, return 0.
60764
- */
60765
- if( combined_flags&MEM_Null ){
60766
- return (f2&MEM_Null) - (f1&MEM_Null);
60767
- }
60768
-
60769
- /* If one value is a number and the other is not, the number is less.
60770
- ** If both are numbers, compare as reals if one is a real, or as integers
60771
- ** if both values are integers.
60772
- */
60773
- if( combined_flags&(MEM_Int|MEM_Real) ){
60774
- double r1, r2;
60775
- if( (f1 & f2 & MEM_Int)!=0 ){
60776
- if( pMem1->u.i < pMem2->u.i ) return -1;
60777
- if( pMem1->u.i > pMem2->u.i ) return 1;
60778
- return 0;
60779
- }
60780
- if( (f1&MEM_Real)!=0 ){
60781
- r1 = pMem1->r;
60782
- }else if( (f1&MEM_Int)!=0 ){
60783
- r1 = (double)pMem1->u.i;
60784
- }else{
60785
- return 1;
60786
- }
60787
- if( (f2&MEM_Real)!=0 ){
60788
- r2 = pMem2->r;
60789
- }else if( (f2&MEM_Int)!=0 ){
60790
- r2 = (double)pMem2->u.i;
60791
- }else{
60792
- return -1;
60793
- }
60794
- if( r1<r2 ) return -1;
60795
- if( r1>r2 ) return 1;
60796
- return 0;
60797
- }
60798
-
60799
- /* If one value is a string and the other is a blob, the string is less.
60800
- ** If both are strings, compare using the collating functions.
60801
- */
60802
- if( combined_flags&MEM_Str ){
60803
- if( (f1 & MEM_Str)==0 ){
60804
- return 1;
60805
- }
60806
- if( (f2 & MEM_Str)==0 ){
60807
- return -1;
60808
- }
60809
-
60810
- assert( pMem1->enc==pMem2->enc );
60811
- assert( pMem1->enc==SQLITE_UTF8 ||
60812
- pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
60813
-
60814
- /* The collation sequence must be defined at this point, even if
60815
- ** the user deletes the collation sequence after the vdbe program is
60816
- ** compiled (this was not always the case).
60817
- */
60818
- assert( !pColl || pColl->xCmp );
60819
-
60820
- if( pColl ){
60821
- if( pMem1->enc==pColl->enc ){
60822
- /* The strings are already in the correct encoding. Call the
60823
- ** comparison function directly */
60824
- return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
60825
- }else{
60826
- const void *v1, *v2;
60827
- int n1, n2;
60828
- Mem c1;
60829
- Mem c2;
60830
- memset(&c1, 0, sizeof(c1));
60831
- memset(&c2, 0, sizeof(c2));
60832
- sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
60833
- sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
60834
- v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
60835
- n1 = v1==0 ? 0 : c1.n;
60836
- v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
60837
- n2 = v2==0 ? 0 : c2.n;
60838
- rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
60839
- sqlite3VdbeMemRelease(&c1);
60840
- sqlite3VdbeMemRelease(&c2);
60841
- return rc;
60842
- }
60843
- }
60844
- /* If a NULL pointer was passed as the collate function, fall through
60845
- ** to the blob case and use memcmp(). */
60846
- }
60847
-
60848
- /* Both values must be blobs. Compare using memcmp(). */
60849
- rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
60850
- if( rc==0 ){
60851
- rc = pMem1->n - pMem2->n;
60852
- }
60853
- return rc;
60854
-}
60855
-
6085660820
/*
6085760821
** Move data out of a btree key or data field and into a Mem structure.
6085860822
** The data or key is taken from the entry that pCur is currently pointing
6085960823
** to. offset and amt determine what portion of the data or key to retrieve.
6086060824
** key is true to get the key or false to get data. The result is written
@@ -60891,26 +60855,26 @@
6089160855
6089260856
if( offset+amt<=available ){
6089360857
sqlite3VdbeMemRelease(pMem);
6089460858
pMem->z = &zData[offset];
6089560859
pMem->flags = MEM_Blob|MEM_Ephem;
60860
+ pMem->n = (int)amt;
6089660861
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
60897
- pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
60898
- pMem->enc = 0;
60899
- pMem->memType = MEM_Blob;
6090060862
if( key ){
6090160863
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
6090260864
}else{
6090360865
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
6090460866
}
60905
- pMem->z[amt] = 0;
60906
- pMem->z[amt+1] = 0;
60907
- if( rc!=SQLITE_OK ){
60867
+ if( rc==SQLITE_OK ){
60868
+ pMem->z[amt] = 0;
60869
+ pMem->z[amt+1] = 0;
60870
+ pMem->flags = MEM_Blob|MEM_Term;
60871
+ pMem->n = (int)amt;
60872
+ }else{
6090860873
sqlite3VdbeMemRelease(pMem);
6090960874
}
6091060875
}
60911
- pMem->n = (int)amt;
6091260876
6091360877
return rc;
6091460878
}
6091560879
6091660880
/* This function is only available internally, it is not part of the
@@ -60964,11 +60928,10 @@
6096460928
*/
6096560929
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
6096660930
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
6096760931
if( p ){
6096860932
p->flags = MEM_Null;
60969
- p->memType = MEM_Null;
6097060933
p->db = db;
6097160934
}
6097260935
return p;
6097360936
}
6097460937
@@ -61010,15 +60973,13 @@
6101060973
if( pRec ){
6101160974
pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
6101260975
if( pRec->pKeyInfo ){
6101360976
assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
6101460977
assert( pRec->pKeyInfo->enc==ENC(db) );
61015
- pRec->flags = UNPACKED_PREFIX_MATCH;
6101660978
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
6101760979
for(i=0; i<nCol; i++){
6101860980
pRec->aMem[i].flags = MEM_Null;
61019
- pRec->aMem[i].memType = MEM_Null;
6102060981
pRec->aMem[i].db = db;
6102160982
}
6102260983
}else{
6102360984
sqlite3DbFree(db, pRec);
6102460985
pRec = 0;
@@ -61087,11 +61048,10 @@
6108761048
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
6108861049
}else{
6108961050
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
6109061051
if( zVal==0 ) goto no_mem;
6109161052
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
61092
- if( op==TK_FLOAT ) pVal->memType = MEM_Real;
6109361053
}
6109461054
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
6109561055
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
6109661056
}else{
6109761057
sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
@@ -61105,13 +61065,13 @@
6110561065
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
6110661066
&& pVal!=0
6110761067
){
6110861068
sqlite3VdbeMemNumerify(pVal);
6110961069
if( pVal->u.i==SMALLEST_INT64 ){
61110
- pVal->flags &= MEM_Int;
61070
+ pVal->flags &= ~MEM_Int;
6111161071
pVal->flags |= MEM_Real;
61112
- pVal->r = (double)LARGEST_INT64;
61072
+ pVal->r = (double)SMALLEST_INT64;
6111361073
}else{
6111461074
pVal->u.i = -pVal->u.i;
6111561075
}
6111661076
pVal->r = -pVal->r;
6111761077
sqlite3ValueApplyAffinity(pVal, affinity, enc);
@@ -61133,13 +61093,10 @@
6113361093
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
6113461094
0, SQLITE_DYNAMIC);
6113561095
}
6113661096
#endif
6113761097
61138
- if( pVal ){
61139
- sqlite3VdbeMemStoreType(pVal);
61140
- }
6114161098
*ppVal = pVal;
6114261099
return rc;
6114361100
6114461101
no_mem:
6114561102
db->mallocFailed = 1;
@@ -61299,11 +61256,10 @@
6129961256
rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
6130061257
if( rc==SQLITE_OK ){
6130161258
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
6130261259
}
6130361260
pVal->db = pParse->db;
61304
- sqlite3VdbeMemStoreType((Mem*)pVal);
6130561261
}
6130661262
}
6130761263
}else{
6130861264
rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
6130961265
}
@@ -62591,10 +62547,11 @@
6259162547
}
6259262548
return;
6259362549
}
6259462550
for(pEnd=&p[N]; p<pEnd; p++){
6259562551
assert( (&p[1])==pEnd || p[0].db==p[1].db );
62552
+ assert( sqlite3VdbeCheckMemInvariants(p) );
6259662553
6259762554
/* This block is really an inlined version of sqlite3VdbeMemRelease()
6259862555
** that takes advantage of the fact that the memory cell value is
6259962556
** being set to NULL after releasing any dynamic resources.
6260062557
**
@@ -62733,19 +62690,17 @@
6273362690
}
6273462691
pOp = &apSub[j]->aOp[i];
6273562692
}
6273662693
if( p->explain==1 ){
6273762694
pMem->flags = MEM_Int;
62738
- pMem->memType = MEM_Int;
6273962695
pMem->u.i = i; /* Program counter */
6274062696
pMem++;
6274162697
6274262698
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
6274362699
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
6274462700
assert( pMem->z!=0 );
6274562701
pMem->n = sqlite3Strlen30(pMem->z);
62746
- pMem->memType = MEM_Str;
6274762702
pMem->enc = SQLITE_UTF8;
6274862703
pMem++;
6274962704
6275062705
/* When an OP_Program opcode is encounter (the only opcode that has
6275162706
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
@@ -62767,63 +62722,56 @@
6276762722
}
6276862723
}
6276962724
6277062725
pMem->flags = MEM_Int;
6277162726
pMem->u.i = pOp->p1; /* P1 */
62772
- pMem->memType = MEM_Int;
6277362727
pMem++;
6277462728
6277562729
pMem->flags = MEM_Int;
6277662730
pMem->u.i = pOp->p2; /* P2 */
62777
- pMem->memType = MEM_Int;
6277862731
pMem++;
6277962732
6278062733
pMem->flags = MEM_Int;
6278162734
pMem->u.i = pOp->p3; /* P3 */
62782
- pMem->memType = MEM_Int;
6278362735
pMem++;
6278462736
6278562737
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
6278662738
assert( p->db->mallocFailed );
6278762739
return SQLITE_ERROR;
6278862740
}
62789
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62741
+ pMem->flags = MEM_Str|MEM_Term;
6279062742
zP4 = displayP4(pOp, pMem->z, 32);
6279162743
if( zP4!=pMem->z ){
6279262744
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
6279362745
}else{
6279462746
assert( pMem->z!=0 );
6279562747
pMem->n = sqlite3Strlen30(pMem->z);
6279662748
pMem->enc = SQLITE_UTF8;
6279762749
}
62798
- pMem->memType = MEM_Str;
6279962750
pMem++;
6280062751
6280162752
if( p->explain==1 ){
6280262753
if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
6280362754
assert( p->db->mallocFailed );
6280462755
return SQLITE_ERROR;
6280562756
}
62806
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62757
+ pMem->flags = MEM_Str|MEM_Term;
6280762758
pMem->n = 2;
6280862759
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
62809
- pMem->memType = MEM_Str;
6281062760
pMem->enc = SQLITE_UTF8;
6281162761
pMem++;
6281262762
6281362763
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
6281462764
if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
6281562765
assert( p->db->mallocFailed );
6281662766
return SQLITE_ERROR;
6281762767
}
62818
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62768
+ pMem->flags = MEM_Str|MEM_Term;
6281962769
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
62820
- pMem->memType = MEM_Str;
6282162770
pMem->enc = SQLITE_UTF8;
6282262771
#else
6282362772
pMem->flags = MEM_Null; /* Comment */
62824
- pMem->memType = MEM_Null;
6282562773
#endif
6282662774
}
6282762775
6282862776
p->nResColumn = 8 - 4*(p->explain-1);
6282962777
p->pResultSet = &p->aMem[1];
@@ -64312,10 +64260,18 @@
6431264260
6431364261
/* NULL or constants 0 or 1 */
6431464262
return 0;
6431564263
}
6431664264
64265
+/* Input "x" is a sequence of unsigned characters that represent a
64266
+** big-endian integer. Return the equivalent native integer
64267
+*/
64268
+#define ONE_BYTE_INT(x) ((i8)(x)[0])
64269
+#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
64270
+#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
64271
+#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
64272
+
6431764273
/*
6431864274
** Deserialize the data blob pointed to by buf as serial type serial_type
6431964275
** and store the result in pMem. Return the number of bytes read.
6432064276
*/
6432164277
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
@@ -64323,46 +64279,40 @@
6432364279
u32 serial_type, /* Serial type to deserialize */
6432464280
Mem *pMem /* Memory cell to write value into */
6432564281
){
6432664282
u64 x;
6432764283
u32 y;
64328
- int i;
6432964284
switch( serial_type ){
6433064285
case 10: /* Reserved for future use */
6433164286
case 11: /* Reserved for future use */
6433264287
case 0: { /* NULL */
6433364288
pMem->flags = MEM_Null;
6433464289
break;
6433564290
}
6433664291
case 1: { /* 1-byte signed integer */
64337
- pMem->u.i = (signed char)buf[0];
64292
+ pMem->u.i = ONE_BYTE_INT(buf);
6433864293
pMem->flags = MEM_Int;
6433964294
return 1;
6434064295
}
6434164296
case 2: { /* 2-byte signed integer */
64342
- i = 256*(signed char)buf[0] | buf[1];
64343
- pMem->u.i = (i64)i;
64297
+ pMem->u.i = TWO_BYTE_INT(buf);
6434464298
pMem->flags = MEM_Int;
6434564299
return 2;
6434664300
}
6434764301
case 3: { /* 3-byte signed integer */
64348
- i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64349
- pMem->u.i = (i64)i;
64302
+ pMem->u.i = THREE_BYTE_INT(buf);
6435064303
pMem->flags = MEM_Int;
6435164304
return 3;
6435264305
}
6435364306
case 4: { /* 4-byte signed integer */
64354
- y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64307
+ y = FOUR_BYTE_UINT(buf);
6435564308
pMem->u.i = (i64)*(int*)&y;
6435664309
pMem->flags = MEM_Int;
6435764310
return 4;
6435864311
}
6435964312
case 5: { /* 6-byte signed integer */
64360
- x = 256*(signed char)buf[0] + buf[1];
64361
- y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64362
- x = (x<<32) | y;
64363
- pMem->u.i = *(i64*)&x;
64313
+ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
6436464314
pMem->flags = MEM_Int;
6436564315
return 6;
6436664316
}
6436764317
case 6: /* 8-byte signed integer */
6436864318
case 7: { /* IEEE floating point */
@@ -64376,12 +64326,12 @@
6437664326
static const double r1 = 1.0;
6437764327
u64 t2 = t1;
6437864328
swapMixedEndianFloat(t2);
6437964329
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
6438064330
#endif
64381
- x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64382
- y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64331
+ x = FOUR_BYTE_UINT(buf);
64332
+ y = FOUR_BYTE_UINT(buf+4);
6438364333
x = (x<<32) | y;
6438464334
if( serial_type==6 ){
6438564335
pMem->u.i = *(i64*)&x;
6438664336
pMem->flags = MEM_Int;
6438764337
}else{
@@ -64473,11 +64423,11 @@
6447364423
u32 idx; /* Offset in aKey[] to read from */
6447464424
u16 u; /* Unsigned loop counter */
6447564425
u32 szHdr;
6447664426
Mem *pMem = p->aMem;
6447764427
64478
- p->flags = 0;
64428
+ p->default_rc = 0;
6447964429
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
6448064430
idx = getVarint32(aKey, szHdr);
6448164431
d = szHdr;
6448264432
u = 0;
6448364433
while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -64494,30 +64444,22 @@
6449464444
}
6449564445
assert( u<=pKeyInfo->nField + 1 );
6449664446
p->nField = u;
6449764447
}
6449864448
64449
+#if SQLITE_DEBUG
6449964450
/*
64500
-** This function compares the two table rows or index records
64501
-** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
64502
-** or positive integer if key1 is less than, equal to or
64503
-** greater than key2. The {nKey1, pKey1} key must be a blob
64504
-** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
64505
-** key must be a parsed key such as obtained from
64506
-** sqlite3VdbeParseRecord.
64507
-**
64508
-** Key1 and Key2 do not have to contain the same number of fields.
64509
-** The key with fewer fields is usually compares less than the
64510
-** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
64511
-** and the common prefixes are equal, then key1 is less than key2.
64512
-** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
64513
-** equal, then the keys are considered to be equal and
64514
-** the parts beyond the common prefix are ignored.
64451
+** This function compares two index or table record keys in the same way
64452
+** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
64453
+** this function deserializes and compares values using the
64454
+** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
64455
+** in assert() statements to ensure that the optimized code in
64456
+** sqlite3VdbeRecordCompare() returns results with these two primitives.
6451564457
*/
64516
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
64458
+static int vdbeRecordCompareDebug(
6451764459
int nKey1, const void *pKey1, /* Left key */
64518
- UnpackedRecord *pPKey2 /* Right key */
64460
+ const UnpackedRecord *pPKey2 /* Right key */
6451964461
){
6452064462
u32 d1; /* Offset into aKey[] of next data element */
6452164463
u32 idx1; /* Offset into aKey[] of next header element */
6452264464
u32 szHdr1; /* Number of bytes in header */
6452364465
int i = 0;
@@ -64587,28 +64529,559 @@
6458764529
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
6458864530
*/
6458964531
assert( mem1.zMalloc==0 );
6459064532
6459164533
/* rc==0 here means that one of the keys ran out of fields and
64592
- ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
64593
- ** flag is set, then break the tie by treating key2 as larger.
64594
- ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
64595
- ** are considered to be equal. Otherwise, the longer key is the
64596
- ** larger. As it happens, the pPKey2 will always be the longer
64597
- ** if there is a difference.
64598
- */
64599
- assert( rc==0 );
64600
- if( pPKey2->flags & UNPACKED_INCRKEY ){
64601
- rc = -1;
64602
- }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
64603
- /* Leave rc==0 */
64604
- }else if( idx1<szHdr1 ){
64605
- rc = 1;
64606
- }
64607
- return rc;
64608
-}
64609
-
64534
+ ** all the fields up to that point were equal. Return the the default_rc
64535
+ ** value. */
64536
+ return pPKey2->default_rc;
64537
+}
64538
+#endif
64539
+
64540
+/*
64541
+** Both *pMem1 and *pMem2 contain string values. Compare the two values
64542
+** using the collation sequence pColl. As usual, return a negative , zero
64543
+** or positive value if *pMem1 is less than, equal to or greater than
64544
+** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
64545
+*/
64546
+static int vdbeCompareMemString(
64547
+ const Mem *pMem1,
64548
+ const Mem *pMem2,
64549
+ const CollSeq *pColl
64550
+){
64551
+ if( pMem1->enc==pColl->enc ){
64552
+ /* The strings are already in the correct encoding. Call the
64553
+ ** comparison function directly */
64554
+ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
64555
+ }else{
64556
+ int rc;
64557
+ const void *v1, *v2;
64558
+ int n1, n2;
64559
+ Mem c1;
64560
+ Mem c2;
64561
+ memset(&c1, 0, sizeof(c1));
64562
+ memset(&c2, 0, sizeof(c2));
64563
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
64564
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
64565
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
64566
+ n1 = v1==0 ? 0 : c1.n;
64567
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
64568
+ n2 = v2==0 ? 0 : c2.n;
64569
+ rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
64570
+ sqlite3VdbeMemRelease(&c1);
64571
+ sqlite3VdbeMemRelease(&c2);
64572
+ return rc;
64573
+ }
64574
+}
64575
+
64576
+/*
64577
+** Compare the values contained by the two memory cells, returning
64578
+** negative, zero or positive if pMem1 is less than, equal to, or greater
64579
+** than pMem2. Sorting order is NULL's first, followed by numbers (integers
64580
+** and reals) sorted numerically, followed by text ordered by the collating
64581
+** sequence pColl and finally blob's ordered by memcmp().
64582
+**
64583
+** Two NULL values are considered equal by this function.
64584
+*/
64585
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
64586
+ int rc;
64587
+ int f1, f2;
64588
+ int combined_flags;
64589
+
64590
+ f1 = pMem1->flags;
64591
+ f2 = pMem2->flags;
64592
+ combined_flags = f1|f2;
64593
+ assert( (combined_flags & MEM_RowSet)==0 );
64594
+
64595
+ /* If one value is NULL, it is less than the other. If both values
64596
+ ** are NULL, return 0.
64597
+ */
64598
+ if( combined_flags&MEM_Null ){
64599
+ return (f2&MEM_Null) - (f1&MEM_Null);
64600
+ }
64601
+
64602
+ /* If one value is a number and the other is not, the number is less.
64603
+ ** If both are numbers, compare as reals if one is a real, or as integers
64604
+ ** if both values are integers.
64605
+ */
64606
+ if( combined_flags&(MEM_Int|MEM_Real) ){
64607
+ double r1, r2;
64608
+ if( (f1 & f2 & MEM_Int)!=0 ){
64609
+ if( pMem1->u.i < pMem2->u.i ) return -1;
64610
+ if( pMem1->u.i > pMem2->u.i ) return 1;
64611
+ return 0;
64612
+ }
64613
+ if( (f1&MEM_Real)!=0 ){
64614
+ r1 = pMem1->r;
64615
+ }else if( (f1&MEM_Int)!=0 ){
64616
+ r1 = (double)pMem1->u.i;
64617
+ }else{
64618
+ return 1;
64619
+ }
64620
+ if( (f2&MEM_Real)!=0 ){
64621
+ r2 = pMem2->r;
64622
+ }else if( (f2&MEM_Int)!=0 ){
64623
+ r2 = (double)pMem2->u.i;
64624
+ }else{
64625
+ return -1;
64626
+ }
64627
+ if( r1<r2 ) return -1;
64628
+ if( r1>r2 ) return 1;
64629
+ return 0;
64630
+ }
64631
+
64632
+ /* If one value is a string and the other is a blob, the string is less.
64633
+ ** If both are strings, compare using the collating functions.
64634
+ */
64635
+ if( combined_flags&MEM_Str ){
64636
+ if( (f1 & MEM_Str)==0 ){
64637
+ return 1;
64638
+ }
64639
+ if( (f2 & MEM_Str)==0 ){
64640
+ return -1;
64641
+ }
64642
+
64643
+ assert( pMem1->enc==pMem2->enc );
64644
+ assert( pMem1->enc==SQLITE_UTF8 ||
64645
+ pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
64646
+
64647
+ /* The collation sequence must be defined at this point, even if
64648
+ ** the user deletes the collation sequence after the vdbe program is
64649
+ ** compiled (this was not always the case).
64650
+ */
64651
+ assert( !pColl || pColl->xCmp );
64652
+
64653
+ if( pColl ){
64654
+ return vdbeCompareMemString(pMem1, pMem2, pColl);
64655
+ }
64656
+ /* If a NULL pointer was passed as the collate function, fall through
64657
+ ** to the blob case and use memcmp(). */
64658
+ }
64659
+
64660
+ /* Both values must be blobs. Compare using memcmp(). */
64661
+ rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
64662
+ if( rc==0 ){
64663
+ rc = pMem1->n - pMem2->n;
64664
+ }
64665
+ return rc;
64666
+}
64667
+
64668
+
64669
+/*
64670
+** The first argument passed to this function is a serial-type that
64671
+** corresponds to an integer - all values between 1 and 9 inclusive
64672
+** except 7. The second points to a buffer containing an integer value
64673
+** serialized according to serial_type. This function deserializes
64674
+** and returns the value.
64675
+*/
64676
+static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
64677
+ u32 y;
64678
+ assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
64679
+ switch( serial_type ){
64680
+ case 0:
64681
+ case 1:
64682
+ return ONE_BYTE_INT(aKey);
64683
+ case 2:
64684
+ return TWO_BYTE_INT(aKey);
64685
+ case 3:
64686
+ return THREE_BYTE_INT(aKey);
64687
+ case 4: {
64688
+ y = FOUR_BYTE_UINT(aKey);
64689
+ return (i64)*(int*)&y;
64690
+ }
64691
+ case 5: {
64692
+ return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
64693
+ }
64694
+ case 6: {
64695
+ u64 x = FOUR_BYTE_UINT(aKey);
64696
+ x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
64697
+ return (i64)*(i64*)&x;
64698
+ }
64699
+ }
64700
+
64701
+ return (serial_type - 8);
64702
+}
64703
+
64704
+/*
64705
+** This function compares the two table rows or index records
64706
+** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
64707
+** or positive integer if key1 is less than, equal to or
64708
+** greater than key2. The {nKey1, pKey1} key must be a blob
64709
+** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
64710
+** key must be a parsed key such as obtained from
64711
+** sqlite3VdbeParseRecord.
64712
+**
64713
+** If argument bSkip is non-zero, it is assumed that the caller has already
64714
+** determined that the first fields of the keys are equal.
64715
+**
64716
+** Key1 and Key2 do not have to contain the same number of fields. If all
64717
+** fields that appear in both keys are equal, then pPKey2->default_rc is
64718
+** returned.
64719
+*/
64720
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
64721
+ int nKey1, const void *pKey1, /* Left key */
64722
+ const UnpackedRecord *pPKey2, /* Right key */
64723
+ int bSkip /* If true, skip the first field */
64724
+){
64725
+ u32 d1; /* Offset into aKey[] of next data element */
64726
+ int i; /* Index of next field to compare */
64727
+ u32 szHdr1; /* Size of record header in bytes */
64728
+ u32 idx1; /* Offset of first type in header */
64729
+ int rc = 0; /* Return value */
64730
+ Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
64731
+ KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
64732
+ const unsigned char *aKey1 = (const unsigned char *)pKey1;
64733
+ Mem mem1;
64734
+
64735
+ /* If bSkip is true, then the caller has already determined that the first
64736
+ ** two elements in the keys are equal. Fix the various stack variables so
64737
+ ** that this routine begins comparing at the second field. */
64738
+ if( bSkip ){
64739
+ u32 s1;
64740
+ idx1 = 1 + getVarint32(&aKey1[1], s1);
64741
+ szHdr1 = aKey1[0];
64742
+ d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
64743
+ i = 1;
64744
+ pRhs++;
64745
+ }else{
64746
+ idx1 = getVarint32(aKey1, szHdr1);
64747
+ d1 = szHdr1;
64748
+ i = 0;
64749
+ }
64750
+
64751
+ VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
64752
+ assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
64753
+ || CORRUPT_DB );
64754
+ assert( pPKey2->pKeyInfo->aSortOrder!=0 );
64755
+ assert( pPKey2->pKeyInfo->nField>0 );
64756
+ assert( idx1<=szHdr1 || CORRUPT_DB );
64757
+ do{
64758
+ u32 serial_type;
64759
+
64760
+ /* RHS is an integer */
64761
+ if( pRhs->flags & MEM_Int ){
64762
+ serial_type = aKey1[idx1];
64763
+ if( serial_type>=12 ){
64764
+ rc = +1;
64765
+ }else if( serial_type==0 ){
64766
+ rc = -1;
64767
+ }else if( serial_type==7 ){
64768
+ double rhs = (double)pRhs->u.i;
64769
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
64770
+ if( mem1.r<rhs ){
64771
+ rc = -1;
64772
+ }else if( mem1.r>rhs ){
64773
+ rc = +1;
64774
+ }
64775
+ }else{
64776
+ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
64777
+ i64 rhs = pRhs->u.i;
64778
+ if( lhs<rhs ){
64779
+ rc = -1;
64780
+ }else if( lhs>rhs ){
64781
+ rc = +1;
64782
+ }
64783
+ }
64784
+ }
64785
+
64786
+ /* RHS is real */
64787
+ else if( pRhs->flags & MEM_Real ){
64788
+ serial_type = aKey1[idx1];
64789
+ if( serial_type>=12 ){
64790
+ rc = +1;
64791
+ }else if( serial_type==0 ){
64792
+ rc = -1;
64793
+ }else{
64794
+ double rhs = pRhs->r;
64795
+ double lhs;
64796
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
64797
+ if( serial_type==7 ){
64798
+ lhs = mem1.r;
64799
+ }else{
64800
+ lhs = (double)mem1.u.i;
64801
+ }
64802
+ if( lhs<rhs ){
64803
+ rc = -1;
64804
+ }else if( lhs>rhs ){
64805
+ rc = +1;
64806
+ }
64807
+ }
64808
+ }
64809
+
64810
+ /* RHS is a string */
64811
+ else if( pRhs->flags & MEM_Str ){
64812
+ getVarint32(&aKey1[idx1], serial_type);
64813
+ if( serial_type<12 ){
64814
+ rc = -1;
64815
+ }else if( !(serial_type & 0x01) ){
64816
+ rc = +1;
64817
+ }else{
64818
+ mem1.n = (serial_type - 12) / 2;
64819
+ if( (d1+mem1.n) > (unsigned)nKey1 ){
64820
+ rc = 1; /* Corruption */
64821
+ }else if( pKeyInfo->aColl[i] ){
64822
+ mem1.enc = pKeyInfo->enc;
64823
+ mem1.db = pKeyInfo->db;
64824
+ mem1.flags = MEM_Str;
64825
+ mem1.z = (char*)&aKey1[d1];
64826
+ rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
64827
+ }else{
64828
+ int nCmp = MIN(mem1.n, pRhs->n);
64829
+ rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
64830
+ if( rc==0 ) rc = mem1.n - pRhs->n;
64831
+ }
64832
+ }
64833
+ }
64834
+
64835
+ /* RHS is a blob */
64836
+ else if( pRhs->flags & MEM_Blob ){
64837
+ getVarint32(&aKey1[idx1], serial_type);
64838
+ if( serial_type<12 || (serial_type & 0x01) ){
64839
+ rc = -1;
64840
+ }else{
64841
+ int nStr = (serial_type - 12) / 2;
64842
+ if( (d1+nStr) > (unsigned)nKey1 ){
64843
+ rc = 1; /* Corruption */
64844
+ }else{
64845
+ int nCmp = MIN(nStr, pRhs->n);
64846
+ rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
64847
+ if( rc==0 ) rc = nStr - pRhs->n;
64848
+ }
64849
+ }
64850
+ }
64851
+
64852
+ /* RHS is null */
64853
+ else{
64854
+ serial_type = aKey1[idx1];
64855
+ rc = (serial_type!=0);
64856
+ }
64857
+
64858
+ if( rc!=0 ){
64859
+ if( pKeyInfo->aSortOrder[i] ){
64860
+ rc = -rc;
64861
+ }
64862
+ assert( CORRUPT_DB
64863
+ || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
64864
+ || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
64865
+ || pKeyInfo->db->mallocFailed
64866
+ );
64867
+ assert( mem1.zMalloc==0 ); /* See comment below */
64868
+ return rc;
64869
+ }
64870
+
64871
+ i++;
64872
+ pRhs++;
64873
+ d1 += sqlite3VdbeSerialTypeLen(serial_type);
64874
+ idx1 += sqlite3VarintLen(serial_type);
64875
+ }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
64876
+
64877
+ /* No memory allocation is ever used on mem1. Prove this using
64878
+ ** the following assert(). If the assert() fails, it indicates a
64879
+ ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
64880
+ assert( mem1.zMalloc==0 );
64881
+
64882
+ /* rc==0 here means that one or both of the keys ran out of fields and
64883
+ ** all the fields up to that point were equal. Return the the default_rc
64884
+ ** value. */
64885
+ assert( CORRUPT_DB
64886
+ || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
64887
+ );
64888
+ return pPKey2->default_rc;
64889
+}
64890
+
64891
+/*
64892
+** This function is an optimized version of sqlite3VdbeRecordCompare()
64893
+** that (a) the first field of pPKey2 is an integer, and (b) the
64894
+** size-of-header varint at the start of (pKey1/nKey1) fits in a single
64895
+** byte (i.e. is less than 128).
64896
+*/
64897
+static int vdbeRecordCompareInt(
64898
+ int nKey1, const void *pKey1, /* Left key */
64899
+ const UnpackedRecord *pPKey2, /* Right key */
64900
+ int bSkip /* Ignored */
64901
+){
64902
+ const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
64903
+ int serial_type = ((const u8*)pKey1)[1];
64904
+ int res;
64905
+ u32 y;
64906
+ u64 x;
64907
+ i64 v = pPKey2->aMem[0].u.i;
64908
+ i64 lhs;
64909
+ UNUSED_PARAMETER(bSkip);
64910
+
64911
+ assert( bSkip==0 );
64912
+ switch( serial_type ){
64913
+ case 1: { /* 1-byte signed integer */
64914
+ lhs = ONE_BYTE_INT(aKey);
64915
+ break;
64916
+ }
64917
+ case 2: { /* 2-byte signed integer */
64918
+ lhs = TWO_BYTE_INT(aKey);
64919
+ break;
64920
+ }
64921
+ case 3: { /* 3-byte signed integer */
64922
+ lhs = THREE_BYTE_INT(aKey);
64923
+ break;
64924
+ }
64925
+ case 4: { /* 4-byte signed integer */
64926
+ y = FOUR_BYTE_UINT(aKey);
64927
+ lhs = (i64)*(int*)&y;
64928
+ break;
64929
+ }
64930
+ case 5: { /* 6-byte signed integer */
64931
+ lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
64932
+ break;
64933
+ }
64934
+ case 6: { /* 8-byte signed integer */
64935
+ x = FOUR_BYTE_UINT(aKey);
64936
+ x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
64937
+ lhs = *(i64*)&x;
64938
+ break;
64939
+ }
64940
+ case 8:
64941
+ lhs = 0;
64942
+ break;
64943
+ case 9:
64944
+ lhs = 1;
64945
+ break;
64946
+
64947
+ /* This case could be removed without changing the results of running
64948
+ ** this code. Including it causes gcc to generate a faster switch
64949
+ ** statement (since the range of switch targets now starts at zero and
64950
+ ** is contiguous) but does not cause any duplicate code to be generated
64951
+ ** (as gcc is clever enough to combine the two like cases). Other
64952
+ ** compilers might be similar. */
64953
+ case 0: case 7:
64954
+ return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
64955
+
64956
+ default:
64957
+ return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
64958
+ }
64959
+
64960
+ if( v>lhs ){
64961
+ res = pPKey2->r1;
64962
+ }else if( v<lhs ){
64963
+ res = pPKey2->r2;
64964
+ }else if( pPKey2->nField>1 ){
64965
+ /* The first fields of the two keys are equal. Compare the trailing
64966
+ ** fields. */
64967
+ res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
64968
+ }else{
64969
+ /* The first fields of the two keys are equal and there are no trailing
64970
+ ** fields. Return pPKey2->default_rc in this case. */
64971
+ res = pPKey2->default_rc;
64972
+ }
64973
+
64974
+ assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
64975
+ || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
64976
+ || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
64977
+ || CORRUPT_DB
64978
+ );
64979
+ return res;
64980
+}
64981
+
64982
+/*
64983
+** This function is an optimized version of sqlite3VdbeRecordCompare()
64984
+** that (a) the first field of pPKey2 is a string, that (b) the first field
64985
+** uses the collation sequence BINARY and (c) that the size-of-header varint
64986
+** at the start of (pKey1/nKey1) fits in a single byte.
64987
+*/
64988
+static int vdbeRecordCompareString(
64989
+ int nKey1, const void *pKey1, /* Left key */
64990
+ const UnpackedRecord *pPKey2, /* Right key */
64991
+ int bSkip
64992
+){
64993
+ const u8 *aKey1 = (const u8*)pKey1;
64994
+ int serial_type;
64995
+ int res;
64996
+ UNUSED_PARAMETER(bSkip);
64997
+
64998
+ assert( bSkip==0 );
64999
+ getVarint32(&aKey1[1], serial_type);
65000
+
65001
+ if( serial_type<12 ){
65002
+ res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
65003
+ }else if( !(serial_type & 0x01) ){
65004
+ res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
65005
+ }else{
65006
+ int nCmp;
65007
+ int nStr;
65008
+ int szHdr = aKey1[0];
65009
+
65010
+ nStr = (serial_type-12) / 2;
65011
+ if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
65012
+ nCmp = MIN( pPKey2->aMem[0].n, nStr );
65013
+ res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
65014
+
65015
+ if( res==0 ){
65016
+ res = nStr - pPKey2->aMem[0].n;
65017
+ if( res==0 ){
65018
+ if( pPKey2->nField>1 ){
65019
+ res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
65020
+ }else{
65021
+ res = pPKey2->default_rc;
65022
+ }
65023
+ }else if( res>0 ){
65024
+ res = pPKey2->r2;
65025
+ }else{
65026
+ res = pPKey2->r1;
65027
+ }
65028
+ }else if( res>0 ){
65029
+ res = pPKey2->r2;
65030
+ }else{
65031
+ res = pPKey2->r1;
65032
+ }
65033
+ }
65034
+
65035
+ assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
65036
+ || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
65037
+ || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
65038
+ || CORRUPT_DB
65039
+ );
65040
+ return res;
65041
+}
65042
+
65043
+/*
65044
+** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
65045
+** suitable for comparing serialized records to the unpacked record passed
65046
+** as the only argument.
65047
+*/
65048
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
65049
+ /* varintRecordCompareInt() and varintRecordCompareString() both assume
65050
+ ** that the size-of-header varint that occurs at the start of each record
65051
+ ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
65052
+ ** also assumes that it is safe to overread a buffer by at least the
65053
+ ** maximum possible legal header size plus 8 bytes. Because there is
65054
+ ** guaranteed to be at least 74 (but not 136) bytes of padding following each
65055
+ ** buffer passed to varintRecordCompareInt() this makes it convenient to
65056
+ ** limit the size of the header to 64 bytes in cases where the first field
65057
+ ** is an integer.
65058
+ **
65059
+ ** The easiest way to enforce this limit is to consider only records with
65060
+ ** 13 fields or less. If the first field is an integer, the maximum legal
65061
+ ** header size is (12*5 + 1 + 1) bytes. */
65062
+ if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
65063
+ int flags = p->aMem[0].flags;
65064
+ if( p->pKeyInfo->aSortOrder[0] ){
65065
+ p->r1 = 1;
65066
+ p->r2 = -1;
65067
+ }else{
65068
+ p->r1 = -1;
65069
+ p->r2 = 1;
65070
+ }
65071
+ if( (flags & MEM_Int) ){
65072
+ return vdbeRecordCompareInt;
65073
+ }
65074
+ if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0
65075
+ && p->pKeyInfo->aColl[0]==0
65076
+ ){
65077
+ return vdbeRecordCompareString;
65078
+ }
65079
+ }
65080
+
65081
+ return sqlite3VdbeRecordCompare;
65082
+}
6461065083
6461165084
/*
6461265085
** pCur points at an index entry created using the OP_MakeRecord opcode.
6461365086
** Read the rowid (the last field in the record) and store it in *rowid.
6461465087
** Return SQLITE_OK if everything works, or an error code otherwise.
@@ -64695,23 +65168,23 @@
6469565168
** omits the rowid at the end. The rowid at the end of the index entry
6469665169
** is ignored as well. Hence, this routine only compares the prefixes
6469765170
** of the keys prior to the final rowid, not the entire key.
6469865171
*/
6469965172
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
64700
- VdbeCursor *pC, /* The cursor to compare against */
64701
- UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
64702
- int *res /* Write the comparison result here */
65173
+ VdbeCursor *pC, /* The cursor to compare against */
65174
+ const UnpackedRecord *pUnpacked, /* Unpacked version of key */
65175
+ int *res /* Write the comparison result here */
6470365176
){
6470465177
i64 nCellKey = 0;
6470565178
int rc;
6470665179
BtCursor *pCur = pC->pCursor;
6470765180
Mem m;
6470865181
6470965182
assert( sqlite3BtreeCursorIsValid(pCur) );
6471065183
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
6471165184
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
64712
- /* nCellKey will always be between 0 and 0xffffffff because of the say
65185
+ /* nCellKey will always be between 0 and 0xffffffff because of the way
6471365186
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
6471465187
if( nCellKey<=0 || nCellKey>0x7fffffff ){
6471565188
*res = 0;
6471665189
return SQLITE_CORRUPT_BKPT;
6471765190
}
@@ -64718,12 +65191,11 @@
6471865191
memset(&m, 0, sizeof(m));
6471965192
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
6472065193
if( rc ){
6472165194
return rc;
6472265195
}
64723
- assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
64724
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
65196
+ *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
6472565197
sqlite3VdbeMemRelease(&m);
6472665198
return SQLITE_OK;
6472765199
}
6472865200
6472965201
/*
@@ -64783,11 +65255,10 @@
6478365255
if( 0==(pMem->flags & MEM_Null) ){
6478465256
sqlite3_value *pRet = sqlite3ValueNew(v->db);
6478565257
if( pRet ){
6478665258
sqlite3VdbeMemCopy((Mem *)pRet, pMem);
6478765259
sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
64788
- sqlite3VdbeMemStoreType((Mem *)pRet);
6478965260
}
6479065261
return pRet;
6479165262
}
6479265263
}
6479365264
return 0;
@@ -64957,11 +65428,10 @@
6495765428
*/
6495865429
SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
6495965430
Mem *p = (Mem*)pVal;
6496065431
if( p->flags & (MEM_Blob|MEM_Str) ){
6496165432
sqlite3VdbeMemExpandBlob(p);
64962
- p->flags &= ~MEM_Str;
6496365433
p->flags |= MEM_Blob;
6496465434
return p->n ? p->z : 0;
6496565435
}else{
6496665436
return sqlite3_value_text(pVal);
6496765437
}
@@ -65028,11 +65498,11 @@
6502865498
SQLITE_INTEGER, /* 0x1c */
6502965499
SQLITE_NULL, /* 0x1d */
6503065500
SQLITE_INTEGER, /* 0x1e */
6503165501
SQLITE_NULL, /* 0x1f */
6503265502
};
65033
- return aType[pVal->memType&0x1f];
65503
+ return aType[pVal->flags&MEM_AffMask];
6503465504
}
6503565505
6503665506
/**************************** sqlite3_result_ *******************************
6503765507
** The following routines are used by user-defined functions to specify
6503865508
** the function result.
@@ -65549,10 +66019,34 @@
6554966019
Vdbe *pVm = (Vdbe *)pStmt;
6555066020
if( pVm==0 || pVm->pResultSet==0 ) return 0;
6555166021
return pVm->nResColumn;
6555266022
}
6555366023
66024
+/*
66025
+** Return a pointer to static memory containing an SQL NULL value.
66026
+*/
66027
+static const Mem *columnNullValue(void){
66028
+ /* Even though the Mem structure contains an element
66029
+ ** of type i64, on certain architectures (x86) with certain compiler
66030
+ ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
66031
+ ** instead of an 8-byte one. This all works fine, except that when
66032
+ ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
66033
+ ** that a Mem structure is located on an 8-byte boundary. To prevent
66034
+ ** these assert()s from failing, when building with SQLITE_DEBUG defined
66035
+ ** using gcc, we force nullMem to be 8-byte aligned using the magical
66036
+ ** __attribute__((aligned(8))) macro. */
66037
+ static const Mem nullMem
66038
+#if defined(SQLITE_DEBUG) && defined(__GNUC__)
66039
+ __attribute__((aligned(8)))
66040
+#endif
66041
+ = {0, "", (double)0, {0}, 0, MEM_Null, 0,
66042
+#ifdef SQLITE_DEBUG
66043
+ 0, 0, /* pScopyFrom, pFiller */
66044
+#endif
66045
+ 0, 0 };
66046
+ return &nullMem;
66047
+}
6555466048
6555566049
/*
6555666050
** Check to see if column iCol of the given statement is valid. If
6555766051
** it is, return a pointer to the Mem for the value of that column.
6555866052
** If iCol is not valid, return a pointer to a Mem which has a value
@@ -65565,36 +66059,15 @@
6556566059
pVm = (Vdbe *)pStmt;
6556666060
if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
6556766061
sqlite3_mutex_enter(pVm->db->mutex);
6556866062
pOut = &pVm->pResultSet[i];
6556966063
}else{
65570
- /* If the value passed as the second argument is out of range, return
65571
- ** a pointer to the following static Mem object which contains the
65572
- ** value SQL NULL. Even though the Mem structure contains an element
65573
- ** of type i64, on certain architectures (x86) with certain compiler
65574
- ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
65575
- ** instead of an 8-byte one. This all works fine, except that when
65576
- ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
65577
- ** that a Mem structure is located on an 8-byte boundary. To prevent
65578
- ** these assert()s from failing, when building with SQLITE_DEBUG defined
65579
- ** using gcc, we force nullMem to be 8-byte aligned using the magical
65580
- ** __attribute__((aligned(8))) macro. */
65581
- static const Mem nullMem
65582
-#if defined(SQLITE_DEBUG) && defined(__GNUC__)
65583
- __attribute__((aligned(8)))
65584
-#endif
65585
- = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
65586
-#ifdef SQLITE_DEBUG
65587
- 0, 0, /* pScopyFrom, pFiller */
65588
-#endif
65589
- 0, 0 };
65590
-
6559166064
if( pVm && ALWAYS(pVm->db) ){
6559266065
sqlite3_mutex_enter(pVm->db->mutex);
6559366066
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
6559466067
}
65595
- pOut = (Mem*)&nullMem;
66068
+ pOut = (Mem*)columnNullValue();
6559666069
}
6559766070
return pOut;
6559866071
}
6559966072
6560066073
/*
@@ -66629,11 +67102,11 @@
6662967102
** does not control the string, it might be deleted without the register
6663067103
** knowing it.
6663167104
**
6663267105
** This routine converts an ephemeral string into a dynamically allocated
6663367106
** string that the register itself controls. In other words, it
66634
-** converts an MEM_Ephem string into an MEM_Dyn string.
67107
+** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
6663567108
*/
6663667109
#define Deephemeralize(P) \
6663767110
if( ((P)->flags&MEM_Ephem)!=0 \
6663867111
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
6663967112
@@ -66770,11 +67243,10 @@
6677067243
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
6677167244
int eType = sqlite3_value_type(pVal);
6677267245
if( eType==SQLITE_TEXT ){
6677367246
Mem *pMem = (Mem*)pVal;
6677467247
applyNumericAffinity(pMem);
66775
- sqlite3VdbeMemStoreType(pMem);
6677667248
eType = sqlite3_value_type(pVal);
6677767249
}
6677867250
return eType;
6677967251
}
6678067252
@@ -67166,22 +67638,25 @@
6716667638
#ifdef SQLITE_DEBUG
6716767639
if( (pOp->opflags & OPFLG_IN1)!=0 ){
6716867640
assert( pOp->p1>0 );
6716967641
assert( pOp->p1<=(p->nMem-p->nCursor) );
6717067642
assert( memIsValid(&aMem[pOp->p1]) );
67643
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
6717167644
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
6717267645
}
6717367646
if( (pOp->opflags & OPFLG_IN2)!=0 ){
6717467647
assert( pOp->p2>0 );
6717567648
assert( pOp->p2<=(p->nMem-p->nCursor) );
6717667649
assert( memIsValid(&aMem[pOp->p2]) );
67650
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
6717767651
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
6717867652
}
6717967653
if( (pOp->opflags & OPFLG_IN3)!=0 ){
6718067654
assert( pOp->p3>0 );
6718167655
assert( pOp->p3<=(p->nMem-p->nCursor) );
6718267656
assert( memIsValid(&aMem[pOp->p3]) );
67657
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
6718367658
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
6718467659
}
6718567660
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
6718667661
assert( pOp->p2>0 );
6718767662
assert( pOp->p2<=(p->nMem-p->nCursor) );
@@ -67279,11 +67754,11 @@
6727967754
** and then jump to address P2.
6728067755
*/
6728167756
case OP_Gosub: { /* jump */
6728267757
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
6728367758
pIn1 = &aMem[pOp->p1];
67284
- assert( (pIn1->flags & MEM_Dyn)==0 );
67759
+ assert( VdbeMemDynamic(pIn1)==0 );
6728567760
memAboutToChange(p, pIn1);
6728667761
pIn1->flags = MEM_Int;
6728767762
pIn1->u.i = pc;
6728867763
REGISTER_TRACE(pOp->p1, pIn1);
6728967764
pc = pOp->p2 - 1;
@@ -67352,11 +67827,11 @@
6735267827
** OP_EndCoroutine, jump immediately to P2.
6735367828
*/
6735467829
case OP_Yield: { /* in1, jump */
6735567830
int pcDest;
6735667831
pIn1 = &aMem[pOp->p1];
67357
- assert( (pIn1->flags & MEM_Dyn)==0 );
67832
+ assert( VdbeMemDynamic(pIn1)==0 );
6735867833
pIn1->flags = MEM_Int;
6735967834
pcDest = (int)pIn1->u.i;
6736067835
pIn1->u.i = pc;
6736167836
REGISTER_TRACE(pOp->p1, pIn1);
6736267837
pc = pcDest;
@@ -67525,14 +68000,13 @@
6752568000
if( encoding!=SQLITE_UTF8 ){
6752668001
rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
6752768002
if( rc==SQLITE_TOOBIG ) goto too_big;
6752868003
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
6752968004
assert( pOut->zMalloc==pOut->z );
67530
- assert( pOut->flags & MEM_Dyn );
68005
+ assert( VdbeMemDynamic(pOut)==0 );
6753168006
pOut->zMalloc = 0;
6753268007
pOut->flags |= MEM_Static;
67533
- pOut->flags &= ~MEM_Dyn;
6753468008
if( pOp->p4type==P4_DYNAMIC ){
6753568009
sqlite3DbFree(db, pOp->p4.z);
6753668010
}
6753768011
pOp->p4type = P4_DYNAMIC;
6753868012
pOp->p4.z = pOut->z;
@@ -67664,18 +68138,20 @@
6766468138
do{
6766568139
assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
6766668140
assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
6766768141
assert( memIsValid(pIn1) );
6766868142
memAboutToChange(p, pOut);
68143
+ VdbeMemRelease(pOut);
6766968144
zMalloc = pOut->zMalloc;
67670
- pOut->zMalloc = 0;
67671
- sqlite3VdbeMemMove(pOut, pIn1);
68145
+ memcpy(pOut, pIn1, sizeof(Mem));
6767268146
#ifdef SQLITE_DEBUG
6767368147
if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
6767468148
pOut->pScopyFrom += p1 - pOp->p2;
6767568149
}
6767668150
#endif
68151
+ pIn1->flags = MEM_Undefined;
68152
+ pIn1->xDel = 0;
6767768153
pIn1->zMalloc = zMalloc;
6767868154
REGISTER_TRACE(p2++, pOut);
6767968155
pIn1++;
6768068156
pOut++;
6768168157
}while( n-- );
@@ -67805,11 +68281,10 @@
6780568281
assert( memIsValid(&pMem[i]) );
6780668282
Deephemeralize(&pMem[i]);
6780768283
assert( (pMem[i].flags & MEM_Ephem)==0
6780868284
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
6780968285
sqlite3VdbeMemNulTerminate(&pMem[i]);
67810
- sqlite3VdbeMemStoreType(&pMem[i]);
6781168286
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
6781268287
}
6781368288
if( db->mallocFailed ) goto no_mem;
6781468289
6781568290
/* Return SQLITE_ROW
@@ -67848,14 +68323,14 @@
6784868323
Stringify(pIn2, encoding);
6784968324
nByte = pIn1->n + pIn2->n;
6785068325
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
6785168326
goto too_big;
6785268327
}
67853
- MemSetTypeFlag(pOut, MEM_Str);
6785468328
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
6785568329
goto no_mem;
6785668330
}
68331
+ MemSetTypeFlag(pOut, MEM_Str);
6785768332
if( pOut!=pIn2 ){
6785868333
memcpy(pOut->z, pIn2->z, pIn2->n);
6785968334
}
6786068335
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
6786168336
pOut->z[nByte]=0;
@@ -68051,11 +68526,10 @@
6805168526
pArg = &aMem[pOp->p2];
6805268527
for(i=0; i<n; i++, pArg++){
6805368528
assert( memIsValid(pArg) );
6805468529
apVal[i] = pArg;
6805568530
Deephemeralize(pArg);
68056
- sqlite3VdbeMemStoreType(pArg);
6805768531
REGISTER_TRACE(pOp->p2+i, pArg);
6805868532
}
6805968533
6806068534
assert( pOp->p4type==P4_FUNCDEF );
6806168535
ctx.pFunc = pOp->p4.pFunc;
@@ -69026,10 +69500,11 @@
6902669500
** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
6902769501
** all valid.
6902869502
*/
6902969503
assert( p2<pC->nHdrParsed );
6903069504
assert( rc==SQLITE_OK );
69505
+ assert( sqlite3VdbeCheckMemInvariants(pDest) );
6903169506
if( pC->szRow>=aOffset[p2+1] ){
6903269507
/* This is the common case where the desired content fits on the original
6903369508
** page - where the content is not on an overflow page */
6903469509
VdbeMemRelease(pDest);
6903569510
sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
@@ -69063,12 +69538,12 @@
6906369538
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
6906469539
** dynamically allocated space over to the pDest structure.
6906569540
** This prevents a memory copy. */
6906669541
if( sMem.zMalloc ){
6906769542
assert( sMem.z==sMem.zMalloc );
69068
- assert( !(pDest->flags & MEM_Dyn) );
69069
- assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
69543
+ assert( VdbeMemDynamic(pDest)==0 );
69544
+ assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
6907069545
pDest->flags &= ~(MEM_Ephem|MEM_Static);
6907169546
pDest->flags |= MEM_Term;
6907269547
pDest->z = sMem.z;
6907369548
pDest->zMalloc = sMem.zMalloc;
6907469549
}
@@ -69247,11 +69722,11 @@
6924769722
assert( i==nHdr );
6924869723
assert( j==nByte );
6924969724
6925069725
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
6925169726
pOut->n = (int)nByte;
69252
- pOut->flags = MEM_Blob | MEM_Dyn;
69727
+ pOut->flags = MEM_Blob;
6925369728
pOut->xDel = 0;
6925469729
if( nZero ){
6925569730
pOut->u.nZero = nZero;
6925669731
pOut->flags |= MEM_Zero;
6925769732
}
@@ -70121,20 +70596,20 @@
7012170596
r.pKeyInfo = pC->pKeyInfo;
7012270597
r.nField = (u16)nField;
7012370598
7012470599
/* The next line of code computes as follows, only faster:
7012570600
** if( oc==OP_SeekGT || oc==OP_SeekLE ){
70126
- ** r.flags = UNPACKED_INCRKEY;
70601
+ ** r.default_rc = -1;
7012770602
** }else{
70128
- ** r.flags = 0;
70603
+ ** r.default_rc = +1;
7012970604
** }
7013070605
*/
70131
- r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT)));
70132
- assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY );
70133
- assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY );
70134
- assert( oc!=OP_SeekGE || r.flags==0 );
70135
- assert( oc!=OP_SeekLT || r.flags==0 );
70606
+ r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
70607
+ assert( oc!=OP_SeekGT || r.default_rc==-1 );
70608
+ assert( oc!=OP_SeekLE || r.default_rc==-1 );
70609
+ assert( oc!=OP_SeekGE || r.default_rc==+1 );
70610
+ assert( oc!=OP_SeekLT || r.default_rc==+1 );
7013670611
7013770612
r.aMem = &aMem[pOp->p3];
7013870613
#ifdef SQLITE_DEBUG
7013970614
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
7014070615
#endif
@@ -70288,22 +70763,21 @@
7028870763
ExpandBlob(&r.aMem[ii]);
7028970764
#ifdef SQLITE_DEBUG
7029070765
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
7029170766
#endif
7029270767
}
70293
- r.flags = UNPACKED_PREFIX_MATCH;
7029470768
pIdxKey = &r;
7029570769
}else{
7029670770
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
7029770771
pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
7029870772
);
7029970773
if( pIdxKey==0 ) goto no_mem;
7030070774
assert( pIn3->flags & MEM_Blob );
7030170775
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
7030270776
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
70303
- pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
7030470777
}
70778
+ pIdxKey->default_rc = 0;
7030570779
if( pOp->opcode==OP_NoConflict ){
7030670780
/* For the OP_NoConflict opcode, take the jump if any of the
7030770781
** input fields are NULL, since any key with a NULL will not
7030870782
** conflict */
7030970783
for(ii=0; ii<r.nField; ii++){
@@ -71188,11 +71662,11 @@
7118871662
pCrsr = pC->pCursor;
7118971663
assert( pCrsr!=0 );
7119071664
assert( pOp->p5==0 );
7119171665
r.pKeyInfo = pC->pKeyInfo;
7119271666
r.nField = (u16)pOp->p3;
71193
- r.flags = UNPACKED_PREFIX_MATCH;
71667
+ r.default_rc = 0;
7119471668
r.aMem = &aMem[pOp->p2];
7119571669
#ifdef SQLITE_DEBUG
7119671670
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
7119771671
#endif
7119871672
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
@@ -71302,14 +71776,14 @@
7130271776
assert( pOp->p4type==P4_INT32 );
7130371777
r.pKeyInfo = pC->pKeyInfo;
7130471778
r.nField = (u16)pOp->p4.i;
7130571779
if( pOp->opcode<OP_IdxLT ){
7130671780
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
71307
- r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
71781
+ r.default_rc = -1;
7130871782
}else{
7130971783
assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
71310
- r.flags = UNPACKED_PREFIX_MATCH;
71784
+ r.default_rc = 0;
7131171785
}
7131271786
r.aMem = &aMem[pOp->p3];
7131371787
#ifdef SQLITE_DEBUG
7131471788
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
7131571789
#endif
@@ -72056,11 +72530,10 @@
7205672530
assert( apVal || n==0 );
7205772531
for(i=0; i<n; i++, pRec++){
7205872532
assert( memIsValid(pRec) );
7205972533
apVal[i] = pRec;
7206072534
memAboutToChange(p, pRec);
72061
- sqlite3VdbeMemStoreType(pRec);
7206272535
}
7206372536
ctx.pFunc = pOp->p4.pFunc;
7206472537
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
7206572538
ctx.pMem = pMem = &aMem[pOp->p3];
7206672539
pMem->n++;
@@ -72490,11 +72963,10 @@
7249072963
{
7249172964
res = 0;
7249272965
apArg = p->apArg;
7249372966
for(i = 0; i<nArg; i++){
7249472967
apArg[i] = &pArgc[i+1];
72495
- sqlite3VdbeMemStoreType(apArg[i]);
7249672968
}
7249772969
7249872970
p->inVtabMethod = 1;
7249972971
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
7250072972
p->inVtabMethod = 0;
@@ -72697,11 +73169,10 @@
7269773169
apArg = p->apArg;
7269873170
pX = &aMem[pOp->p3];
7269973171
for(i=0; i<nArg; i++){
7270073172
assert( memIsValid(pX) );
7270173173
memAboutToChange(p, pX);
72702
- sqlite3VdbeMemStoreType(pX);
7270373174
apArg[i] = pX;
7270473175
pX++;
7270573176
}
7270673177
db->vtabOnConflict = pOp->p5;
7270773178
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
@@ -73809,14 +74280,14 @@
7380974280
if( r2->aMem[i].flags & MEM_Null ){
7381074281
*pRes = -1;
7381174282
return;
7381274283
}
7381374284
}
73814
- r2->flags |= UNPACKED_PREFIX_MATCH;
74285
+ assert( r2->default_rc==0 );
7381574286
}
7381674287
73817
- *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
74288
+ *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
7381874289
}
7381974290
7382074291
/*
7382174292
** This function is called to compare two iterator keys when merging
7382274293
** multiple b-tree segments. Parameter iOut is the index of the aTree[]
@@ -75449,10 +75920,12 @@
7544975920
pExpr->iTable = 1;
7545075921
pTab = pParse->pTriggerTab;
7545175922
}else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
7545275923
pExpr->iTable = 0;
7545375924
pTab = pParse->pTriggerTab;
75925
+ }else{
75926
+ pTab = 0;
7545475927
}
7545575928
7545675929
if( pTab ){
7545775930
int iCol;
7545875931
pSchema = pTab->pSchema;
@@ -87719,11 +88192,11 @@
8771988192
assert( nExtra>=1 );
8772088193
assert( pSrc!=0 );
8772188194
assert( iStart<=pSrc->nSrc );
8772288195
8772388196
/* Allocate additional space if needed */
87724
- if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
88197
+ if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
8772588198
SrcList *pNew;
8772688199
int nAlloc = pSrc->nSrc+nExtra;
8772788200
int nGot;
8772888201
pNew = sqlite3DbRealloc(db, pSrc,
8772988202
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
@@ -87731,19 +88204,19 @@
8773188204
assert( db->mallocFailed );
8773288205
return pSrc;
8773388206
}
8773488207
pSrc = pNew;
8773588208
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
87736
- pSrc->nAlloc = (u8)nGot;
88209
+ pSrc->nAlloc = nGot;
8773788210
}
8773888211
8773988212
/* Move existing slots that come after the newly inserted slots
8774088213
** out of the way */
8774188214
for(i=pSrc->nSrc-1; i>=iStart; i--){
8774288215
pSrc->a[i+nExtra] = pSrc->a[i];
8774388216
}
87744
- pSrc->nSrc += (i8)nExtra;
88217
+ pSrc->nSrc += nExtra;
8774588218
8774688219
/* Zero the newly allocated slots */
8774788220
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
8774888221
for(i=iStart; i<iStart+nExtra; i++){
8774988222
pSrc->a[i].iCursor = -1;
@@ -100117,11 +100590,11 @@
100117100590
}else if( eDest!=SRT_Exists ){
100118100591
/* If the destination is an EXISTS(...) expression, the actual
100119100592
** values returned by the SELECT are not required.
100120100593
*/
100121100594
sqlite3ExprCodeExprList(pParse, pEList, regResult,
100122
- (eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
100595
+ (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0);
100123100596
}
100124100597
100125100598
/* If the DISTINCT keyword was present on the SELECT statement
100126100599
** and this row has been seen before, then do not make this row
100127100600
** part of the result.
@@ -101030,11 +101503,11 @@
101030101503
for(j=cnt=0; j<i; j++){
101031101504
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
101032101505
char *zNewName;
101033101506
int k;
101034101507
for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
101035
- if( zName[k]==':' ) nName = k;
101508
+ if( k>=0 && zName[k]==':' ) nName = k;
101036101509
zName[nName] = 0;
101037101510
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
101038101511
sqlite3DbFree(db, zName);
101039101512
zName = zNewName;
101040101513
j = -1;
@@ -110767,11 +111240,11 @@
110767111240
iCol = pRec->nField - 1;
110768111241
assert( pIdx->nSample>0 );
110769111242
assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
110770111243
do{
110771111244
iTest = (iMin+i)/2;
110772
- res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
111245
+ res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
110773111246
if( res<0 ){
110774111247
iMin = iTest+1;
110775111248
}else{
110776111249
i = iTest;
110777111250
}
@@ -110782,20 +111255,20 @@
110782111255
** above found the right answer. This block serves no purpose other
110783111256
** than to invoke the asserts. */
110784111257
if( res==0 ){
110785111258
/* If (res==0) is true, then sample $i must be equal to pRec */
110786111259
assert( i<pIdx->nSample );
110787
- assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
111260
+ assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
110788111261
|| pParse->db->mallocFailed );
110789111262
}else{
110790111263
/* Otherwise, pRec must be smaller than sample $i and larger than
110791111264
** sample ($i-1). */
110792111265
assert( i==pIdx->nSample
110793
- || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
111266
+ || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
110794111267
|| pParse->db->mallocFailed );
110795111268
assert( i==0
110796
- || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
111269
+ || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
110797111270
|| pParse->db->mallocFailed );
110798111271
}
110799111272
#endif /* ifdef SQLITE_DEBUG */
110800111273
110801111274
/* At this point, aSample[i] is the first sample that is greater than
@@ -114724,11 +115197,11 @@
114724115197
114725115198
/* For a co-routine, change all OP_Column references to the table of
114726115199
** the co-routine into OP_SCopy of result contained in a register.
114727115200
** OP_Rowid becomes OP_Null.
114728115201
*/
114729
- if( pTabItem->viaCoroutine ){
115202
+ if( pTabItem->viaCoroutine && !db->mallocFailed ){
114730115203
last = sqlite3VdbeCurrentAddr(v);
114731115204
k = pLevel->addrBody;
114732115205
pOp = sqlite3VdbeGetOp(v, k);
114733115206
for(; k<last; k++, pOp++){
114734115207
if( pOp->p1!=pLevel->iTabCur ) continue;
114735115208
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -73,12 +73,45 @@
73 # define _FILE_OFFSET_BITS 64
74 # endif
75 # define _LARGEFILE_SOURCE 1
76 #endif
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78 /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
79 ** first in QNX.
 
80 */
81 /************** Include sqlite3.h in the middle of sqliteInt.h ***************/
82 /************** Begin file sqlite3.h *****************************************/
83 /*
84 ** 2001 September 15
@@ -189,11 +222,11 @@
189 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
190 ** [sqlite_version()] and [sqlite_source_id()].
191 */
192 #define SQLITE_VERSION "3.8.4"
193 #define SQLITE_VERSION_NUMBER 3008004
194 #define SQLITE_SOURCE_ID "2014-02-27 15:04:13 a6690400235705ecc0d1a60dacff6ad5fb1f944a"
195
196 /*
197 ** CAPI3REF: Run-Time Library Version Numbers
198 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
199 **
@@ -9334,12 +9367,15 @@
9334 #ifndef SQLITE_OMIT_TRACE
9335 SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
9336 #endif
9337
9338 SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
9339 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
9340 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
 
 
 
9341
9342 #ifndef SQLITE_OMIT_TRIGGER
9343 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
9344 #endif
9345
@@ -10950,23 +10986,23 @@
10950 ** the OP_MakeRecord opcode of the VDBE and is disassembled by the
10951 ** OP_Column opcode.
10952 **
10953 ** This structure holds a record that has already been disassembled
10954 ** into its constituent fields.
 
 
 
10955 */
10956 struct UnpackedRecord {
10957 KeyInfo *pKeyInfo; /* Collation and sort-order information */
10958 u16 nField; /* Number of entries in apMem[] */
10959 u8 flags; /* Boolean settings. UNPACKED_... below */
10960 Mem *aMem; /* Values */
 
 
10961 };
10962
10963 /*
10964 ** Allowed values of UnpackedRecord.flags
10965 */
10966 #define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
10967 #define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
10968
10969 /*
10970 ** Each SQL index is represented in memory by an
10971 ** instance of the following structure.
10972 **
@@ -11382,12 +11418,12 @@
11382 **
11383 ** In the colUsed field, the high-order bit (bit 63) is set if the table
11384 ** contains more than 63 columns and the 64-th or later column is used.
11385 */
11386 struct SrcList {
11387 u8 nSrc; /* Number of tables or subqueries in the FROM clause */
11388 u8 nAlloc; /* Number of entries allocated in a[] below */
11389 struct SrcList_item {
11390 Schema *pSchema; /* Schema to which this item is fixed */
11391 char *zDatabase; /* Name of database holding this table */
11392 char *zName; /* Name of the table */
11393 char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
@@ -13415,10 +13451,13 @@
13415 #ifdef SQLITE_OMIT_COMPLETE
13416 "OMIT_COMPLETE",
13417 #endif
13418 #ifdef SQLITE_OMIT_COMPOUND_SELECT
13419 "OMIT_COMPOUND_SELECT",
 
 
 
13420 #endif
13421 #ifdef SQLITE_OMIT_DATETIME_FUNCS
13422 "OMIT_DATETIME_FUNCS",
13423 #endif
13424 #ifdef SQLITE_OMIT_DECLTYPE
@@ -13800,11 +13839,10 @@
13800 RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
13801 VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
13802 } u;
13803 int n; /* Number of characters in string value, excluding '\0' */
13804 u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
13805 u8 memType; /* Lower 5 bits of flags */
13806 u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
13807 #ifdef SQLITE_DEBUG
13808 Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
13809 void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
13810 #endif
@@ -13827,10 +13865,11 @@
13827 #define MEM_Null 0x0001 /* Value is NULL */
13828 #define MEM_Str 0x0002 /* Value is a string */
13829 #define MEM_Int 0x0004 /* Value is an integer */
13830 #define MEM_Real 0x0008 /* Value is a real number */
13831 #define MEM_Blob 0x0010 /* Value is a BLOB */
 
13832 #define MEM_RowSet 0x0020 /* Value is a RowSet object */
13833 #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
13834 #define MEM_Undefined 0x0080 /* Value is undefined */
13835 #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
13836 #define MEM_TypeMask 0x01ff /* Mask of type bits */
@@ -13840,11 +13879,11 @@
13840 ** the following flags must be set to determine the memory management
13841 ** policy for Mem.z. The MEM_Term flag tells us whether or not the
13842 ** string is \000 or \u0000 terminated
13843 */
13844 #define MEM_Term 0x0200 /* String rep is nul terminated */
13845 #define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
13846 #define MEM_Static 0x0800 /* Mem.z points to a static string */
13847 #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
13848 #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
13849 #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
13850 #ifdef SQLITE_OMIT_INCRBLOB
@@ -14023,11 +14062,11 @@
14023 SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
14024 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
14025 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
14026
14027 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
14028 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
14029 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
14030 SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
14031 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
14032 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
14033 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -14066,12 +14105,10 @@
14066 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
14067 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
14068 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
14069 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
14070 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
14071 #define sqlite3VdbeMemStoreType(X) (X)->memType = (u8)((X)->flags&0x1f)
14072 /* void sqlite3VdbeMemStoreType(Mem *pMem); */
14073 SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
14074
14075 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
14076 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
14077 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -14088,10 +14125,11 @@
14088 # define sqlite3VdbeLeave(X)
14089 #endif
14090
14091 #ifdef SQLITE_DEBUG
14092 SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
 
14093 #endif
14094
14095 #ifndef SQLITE_OMIT_FOREIGN_KEY
14096 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
14097 #else
@@ -21471,11 +21509,11 @@
21471 assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
21472
21473 sqlite3VdbeMemRelease(pMem);
21474 pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
21475 pMem->enc = desiredEnc;
21476 pMem->flags |= (MEM_Term|MEM_Dyn);
21477 pMem->z = (char*)zOut;
21478 pMem->zMalloc = pMem->z;
21479
21480 translate_out:
21481 #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
@@ -21599,11 +21637,10 @@
21599 sqlite3VdbeMemRelease(&m);
21600 m.z = 0;
21601 }
21602 assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
21603 assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
21604 assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
21605 assert( m.z || db->mallocFailed );
21606 return m.z;
21607 }
21608
21609 /*
@@ -55305,10 +55342,11 @@
55305 i64 intKey, /* The table key */
55306 int biasRight, /* If true, bias the search to the high end */
55307 int *pRes /* Write search results here */
55308 ){
55309 int rc;
 
55310
55311 assert( cursorHoldsMutex(pCur) );
55312 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
55313 assert( pRes );
55314 assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
@@ -55325,10 +55363,20 @@
55325 if( pCur->atLast && pCur->info.nKey<intKey ){
55326 *pRes = -1;
55327 return SQLITE_OK;
55328 }
55329 }
 
 
 
 
 
 
 
 
 
 
55330
55331 rc = moveToRoot(pCur);
55332 if( rc ){
55333 return rc;
55334 }
@@ -55358,11 +55406,11 @@
55358 lwr = 0;
55359 upr = pPage->nCell-1;
55360 assert( biasRight==0 || biasRight==1 );
55361 idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
55362 pCur->aiIdx[pCur->iPage] = (u16)idx;
55363 if( pPage->intKey ){
55364 for(;;){
55365 i64 nCellKey;
55366 pCell = findCell(pPage, idx) + pPage->childPtrSize;
55367 if( pPage->hasData ){
55368 while( 0x80 <= *(pCell++) ){
@@ -55410,18 +55458,18 @@
55410 if( nCell<=pPage->max1bytePayload ){
55411 /* This branch runs if the record-size field of the cell is a
55412 ** single byte varint and the record fits entirely on the main
55413 ** b-tree page. */
55414 testcase( pCell+nCell+1==pPage->aDataEnd );
55415 c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
55416 }else if( !(pCell[1] & 0x80)
55417 && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
55418 ){
55419 /* The record-size field is a 2 byte varint and the record
55420 ** fits entirely on the main b-tree page. */
55421 testcase( pCell+nCell+2==pPage->aDataEnd );
55422 c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
55423 }else{
55424 /* The record flows over onto one or more overflow pages. In
55425 ** this case the whole cell needs to be parsed, a buffer allocated
55426 ** and accessPayload() used to retrieve the record into the
55427 ** buffer before VdbeRecordCompare() can be called. */
@@ -55438,11 +55486,11 @@
55438 rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
55439 if( rc ){
55440 sqlite3_free(pCellKey);
55441 goto moveto_finish;
55442 }
55443 c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
55444 sqlite3_free(pCellKey);
55445 }
55446 if( c<0 ){
55447 lwr = idx+1;
55448 }else if( c>0 ){
@@ -60001,10 +60049,46 @@
60001 ** This file contains code use to manipulate "Mem" structure. A "Mem"
60002 ** stores a single value in the VDBE. Mem is an opaque structure visible
60003 ** only within the VDBE. Interface routines refer to a Mem using the
60004 ** name sqlite_value
60005 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60006
60007 /*
60008 ** If pMem is an object with a valid string representation, this routine
60009 ** ensures the internal encoding for the string representation is
60010 ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
@@ -60051,16 +60135,11 @@
60051 ** pMem->z into the new allocation. pMem must be either a string or
60052 ** blob if bPreserve is true. If bPreserve is false, any prior content
60053 ** in pMem->z is discarded.
60054 */
60055 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
60056 assert( 1 >=
60057 ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
60058 (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
60059 ((pMem->flags&MEM_Ephem) ? 1 : 0) +
60060 ((pMem->flags&MEM_Static) ? 1 : 0)
60061 );
60062 assert( (pMem->flags&MEM_RowSet)==0 );
60063
60064 /* If the bPreserve flag is set to true, then the memory cell must already
60065 ** contain a valid string or blob value. */
60066 assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
@@ -60074,26 +60153,27 @@
60074 }else{
60075 sqlite3DbFree(pMem->db, pMem->zMalloc);
60076 pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
60077 }
60078 if( pMem->zMalloc==0 ){
60079 sqlite3VdbeMemRelease(pMem);
 
60080 pMem->flags = MEM_Null;
60081 return SQLITE_NOMEM;
60082 }
60083 }
60084
60085 if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
60086 memcpy(pMem->zMalloc, pMem->z, pMem->n);
60087 }
60088 if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
60089 assert( pMem->xDel!=SQLITE_DYNAMIC );
60090 pMem->xDel((void *)(pMem->z));
60091 }
60092
60093 pMem->z = pMem->zMalloc;
60094 pMem->flags &= ~(MEM_Ephem|MEM_Static);
60095 pMem->xDel = 0;
60096 return SQLITE_OK;
60097 }
60098
60099 /*
@@ -60258,13 +60338,13 @@
60258 assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
60259 if( p->flags&MEM_Agg ){
60260 sqlite3VdbeMemFinalize(p, p->u.pDef);
60261 assert( (p->flags & MEM_Agg)==0 );
60262 sqlite3VdbeMemRelease(p);
60263 }else if( p->flags&MEM_Dyn && p->xDel ){
60264 assert( (p->flags&MEM_RowSet)==0 );
60265 assert( p->xDel!=SQLITE_DYNAMIC );
60266 p->xDel((void *)p->z);
60267 p->xDel = 0;
60268 }else if( p->flags&MEM_RowSet ){
60269 sqlite3RowSetClear(p->u.pRowSet);
60270 }else if( p->flags&MEM_Frame ){
@@ -60273,13 +60353,14 @@
60273 }
60274
60275 /*
60276 ** Release any memory held by the Mem. This may leave the Mem in an
60277 ** inconsistent state, for example with (Mem.z==0) and
60278 ** (Mem.memType==MEM_Str).
60279 */
60280 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
 
60281 VdbeMemRelease(p);
60282 if( p->zMalloc ){
60283 sqlite3DbFree(p->db, p->zMalloc);
60284 p->zMalloc = 0;
60285 }
@@ -60464,11 +60545,10 @@
60464 }
60465 if( pMem->flags & MEM_RowSet ){
60466 sqlite3RowSetClear(pMem->u.pRowSet);
60467 }
60468 MemSetTypeFlag(pMem, MEM_Null);
60469 pMem->memType = MEM_Null;
60470 }
60471 SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
60472 sqlite3VdbeMemSetNull((Mem*)p);
60473 }
60474
@@ -60477,11 +60557,10 @@
60477 ** n containing all zeros.
60478 */
60479 SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
60480 sqlite3VdbeMemRelease(pMem);
60481 pMem->flags = MEM_Blob|MEM_Zero;
60482 pMem->memType = MEM_Blob;
60483 pMem->n = 0;
60484 if( n<0 ) n = 0;
60485 pMem->u.nZero = n;
60486 pMem->enc = SQLITE_UTF8;
60487
@@ -60500,11 +60579,10 @@
60500 */
60501 SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
60502 sqlite3VdbeMemRelease(pMem);
60503 pMem->u.i = val;
60504 pMem->flags = MEM_Int;
60505 pMem->memType = MEM_Int;
60506 }
60507
60508 #ifndef SQLITE_OMIT_FLOATING_POINT
60509 /*
60510 ** Delete any previous value and set the value stored in *pMem to val,
@@ -60515,11 +60593,10 @@
60515 sqlite3VdbeMemSetNull(pMem);
60516 }else{
60517 sqlite3VdbeMemRelease(pMem);
60518 pMem->r = val;
60519 pMem->flags = MEM_Real;
60520 pMem->memType = MEM_Real;
60521 }
60522 }
60523 #endif
60524
60525 /*
@@ -60613,10 +60690,11 @@
60613
60614 assert( (pFrom->flags & MEM_RowSet)==0 );
60615 VdbeMemRelease(pTo);
60616 memcpy(pTo, pFrom, MEMCELLSIZE);
60617 pTo->flags &= ~MEM_Dyn;
 
60618
60619 if( pTo->flags&(MEM_Str|MEM_Blob) ){
60620 if( 0==(pFrom->flags&MEM_Static) ){
60621 pTo->flags |= MEM_Ephem;
60622 rc = sqlite3VdbeMemMakeWriteable(pTo);
@@ -60723,11 +60801,10 @@
60723 }
60724
60725 pMem->n = nByte;
60726 pMem->flags = flags;
60727 pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
60728 pMem->memType = flags&0x1f;
60729
60730 #ifndef SQLITE_OMIT_UTF16
60731 if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
60732 return SQLITE_NOMEM;
60733 }
@@ -60738,123 +60815,10 @@
60738 }
60739
60740 return SQLITE_OK;
60741 }
60742
60743 /*
60744 ** Compare the values contained by the two memory cells, returning
60745 ** negative, zero or positive if pMem1 is less than, equal to, or greater
60746 ** than pMem2. Sorting order is NULL's first, followed by numbers (integers
60747 ** and reals) sorted numerically, followed by text ordered by the collating
60748 ** sequence pColl and finally blob's ordered by memcmp().
60749 **
60750 ** Two NULL values are considered equal by this function.
60751 */
60752 SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
60753 int rc;
60754 int f1, f2;
60755 int combined_flags;
60756
60757 f1 = pMem1->flags;
60758 f2 = pMem2->flags;
60759 combined_flags = f1|f2;
60760 assert( (combined_flags & MEM_RowSet)==0 );
60761
60762 /* If one value is NULL, it is less than the other. If both values
60763 ** are NULL, return 0.
60764 */
60765 if( combined_flags&MEM_Null ){
60766 return (f2&MEM_Null) - (f1&MEM_Null);
60767 }
60768
60769 /* If one value is a number and the other is not, the number is less.
60770 ** If both are numbers, compare as reals if one is a real, or as integers
60771 ** if both values are integers.
60772 */
60773 if( combined_flags&(MEM_Int|MEM_Real) ){
60774 double r1, r2;
60775 if( (f1 & f2 & MEM_Int)!=0 ){
60776 if( pMem1->u.i < pMem2->u.i ) return -1;
60777 if( pMem1->u.i > pMem2->u.i ) return 1;
60778 return 0;
60779 }
60780 if( (f1&MEM_Real)!=0 ){
60781 r1 = pMem1->r;
60782 }else if( (f1&MEM_Int)!=0 ){
60783 r1 = (double)pMem1->u.i;
60784 }else{
60785 return 1;
60786 }
60787 if( (f2&MEM_Real)!=0 ){
60788 r2 = pMem2->r;
60789 }else if( (f2&MEM_Int)!=0 ){
60790 r2 = (double)pMem2->u.i;
60791 }else{
60792 return -1;
60793 }
60794 if( r1<r2 ) return -1;
60795 if( r1>r2 ) return 1;
60796 return 0;
60797 }
60798
60799 /* If one value is a string and the other is a blob, the string is less.
60800 ** If both are strings, compare using the collating functions.
60801 */
60802 if( combined_flags&MEM_Str ){
60803 if( (f1 & MEM_Str)==0 ){
60804 return 1;
60805 }
60806 if( (f2 & MEM_Str)==0 ){
60807 return -1;
60808 }
60809
60810 assert( pMem1->enc==pMem2->enc );
60811 assert( pMem1->enc==SQLITE_UTF8 ||
60812 pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
60813
60814 /* The collation sequence must be defined at this point, even if
60815 ** the user deletes the collation sequence after the vdbe program is
60816 ** compiled (this was not always the case).
60817 */
60818 assert( !pColl || pColl->xCmp );
60819
60820 if( pColl ){
60821 if( pMem1->enc==pColl->enc ){
60822 /* The strings are already in the correct encoding. Call the
60823 ** comparison function directly */
60824 return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
60825 }else{
60826 const void *v1, *v2;
60827 int n1, n2;
60828 Mem c1;
60829 Mem c2;
60830 memset(&c1, 0, sizeof(c1));
60831 memset(&c2, 0, sizeof(c2));
60832 sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
60833 sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
60834 v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
60835 n1 = v1==0 ? 0 : c1.n;
60836 v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
60837 n2 = v2==0 ? 0 : c2.n;
60838 rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
60839 sqlite3VdbeMemRelease(&c1);
60840 sqlite3VdbeMemRelease(&c2);
60841 return rc;
60842 }
60843 }
60844 /* If a NULL pointer was passed as the collate function, fall through
60845 ** to the blob case and use memcmp(). */
60846 }
60847
60848 /* Both values must be blobs. Compare using memcmp(). */
60849 rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
60850 if( rc==0 ){
60851 rc = pMem1->n - pMem2->n;
60852 }
60853 return rc;
60854 }
60855
60856 /*
60857 ** Move data out of a btree key or data field and into a Mem structure.
60858 ** The data or key is taken from the entry that pCur is currently pointing
60859 ** to. offset and amt determine what portion of the data or key to retrieve.
60860 ** key is true to get the key or false to get data. The result is written
@@ -60891,26 +60855,26 @@
60891
60892 if( offset+amt<=available ){
60893 sqlite3VdbeMemRelease(pMem);
60894 pMem->z = &zData[offset];
60895 pMem->flags = MEM_Blob|MEM_Ephem;
 
60896 }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
60897 pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
60898 pMem->enc = 0;
60899 pMem->memType = MEM_Blob;
60900 if( key ){
60901 rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
60902 }else{
60903 rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
60904 }
60905 pMem->z[amt] = 0;
60906 pMem->z[amt+1] = 0;
60907 if( rc!=SQLITE_OK ){
 
 
 
60908 sqlite3VdbeMemRelease(pMem);
60909 }
60910 }
60911 pMem->n = (int)amt;
60912
60913 return rc;
60914 }
60915
60916 /* This function is only available internally, it is not part of the
@@ -60964,11 +60928,10 @@
60964 */
60965 SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
60966 Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
60967 if( p ){
60968 p->flags = MEM_Null;
60969 p->memType = MEM_Null;
60970 p->db = db;
60971 }
60972 return p;
60973 }
60974
@@ -61010,15 +60973,13 @@
61010 if( pRec ){
61011 pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
61012 if( pRec->pKeyInfo ){
61013 assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
61014 assert( pRec->pKeyInfo->enc==ENC(db) );
61015 pRec->flags = UNPACKED_PREFIX_MATCH;
61016 pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
61017 for(i=0; i<nCol; i++){
61018 pRec->aMem[i].flags = MEM_Null;
61019 pRec->aMem[i].memType = MEM_Null;
61020 pRec->aMem[i].db = db;
61021 }
61022 }else{
61023 sqlite3DbFree(db, pRec);
61024 pRec = 0;
@@ -61087,11 +61048,10 @@
61087 sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
61088 }else{
61089 zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
61090 if( zVal==0 ) goto no_mem;
61091 sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
61092 if( op==TK_FLOAT ) pVal->memType = MEM_Real;
61093 }
61094 if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
61095 sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
61096 }else{
61097 sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
@@ -61105,13 +61065,13 @@
61105 if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
61106 && pVal!=0
61107 ){
61108 sqlite3VdbeMemNumerify(pVal);
61109 if( pVal->u.i==SMALLEST_INT64 ){
61110 pVal->flags &= MEM_Int;
61111 pVal->flags |= MEM_Real;
61112 pVal->r = (double)LARGEST_INT64;
61113 }else{
61114 pVal->u.i = -pVal->u.i;
61115 }
61116 pVal->r = -pVal->r;
61117 sqlite3ValueApplyAffinity(pVal, affinity, enc);
@@ -61133,13 +61093,10 @@
61133 sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
61134 0, SQLITE_DYNAMIC);
61135 }
61136 #endif
61137
61138 if( pVal ){
61139 sqlite3VdbeMemStoreType(pVal);
61140 }
61141 *ppVal = pVal;
61142 return rc;
61143
61144 no_mem:
61145 db->mallocFailed = 1;
@@ -61299,11 +61256,10 @@
61299 rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
61300 if( rc==SQLITE_OK ){
61301 sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
61302 }
61303 pVal->db = pParse->db;
61304 sqlite3VdbeMemStoreType((Mem*)pVal);
61305 }
61306 }
61307 }else{
61308 rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
61309 }
@@ -62591,10 +62547,11 @@
62591 }
62592 return;
62593 }
62594 for(pEnd=&p[N]; p<pEnd; p++){
62595 assert( (&p[1])==pEnd || p[0].db==p[1].db );
 
62596
62597 /* This block is really an inlined version of sqlite3VdbeMemRelease()
62598 ** that takes advantage of the fact that the memory cell value is
62599 ** being set to NULL after releasing any dynamic resources.
62600 **
@@ -62733,19 +62690,17 @@
62733 }
62734 pOp = &apSub[j]->aOp[i];
62735 }
62736 if( p->explain==1 ){
62737 pMem->flags = MEM_Int;
62738 pMem->memType = MEM_Int;
62739 pMem->u.i = i; /* Program counter */
62740 pMem++;
62741
62742 pMem->flags = MEM_Static|MEM_Str|MEM_Term;
62743 pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
62744 assert( pMem->z!=0 );
62745 pMem->n = sqlite3Strlen30(pMem->z);
62746 pMem->memType = MEM_Str;
62747 pMem->enc = SQLITE_UTF8;
62748 pMem++;
62749
62750 /* When an OP_Program opcode is encounter (the only opcode that has
62751 ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
@@ -62767,63 +62722,56 @@
62767 }
62768 }
62769
62770 pMem->flags = MEM_Int;
62771 pMem->u.i = pOp->p1; /* P1 */
62772 pMem->memType = MEM_Int;
62773 pMem++;
62774
62775 pMem->flags = MEM_Int;
62776 pMem->u.i = pOp->p2; /* P2 */
62777 pMem->memType = MEM_Int;
62778 pMem++;
62779
62780 pMem->flags = MEM_Int;
62781 pMem->u.i = pOp->p3; /* P3 */
62782 pMem->memType = MEM_Int;
62783 pMem++;
62784
62785 if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
62786 assert( p->db->mallocFailed );
62787 return SQLITE_ERROR;
62788 }
62789 pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62790 zP4 = displayP4(pOp, pMem->z, 32);
62791 if( zP4!=pMem->z ){
62792 sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
62793 }else{
62794 assert( pMem->z!=0 );
62795 pMem->n = sqlite3Strlen30(pMem->z);
62796 pMem->enc = SQLITE_UTF8;
62797 }
62798 pMem->memType = MEM_Str;
62799 pMem++;
62800
62801 if( p->explain==1 ){
62802 if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
62803 assert( p->db->mallocFailed );
62804 return SQLITE_ERROR;
62805 }
62806 pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62807 pMem->n = 2;
62808 sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
62809 pMem->memType = MEM_Str;
62810 pMem->enc = SQLITE_UTF8;
62811 pMem++;
62812
62813 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
62814 if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
62815 assert( p->db->mallocFailed );
62816 return SQLITE_ERROR;
62817 }
62818 pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
62819 pMem->n = displayComment(pOp, zP4, pMem->z, 500);
62820 pMem->memType = MEM_Str;
62821 pMem->enc = SQLITE_UTF8;
62822 #else
62823 pMem->flags = MEM_Null; /* Comment */
62824 pMem->memType = MEM_Null;
62825 #endif
62826 }
62827
62828 p->nResColumn = 8 - 4*(p->explain-1);
62829 p->pResultSet = &p->aMem[1];
@@ -64312,10 +64260,18 @@
64312
64313 /* NULL or constants 0 or 1 */
64314 return 0;
64315 }
64316
 
 
 
 
 
 
 
 
64317 /*
64318 ** Deserialize the data blob pointed to by buf as serial type serial_type
64319 ** and store the result in pMem. Return the number of bytes read.
64320 */
64321 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
@@ -64323,46 +64279,40 @@
64323 u32 serial_type, /* Serial type to deserialize */
64324 Mem *pMem /* Memory cell to write value into */
64325 ){
64326 u64 x;
64327 u32 y;
64328 int i;
64329 switch( serial_type ){
64330 case 10: /* Reserved for future use */
64331 case 11: /* Reserved for future use */
64332 case 0: { /* NULL */
64333 pMem->flags = MEM_Null;
64334 break;
64335 }
64336 case 1: { /* 1-byte signed integer */
64337 pMem->u.i = (signed char)buf[0];
64338 pMem->flags = MEM_Int;
64339 return 1;
64340 }
64341 case 2: { /* 2-byte signed integer */
64342 i = 256*(signed char)buf[0] | buf[1];
64343 pMem->u.i = (i64)i;
64344 pMem->flags = MEM_Int;
64345 return 2;
64346 }
64347 case 3: { /* 3-byte signed integer */
64348 i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64349 pMem->u.i = (i64)i;
64350 pMem->flags = MEM_Int;
64351 return 3;
64352 }
64353 case 4: { /* 4-byte signed integer */
64354 y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64355 pMem->u.i = (i64)*(int*)&y;
64356 pMem->flags = MEM_Int;
64357 return 4;
64358 }
64359 case 5: { /* 6-byte signed integer */
64360 x = 256*(signed char)buf[0] + buf[1];
64361 y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64362 x = (x<<32) | y;
64363 pMem->u.i = *(i64*)&x;
64364 pMem->flags = MEM_Int;
64365 return 6;
64366 }
64367 case 6: /* 8-byte signed integer */
64368 case 7: { /* IEEE floating point */
@@ -64376,12 +64326,12 @@
64376 static const double r1 = 1.0;
64377 u64 t2 = t1;
64378 swapMixedEndianFloat(t2);
64379 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64380 #endif
64381 x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64382 y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64383 x = (x<<32) | y;
64384 if( serial_type==6 ){
64385 pMem->u.i = *(i64*)&x;
64386 pMem->flags = MEM_Int;
64387 }else{
@@ -64473,11 +64423,11 @@
64473 u32 idx; /* Offset in aKey[] to read from */
64474 u16 u; /* Unsigned loop counter */
64475 u32 szHdr;
64476 Mem *pMem = p->aMem;
64477
64478 p->flags = 0;
64479 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
64480 idx = getVarint32(aKey, szHdr);
64481 d = szHdr;
64482 u = 0;
64483 while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -64494,30 +64444,22 @@
64494 }
64495 assert( u<=pKeyInfo->nField + 1 );
64496 p->nField = u;
64497 }
64498
 
64499 /*
64500 ** This function compares the two table rows or index records
64501 ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
64502 ** or positive integer if key1 is less than, equal to or
64503 ** greater than key2. The {nKey1, pKey1} key must be a blob
64504 ** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
64505 ** key must be a parsed key such as obtained from
64506 ** sqlite3VdbeParseRecord.
64507 **
64508 ** Key1 and Key2 do not have to contain the same number of fields.
64509 ** The key with fewer fields is usually compares less than the
64510 ** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
64511 ** and the common prefixes are equal, then key1 is less than key2.
64512 ** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
64513 ** equal, then the keys are considered to be equal and
64514 ** the parts beyond the common prefix are ignored.
64515 */
64516 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
64517 int nKey1, const void *pKey1, /* Left key */
64518 UnpackedRecord *pPKey2 /* Right key */
64519 ){
64520 u32 d1; /* Offset into aKey[] of next data element */
64521 u32 idx1; /* Offset into aKey[] of next header element */
64522 u32 szHdr1; /* Number of bytes in header */
64523 int i = 0;
@@ -64587,28 +64529,559 @@
64587 ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
64588 */
64589 assert( mem1.zMalloc==0 );
64590
64591 /* rc==0 here means that one of the keys ran out of fields and
64592 ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
64593 ** flag is set, then break the tie by treating key2 as larger.
64594 ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
64595 ** are considered to be equal. Otherwise, the longer key is the
64596 ** larger. As it happens, the pPKey2 will always be the longer
64597 ** if there is a difference.
64598 */
64599 assert( rc==0 );
64600 if( pPKey2->flags & UNPACKED_INCRKEY ){
64601 rc = -1;
64602 }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
64603 /* Leave rc==0 */
64604 }else if( idx1<szHdr1 ){
64605 rc = 1;
64606 }
64607 return rc;
64608 }
64609
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64610
64611 /*
64612 ** pCur points at an index entry created using the OP_MakeRecord opcode.
64613 ** Read the rowid (the last field in the record) and store it in *rowid.
64614 ** Return SQLITE_OK if everything works, or an error code otherwise.
@@ -64695,23 +65168,23 @@
64695 ** omits the rowid at the end. The rowid at the end of the index entry
64696 ** is ignored as well. Hence, this routine only compares the prefixes
64697 ** of the keys prior to the final rowid, not the entire key.
64698 */
64699 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
64700 VdbeCursor *pC, /* The cursor to compare against */
64701 UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
64702 int *res /* Write the comparison result here */
64703 ){
64704 i64 nCellKey = 0;
64705 int rc;
64706 BtCursor *pCur = pC->pCursor;
64707 Mem m;
64708
64709 assert( sqlite3BtreeCursorIsValid(pCur) );
64710 VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
64711 assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
64712 /* nCellKey will always be between 0 and 0xffffffff because of the say
64713 ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
64714 if( nCellKey<=0 || nCellKey>0x7fffffff ){
64715 *res = 0;
64716 return SQLITE_CORRUPT_BKPT;
64717 }
@@ -64718,12 +65191,11 @@
64718 memset(&m, 0, sizeof(m));
64719 rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
64720 if( rc ){
64721 return rc;
64722 }
64723 assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
64724 *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
64725 sqlite3VdbeMemRelease(&m);
64726 return SQLITE_OK;
64727 }
64728
64729 /*
@@ -64783,11 +65255,10 @@
64783 if( 0==(pMem->flags & MEM_Null) ){
64784 sqlite3_value *pRet = sqlite3ValueNew(v->db);
64785 if( pRet ){
64786 sqlite3VdbeMemCopy((Mem *)pRet, pMem);
64787 sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
64788 sqlite3VdbeMemStoreType((Mem *)pRet);
64789 }
64790 return pRet;
64791 }
64792 }
64793 return 0;
@@ -64957,11 +65428,10 @@
64957 */
64958 SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
64959 Mem *p = (Mem*)pVal;
64960 if( p->flags & (MEM_Blob|MEM_Str) ){
64961 sqlite3VdbeMemExpandBlob(p);
64962 p->flags &= ~MEM_Str;
64963 p->flags |= MEM_Blob;
64964 return p->n ? p->z : 0;
64965 }else{
64966 return sqlite3_value_text(pVal);
64967 }
@@ -65028,11 +65498,11 @@
65028 SQLITE_INTEGER, /* 0x1c */
65029 SQLITE_NULL, /* 0x1d */
65030 SQLITE_INTEGER, /* 0x1e */
65031 SQLITE_NULL, /* 0x1f */
65032 };
65033 return aType[pVal->memType&0x1f];
65034 }
65035
65036 /**************************** sqlite3_result_ *******************************
65037 ** The following routines are used by user-defined functions to specify
65038 ** the function result.
@@ -65549,10 +66019,34 @@
65549 Vdbe *pVm = (Vdbe *)pStmt;
65550 if( pVm==0 || pVm->pResultSet==0 ) return 0;
65551 return pVm->nResColumn;
65552 }
65553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65554
65555 /*
65556 ** Check to see if column iCol of the given statement is valid. If
65557 ** it is, return a pointer to the Mem for the value of that column.
65558 ** If iCol is not valid, return a pointer to a Mem which has a value
@@ -65565,36 +66059,15 @@
65565 pVm = (Vdbe *)pStmt;
65566 if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
65567 sqlite3_mutex_enter(pVm->db->mutex);
65568 pOut = &pVm->pResultSet[i];
65569 }else{
65570 /* If the value passed as the second argument is out of range, return
65571 ** a pointer to the following static Mem object which contains the
65572 ** value SQL NULL. Even though the Mem structure contains an element
65573 ** of type i64, on certain architectures (x86) with certain compiler
65574 ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
65575 ** instead of an 8-byte one. This all works fine, except that when
65576 ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
65577 ** that a Mem structure is located on an 8-byte boundary. To prevent
65578 ** these assert()s from failing, when building with SQLITE_DEBUG defined
65579 ** using gcc, we force nullMem to be 8-byte aligned using the magical
65580 ** __attribute__((aligned(8))) macro. */
65581 static const Mem nullMem
65582 #if defined(SQLITE_DEBUG) && defined(__GNUC__)
65583 __attribute__((aligned(8)))
65584 #endif
65585 = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
65586 #ifdef SQLITE_DEBUG
65587 0, 0, /* pScopyFrom, pFiller */
65588 #endif
65589 0, 0 };
65590
65591 if( pVm && ALWAYS(pVm->db) ){
65592 sqlite3_mutex_enter(pVm->db->mutex);
65593 sqlite3Error(pVm->db, SQLITE_RANGE, 0);
65594 }
65595 pOut = (Mem*)&nullMem;
65596 }
65597 return pOut;
65598 }
65599
65600 /*
@@ -66629,11 +67102,11 @@
66629 ** does not control the string, it might be deleted without the register
66630 ** knowing it.
66631 **
66632 ** This routine converts an ephemeral string into a dynamically allocated
66633 ** string that the register itself controls. In other words, it
66634 ** converts an MEM_Ephem string into an MEM_Dyn string.
66635 */
66636 #define Deephemeralize(P) \
66637 if( ((P)->flags&MEM_Ephem)!=0 \
66638 && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
66639
@@ -66770,11 +67243,10 @@
66770 SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
66771 int eType = sqlite3_value_type(pVal);
66772 if( eType==SQLITE_TEXT ){
66773 Mem *pMem = (Mem*)pVal;
66774 applyNumericAffinity(pMem);
66775 sqlite3VdbeMemStoreType(pMem);
66776 eType = sqlite3_value_type(pVal);
66777 }
66778 return eType;
66779 }
66780
@@ -67166,22 +67638,25 @@
67166 #ifdef SQLITE_DEBUG
67167 if( (pOp->opflags & OPFLG_IN1)!=0 ){
67168 assert( pOp->p1>0 );
67169 assert( pOp->p1<=(p->nMem-p->nCursor) );
67170 assert( memIsValid(&aMem[pOp->p1]) );
 
67171 REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
67172 }
67173 if( (pOp->opflags & OPFLG_IN2)!=0 ){
67174 assert( pOp->p2>0 );
67175 assert( pOp->p2<=(p->nMem-p->nCursor) );
67176 assert( memIsValid(&aMem[pOp->p2]) );
 
67177 REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
67178 }
67179 if( (pOp->opflags & OPFLG_IN3)!=0 ){
67180 assert( pOp->p3>0 );
67181 assert( pOp->p3<=(p->nMem-p->nCursor) );
67182 assert( memIsValid(&aMem[pOp->p3]) );
 
67183 REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
67184 }
67185 if( (pOp->opflags & OPFLG_OUT2)!=0 ){
67186 assert( pOp->p2>0 );
67187 assert( pOp->p2<=(p->nMem-p->nCursor) );
@@ -67279,11 +67754,11 @@
67279 ** and then jump to address P2.
67280 */
67281 case OP_Gosub: { /* jump */
67282 assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
67283 pIn1 = &aMem[pOp->p1];
67284 assert( (pIn1->flags & MEM_Dyn)==0 );
67285 memAboutToChange(p, pIn1);
67286 pIn1->flags = MEM_Int;
67287 pIn1->u.i = pc;
67288 REGISTER_TRACE(pOp->p1, pIn1);
67289 pc = pOp->p2 - 1;
@@ -67352,11 +67827,11 @@
67352 ** OP_EndCoroutine, jump immediately to P2.
67353 */
67354 case OP_Yield: { /* in1, jump */
67355 int pcDest;
67356 pIn1 = &aMem[pOp->p1];
67357 assert( (pIn1->flags & MEM_Dyn)==0 );
67358 pIn1->flags = MEM_Int;
67359 pcDest = (int)pIn1->u.i;
67360 pIn1->u.i = pc;
67361 REGISTER_TRACE(pOp->p1, pIn1);
67362 pc = pcDest;
@@ -67525,14 +68000,13 @@
67525 if( encoding!=SQLITE_UTF8 ){
67526 rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
67527 if( rc==SQLITE_TOOBIG ) goto too_big;
67528 if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
67529 assert( pOut->zMalloc==pOut->z );
67530 assert( pOut->flags & MEM_Dyn );
67531 pOut->zMalloc = 0;
67532 pOut->flags |= MEM_Static;
67533 pOut->flags &= ~MEM_Dyn;
67534 if( pOp->p4type==P4_DYNAMIC ){
67535 sqlite3DbFree(db, pOp->p4.z);
67536 }
67537 pOp->p4type = P4_DYNAMIC;
67538 pOp->p4.z = pOut->z;
@@ -67664,18 +68138,20 @@
67664 do{
67665 assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
67666 assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
67667 assert( memIsValid(pIn1) );
67668 memAboutToChange(p, pOut);
 
67669 zMalloc = pOut->zMalloc;
67670 pOut->zMalloc = 0;
67671 sqlite3VdbeMemMove(pOut, pIn1);
67672 #ifdef SQLITE_DEBUG
67673 if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
67674 pOut->pScopyFrom += p1 - pOp->p2;
67675 }
67676 #endif
 
 
67677 pIn1->zMalloc = zMalloc;
67678 REGISTER_TRACE(p2++, pOut);
67679 pIn1++;
67680 pOut++;
67681 }while( n-- );
@@ -67805,11 +68281,10 @@
67805 assert( memIsValid(&pMem[i]) );
67806 Deephemeralize(&pMem[i]);
67807 assert( (pMem[i].flags & MEM_Ephem)==0
67808 || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
67809 sqlite3VdbeMemNulTerminate(&pMem[i]);
67810 sqlite3VdbeMemStoreType(&pMem[i]);
67811 REGISTER_TRACE(pOp->p1+i, &pMem[i]);
67812 }
67813 if( db->mallocFailed ) goto no_mem;
67814
67815 /* Return SQLITE_ROW
@@ -67848,14 +68323,14 @@
67848 Stringify(pIn2, encoding);
67849 nByte = pIn1->n + pIn2->n;
67850 if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
67851 goto too_big;
67852 }
67853 MemSetTypeFlag(pOut, MEM_Str);
67854 if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
67855 goto no_mem;
67856 }
 
67857 if( pOut!=pIn2 ){
67858 memcpy(pOut->z, pIn2->z, pIn2->n);
67859 }
67860 memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
67861 pOut->z[nByte]=0;
@@ -68051,11 +68526,10 @@
68051 pArg = &aMem[pOp->p2];
68052 for(i=0; i<n; i++, pArg++){
68053 assert( memIsValid(pArg) );
68054 apVal[i] = pArg;
68055 Deephemeralize(pArg);
68056 sqlite3VdbeMemStoreType(pArg);
68057 REGISTER_TRACE(pOp->p2+i, pArg);
68058 }
68059
68060 assert( pOp->p4type==P4_FUNCDEF );
68061 ctx.pFunc = pOp->p4.pFunc;
@@ -69026,10 +69500,11 @@
69026 ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
69027 ** all valid.
69028 */
69029 assert( p2<pC->nHdrParsed );
69030 assert( rc==SQLITE_OK );
 
69031 if( pC->szRow>=aOffset[p2+1] ){
69032 /* This is the common case where the desired content fits on the original
69033 ** page - where the content is not on an overflow page */
69034 VdbeMemRelease(pDest);
69035 sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
@@ -69063,12 +69538,12 @@
69063 ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
69064 ** dynamically allocated space over to the pDest structure.
69065 ** This prevents a memory copy. */
69066 if( sMem.zMalloc ){
69067 assert( sMem.z==sMem.zMalloc );
69068 assert( !(pDest->flags & MEM_Dyn) );
69069 assert( !(pDest->flags & (MEM_Blob|MEM_Str)) || pDest->z==sMem.z );
69070 pDest->flags &= ~(MEM_Ephem|MEM_Static);
69071 pDest->flags |= MEM_Term;
69072 pDest->z = sMem.z;
69073 pDest->zMalloc = sMem.zMalloc;
69074 }
@@ -69247,11 +69722,11 @@
69247 assert( i==nHdr );
69248 assert( j==nByte );
69249
69250 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
69251 pOut->n = (int)nByte;
69252 pOut->flags = MEM_Blob | MEM_Dyn;
69253 pOut->xDel = 0;
69254 if( nZero ){
69255 pOut->u.nZero = nZero;
69256 pOut->flags |= MEM_Zero;
69257 }
@@ -70121,20 +70596,20 @@
70121 r.pKeyInfo = pC->pKeyInfo;
70122 r.nField = (u16)nField;
70123
70124 /* The next line of code computes as follows, only faster:
70125 ** if( oc==OP_SeekGT || oc==OP_SeekLE ){
70126 ** r.flags = UNPACKED_INCRKEY;
70127 ** }else{
70128 ** r.flags = 0;
70129 ** }
70130 */
70131 r.flags = (u8)(UNPACKED_INCRKEY * (1 & (oc - OP_SeekLT)));
70132 assert( oc!=OP_SeekGT || r.flags==UNPACKED_INCRKEY );
70133 assert( oc!=OP_SeekLE || r.flags==UNPACKED_INCRKEY );
70134 assert( oc!=OP_SeekGE || r.flags==0 );
70135 assert( oc!=OP_SeekLT || r.flags==0 );
70136
70137 r.aMem = &aMem[pOp->p3];
70138 #ifdef SQLITE_DEBUG
70139 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
70140 #endif
@@ -70288,22 +70763,21 @@
70288 ExpandBlob(&r.aMem[ii]);
70289 #ifdef SQLITE_DEBUG
70290 if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
70291 #endif
70292 }
70293 r.flags = UNPACKED_PREFIX_MATCH;
70294 pIdxKey = &r;
70295 }else{
70296 pIdxKey = sqlite3VdbeAllocUnpackedRecord(
70297 pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
70298 );
70299 if( pIdxKey==0 ) goto no_mem;
70300 assert( pIn3->flags & MEM_Blob );
70301 assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
70302 sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
70303 pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
70304 }
 
70305 if( pOp->opcode==OP_NoConflict ){
70306 /* For the OP_NoConflict opcode, take the jump if any of the
70307 ** input fields are NULL, since any key with a NULL will not
70308 ** conflict */
70309 for(ii=0; ii<r.nField; ii++){
@@ -71188,11 +71662,11 @@
71188 pCrsr = pC->pCursor;
71189 assert( pCrsr!=0 );
71190 assert( pOp->p5==0 );
71191 r.pKeyInfo = pC->pKeyInfo;
71192 r.nField = (u16)pOp->p3;
71193 r.flags = UNPACKED_PREFIX_MATCH;
71194 r.aMem = &aMem[pOp->p2];
71195 #ifdef SQLITE_DEBUG
71196 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
71197 #endif
71198 rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
@@ -71302,14 +71776,14 @@
71302 assert( pOp->p4type==P4_INT32 );
71303 r.pKeyInfo = pC->pKeyInfo;
71304 r.nField = (u16)pOp->p4.i;
71305 if( pOp->opcode<OP_IdxLT ){
71306 assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
71307 r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
71308 }else{
71309 assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
71310 r.flags = UNPACKED_PREFIX_MATCH;
71311 }
71312 r.aMem = &aMem[pOp->p3];
71313 #ifdef SQLITE_DEBUG
71314 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
71315 #endif
@@ -72056,11 +72530,10 @@
72056 assert( apVal || n==0 );
72057 for(i=0; i<n; i++, pRec++){
72058 assert( memIsValid(pRec) );
72059 apVal[i] = pRec;
72060 memAboutToChange(p, pRec);
72061 sqlite3VdbeMemStoreType(pRec);
72062 }
72063 ctx.pFunc = pOp->p4.pFunc;
72064 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
72065 ctx.pMem = pMem = &aMem[pOp->p3];
72066 pMem->n++;
@@ -72490,11 +72963,10 @@
72490 {
72491 res = 0;
72492 apArg = p->apArg;
72493 for(i = 0; i<nArg; i++){
72494 apArg[i] = &pArgc[i+1];
72495 sqlite3VdbeMemStoreType(apArg[i]);
72496 }
72497
72498 p->inVtabMethod = 1;
72499 rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
72500 p->inVtabMethod = 0;
@@ -72697,11 +73169,10 @@
72697 apArg = p->apArg;
72698 pX = &aMem[pOp->p3];
72699 for(i=0; i<nArg; i++){
72700 assert( memIsValid(pX) );
72701 memAboutToChange(p, pX);
72702 sqlite3VdbeMemStoreType(pX);
72703 apArg[i] = pX;
72704 pX++;
72705 }
72706 db->vtabOnConflict = pOp->p5;
72707 rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
@@ -73809,14 +74280,14 @@
73809 if( r2->aMem[i].flags & MEM_Null ){
73810 *pRes = -1;
73811 return;
73812 }
73813 }
73814 r2->flags |= UNPACKED_PREFIX_MATCH;
73815 }
73816
73817 *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
73818 }
73819
73820 /*
73821 ** This function is called to compare two iterator keys when merging
73822 ** multiple b-tree segments. Parameter iOut is the index of the aTree[]
@@ -75449,10 +75920,12 @@
75449 pExpr->iTable = 1;
75450 pTab = pParse->pTriggerTab;
75451 }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
75452 pExpr->iTable = 0;
75453 pTab = pParse->pTriggerTab;
 
 
75454 }
75455
75456 if( pTab ){
75457 int iCol;
75458 pSchema = pTab->pSchema;
@@ -87719,11 +88192,11 @@
87719 assert( nExtra>=1 );
87720 assert( pSrc!=0 );
87721 assert( iStart<=pSrc->nSrc );
87722
87723 /* Allocate additional space if needed */
87724 if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
87725 SrcList *pNew;
87726 int nAlloc = pSrc->nSrc+nExtra;
87727 int nGot;
87728 pNew = sqlite3DbRealloc(db, pSrc,
87729 sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
@@ -87731,19 +88204,19 @@
87731 assert( db->mallocFailed );
87732 return pSrc;
87733 }
87734 pSrc = pNew;
87735 nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
87736 pSrc->nAlloc = (u8)nGot;
87737 }
87738
87739 /* Move existing slots that come after the newly inserted slots
87740 ** out of the way */
87741 for(i=pSrc->nSrc-1; i>=iStart; i--){
87742 pSrc->a[i+nExtra] = pSrc->a[i];
87743 }
87744 pSrc->nSrc += (i8)nExtra;
87745
87746 /* Zero the newly allocated slots */
87747 memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
87748 for(i=iStart; i<iStart+nExtra; i++){
87749 pSrc->a[i].iCursor = -1;
@@ -100117,11 +100590,11 @@
100117 }else if( eDest!=SRT_Exists ){
100118 /* If the destination is an EXISTS(...) expression, the actual
100119 ** values returned by the SELECT are not required.
100120 */
100121 sqlite3ExprCodeExprList(pParse, pEList, regResult,
100122 (eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
100123 }
100124
100125 /* If the DISTINCT keyword was present on the SELECT statement
100126 ** and this row has been seen before, then do not make this row
100127 ** part of the result.
@@ -101030,11 +101503,11 @@
101030 for(j=cnt=0; j<i; j++){
101031 if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
101032 char *zNewName;
101033 int k;
101034 for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
101035 if( zName[k]==':' ) nName = k;
101036 zName[nName] = 0;
101037 zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
101038 sqlite3DbFree(db, zName);
101039 zName = zNewName;
101040 j = -1;
@@ -110767,11 +111240,11 @@
110767 iCol = pRec->nField - 1;
110768 assert( pIdx->nSample>0 );
110769 assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
110770 do{
110771 iTest = (iMin+i)/2;
110772 res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
110773 if( res<0 ){
110774 iMin = iTest+1;
110775 }else{
110776 i = iTest;
110777 }
@@ -110782,20 +111255,20 @@
110782 ** above found the right answer. This block serves no purpose other
110783 ** than to invoke the asserts. */
110784 if( res==0 ){
110785 /* If (res==0) is true, then sample $i must be equal to pRec */
110786 assert( i<pIdx->nSample );
110787 assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
110788 || pParse->db->mallocFailed );
110789 }else{
110790 /* Otherwise, pRec must be smaller than sample $i and larger than
110791 ** sample ($i-1). */
110792 assert( i==pIdx->nSample
110793 || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
110794 || pParse->db->mallocFailed );
110795 assert( i==0
110796 || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
110797 || pParse->db->mallocFailed );
110798 }
110799 #endif /* ifdef SQLITE_DEBUG */
110800
110801 /* At this point, aSample[i] is the first sample that is greater than
@@ -114724,11 +115197,11 @@
114724
114725 /* For a co-routine, change all OP_Column references to the table of
114726 ** the co-routine into OP_SCopy of result contained in a register.
114727 ** OP_Rowid becomes OP_Null.
114728 */
114729 if( pTabItem->viaCoroutine ){
114730 last = sqlite3VdbeCurrentAddr(v);
114731 k = pLevel->addrBody;
114732 pOp = sqlite3VdbeGetOp(v, k);
114733 for(; k<last; k++, pOp++){
114734 if( pOp->p1!=pLevel->iTabCur ) continue;
114735
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -73,12 +73,45 @@
73 # define _FILE_OFFSET_BITS 64
74 # endif
75 # define _LARGEFILE_SOURCE 1
76 #endif
77
78 /*
79 ** For MinGW, check to see if we can include the header file containing its
80 ** version information, among other things. Normally, this internal MinGW
81 ** header file would [only] be included automatically by other MinGW header
82 ** files; however, the contained version information is now required by this
83 ** header file to work around binary compatibility issues (see below) and
84 ** this is the only known way to reliably obtain it. This entire #if block
85 ** would be completely unnecessary if there was any other way of detecting
86 ** MinGW via their preprocessor (e.g. if they customized their GCC to define
87 ** some MinGW-specific macros). When compiling for MinGW, either the
88 ** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
89 ** defined; otherwise, detection of conditions specific to MinGW will be
90 ** disabled.
91 */
92 #if defined(_HAVE_MINGW_H)
93 # include "mingw.h"
94 #elif defined(_HAVE__MINGW_H)
95 # include "_mingw.h"
96 #endif
97
98 /*
99 ** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
100 ** define is required to maintain binary compatibility with the MSVC runtime
101 ** library in use (e.g. for Windows XP).
102 */
103 #if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
104 defined(_WIN32) && !defined(_WIN64) && \
105 defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
106 defined(__MSVCRT__)
107 # define _USE_32BIT_TIME_T
108 #endif
109
110 /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
111 ** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
112 ** MinGW.
113 */
114 /************** Include sqlite3.h in the middle of sqliteInt.h ***************/
115 /************** Begin file sqlite3.h *****************************************/
116 /*
117 ** 2001 September 15
@@ -189,11 +222,11 @@
222 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
223 ** [sqlite_version()] and [sqlite_source_id()].
224 */
225 #define SQLITE_VERSION "3.8.4"
226 #define SQLITE_VERSION_NUMBER 3008004
227 #define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042"
228
229 /*
230 ** CAPI3REF: Run-Time Library Version Numbers
231 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
232 **
@@ -9334,12 +9367,15 @@
9367 #ifndef SQLITE_OMIT_TRACE
9368 SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
9369 #endif
9370
9371 SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
9372 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
9373 SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
9374
9375 typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
9376 SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
9377
9378 #ifndef SQLITE_OMIT_TRIGGER
9379 SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
9380 #endif
9381
@@ -10950,23 +10986,23 @@
10986 ** the OP_MakeRecord opcode of the VDBE and is disassembled by the
10987 ** OP_Column opcode.
10988 **
10989 ** This structure holds a record that has already been disassembled
10990 ** into its constituent fields.
10991 **
10992 ** The r1 and r2 member variables are only used by the optimized comparison
10993 ** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
10994 */
10995 struct UnpackedRecord {
10996 KeyInfo *pKeyInfo; /* Collation and sort-order information */
10997 u16 nField; /* Number of entries in apMem[] */
10998 i8 default_rc; /* Comparison result if keys are equal */
10999 Mem *aMem; /* Values */
11000 int r1; /* Value to return if (lhs > rhs) */
11001 int r2; /* Value to return if (rhs < lhs) */
11002 };
11003
 
 
 
 
 
11004
11005 /*
11006 ** Each SQL index is represented in memory by an
11007 ** instance of the following structure.
11008 **
@@ -11382,12 +11418,12 @@
11418 **
11419 ** In the colUsed field, the high-order bit (bit 63) is set if the table
11420 ** contains more than 63 columns and the 64-th or later column is used.
11421 */
11422 struct SrcList {
11423 int nSrc; /* Number of tables or subqueries in the FROM clause */
11424 u32 nAlloc; /* Number of entries allocated in a[] below */
11425 struct SrcList_item {
11426 Schema *pSchema; /* Schema to which this item is fixed */
11427 char *zDatabase; /* Name of database holding this table */
11428 char *zName; /* Name of the table */
11429 char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
@@ -13415,10 +13451,13 @@
13451 #ifdef SQLITE_OMIT_COMPLETE
13452 "OMIT_COMPLETE",
13453 #endif
13454 #ifdef SQLITE_OMIT_COMPOUND_SELECT
13455 "OMIT_COMPOUND_SELECT",
13456 #endif
13457 #ifdef SQLITE_OMIT_CTE
13458 "OMIT_CTE",
13459 #endif
13460 #ifdef SQLITE_OMIT_DATETIME_FUNCS
13461 "OMIT_DATETIME_FUNCS",
13462 #endif
13463 #ifdef SQLITE_OMIT_DECLTYPE
@@ -13800,11 +13839,10 @@
13839 RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
13840 VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
13841 } u;
13842 int n; /* Number of characters in string value, excluding '\0' */
13843 u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
 
13844 u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
13845 #ifdef SQLITE_DEBUG
13846 Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
13847 void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
13848 #endif
@@ -13827,10 +13865,11 @@
13865 #define MEM_Null 0x0001 /* Value is NULL */
13866 #define MEM_Str 0x0002 /* Value is a string */
13867 #define MEM_Int 0x0004 /* Value is an integer */
13868 #define MEM_Real 0x0008 /* Value is a real number */
13869 #define MEM_Blob 0x0010 /* Value is a BLOB */
13870 #define MEM_AffMask 0x001f /* Mask of affinity bits */
13871 #define MEM_RowSet 0x0020 /* Value is a RowSet object */
13872 #define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
13873 #define MEM_Undefined 0x0080 /* Value is undefined */
13874 #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
13875 #define MEM_TypeMask 0x01ff /* Mask of type bits */
@@ -13840,11 +13879,11 @@
13879 ** the following flags must be set to determine the memory management
13880 ** policy for Mem.z. The MEM_Term flag tells us whether or not the
13881 ** string is \000 or \u0000 terminated
13882 */
13883 #define MEM_Term 0x0200 /* String rep is nul terminated */
13884 #define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
13885 #define MEM_Static 0x0800 /* Mem.z points to a static string */
13886 #define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
13887 #define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
13888 #define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
13889 #ifdef SQLITE_OMIT_INCRBLOB
@@ -14023,11 +14062,11 @@
14062 SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
14063 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
14064 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
14065
14066 int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
14067 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
14068 SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
14069 SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
14070 SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
14071 SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
14072 SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -14066,12 +14105,10 @@
14105 SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
14106 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
14107 SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
14108 SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
14109 SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
 
 
14110 SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
14111
14112 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
14113 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
14114 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -14088,10 +14125,11 @@
14125 # define sqlite3VdbeLeave(X)
14126 #endif
14127
14128 #ifdef SQLITE_DEBUG
14129 SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
14130 SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
14131 #endif
14132
14133 #ifndef SQLITE_OMIT_FOREIGN_KEY
14134 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
14135 #else
@@ -21471,11 +21509,11 @@
21509 assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
21510
21511 sqlite3VdbeMemRelease(pMem);
21512 pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
21513 pMem->enc = desiredEnc;
21514 pMem->flags |= (MEM_Term);
21515 pMem->z = (char*)zOut;
21516 pMem->zMalloc = pMem->z;
21517
21518 translate_out:
21519 #if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
@@ -21599,11 +21637,10 @@
21637 sqlite3VdbeMemRelease(&m);
21638 m.z = 0;
21639 }
21640 assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
21641 assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
 
21642 assert( m.z || db->mallocFailed );
21643 return m.z;
21644 }
21645
21646 /*
@@ -55305,10 +55342,11 @@
55342 i64 intKey, /* The table key */
55343 int biasRight, /* If true, bias the search to the high end */
55344 int *pRes /* Write search results here */
55345 ){
55346 int rc;
55347 RecordCompare xRecordCompare;
55348
55349 assert( cursorHoldsMutex(pCur) );
55350 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
55351 assert( pRes );
55352 assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
@@ -55325,10 +55363,20 @@
55363 if( pCur->atLast && pCur->info.nKey<intKey ){
55364 *pRes = -1;
55365 return SQLITE_OK;
55366 }
55367 }
55368
55369 if( pIdxKey ){
55370 xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
55371 assert( pIdxKey->default_rc==1
55372 || pIdxKey->default_rc==0
55373 || pIdxKey->default_rc==-1
55374 );
55375 }else{
55376 xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */
55377 }
55378
55379 rc = moveToRoot(pCur);
55380 if( rc ){
55381 return rc;
55382 }
@@ -55358,11 +55406,11 @@
55406 lwr = 0;
55407 upr = pPage->nCell-1;
55408 assert( biasRight==0 || biasRight==1 );
55409 idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
55410 pCur->aiIdx[pCur->iPage] = (u16)idx;
55411 if( xRecordCompare==0 ){
55412 for(;;){
55413 i64 nCellKey;
55414 pCell = findCell(pPage, idx) + pPage->childPtrSize;
55415 if( pPage->hasData ){
55416 while( 0x80 <= *(pCell++) ){
@@ -55410,18 +55458,18 @@
55458 if( nCell<=pPage->max1bytePayload ){
55459 /* This branch runs if the record-size field of the cell is a
55460 ** single byte varint and the record fits entirely on the main
55461 ** b-tree page. */
55462 testcase( pCell+nCell+1==pPage->aDataEnd );
55463 c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
55464 }else if( !(pCell[1] & 0x80)
55465 && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
55466 ){
55467 /* The record-size field is a 2 byte varint and the record
55468 ** fits entirely on the main b-tree page. */
55469 testcase( pCell+nCell+2==pPage->aDataEnd );
55470 c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
55471 }else{
55472 /* The record flows over onto one or more overflow pages. In
55473 ** this case the whole cell needs to be parsed, a buffer allocated
55474 ** and accessPayload() used to retrieve the record into the
55475 ** buffer before VdbeRecordCompare() can be called. */
@@ -55438,11 +55486,11 @@
55486 rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
55487 if( rc ){
55488 sqlite3_free(pCellKey);
55489 goto moveto_finish;
55490 }
55491 c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
55492 sqlite3_free(pCellKey);
55493 }
55494 if( c<0 ){
55495 lwr = idx+1;
55496 }else if( c>0 ){
@@ -60001,10 +60049,46 @@
60049 ** This file contains code use to manipulate "Mem" structure. A "Mem"
60050 ** stores a single value in the VDBE. Mem is an opaque structure visible
60051 ** only within the VDBE. Interface routines refer to a Mem using the
60052 ** name sqlite_value
60053 */
60054
60055 #ifdef SQLITE_DEBUG
60056 /*
60057 ** Check invariants on a Mem object.
60058 **
60059 ** This routine is intended for use inside of assert() statements, like
60060 ** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
60061 */
60062 SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
60063 /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
60064 ** function for Mem.z
60065 */
60066 assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
60067 assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
60068
60069 /* If p holds a string or blob, the Mem.z must point to exactly
60070 ** one of the following:
60071 **
60072 ** (1) Memory in Mem.zMalloc and managed by the Mem object
60073 ** (2) Memory to be freed using Mem.xDel
60074 ** (3) An ephermal string or blob
60075 ** (4) A static string or blob
60076 */
60077 if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
60078 assert(
60079 ((p->z==p->zMalloc)? 1 : 0) +
60080 ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
60081 ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
60082 ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
60083 );
60084 }
60085
60086 return 1;
60087 }
60088 #endif
60089
60090
60091 /*
60092 ** If pMem is an object with a valid string representation, this routine
60093 ** ensures the internal encoding for the string representation is
60094 ** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
@@ -60051,16 +60135,11 @@
60135 ** pMem->z into the new allocation. pMem must be either a string or
60136 ** blob if bPreserve is true. If bPreserve is false, any prior content
60137 ** in pMem->z is discarded.
60138 */
60139 SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
60140 assert( sqlite3VdbeCheckMemInvariants(pMem) );
 
 
 
 
 
60141 assert( (pMem->flags&MEM_RowSet)==0 );
60142
60143 /* If the bPreserve flag is set to true, then the memory cell must already
60144 ** contain a valid string or blob value. */
60145 assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
@@ -60074,26 +60153,27 @@
60153 }else{
60154 sqlite3DbFree(pMem->db, pMem->zMalloc);
60155 pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
60156 }
60157 if( pMem->zMalloc==0 ){
60158 VdbeMemRelease(pMem);
60159 pMem->z = 0;
60160 pMem->flags = MEM_Null;
60161 return SQLITE_NOMEM;
60162 }
60163 }
60164
60165 if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
60166 memcpy(pMem->zMalloc, pMem->z, pMem->n);
60167 }
60168 if( (pMem->flags&MEM_Dyn)!=0 ){
60169 assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
60170 pMem->xDel((void *)(pMem->z));
60171 }
60172
60173 pMem->z = pMem->zMalloc;
60174 pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
60175 pMem->xDel = 0;
60176 return SQLITE_OK;
60177 }
60178
60179 /*
@@ -60258,13 +60338,13 @@
60338 assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
60339 if( p->flags&MEM_Agg ){
60340 sqlite3VdbeMemFinalize(p, p->u.pDef);
60341 assert( (p->flags & MEM_Agg)==0 );
60342 sqlite3VdbeMemRelease(p);
60343 }else if( p->flags&MEM_Dyn ){
60344 assert( (p->flags&MEM_RowSet)==0 );
60345 assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
60346 p->xDel((void *)p->z);
60347 p->xDel = 0;
60348 }else if( p->flags&MEM_RowSet ){
60349 sqlite3RowSetClear(p->u.pRowSet);
60350 }else if( p->flags&MEM_Frame ){
@@ -60273,13 +60353,14 @@
60353 }
60354
60355 /*
60356 ** Release any memory held by the Mem. This may leave the Mem in an
60357 ** inconsistent state, for example with (Mem.z==0) and
60358 ** (Mem.flags==MEM_Str).
60359 */
60360 SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
60361 assert( sqlite3VdbeCheckMemInvariants(p) );
60362 VdbeMemRelease(p);
60363 if( p->zMalloc ){
60364 sqlite3DbFree(p->db, p->zMalloc);
60365 p->zMalloc = 0;
60366 }
@@ -60464,11 +60545,10 @@
60545 }
60546 if( pMem->flags & MEM_RowSet ){
60547 sqlite3RowSetClear(pMem->u.pRowSet);
60548 }
60549 MemSetTypeFlag(pMem, MEM_Null);
 
60550 }
60551 SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
60552 sqlite3VdbeMemSetNull((Mem*)p);
60553 }
60554
@@ -60477,11 +60557,10 @@
60557 ** n containing all zeros.
60558 */
60559 SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
60560 sqlite3VdbeMemRelease(pMem);
60561 pMem->flags = MEM_Blob|MEM_Zero;
 
60562 pMem->n = 0;
60563 if( n<0 ) n = 0;
60564 pMem->u.nZero = n;
60565 pMem->enc = SQLITE_UTF8;
60566
@@ -60500,11 +60579,10 @@
60579 */
60580 SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
60581 sqlite3VdbeMemRelease(pMem);
60582 pMem->u.i = val;
60583 pMem->flags = MEM_Int;
 
60584 }
60585
60586 #ifndef SQLITE_OMIT_FLOATING_POINT
60587 /*
60588 ** Delete any previous value and set the value stored in *pMem to val,
@@ -60515,11 +60593,10 @@
60593 sqlite3VdbeMemSetNull(pMem);
60594 }else{
60595 sqlite3VdbeMemRelease(pMem);
60596 pMem->r = val;
60597 pMem->flags = MEM_Real;
 
60598 }
60599 }
60600 #endif
60601
60602 /*
@@ -60613,10 +60690,11 @@
60690
60691 assert( (pFrom->flags & MEM_RowSet)==0 );
60692 VdbeMemRelease(pTo);
60693 memcpy(pTo, pFrom, MEMCELLSIZE);
60694 pTo->flags &= ~MEM_Dyn;
60695 pTo->xDel = 0;
60696
60697 if( pTo->flags&(MEM_Str|MEM_Blob) ){
60698 if( 0==(pFrom->flags&MEM_Static) ){
60699 pTo->flags |= MEM_Ephem;
60700 rc = sqlite3VdbeMemMakeWriteable(pTo);
@@ -60723,11 +60801,10 @@
60801 }
60802
60803 pMem->n = nByte;
60804 pMem->flags = flags;
60805 pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
 
60806
60807 #ifndef SQLITE_OMIT_UTF16
60808 if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
60809 return SQLITE_NOMEM;
60810 }
@@ -60738,123 +60815,10 @@
60815 }
60816
60817 return SQLITE_OK;
60818 }
60819
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60820 /*
60821 ** Move data out of a btree key or data field and into a Mem structure.
60822 ** The data or key is taken from the entry that pCur is currently pointing
60823 ** to. offset and amt determine what portion of the data or key to retrieve.
60824 ** key is true to get the key or false to get data. The result is written
@@ -60891,26 +60855,26 @@
60855
60856 if( offset+amt<=available ){
60857 sqlite3VdbeMemRelease(pMem);
60858 pMem->z = &zData[offset];
60859 pMem->flags = MEM_Blob|MEM_Ephem;
60860 pMem->n = (int)amt;
60861 }else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
 
 
 
60862 if( key ){
60863 rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
60864 }else{
60865 rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
60866 }
60867 if( rc==SQLITE_OK ){
60868 pMem->z[amt] = 0;
60869 pMem->z[amt+1] = 0;
60870 pMem->flags = MEM_Blob|MEM_Term;
60871 pMem->n = (int)amt;
60872 }else{
60873 sqlite3VdbeMemRelease(pMem);
60874 }
60875 }
 
60876
60877 return rc;
60878 }
60879
60880 /* This function is only available internally, it is not part of the
@@ -60964,11 +60928,10 @@
60928 */
60929 SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
60930 Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
60931 if( p ){
60932 p->flags = MEM_Null;
 
60933 p->db = db;
60934 }
60935 return p;
60936 }
60937
@@ -61010,15 +60973,13 @@
60973 if( pRec ){
60974 pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
60975 if( pRec->pKeyInfo ){
60976 assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
60977 assert( pRec->pKeyInfo->enc==ENC(db) );
 
60978 pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
60979 for(i=0; i<nCol; i++){
60980 pRec->aMem[i].flags = MEM_Null;
 
60981 pRec->aMem[i].db = db;
60982 }
60983 }else{
60984 sqlite3DbFree(db, pRec);
60985 pRec = 0;
@@ -61087,11 +61048,10 @@
61048 sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
61049 }else{
61050 zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
61051 if( zVal==0 ) goto no_mem;
61052 sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
 
61053 }
61054 if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
61055 sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
61056 }else{
61057 sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
@@ -61105,13 +61065,13 @@
61065 if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
61066 && pVal!=0
61067 ){
61068 sqlite3VdbeMemNumerify(pVal);
61069 if( pVal->u.i==SMALLEST_INT64 ){
61070 pVal->flags &= ~MEM_Int;
61071 pVal->flags |= MEM_Real;
61072 pVal->r = (double)SMALLEST_INT64;
61073 }else{
61074 pVal->u.i = -pVal->u.i;
61075 }
61076 pVal->r = -pVal->r;
61077 sqlite3ValueApplyAffinity(pVal, affinity, enc);
@@ -61133,13 +61093,10 @@
61093 sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
61094 0, SQLITE_DYNAMIC);
61095 }
61096 #endif
61097
 
 
 
61098 *ppVal = pVal;
61099 return rc;
61100
61101 no_mem:
61102 db->mallocFailed = 1;
@@ -61299,11 +61256,10 @@
61256 rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
61257 if( rc==SQLITE_OK ){
61258 sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
61259 }
61260 pVal->db = pParse->db;
 
61261 }
61262 }
61263 }else{
61264 rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
61265 }
@@ -62591,10 +62547,11 @@
62547 }
62548 return;
62549 }
62550 for(pEnd=&p[N]; p<pEnd; p++){
62551 assert( (&p[1])==pEnd || p[0].db==p[1].db );
62552 assert( sqlite3VdbeCheckMemInvariants(p) );
62553
62554 /* This block is really an inlined version of sqlite3VdbeMemRelease()
62555 ** that takes advantage of the fact that the memory cell value is
62556 ** being set to NULL after releasing any dynamic resources.
62557 **
@@ -62733,19 +62690,17 @@
62690 }
62691 pOp = &apSub[j]->aOp[i];
62692 }
62693 if( p->explain==1 ){
62694 pMem->flags = MEM_Int;
 
62695 pMem->u.i = i; /* Program counter */
62696 pMem++;
62697
62698 pMem->flags = MEM_Static|MEM_Str|MEM_Term;
62699 pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
62700 assert( pMem->z!=0 );
62701 pMem->n = sqlite3Strlen30(pMem->z);
 
62702 pMem->enc = SQLITE_UTF8;
62703 pMem++;
62704
62705 /* When an OP_Program opcode is encounter (the only opcode that has
62706 ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
@@ -62767,63 +62722,56 @@
62722 }
62723 }
62724
62725 pMem->flags = MEM_Int;
62726 pMem->u.i = pOp->p1; /* P1 */
 
62727 pMem++;
62728
62729 pMem->flags = MEM_Int;
62730 pMem->u.i = pOp->p2; /* P2 */
 
62731 pMem++;
62732
62733 pMem->flags = MEM_Int;
62734 pMem->u.i = pOp->p3; /* P3 */
 
62735 pMem++;
62736
62737 if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
62738 assert( p->db->mallocFailed );
62739 return SQLITE_ERROR;
62740 }
62741 pMem->flags = MEM_Str|MEM_Term;
62742 zP4 = displayP4(pOp, pMem->z, 32);
62743 if( zP4!=pMem->z ){
62744 sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
62745 }else{
62746 assert( pMem->z!=0 );
62747 pMem->n = sqlite3Strlen30(pMem->z);
62748 pMem->enc = SQLITE_UTF8;
62749 }
 
62750 pMem++;
62751
62752 if( p->explain==1 ){
62753 if( sqlite3VdbeMemGrow(pMem, 4, 0) ){
62754 assert( p->db->mallocFailed );
62755 return SQLITE_ERROR;
62756 }
62757 pMem->flags = MEM_Str|MEM_Term;
62758 pMem->n = 2;
62759 sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
 
62760 pMem->enc = SQLITE_UTF8;
62761 pMem++;
62762
62763 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
62764 if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
62765 assert( p->db->mallocFailed );
62766 return SQLITE_ERROR;
62767 }
62768 pMem->flags = MEM_Str|MEM_Term;
62769 pMem->n = displayComment(pOp, zP4, pMem->z, 500);
 
62770 pMem->enc = SQLITE_UTF8;
62771 #else
62772 pMem->flags = MEM_Null; /* Comment */
 
62773 #endif
62774 }
62775
62776 p->nResColumn = 8 - 4*(p->explain-1);
62777 p->pResultSet = &p->aMem[1];
@@ -64312,10 +64260,18 @@
64260
64261 /* NULL or constants 0 or 1 */
64262 return 0;
64263 }
64264
64265 /* Input "x" is a sequence of unsigned characters that represent a
64266 ** big-endian integer. Return the equivalent native integer
64267 */
64268 #define ONE_BYTE_INT(x) ((i8)(x)[0])
64269 #define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
64270 #define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
64271 #define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
64272
64273 /*
64274 ** Deserialize the data blob pointed to by buf as serial type serial_type
64275 ** and store the result in pMem. Return the number of bytes read.
64276 */
64277 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
@@ -64323,46 +64279,40 @@
64279 u32 serial_type, /* Serial type to deserialize */
64280 Mem *pMem /* Memory cell to write value into */
64281 ){
64282 u64 x;
64283 u32 y;
 
64284 switch( serial_type ){
64285 case 10: /* Reserved for future use */
64286 case 11: /* Reserved for future use */
64287 case 0: { /* NULL */
64288 pMem->flags = MEM_Null;
64289 break;
64290 }
64291 case 1: { /* 1-byte signed integer */
64292 pMem->u.i = ONE_BYTE_INT(buf);
64293 pMem->flags = MEM_Int;
64294 return 1;
64295 }
64296 case 2: { /* 2-byte signed integer */
64297 pMem->u.i = TWO_BYTE_INT(buf);
 
64298 pMem->flags = MEM_Int;
64299 return 2;
64300 }
64301 case 3: { /* 3-byte signed integer */
64302 pMem->u.i = THREE_BYTE_INT(buf);
 
64303 pMem->flags = MEM_Int;
64304 return 3;
64305 }
64306 case 4: { /* 4-byte signed integer */
64307 y = FOUR_BYTE_UINT(buf);
64308 pMem->u.i = (i64)*(int*)&y;
64309 pMem->flags = MEM_Int;
64310 return 4;
64311 }
64312 case 5: { /* 6-byte signed integer */
64313 pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
 
 
 
64314 pMem->flags = MEM_Int;
64315 return 6;
64316 }
64317 case 6: /* 8-byte signed integer */
64318 case 7: { /* IEEE floating point */
@@ -64376,12 +64326,12 @@
64326 static const double r1 = 1.0;
64327 u64 t2 = t1;
64328 swapMixedEndianFloat(t2);
64329 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64330 #endif
64331 x = FOUR_BYTE_UINT(buf);
64332 y = FOUR_BYTE_UINT(buf+4);
64333 x = (x<<32) | y;
64334 if( serial_type==6 ){
64335 pMem->u.i = *(i64*)&x;
64336 pMem->flags = MEM_Int;
64337 }else{
@@ -64473,11 +64423,11 @@
64423 u32 idx; /* Offset in aKey[] to read from */
64424 u16 u; /* Unsigned loop counter */
64425 u32 szHdr;
64426 Mem *pMem = p->aMem;
64427
64428 p->default_rc = 0;
64429 assert( EIGHT_BYTE_ALIGNMENT(pMem) );
64430 idx = getVarint32(aKey, szHdr);
64431 d = szHdr;
64432 u = 0;
64433 while( idx<szHdr && u<p->nField && d<=nKey ){
@@ -64494,30 +64444,22 @@
64444 }
64445 assert( u<=pKeyInfo->nField + 1 );
64446 p->nField = u;
64447 }
64448
64449 #if SQLITE_DEBUG
64450 /*
64451 ** This function compares two index or table record keys in the same way
64452 ** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
64453 ** this function deserializes and compares values using the
64454 ** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
64455 ** in assert() statements to ensure that the optimized code in
64456 ** sqlite3VdbeRecordCompare() returns results with these two primitives.
 
 
 
 
 
 
 
 
 
64457 */
64458 static int vdbeRecordCompareDebug(
64459 int nKey1, const void *pKey1, /* Left key */
64460 const UnpackedRecord *pPKey2 /* Right key */
64461 ){
64462 u32 d1; /* Offset into aKey[] of next data element */
64463 u32 idx1; /* Offset into aKey[] of next header element */
64464 u32 szHdr1; /* Number of bytes in header */
64465 int i = 0;
@@ -64587,28 +64529,559 @@
64529 ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
64530 */
64531 assert( mem1.zMalloc==0 );
64532
64533 /* rc==0 here means that one of the keys ran out of fields and
64534 ** all the fields up to that point were equal. Return the the default_rc
64535 ** value. */
64536 return pPKey2->default_rc;
64537 }
64538 #endif
64539
64540 /*
64541 ** Both *pMem1 and *pMem2 contain string values. Compare the two values
64542 ** using the collation sequence pColl. As usual, return a negative , zero
64543 ** or positive value if *pMem1 is less than, equal to or greater than
64544 ** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
64545 */
64546 static int vdbeCompareMemString(
64547 const Mem *pMem1,
64548 const Mem *pMem2,
64549 const CollSeq *pColl
64550 ){
64551 if( pMem1->enc==pColl->enc ){
64552 /* The strings are already in the correct encoding. Call the
64553 ** comparison function directly */
64554 return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
64555 }else{
64556 int rc;
64557 const void *v1, *v2;
64558 int n1, n2;
64559 Mem c1;
64560 Mem c2;
64561 memset(&c1, 0, sizeof(c1));
64562 memset(&c2, 0, sizeof(c2));
64563 sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
64564 sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
64565 v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
64566 n1 = v1==0 ? 0 : c1.n;
64567 v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
64568 n2 = v2==0 ? 0 : c2.n;
64569 rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
64570 sqlite3VdbeMemRelease(&c1);
64571 sqlite3VdbeMemRelease(&c2);
64572 return rc;
64573 }
64574 }
64575
64576 /*
64577 ** Compare the values contained by the two memory cells, returning
64578 ** negative, zero or positive if pMem1 is less than, equal to, or greater
64579 ** than pMem2. Sorting order is NULL's first, followed by numbers (integers
64580 ** and reals) sorted numerically, followed by text ordered by the collating
64581 ** sequence pColl and finally blob's ordered by memcmp().
64582 **
64583 ** Two NULL values are considered equal by this function.
64584 */
64585 SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
64586 int rc;
64587 int f1, f2;
64588 int combined_flags;
64589
64590 f1 = pMem1->flags;
64591 f2 = pMem2->flags;
64592 combined_flags = f1|f2;
64593 assert( (combined_flags & MEM_RowSet)==0 );
64594
64595 /* If one value is NULL, it is less than the other. If both values
64596 ** are NULL, return 0.
64597 */
64598 if( combined_flags&MEM_Null ){
64599 return (f2&MEM_Null) - (f1&MEM_Null);
64600 }
64601
64602 /* If one value is a number and the other is not, the number is less.
64603 ** If both are numbers, compare as reals if one is a real, or as integers
64604 ** if both values are integers.
64605 */
64606 if( combined_flags&(MEM_Int|MEM_Real) ){
64607 double r1, r2;
64608 if( (f1 & f2 & MEM_Int)!=0 ){
64609 if( pMem1->u.i < pMem2->u.i ) return -1;
64610 if( pMem1->u.i > pMem2->u.i ) return 1;
64611 return 0;
64612 }
64613 if( (f1&MEM_Real)!=0 ){
64614 r1 = pMem1->r;
64615 }else if( (f1&MEM_Int)!=0 ){
64616 r1 = (double)pMem1->u.i;
64617 }else{
64618 return 1;
64619 }
64620 if( (f2&MEM_Real)!=0 ){
64621 r2 = pMem2->r;
64622 }else if( (f2&MEM_Int)!=0 ){
64623 r2 = (double)pMem2->u.i;
64624 }else{
64625 return -1;
64626 }
64627 if( r1<r2 ) return -1;
64628 if( r1>r2 ) return 1;
64629 return 0;
64630 }
64631
64632 /* If one value is a string and the other is a blob, the string is less.
64633 ** If both are strings, compare using the collating functions.
64634 */
64635 if( combined_flags&MEM_Str ){
64636 if( (f1 & MEM_Str)==0 ){
64637 return 1;
64638 }
64639 if( (f2 & MEM_Str)==0 ){
64640 return -1;
64641 }
64642
64643 assert( pMem1->enc==pMem2->enc );
64644 assert( pMem1->enc==SQLITE_UTF8 ||
64645 pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
64646
64647 /* The collation sequence must be defined at this point, even if
64648 ** the user deletes the collation sequence after the vdbe program is
64649 ** compiled (this was not always the case).
64650 */
64651 assert( !pColl || pColl->xCmp );
64652
64653 if( pColl ){
64654 return vdbeCompareMemString(pMem1, pMem2, pColl);
64655 }
64656 /* If a NULL pointer was passed as the collate function, fall through
64657 ** to the blob case and use memcmp(). */
64658 }
64659
64660 /* Both values must be blobs. Compare using memcmp(). */
64661 rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
64662 if( rc==0 ){
64663 rc = pMem1->n - pMem2->n;
64664 }
64665 return rc;
64666 }
64667
64668
64669 /*
64670 ** The first argument passed to this function is a serial-type that
64671 ** corresponds to an integer - all values between 1 and 9 inclusive
64672 ** except 7. The second points to a buffer containing an integer value
64673 ** serialized according to serial_type. This function deserializes
64674 ** and returns the value.
64675 */
64676 static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
64677 u32 y;
64678 assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
64679 switch( serial_type ){
64680 case 0:
64681 case 1:
64682 return ONE_BYTE_INT(aKey);
64683 case 2:
64684 return TWO_BYTE_INT(aKey);
64685 case 3:
64686 return THREE_BYTE_INT(aKey);
64687 case 4: {
64688 y = FOUR_BYTE_UINT(aKey);
64689 return (i64)*(int*)&y;
64690 }
64691 case 5: {
64692 return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
64693 }
64694 case 6: {
64695 u64 x = FOUR_BYTE_UINT(aKey);
64696 x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
64697 return (i64)*(i64*)&x;
64698 }
64699 }
64700
64701 return (serial_type - 8);
64702 }
64703
64704 /*
64705 ** This function compares the two table rows or index records
64706 ** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
64707 ** or positive integer if key1 is less than, equal to or
64708 ** greater than key2. The {nKey1, pKey1} key must be a blob
64709 ** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
64710 ** key must be a parsed key such as obtained from
64711 ** sqlite3VdbeParseRecord.
64712 **
64713 ** If argument bSkip is non-zero, it is assumed that the caller has already
64714 ** determined that the first fields of the keys are equal.
64715 **
64716 ** Key1 and Key2 do not have to contain the same number of fields. If all
64717 ** fields that appear in both keys are equal, then pPKey2->default_rc is
64718 ** returned.
64719 */
64720 SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
64721 int nKey1, const void *pKey1, /* Left key */
64722 const UnpackedRecord *pPKey2, /* Right key */
64723 int bSkip /* If true, skip the first field */
64724 ){
64725 u32 d1; /* Offset into aKey[] of next data element */
64726 int i; /* Index of next field to compare */
64727 u32 szHdr1; /* Size of record header in bytes */
64728 u32 idx1; /* Offset of first type in header */
64729 int rc = 0; /* Return value */
64730 Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
64731 KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
64732 const unsigned char *aKey1 = (const unsigned char *)pKey1;
64733 Mem mem1;
64734
64735 /* If bSkip is true, then the caller has already determined that the first
64736 ** two elements in the keys are equal. Fix the various stack variables so
64737 ** that this routine begins comparing at the second field. */
64738 if( bSkip ){
64739 u32 s1;
64740 idx1 = 1 + getVarint32(&aKey1[1], s1);
64741 szHdr1 = aKey1[0];
64742 d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
64743 i = 1;
64744 pRhs++;
64745 }else{
64746 idx1 = getVarint32(aKey1, szHdr1);
64747 d1 = szHdr1;
64748 i = 0;
64749 }
64750
64751 VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
64752 assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
64753 || CORRUPT_DB );
64754 assert( pPKey2->pKeyInfo->aSortOrder!=0 );
64755 assert( pPKey2->pKeyInfo->nField>0 );
64756 assert( idx1<=szHdr1 || CORRUPT_DB );
64757 do{
64758 u32 serial_type;
64759
64760 /* RHS is an integer */
64761 if( pRhs->flags & MEM_Int ){
64762 serial_type = aKey1[idx1];
64763 if( serial_type>=12 ){
64764 rc = +1;
64765 }else if( serial_type==0 ){
64766 rc = -1;
64767 }else if( serial_type==7 ){
64768 double rhs = (double)pRhs->u.i;
64769 sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
64770 if( mem1.r<rhs ){
64771 rc = -1;
64772 }else if( mem1.r>rhs ){
64773 rc = +1;
64774 }
64775 }else{
64776 i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
64777 i64 rhs = pRhs->u.i;
64778 if( lhs<rhs ){
64779 rc = -1;
64780 }else if( lhs>rhs ){
64781 rc = +1;
64782 }
64783 }
64784 }
64785
64786 /* RHS is real */
64787 else if( pRhs->flags & MEM_Real ){
64788 serial_type = aKey1[idx1];
64789 if( serial_type>=12 ){
64790 rc = +1;
64791 }else if( serial_type==0 ){
64792 rc = -1;
64793 }else{
64794 double rhs = pRhs->r;
64795 double lhs;
64796 sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
64797 if( serial_type==7 ){
64798 lhs = mem1.r;
64799 }else{
64800 lhs = (double)mem1.u.i;
64801 }
64802 if( lhs<rhs ){
64803 rc = -1;
64804 }else if( lhs>rhs ){
64805 rc = +1;
64806 }
64807 }
64808 }
64809
64810 /* RHS is a string */
64811 else if( pRhs->flags & MEM_Str ){
64812 getVarint32(&aKey1[idx1], serial_type);
64813 if( serial_type<12 ){
64814 rc = -1;
64815 }else if( !(serial_type & 0x01) ){
64816 rc = +1;
64817 }else{
64818 mem1.n = (serial_type - 12) / 2;
64819 if( (d1+mem1.n) > (unsigned)nKey1 ){
64820 rc = 1; /* Corruption */
64821 }else if( pKeyInfo->aColl[i] ){
64822 mem1.enc = pKeyInfo->enc;
64823 mem1.db = pKeyInfo->db;
64824 mem1.flags = MEM_Str;
64825 mem1.z = (char*)&aKey1[d1];
64826 rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
64827 }else{
64828 int nCmp = MIN(mem1.n, pRhs->n);
64829 rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
64830 if( rc==0 ) rc = mem1.n - pRhs->n;
64831 }
64832 }
64833 }
64834
64835 /* RHS is a blob */
64836 else if( pRhs->flags & MEM_Blob ){
64837 getVarint32(&aKey1[idx1], serial_type);
64838 if( serial_type<12 || (serial_type & 0x01) ){
64839 rc = -1;
64840 }else{
64841 int nStr = (serial_type - 12) / 2;
64842 if( (d1+nStr) > (unsigned)nKey1 ){
64843 rc = 1; /* Corruption */
64844 }else{
64845 int nCmp = MIN(nStr, pRhs->n);
64846 rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
64847 if( rc==0 ) rc = nStr - pRhs->n;
64848 }
64849 }
64850 }
64851
64852 /* RHS is null */
64853 else{
64854 serial_type = aKey1[idx1];
64855 rc = (serial_type!=0);
64856 }
64857
64858 if( rc!=0 ){
64859 if( pKeyInfo->aSortOrder[i] ){
64860 rc = -rc;
64861 }
64862 assert( CORRUPT_DB
64863 || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
64864 || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
64865 || pKeyInfo->db->mallocFailed
64866 );
64867 assert( mem1.zMalloc==0 ); /* See comment below */
64868 return rc;
64869 }
64870
64871 i++;
64872 pRhs++;
64873 d1 += sqlite3VdbeSerialTypeLen(serial_type);
64874 idx1 += sqlite3VarintLen(serial_type);
64875 }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
64876
64877 /* No memory allocation is ever used on mem1. Prove this using
64878 ** the following assert(). If the assert() fails, it indicates a
64879 ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
64880 assert( mem1.zMalloc==0 );
64881
64882 /* rc==0 here means that one or both of the keys ran out of fields and
64883 ** all the fields up to that point were equal. Return the the default_rc
64884 ** value. */
64885 assert( CORRUPT_DB
64886 || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
64887 );
64888 return pPKey2->default_rc;
64889 }
64890
64891 /*
64892 ** This function is an optimized version of sqlite3VdbeRecordCompare()
64893 ** that (a) the first field of pPKey2 is an integer, and (b) the
64894 ** size-of-header varint at the start of (pKey1/nKey1) fits in a single
64895 ** byte (i.e. is less than 128).
64896 */
64897 static int vdbeRecordCompareInt(
64898 int nKey1, const void *pKey1, /* Left key */
64899 const UnpackedRecord *pPKey2, /* Right key */
64900 int bSkip /* Ignored */
64901 ){
64902 const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
64903 int serial_type = ((const u8*)pKey1)[1];
64904 int res;
64905 u32 y;
64906 u64 x;
64907 i64 v = pPKey2->aMem[0].u.i;
64908 i64 lhs;
64909 UNUSED_PARAMETER(bSkip);
64910
64911 assert( bSkip==0 );
64912 switch( serial_type ){
64913 case 1: { /* 1-byte signed integer */
64914 lhs = ONE_BYTE_INT(aKey);
64915 break;
64916 }
64917 case 2: { /* 2-byte signed integer */
64918 lhs = TWO_BYTE_INT(aKey);
64919 break;
64920 }
64921 case 3: { /* 3-byte signed integer */
64922 lhs = THREE_BYTE_INT(aKey);
64923 break;
64924 }
64925 case 4: { /* 4-byte signed integer */
64926 y = FOUR_BYTE_UINT(aKey);
64927 lhs = (i64)*(int*)&y;
64928 break;
64929 }
64930 case 5: { /* 6-byte signed integer */
64931 lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
64932 break;
64933 }
64934 case 6: { /* 8-byte signed integer */
64935 x = FOUR_BYTE_UINT(aKey);
64936 x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
64937 lhs = *(i64*)&x;
64938 break;
64939 }
64940 case 8:
64941 lhs = 0;
64942 break;
64943 case 9:
64944 lhs = 1;
64945 break;
64946
64947 /* This case could be removed without changing the results of running
64948 ** this code. Including it causes gcc to generate a faster switch
64949 ** statement (since the range of switch targets now starts at zero and
64950 ** is contiguous) but does not cause any duplicate code to be generated
64951 ** (as gcc is clever enough to combine the two like cases). Other
64952 ** compilers might be similar. */
64953 case 0: case 7:
64954 return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
64955
64956 default:
64957 return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
64958 }
64959
64960 if( v>lhs ){
64961 res = pPKey2->r1;
64962 }else if( v<lhs ){
64963 res = pPKey2->r2;
64964 }else if( pPKey2->nField>1 ){
64965 /* The first fields of the two keys are equal. Compare the trailing
64966 ** fields. */
64967 res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
64968 }else{
64969 /* The first fields of the two keys are equal and there are no trailing
64970 ** fields. Return pPKey2->default_rc in this case. */
64971 res = pPKey2->default_rc;
64972 }
64973
64974 assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
64975 || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
64976 || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
64977 || CORRUPT_DB
64978 );
64979 return res;
64980 }
64981
64982 /*
64983 ** This function is an optimized version of sqlite3VdbeRecordCompare()
64984 ** that (a) the first field of pPKey2 is a string, that (b) the first field
64985 ** uses the collation sequence BINARY and (c) that the size-of-header varint
64986 ** at the start of (pKey1/nKey1) fits in a single byte.
64987 */
64988 static int vdbeRecordCompareString(
64989 int nKey1, const void *pKey1, /* Left key */
64990 const UnpackedRecord *pPKey2, /* Right key */
64991 int bSkip
64992 ){
64993 const u8 *aKey1 = (const u8*)pKey1;
64994 int serial_type;
64995 int res;
64996 UNUSED_PARAMETER(bSkip);
64997
64998 assert( bSkip==0 );
64999 getVarint32(&aKey1[1], serial_type);
65000
65001 if( serial_type<12 ){
65002 res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
65003 }else if( !(serial_type & 0x01) ){
65004 res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
65005 }else{
65006 int nCmp;
65007 int nStr;
65008 int szHdr = aKey1[0];
65009
65010 nStr = (serial_type-12) / 2;
65011 if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
65012 nCmp = MIN( pPKey2->aMem[0].n, nStr );
65013 res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
65014
65015 if( res==0 ){
65016 res = nStr - pPKey2->aMem[0].n;
65017 if( res==0 ){
65018 if( pPKey2->nField>1 ){
65019 res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
65020 }else{
65021 res = pPKey2->default_rc;
65022 }
65023 }else if( res>0 ){
65024 res = pPKey2->r2;
65025 }else{
65026 res = pPKey2->r1;
65027 }
65028 }else if( res>0 ){
65029 res = pPKey2->r2;
65030 }else{
65031 res = pPKey2->r1;
65032 }
65033 }
65034
65035 assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
65036 || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
65037 || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
65038 || CORRUPT_DB
65039 );
65040 return res;
65041 }
65042
65043 /*
65044 ** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
65045 ** suitable for comparing serialized records to the unpacked record passed
65046 ** as the only argument.
65047 */
65048 SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
65049 /* varintRecordCompareInt() and varintRecordCompareString() both assume
65050 ** that the size-of-header varint that occurs at the start of each record
65051 ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
65052 ** also assumes that it is safe to overread a buffer by at least the
65053 ** maximum possible legal header size plus 8 bytes. Because there is
65054 ** guaranteed to be at least 74 (but not 136) bytes of padding following each
65055 ** buffer passed to varintRecordCompareInt() this makes it convenient to
65056 ** limit the size of the header to 64 bytes in cases where the first field
65057 ** is an integer.
65058 **
65059 ** The easiest way to enforce this limit is to consider only records with
65060 ** 13 fields or less. If the first field is an integer, the maximum legal
65061 ** header size is (12*5 + 1 + 1) bytes. */
65062 if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
65063 int flags = p->aMem[0].flags;
65064 if( p->pKeyInfo->aSortOrder[0] ){
65065 p->r1 = 1;
65066 p->r2 = -1;
65067 }else{
65068 p->r1 = -1;
65069 p->r2 = 1;
65070 }
65071 if( (flags & MEM_Int) ){
65072 return vdbeRecordCompareInt;
65073 }
65074 if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0
65075 && p->pKeyInfo->aColl[0]==0
65076 ){
65077 return vdbeRecordCompareString;
65078 }
65079 }
65080
65081 return sqlite3VdbeRecordCompare;
65082 }
65083
65084 /*
65085 ** pCur points at an index entry created using the OP_MakeRecord opcode.
65086 ** Read the rowid (the last field in the record) and store it in *rowid.
65087 ** Return SQLITE_OK if everything works, or an error code otherwise.
@@ -64695,23 +65168,23 @@
65168 ** omits the rowid at the end. The rowid at the end of the index entry
65169 ** is ignored as well. Hence, this routine only compares the prefixes
65170 ** of the keys prior to the final rowid, not the entire key.
65171 */
65172 SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
65173 VdbeCursor *pC, /* The cursor to compare against */
65174 const UnpackedRecord *pUnpacked, /* Unpacked version of key */
65175 int *res /* Write the comparison result here */
65176 ){
65177 i64 nCellKey = 0;
65178 int rc;
65179 BtCursor *pCur = pC->pCursor;
65180 Mem m;
65181
65182 assert( sqlite3BtreeCursorIsValid(pCur) );
65183 VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
65184 assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
65185 /* nCellKey will always be between 0 and 0xffffffff because of the way
65186 ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
65187 if( nCellKey<=0 || nCellKey>0x7fffffff ){
65188 *res = 0;
65189 return SQLITE_CORRUPT_BKPT;
65190 }
@@ -64718,12 +65191,11 @@
65191 memset(&m, 0, sizeof(m));
65192 rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
65193 if( rc ){
65194 return rc;
65195 }
65196 *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
 
65197 sqlite3VdbeMemRelease(&m);
65198 return SQLITE_OK;
65199 }
65200
65201 /*
@@ -64783,11 +65255,10 @@
65255 if( 0==(pMem->flags & MEM_Null) ){
65256 sqlite3_value *pRet = sqlite3ValueNew(v->db);
65257 if( pRet ){
65258 sqlite3VdbeMemCopy((Mem *)pRet, pMem);
65259 sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
 
65260 }
65261 return pRet;
65262 }
65263 }
65264 return 0;
@@ -64957,11 +65428,10 @@
65428 */
65429 SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
65430 Mem *p = (Mem*)pVal;
65431 if( p->flags & (MEM_Blob|MEM_Str) ){
65432 sqlite3VdbeMemExpandBlob(p);
 
65433 p->flags |= MEM_Blob;
65434 return p->n ? p->z : 0;
65435 }else{
65436 return sqlite3_value_text(pVal);
65437 }
@@ -65028,11 +65498,11 @@
65498 SQLITE_INTEGER, /* 0x1c */
65499 SQLITE_NULL, /* 0x1d */
65500 SQLITE_INTEGER, /* 0x1e */
65501 SQLITE_NULL, /* 0x1f */
65502 };
65503 return aType[pVal->flags&MEM_AffMask];
65504 }
65505
65506 /**************************** sqlite3_result_ *******************************
65507 ** The following routines are used by user-defined functions to specify
65508 ** the function result.
@@ -65549,10 +66019,34 @@
66019 Vdbe *pVm = (Vdbe *)pStmt;
66020 if( pVm==0 || pVm->pResultSet==0 ) return 0;
66021 return pVm->nResColumn;
66022 }
66023
66024 /*
66025 ** Return a pointer to static memory containing an SQL NULL value.
66026 */
66027 static const Mem *columnNullValue(void){
66028 /* Even though the Mem structure contains an element
66029 ** of type i64, on certain architectures (x86) with certain compiler
66030 ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
66031 ** instead of an 8-byte one. This all works fine, except that when
66032 ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
66033 ** that a Mem structure is located on an 8-byte boundary. To prevent
66034 ** these assert()s from failing, when building with SQLITE_DEBUG defined
66035 ** using gcc, we force nullMem to be 8-byte aligned using the magical
66036 ** __attribute__((aligned(8))) macro. */
66037 static const Mem nullMem
66038 #if defined(SQLITE_DEBUG) && defined(__GNUC__)
66039 __attribute__((aligned(8)))
66040 #endif
66041 = {0, "", (double)0, {0}, 0, MEM_Null, 0,
66042 #ifdef SQLITE_DEBUG
66043 0, 0, /* pScopyFrom, pFiller */
66044 #endif
66045 0, 0 };
66046 return &nullMem;
66047 }
66048
66049 /*
66050 ** Check to see if column iCol of the given statement is valid. If
66051 ** it is, return a pointer to the Mem for the value of that column.
66052 ** If iCol is not valid, return a pointer to a Mem which has a value
@@ -65565,36 +66059,15 @@
66059 pVm = (Vdbe *)pStmt;
66060 if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
66061 sqlite3_mutex_enter(pVm->db->mutex);
66062 pOut = &pVm->pResultSet[i];
66063 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66064 if( pVm && ALWAYS(pVm->db) ){
66065 sqlite3_mutex_enter(pVm->db->mutex);
66066 sqlite3Error(pVm->db, SQLITE_RANGE, 0);
66067 }
66068 pOut = (Mem*)columnNullValue();
66069 }
66070 return pOut;
66071 }
66072
66073 /*
@@ -66629,11 +67102,11 @@
67102 ** does not control the string, it might be deleted without the register
67103 ** knowing it.
67104 **
67105 ** This routine converts an ephemeral string into a dynamically allocated
67106 ** string that the register itself controls. In other words, it
67107 ** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
67108 */
67109 #define Deephemeralize(P) \
67110 if( ((P)->flags&MEM_Ephem)!=0 \
67111 && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
67112
@@ -66770,11 +67243,10 @@
67243 SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
67244 int eType = sqlite3_value_type(pVal);
67245 if( eType==SQLITE_TEXT ){
67246 Mem *pMem = (Mem*)pVal;
67247 applyNumericAffinity(pMem);
 
67248 eType = sqlite3_value_type(pVal);
67249 }
67250 return eType;
67251 }
67252
@@ -67166,22 +67638,25 @@
67638 #ifdef SQLITE_DEBUG
67639 if( (pOp->opflags & OPFLG_IN1)!=0 ){
67640 assert( pOp->p1>0 );
67641 assert( pOp->p1<=(p->nMem-p->nCursor) );
67642 assert( memIsValid(&aMem[pOp->p1]) );
67643 assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
67644 REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
67645 }
67646 if( (pOp->opflags & OPFLG_IN2)!=0 ){
67647 assert( pOp->p2>0 );
67648 assert( pOp->p2<=(p->nMem-p->nCursor) );
67649 assert( memIsValid(&aMem[pOp->p2]) );
67650 assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
67651 REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
67652 }
67653 if( (pOp->opflags & OPFLG_IN3)!=0 ){
67654 assert( pOp->p3>0 );
67655 assert( pOp->p3<=(p->nMem-p->nCursor) );
67656 assert( memIsValid(&aMem[pOp->p3]) );
67657 assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
67658 REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
67659 }
67660 if( (pOp->opflags & OPFLG_OUT2)!=0 ){
67661 assert( pOp->p2>0 );
67662 assert( pOp->p2<=(p->nMem-p->nCursor) );
@@ -67279,11 +67754,11 @@
67754 ** and then jump to address P2.
67755 */
67756 case OP_Gosub: { /* jump */
67757 assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
67758 pIn1 = &aMem[pOp->p1];
67759 assert( VdbeMemDynamic(pIn1)==0 );
67760 memAboutToChange(p, pIn1);
67761 pIn1->flags = MEM_Int;
67762 pIn1->u.i = pc;
67763 REGISTER_TRACE(pOp->p1, pIn1);
67764 pc = pOp->p2 - 1;
@@ -67352,11 +67827,11 @@
67827 ** OP_EndCoroutine, jump immediately to P2.
67828 */
67829 case OP_Yield: { /* in1, jump */
67830 int pcDest;
67831 pIn1 = &aMem[pOp->p1];
67832 assert( VdbeMemDynamic(pIn1)==0 );
67833 pIn1->flags = MEM_Int;
67834 pcDest = (int)pIn1->u.i;
67835 pIn1->u.i = pc;
67836 REGISTER_TRACE(pOp->p1, pIn1);
67837 pc = pcDest;
@@ -67525,14 +68000,13 @@
68000 if( encoding!=SQLITE_UTF8 ){
68001 rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
68002 if( rc==SQLITE_TOOBIG ) goto too_big;
68003 if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
68004 assert( pOut->zMalloc==pOut->z );
68005 assert( VdbeMemDynamic(pOut)==0 );
68006 pOut->zMalloc = 0;
68007 pOut->flags |= MEM_Static;
 
68008 if( pOp->p4type==P4_DYNAMIC ){
68009 sqlite3DbFree(db, pOp->p4.z);
68010 }
68011 pOp->p4type = P4_DYNAMIC;
68012 pOp->p4.z = pOut->z;
@@ -67664,18 +68138,20 @@
68138 do{
68139 assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
68140 assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
68141 assert( memIsValid(pIn1) );
68142 memAboutToChange(p, pOut);
68143 VdbeMemRelease(pOut);
68144 zMalloc = pOut->zMalloc;
68145 memcpy(pOut, pIn1, sizeof(Mem));
 
68146 #ifdef SQLITE_DEBUG
68147 if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
68148 pOut->pScopyFrom += p1 - pOp->p2;
68149 }
68150 #endif
68151 pIn1->flags = MEM_Undefined;
68152 pIn1->xDel = 0;
68153 pIn1->zMalloc = zMalloc;
68154 REGISTER_TRACE(p2++, pOut);
68155 pIn1++;
68156 pOut++;
68157 }while( n-- );
@@ -67805,11 +68281,10 @@
68281 assert( memIsValid(&pMem[i]) );
68282 Deephemeralize(&pMem[i]);
68283 assert( (pMem[i].flags & MEM_Ephem)==0
68284 || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
68285 sqlite3VdbeMemNulTerminate(&pMem[i]);
 
68286 REGISTER_TRACE(pOp->p1+i, &pMem[i]);
68287 }
68288 if( db->mallocFailed ) goto no_mem;
68289
68290 /* Return SQLITE_ROW
@@ -67848,14 +68323,14 @@
68323 Stringify(pIn2, encoding);
68324 nByte = pIn1->n + pIn2->n;
68325 if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
68326 goto too_big;
68327 }
 
68328 if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
68329 goto no_mem;
68330 }
68331 MemSetTypeFlag(pOut, MEM_Str);
68332 if( pOut!=pIn2 ){
68333 memcpy(pOut->z, pIn2->z, pIn2->n);
68334 }
68335 memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
68336 pOut->z[nByte]=0;
@@ -68051,11 +68526,10 @@
68526 pArg = &aMem[pOp->p2];
68527 for(i=0; i<n; i++, pArg++){
68528 assert( memIsValid(pArg) );
68529 apVal[i] = pArg;
68530 Deephemeralize(pArg);
 
68531 REGISTER_TRACE(pOp->p2+i, pArg);
68532 }
68533
68534 assert( pOp->p4type==P4_FUNCDEF );
68535 ctx.pFunc = pOp->p4.pFunc;
@@ -69026,10 +69500,11 @@
69500 ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
69501 ** all valid.
69502 */
69503 assert( p2<pC->nHdrParsed );
69504 assert( rc==SQLITE_OK );
69505 assert( sqlite3VdbeCheckMemInvariants(pDest) );
69506 if( pC->szRow>=aOffset[p2+1] ){
69507 /* This is the common case where the desired content fits on the original
69508 ** page - where the content is not on an overflow page */
69509 VdbeMemRelease(pDest);
69510 sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
@@ -69063,12 +69538,12 @@
69538 ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
69539 ** dynamically allocated space over to the pDest structure.
69540 ** This prevents a memory copy. */
69541 if( sMem.zMalloc ){
69542 assert( sMem.z==sMem.zMalloc );
69543 assert( VdbeMemDynamic(pDest)==0 );
69544 assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
69545 pDest->flags &= ~(MEM_Ephem|MEM_Static);
69546 pDest->flags |= MEM_Term;
69547 pDest->z = sMem.z;
69548 pDest->zMalloc = sMem.zMalloc;
69549 }
@@ -69247,11 +69722,11 @@
69722 assert( i==nHdr );
69723 assert( j==nByte );
69724
69725 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
69726 pOut->n = (int)nByte;
69727 pOut->flags = MEM_Blob;
69728 pOut->xDel = 0;
69729 if( nZero ){
69730 pOut->u.nZero = nZero;
69731 pOut->flags |= MEM_Zero;
69732 }
@@ -70121,20 +70596,20 @@
70596 r.pKeyInfo = pC->pKeyInfo;
70597 r.nField = (u16)nField;
70598
70599 /* The next line of code computes as follows, only faster:
70600 ** if( oc==OP_SeekGT || oc==OP_SeekLE ){
70601 ** r.default_rc = -1;
70602 ** }else{
70603 ** r.default_rc = +1;
70604 ** }
70605 */
70606 r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
70607 assert( oc!=OP_SeekGT || r.default_rc==-1 );
70608 assert( oc!=OP_SeekLE || r.default_rc==-1 );
70609 assert( oc!=OP_SeekGE || r.default_rc==+1 );
70610 assert( oc!=OP_SeekLT || r.default_rc==+1 );
70611
70612 r.aMem = &aMem[pOp->p3];
70613 #ifdef SQLITE_DEBUG
70614 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
70615 #endif
@@ -70288,22 +70763,21 @@
70763 ExpandBlob(&r.aMem[ii]);
70764 #ifdef SQLITE_DEBUG
70765 if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
70766 #endif
70767 }
 
70768 pIdxKey = &r;
70769 }else{
70770 pIdxKey = sqlite3VdbeAllocUnpackedRecord(
70771 pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
70772 );
70773 if( pIdxKey==0 ) goto no_mem;
70774 assert( pIn3->flags & MEM_Blob );
70775 assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
70776 sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
 
70777 }
70778 pIdxKey->default_rc = 0;
70779 if( pOp->opcode==OP_NoConflict ){
70780 /* For the OP_NoConflict opcode, take the jump if any of the
70781 ** input fields are NULL, since any key with a NULL will not
70782 ** conflict */
70783 for(ii=0; ii<r.nField; ii++){
@@ -71188,11 +71662,11 @@
71662 pCrsr = pC->pCursor;
71663 assert( pCrsr!=0 );
71664 assert( pOp->p5==0 );
71665 r.pKeyInfo = pC->pKeyInfo;
71666 r.nField = (u16)pOp->p3;
71667 r.default_rc = 0;
71668 r.aMem = &aMem[pOp->p2];
71669 #ifdef SQLITE_DEBUG
71670 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
71671 #endif
71672 rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
@@ -71302,14 +71776,14 @@
71776 assert( pOp->p4type==P4_INT32 );
71777 r.pKeyInfo = pC->pKeyInfo;
71778 r.nField = (u16)pOp->p4.i;
71779 if( pOp->opcode<OP_IdxLT ){
71780 assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
71781 r.default_rc = -1;
71782 }else{
71783 assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
71784 r.default_rc = 0;
71785 }
71786 r.aMem = &aMem[pOp->p3];
71787 #ifdef SQLITE_DEBUG
71788 { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
71789 #endif
@@ -72056,11 +72530,10 @@
72530 assert( apVal || n==0 );
72531 for(i=0; i<n; i++, pRec++){
72532 assert( memIsValid(pRec) );
72533 apVal[i] = pRec;
72534 memAboutToChange(p, pRec);
 
72535 }
72536 ctx.pFunc = pOp->p4.pFunc;
72537 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
72538 ctx.pMem = pMem = &aMem[pOp->p3];
72539 pMem->n++;
@@ -72490,11 +72963,10 @@
72963 {
72964 res = 0;
72965 apArg = p->apArg;
72966 for(i = 0; i<nArg; i++){
72967 apArg[i] = &pArgc[i+1];
 
72968 }
72969
72970 p->inVtabMethod = 1;
72971 rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
72972 p->inVtabMethod = 0;
@@ -72697,11 +73169,10 @@
73169 apArg = p->apArg;
73170 pX = &aMem[pOp->p3];
73171 for(i=0; i<nArg; i++){
73172 assert( memIsValid(pX) );
73173 memAboutToChange(p, pX);
 
73174 apArg[i] = pX;
73175 pX++;
73176 }
73177 db->vtabOnConflict = pOp->p5;
73178 rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
@@ -73809,14 +74280,14 @@
74280 if( r2->aMem[i].flags & MEM_Null ){
74281 *pRes = -1;
74282 return;
74283 }
74284 }
74285 assert( r2->default_rc==0 );
74286 }
74287
74288 *pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2, 0);
74289 }
74290
74291 /*
74292 ** This function is called to compare two iterator keys when merging
74293 ** multiple b-tree segments. Parameter iOut is the index of the aTree[]
@@ -75449,10 +75920,12 @@
75920 pExpr->iTable = 1;
75921 pTab = pParse->pTriggerTab;
75922 }else if( op!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
75923 pExpr->iTable = 0;
75924 pTab = pParse->pTriggerTab;
75925 }else{
75926 pTab = 0;
75927 }
75928
75929 if( pTab ){
75930 int iCol;
75931 pSchema = pTab->pSchema;
@@ -87719,11 +88192,11 @@
88192 assert( nExtra>=1 );
88193 assert( pSrc!=0 );
88194 assert( iStart<=pSrc->nSrc );
88195
88196 /* Allocate additional space if needed */
88197 if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
88198 SrcList *pNew;
88199 int nAlloc = pSrc->nSrc+nExtra;
88200 int nGot;
88201 pNew = sqlite3DbRealloc(db, pSrc,
88202 sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
@@ -87731,19 +88204,19 @@
88204 assert( db->mallocFailed );
88205 return pSrc;
88206 }
88207 pSrc = pNew;
88208 nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
88209 pSrc->nAlloc = nGot;
88210 }
88211
88212 /* Move existing slots that come after the newly inserted slots
88213 ** out of the way */
88214 for(i=pSrc->nSrc-1; i>=iStart; i--){
88215 pSrc->a[i+nExtra] = pSrc->a[i];
88216 }
88217 pSrc->nSrc += nExtra;
88218
88219 /* Zero the newly allocated slots */
88220 memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
88221 for(i=iStart; i<iStart+nExtra; i++){
88222 pSrc->a[i].iCursor = -1;
@@ -100117,11 +100590,11 @@
100590 }else if( eDest!=SRT_Exists ){
100591 /* If the destination is an EXISTS(...) expression, the actual
100592 ** values returned by the SELECT are not required.
100593 */
100594 sqlite3ExprCodeExprList(pParse, pEList, regResult,
100595 (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0);
100596 }
100597
100598 /* If the DISTINCT keyword was present on the SELECT statement
100599 ** and this row has been seen before, then do not make this row
100600 ** part of the result.
@@ -101030,11 +101503,11 @@
101503 for(j=cnt=0; j<i; j++){
101504 if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
101505 char *zNewName;
101506 int k;
101507 for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
101508 if( k>=0 && zName[k]==':' ) nName = k;
101509 zName[nName] = 0;
101510 zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
101511 sqlite3DbFree(db, zName);
101512 zName = zNewName;
101513 j = -1;
@@ -110767,11 +111240,11 @@
111240 iCol = pRec->nField - 1;
111241 assert( pIdx->nSample>0 );
111242 assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
111243 do{
111244 iTest = (iMin+i)/2;
111245 res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec, 0);
111246 if( res<0 ){
111247 iMin = iTest+1;
111248 }else{
111249 i = iTest;
111250 }
@@ -110782,20 +111255,20 @@
111255 ** above found the right answer. This block serves no purpose other
111256 ** than to invoke the asserts. */
111257 if( res==0 ){
111258 /* If (res==0) is true, then sample $i must be equal to pRec */
111259 assert( i<pIdx->nSample );
111260 assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)
111261 || pParse->db->mallocFailed );
111262 }else{
111263 /* Otherwise, pRec must be smaller than sample $i and larger than
111264 ** sample ($i-1). */
111265 assert( i==pIdx->nSample
111266 || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec, 0)>0
111267 || pParse->db->mallocFailed );
111268 assert( i==0
111269 || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec, 0)<0
111270 || pParse->db->mallocFailed );
111271 }
111272 #endif /* ifdef SQLITE_DEBUG */
111273
111274 /* At this point, aSample[i] is the first sample that is greater than
@@ -114724,11 +115197,11 @@
115197
115198 /* For a co-routine, change all OP_Column references to the table of
115199 ** the co-routine into OP_SCopy of result contained in a register.
115200 ** OP_Rowid becomes OP_Null.
115201 */
115202 if( pTabItem->viaCoroutine && !db->mallocFailed ){
115203 last = sqlite3VdbeCurrentAddr(v);
115204 k = pLevel->addrBody;
115205 pOp = sqlite3VdbeGetOp(v, k);
115206 for(; k<last; k++, pOp++){
115207 if( pOp->p1!=pLevel->iTabCur ) continue;
115208
+1 -1
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110110
#define SQLITE_VERSION "3.8.4"
111111
#define SQLITE_VERSION_NUMBER 3008004
112
-#define SQLITE_SOURCE_ID "2014-02-27 15:04:13 a6690400235705ecc0d1a60dacff6ad5fb1f944a"
112
+#define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.4"
111 #define SQLITE_VERSION_NUMBER 3008004
112 #define SQLITE_SOURCE_ID "2014-02-27 15:04:13 a6690400235705ecc0d1a60dacff6ad5fb1f944a"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -107,11 +107,11 @@
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.4"
111 #define SQLITE_VERSION_NUMBER 3008004
112 #define SQLITE_SOURCE_ID "2014-03-05 19:04:46 0723effc9ccae7c660fb847b36ce9324e0cb5042"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+20 -20
--- src/tkt.c
+++ src/tkt.c
@@ -61,11 +61,11 @@
6161
}
6262
return -1;
6363
}
6464
6565
/*
66
-** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them
66
+** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them
6767
** in sorted order in aField[].
6868
**
6969
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
7070
** TICKETCHANGE tables exist, respectively.
7171
*/
@@ -429,15 +429,15 @@
429429
if( g.perm.WrTkt || g.perm.ApndTkt ){
430430
style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
431431
g.zTop, PD("name",""));
432432
}
433433
if( g.perm.Hyperlink ){
434
- style_submenu_element("History", "History Of This Ticket",
434
+ style_submenu_element("History", "History Of This Ticket",
435435
"%s/tkthistory/%T", g.zTop, zUuid);
436
- style_submenu_element("Timeline", "Timeline Of This Ticket",
436
+ style_submenu_element("Timeline", "Timeline Of This Ticket",
437437
"%s/tkttimeline/%T", g.zTop, zUuid);
438
- style_submenu_element("Check-ins", "Check-ins Of This Ticket",
438
+ style_submenu_element("Check-ins", "Check-ins Of This Ticket",
439439
"%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
440440
}
441441
if( g.perm.NewTkt ){
442442
style_submenu_element("New Ticket", "Create a new ticket",
443443
"%s/tktnew", g.zTop);
@@ -463,17 +463,17 @@
463463
if( P("showfields")!=0 ) showAllFields();
464464
if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1);
465465
Th_Render(zScript);
466466
if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
467467
468
- zFullName = db_text(0,
468
+ zFullName = db_text(0,
469469
"SELECT tkt_uuid FROM ticket"
470470
" WHERE tkt_uuid GLOB '%q*'", zUuid);
471471
if( zFullName ){
472472
attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>");
473473
}
474
-
474
+
475475
style_footer();
476476
}
477477
478478
/*
479479
** TH command: append_field FIELD STRING
@@ -482,14 +482,14 @@
482482
** to append text. STRING is the text to be appended to that
483483
** column. The append does not actually occur until the
484484
** submit_ticket command is run.
485485
*/
486486
static int appendRemarkCmd(
487
- Th_Interp *interp,
488
- void *p,
489
- int argc,
490
- const char **argv,
487
+ Th_Interp *interp,
488
+ void *p,
489
+ int argc,
490
+ const char **argv,
491491
int *argl
492492
){
493493
int idx;
494494
495495
if( argc!=3 ){
@@ -555,14 +555,14 @@
555555
** taken from TH variables. If the content is unchanged, the field is
556556
** omitted from the artifact. Fields whose names begin with "private_"
557557
** are concealed using the db_conceal() function.
558558
*/
559559
static int submitTicketCmd(
560
- Th_Interp *interp,
561
- void *pUuid,
562
- int argc,
563
- const char **argv,
560
+ Th_Interp *interp,
561
+ void *pUuid,
562
+ int argc,
563
+ const char **argv,
564564
int *argl
565565
){
566566
char *zDate;
567567
const char *zUuid;
568568
int i;
@@ -606,11 +606,11 @@
606606
nJ++;
607607
}
608608
}
609609
}
610610
if( *(char**)pUuid ){
611
- zUuid = db_text(0,
611
+ zUuid = db_text(0,
612612
"SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name")
613613
);
614614
}else{
615615
zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
616616
}
@@ -939,14 +939,14 @@
939939
nChng++;
940940
if( zFile!=0 ){
941941
const char *zSrc = db_column_text(&q, 3);
942942
const char *zUser = db_column_text(&q, 5);
943943
if( zSrc==0 || zSrc[0]==0 ){
944
- @
944
+ @
945945
@ <li><p>Delete attachment "%h(zFile)"
946946
}else{
947
- @
947
+ @
948948
@ <li><p>Add attachment
949949
@ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>"
950950
}
951951
@ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
952952
@ (rid %d(rid)) by
@@ -1151,11 +1151,11 @@
11511151
}else{
11521152
/* add a new ticket or set fields on existing tickets */
11531153
tTktShowEncoding tktEncoding;
11541154
11551155
tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
1156
-
1156
+
11571157
if( strncmp(g.argv[2],"show",n)==0 ){
11581158
if( g.argc==3 ){
11591159
usage("show REPORTNR");
11601160
}else{
11611161
const char *zRep = 0;
@@ -1186,11 +1186,11 @@
11861186
eCmd = set;
11871187
}
11881188
if( g.argc==3 ){
11891189
usage("set|change|history TICKETUUID");
11901190
}
1191
- zTktUuid = db_text(0,
1191
+ zTktUuid = db_text(0,
11921192
"SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3]
11931193
);
11941194
if( !zTktUuid ){
11951195
fossil_fatal("unknown ticket: '%s'!",g.argv[3]);
11961196
}
@@ -1217,11 +1217,11 @@
12171217
}
12181218
tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
12191219
zTktUuid);
12201220
if( tagid==0 ){
12211221
fossil_fatal("no such ticket %h", zTktUuid);
1222
- }
1222
+ }
12231223
db_prepare(&q,
12241224
"SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL"
12251225
" FROM event, blob"
12261226
" WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
12271227
" AND blob.rid=event.objid"
12281228
--- src/tkt.c
+++ src/tkt.c
@@ -61,11 +61,11 @@
61 }
62 return -1;
63 }
64
65 /*
66 ** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them
67 ** in sorted order in aField[].
68 **
69 ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
70 ** TICKETCHANGE tables exist, respectively.
71 */
@@ -429,15 +429,15 @@
429 if( g.perm.WrTkt || g.perm.ApndTkt ){
430 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
431 g.zTop, PD("name",""));
432 }
433 if( g.perm.Hyperlink ){
434 style_submenu_element("History", "History Of This Ticket",
435 "%s/tkthistory/%T", g.zTop, zUuid);
436 style_submenu_element("Timeline", "Timeline Of This Ticket",
437 "%s/tkttimeline/%T", g.zTop, zUuid);
438 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
439 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
440 }
441 if( g.perm.NewTkt ){
442 style_submenu_element("New Ticket", "Create a new ticket",
443 "%s/tktnew", g.zTop);
@@ -463,17 +463,17 @@
463 if( P("showfields")!=0 ) showAllFields();
464 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1);
465 Th_Render(zScript);
466 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
467
468 zFullName = db_text(0,
469 "SELECT tkt_uuid FROM ticket"
470 " WHERE tkt_uuid GLOB '%q*'", zUuid);
471 if( zFullName ){
472 attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>");
473 }
474
475 style_footer();
476 }
477
478 /*
479 ** TH command: append_field FIELD STRING
@@ -482,14 +482,14 @@
482 ** to append text. STRING is the text to be appended to that
483 ** column. The append does not actually occur until the
484 ** submit_ticket command is run.
485 */
486 static int appendRemarkCmd(
487 Th_Interp *interp,
488 void *p,
489 int argc,
490 const char **argv,
491 int *argl
492 ){
493 int idx;
494
495 if( argc!=3 ){
@@ -555,14 +555,14 @@
555 ** taken from TH variables. If the content is unchanged, the field is
556 ** omitted from the artifact. Fields whose names begin with "private_"
557 ** are concealed using the db_conceal() function.
558 */
559 static int submitTicketCmd(
560 Th_Interp *interp,
561 void *pUuid,
562 int argc,
563 const char **argv,
564 int *argl
565 ){
566 char *zDate;
567 const char *zUuid;
568 int i;
@@ -606,11 +606,11 @@
606 nJ++;
607 }
608 }
609 }
610 if( *(char**)pUuid ){
611 zUuid = db_text(0,
612 "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name")
613 );
614 }else{
615 zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
616 }
@@ -939,14 +939,14 @@
939 nChng++;
940 if( zFile!=0 ){
941 const char *zSrc = db_column_text(&q, 3);
942 const char *zUser = db_column_text(&q, 5);
943 if( zSrc==0 || zSrc[0]==0 ){
944 @
945 @ <li><p>Delete attachment "%h(zFile)"
946 }else{
947 @
948 @ <li><p>Add attachment
949 @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>"
950 }
951 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
952 @ (rid %d(rid)) by
@@ -1151,11 +1151,11 @@
1151 }else{
1152 /* add a new ticket or set fields on existing tickets */
1153 tTktShowEncoding tktEncoding;
1154
1155 tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
1156
1157 if( strncmp(g.argv[2],"show",n)==0 ){
1158 if( g.argc==3 ){
1159 usage("show REPORTNR");
1160 }else{
1161 const char *zRep = 0;
@@ -1186,11 +1186,11 @@
1186 eCmd = set;
1187 }
1188 if( g.argc==3 ){
1189 usage("set|change|history TICKETUUID");
1190 }
1191 zTktUuid = db_text(0,
1192 "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3]
1193 );
1194 if( !zTktUuid ){
1195 fossil_fatal("unknown ticket: '%s'!",g.argv[3]);
1196 }
@@ -1217,11 +1217,11 @@
1217 }
1218 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
1219 zTktUuid);
1220 if( tagid==0 ){
1221 fossil_fatal("no such ticket %h", zTktUuid);
1222 }
1223 db_prepare(&q,
1224 "SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL"
1225 " FROM event, blob"
1226 " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
1227 " AND blob.rid=event.objid"
1228
--- src/tkt.c
+++ src/tkt.c
@@ -61,11 +61,11 @@
61 }
62 return -1;
63 }
64
65 /*
66 ** Obtain a list of all fields of the TICKET and TICKETCHNG tables. Put them
67 ** in sorted order in aField[].
68 **
69 ** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
70 ** TICKETCHANGE tables exist, respectively.
71 */
@@ -429,15 +429,15 @@
429 if( g.perm.WrTkt || g.perm.ApndTkt ){
430 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
431 g.zTop, PD("name",""));
432 }
433 if( g.perm.Hyperlink ){
434 style_submenu_element("History", "History Of This Ticket",
435 "%s/tkthistory/%T", g.zTop, zUuid);
436 style_submenu_element("Timeline", "Timeline Of This Ticket",
437 "%s/tkttimeline/%T", g.zTop, zUuid);
438 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
439 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid);
440 }
441 if( g.perm.NewTkt ){
442 style_submenu_element("New Ticket", "Create a new ticket",
443 "%s/tktnew", g.zTop);
@@ -463,17 +463,17 @@
463 if( P("showfields")!=0 ) showAllFields();
464 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1);
465 Th_Render(zScript);
466 if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1);
467
468 zFullName = db_text(0,
469 "SELECT tkt_uuid FROM ticket"
470 " WHERE tkt_uuid GLOB '%q*'", zUuid);
471 if( zFullName ){
472 attachment_list(zFullName, "<hr /><h2>Attachments:</h2><ul>");
473 }
474
475 style_footer();
476 }
477
478 /*
479 ** TH command: append_field FIELD STRING
@@ -482,14 +482,14 @@
482 ** to append text. STRING is the text to be appended to that
483 ** column. The append does not actually occur until the
484 ** submit_ticket command is run.
485 */
486 static int appendRemarkCmd(
487 Th_Interp *interp,
488 void *p,
489 int argc,
490 const char **argv,
491 int *argl
492 ){
493 int idx;
494
495 if( argc!=3 ){
@@ -555,14 +555,14 @@
555 ** taken from TH variables. If the content is unchanged, the field is
556 ** omitted from the artifact. Fields whose names begin with "private_"
557 ** are concealed using the db_conceal() function.
558 */
559 static int submitTicketCmd(
560 Th_Interp *interp,
561 void *pUuid,
562 int argc,
563 const char **argv,
564 int *argl
565 ){
566 char *zDate;
567 const char *zUuid;
568 int i;
@@ -606,11 +606,11 @@
606 nJ++;
607 }
608 }
609 }
610 if( *(char**)pUuid ){
611 zUuid = db_text(0,
612 "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%q*'", P("name")
613 );
614 }else{
615 zUuid = db_text(0, "SELECT lower(hex(randomblob(20)))");
616 }
@@ -939,14 +939,14 @@
939 nChng++;
940 if( zFile!=0 ){
941 const char *zSrc = db_column_text(&q, 3);
942 const char *zUser = db_column_text(&q, 5);
943 if( zSrc==0 || zSrc[0]==0 ){
944 @
945 @ <li><p>Delete attachment "%h(zFile)"
946 }else{
947 @
948 @ <li><p>Add attachment
949 @ "%z(href("%R/artifact/%S",zSrc))%s(zFile)</a>"
950 }
951 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
952 @ (rid %d(rid)) by
@@ -1151,11 +1151,11 @@
1151 }else{
1152 /* add a new ticket or set fields on existing tickets */
1153 tTktShowEncoding tktEncoding;
1154
1155 tktEncoding = find_option("quote","q",0) ? tktFossilize : tktNoTab;
1156
1157 if( strncmp(g.argv[2],"show",n)==0 ){
1158 if( g.argc==3 ){
1159 usage("show REPORTNR");
1160 }else{
1161 const char *zRep = 0;
@@ -1186,11 +1186,11 @@
1186 eCmd = set;
1187 }
1188 if( g.argc==3 ){
1189 usage("set|change|history TICKETUUID");
1190 }
1191 zTktUuid = db_text(0,
1192 "SELECT tkt_uuid FROM ticket WHERE tkt_uuid GLOB '%s*'", g.argv[3]
1193 );
1194 if( !zTktUuid ){
1195 fossil_fatal("unknown ticket: '%s'!",g.argv[3]);
1196 }
@@ -1217,11 +1217,11 @@
1217 }
1218 tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
1219 zTktUuid);
1220 if( tagid==0 ){
1221 fossil_fatal("no such ticket %h", zTktUuid);
1222 }
1223 db_prepare(&q,
1224 "SELECT datetime(mtime%s), objid, uuid, NULL, NULL, NULL"
1225 " FROM event, blob"
1226 " WHERE objid IN (SELECT rid FROM tagxref WHERE tagid=%d)"
1227 " AND blob.rid=event.objid"
1228
+31 -31
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -115,11 +115,11 @@
115115
void (*xRebuild)(void), /* Run after successful update */
116116
int height /* Height of the edit box */
117117
){
118118
const char *z;
119119
int isSubmit;
120
-
120
+
121121
login_check_credentials();
122122
if( !g.perm.Setup ){
123123
login_needed();
124124
}
125125
if( P("setup") ){
@@ -314,43 +314,43 @@
314314
@ <td colspan="3">
315315
@ Enter a one-line summary of the ticket:<br />
316316
@ <input type="text" name="title" size="60" value="$<title>" />
317317
@ </td>
318318
@ </tr>
319
-@
319
+@
320320
@ <tr>
321321
@ <td align="right">Type:</td>
322322
@ <td align="left"><th1>combobox type $type_choices 1</th1></td>
323323
@ <td align="left">What type of ticket is this?</td>
324324
@ </tr>
325
-@
325
+@
326326
@ <tr>
327327
@ <td align="right">Version:</td>
328328
@ <td align="left">
329329
@ <input type="text" name="foundin" size="20" value="$<foundin>" />
330330
@ </td>
331331
@ <td align="left">In what version or build number do you observe
332332
@ the problem?</td>
333333
@ </tr>
334
-@
334
+@
335335
@ <tr>
336336
@ <td align="right">Severity:</td>
337337
@ <td align="left"><th1>combobox severity $severity_choices 1</th1></td>
338338
@ <td align="left">How debilitating is the problem? How badly does the problem
339339
@ affect the operation of the product?</td>
340340
@ </tr>
341
-@
341
+@
342342
@ <tr>
343343
@ <td align="right">EMail:</td>
344344
@ <td align="left">
345345
@ <input type="text" name="private_contact" value="$<private_contact>"
346346
@ size="30" />
347347
@ </td>
348348
@ <td align="left"><u>Not publicly visible</u>
349349
@ Used by developers to contact you with questions.</td>
350350
@ </tr>
351
-@
351
+@
352352
@ <tr>
353353
@ <td colspan="3">
354354
@ Enter a detailed description of the problem.
355355
@ For code defects, be sure to provide details on exactly how
356356
@ the problem can be reproduced. Provide as much detail as
@@ -359,11 +359,11 @@
359359
@ <br />
360360
@ <th1>set nline [linecount $comment 50 10]</th1>
361361
@ <textarea name="icomment" cols="80" rows="$nline"
362362
@ wrap="virtual" class="wikiedit">$<icomment></textarea><br />
363363
@ </tr>
364
-@
364
+@
365365
@ <th1>enable_output [info exists preview]</th1>
366366
@ <tr><td colspan="3">
367367
@ Description Preview:<br /><hr />
368368
@ <th1>
369369
@ if {$mutype eq "Wiki"} {
@@ -378,28 +378,28 @@
378378
@ wiki "<nowiki>$icomment\n</nowiki>"
379379
@ }
380380
@ </th1>
381381
@ <hr /></td></tr>
382382
@ <th1>enable_output 1</th1>
383
-@
383
+@
384384
@ <tr>
385385
@ <td><td align="left">
386386
@ <input type="submit" name="preview" value="Preview" />
387387
@ </td>
388388
@ <td align="left">See how the description will appear after formatting.</td>
389389
@ </tr>
390
-@
390
+@
391391
@ <th1>enable_output [info exists preview]</th1>
392392
@ <tr>
393393
@ <td><td align="left">
394394
@ <input type="submit" name="submit" value="Submit" />
395395
@ </td>
396
-@ <td align="left">After filling in the information above, press this
396
+@ <td align="left">After filling in the information above, press this
397397
@ button to create the new ticket</td>
398398
@ </tr>
399399
@ <th1>enable_output 1</th1>
400
-@
400
+@
401401
@ <tr>
402402
@ <td><td align="left">
403403
@ <input type="submit" name="cancel" value="Cancel" />
404404
@ </td>
405405
@ <td>Abandon and forget this ticket</td>
@@ -477,11 +477,11 @@
477477
@ </tr>
478478
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
479479
@ <td colspan="3" valign="top" class="tktDspValue">
480480
@ $<foundin>
481481
@ </td></tr>
482
-@
482
+@
483483
@ <th1>
484484
@ if {[info exists comment] && [string length $comment]>10} {
485485
@ html {
486486
@ <tr><td class="tktDspLabel">Description:</td></tr>
487487
@ <tr><td colspan="5" class="tktDspValue">
@@ -577,55 +577,55 @@
577577
@ </th1>
578578
@ <table cellpadding="5">
579579
@ <tr><td class="tktDspLabel">Title:</td><td>
580580
@ <input type="text" name="title" value="$<title>" size="60" />
581581
@ </td></tr>
582
-@
582
+@
583583
@ <tr><td class="tktDspLabel">Status:</td><td>
584584
@ <th1>combobox status $status_choices 1</th1>
585585
@ </td></tr>
586
-@
586
+@
587587
@ <tr><td class="tktDspLabel">Type:</td><td>
588588
@ <th1>combobox type $type_choices 1</th1>
589589
@ </td></tr>
590
-@
590
+@
591591
@ <tr><td class="tktDspLabel">Severity:</td><td>
592592
@ <th1>combobox severity $severity_choices 1</th1>
593593
@ </td></tr>
594
-@
594
+@
595595
@ <tr><td class="tktDspLabel">Priority:</td><td>
596596
@ <th1>combobox priority $priority_choices 1</th1>
597597
@ </td></tr>
598
-@
598
+@
599599
@ <tr><td class="tktDspLabel">Resolution:</td><td>
600600
@ <th1>combobox resolution $resolution_choices 1</th1>
601601
@ </td></tr>
602
-@
602
+@
603603
@ <tr><td class="tktDspLabel">Subsystem:</td><td>
604604
@ <th1>combobox subsystem $subsystem_choices 1</th1>
605605
@ </td></tr>
606
-@
606
+@
607607
@ <th1>enable_output [hascap e]</th1>
608608
@ <tr><td class="tktDspLabel">Contact:</td><td>
609609
@ <input type="text" name="private_contact" size="40"
610610
@ value="$<private_contact>" />
611611
@ </td></tr>
612612
@ <th1>enable_output 1</th1>
613
-@
613
+@
614614
@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
615615
@ <input type="text" name="foundin" size="50" value="$<foundin>" />
616616
@ </td></tr>
617
-@
617
+@
618618
@ <tr><td colspan="2">
619619
@ Append Remark with format
620620
@ <th1>combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1</th1>
621621
@ from
622622
@ <input type="text" name="username" value="$<username>" size="30" />:<br />
623623
@ <textarea name="icomment" cols="80" rows="15"
624624
@ wrap="virtual" class="wikiedit">$<icomment></textarea>
625625
@ </td></tr>
626
-@
626
+@
627627
@ <th1>enable_output [info exists preview]</th1>
628628
@ <tr><td colspan="2">
629629
@ Description Preview:<br><hr>
630630
@ <th1>
631631
@ if {$mutype eq "Wiki"} {
@@ -641,34 +641,34 @@
641641
@ }
642642
@ </th1>
643643
@ <hr>
644644
@ </td></tr>
645645
@ <th1>enable_output 1</th1>
646
-@
646
+@
647647
@ <tr>
648648
@ <td align="right">
649649
@ <input type="submit" name="preview" value="Preview" />
650650
@ </td>
651651
@ <td align="left">See how the description will appear after formatting.</td>
652652
@ </tr>
653
-@
653
+@
654654
@ <th1>enable_output [info exists preview]</th1>
655655
@ <tr>
656656
@ <td align="right">
657657
@ <input type="submit" name="submit" value="Submit" />
658658
@ </td>
659659
@ <td align="left">Apply the changes shown above</td>
660660
@ </tr>
661661
@ <th1>enable_output 1</th1>
662
-@
662
+@
663663
@ <tr>
664664
@ <td align="right">
665665
@ <input type="submit" name="cancel" value="Cancel" />
666666
@ </td>
667667
@ <td>Abandon this edit</td>
668668
@ </tr>
669
-@
669
+@
670670
@ </table>
671671
;
672672
673673
/*
674674
** Return the code used to generate the edit ticket page
@@ -703,16 +703,16 @@
703703
@ if {[hascap n]} {
704704
@ html "<p>Enter a new ticket:</p>"
705705
@ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
706706
@ }
707707
@ </th1>
708
-@
708
+@
709709
@ <p>Choose a report format from the following list:</p>
710710
@ <ol>
711711
@ <th1>html $report_items</th1>
712712
@ </ol>
713
-@
713
+@
714714
@ <th1>
715715
@ if {[hascap t q]} {
716716
@ html "<p>Other options:</p>\n<ul>\n"
717717
@ if {[hascap t]} {
718718
@ html "<li><a href='rptnew'>New report format</a></li>\n"
@@ -750,11 +750,11 @@
750750
}
751751
752752
/*
753753
** The default template ticket report format:
754754
*/
755
-static char zDefaultReport[] =
755
+static char zDefaultReport[] =
756756
@ SELECT
757757
@ CASE WHEN status IN ('Open','Verified') THEN '#f2dcdc'
758758
@ WHEN status='Review' THEN '#e8e8e8'
759759
@ WHEN status='Fixed' THEN '#cfe8bd'
760760
@ WHEN status='Tested' THEN '#bde5d6'
@@ -799,11 +799,11 @@
799799
}
800800
801801
/*
802802
** The default template ticket key:
803803
*/
804
-static const char zDefaultKey[] =
804
+static const char zDefaultKey[] =
805805
@ #ffffff Key:
806806
@ #f2dcdc Active
807807
@ #e8e8e8 Review
808808
@ #cfe8bd Fixed
809809
@ #bde5d6 Tested
@@ -880,7 +880,7 @@
880880
@ <input type="submit" name="setup" value="Cancel" />
881881
@ </p>
882882
@ </div></form>
883883
db_end_transaction(0);
884884
style_footer();
885
-
885
+
886886
}
887887
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -115,11 +115,11 @@
115 void (*xRebuild)(void), /* Run after successful update */
116 int height /* Height of the edit box */
117 ){
118 const char *z;
119 int isSubmit;
120
121 login_check_credentials();
122 if( !g.perm.Setup ){
123 login_needed();
124 }
125 if( P("setup") ){
@@ -314,43 +314,43 @@
314 @ <td colspan="3">
315 @ Enter a one-line summary of the ticket:<br />
316 @ <input type="text" name="title" size="60" value="$<title>" />
317 @ </td>
318 @ </tr>
319 @
320 @ <tr>
321 @ <td align="right">Type:</td>
322 @ <td align="left"><th1>combobox type $type_choices 1</th1></td>
323 @ <td align="left">What type of ticket is this?</td>
324 @ </tr>
325 @
326 @ <tr>
327 @ <td align="right">Version:</td>
328 @ <td align="left">
329 @ <input type="text" name="foundin" size="20" value="$<foundin>" />
330 @ </td>
331 @ <td align="left">In what version or build number do you observe
332 @ the problem?</td>
333 @ </tr>
334 @
335 @ <tr>
336 @ <td align="right">Severity:</td>
337 @ <td align="left"><th1>combobox severity $severity_choices 1</th1></td>
338 @ <td align="left">How debilitating is the problem? How badly does the problem
339 @ affect the operation of the product?</td>
340 @ </tr>
341 @
342 @ <tr>
343 @ <td align="right">EMail:</td>
344 @ <td align="left">
345 @ <input type="text" name="private_contact" value="$<private_contact>"
346 @ size="30" />
347 @ </td>
348 @ <td align="left"><u>Not publicly visible</u>
349 @ Used by developers to contact you with questions.</td>
350 @ </tr>
351 @
352 @ <tr>
353 @ <td colspan="3">
354 @ Enter a detailed description of the problem.
355 @ For code defects, be sure to provide details on exactly how
356 @ the problem can be reproduced. Provide as much detail as
@@ -359,11 +359,11 @@
359 @ <br />
360 @ <th1>set nline [linecount $comment 50 10]</th1>
361 @ <textarea name="icomment" cols="80" rows="$nline"
362 @ wrap="virtual" class="wikiedit">$<icomment></textarea><br />
363 @ </tr>
364 @
365 @ <th1>enable_output [info exists preview]</th1>
366 @ <tr><td colspan="3">
367 @ Description Preview:<br /><hr />
368 @ <th1>
369 @ if {$mutype eq "Wiki"} {
@@ -378,28 +378,28 @@
378 @ wiki "<nowiki>$icomment\n</nowiki>"
379 @ }
380 @ </th1>
381 @ <hr /></td></tr>
382 @ <th1>enable_output 1</th1>
383 @
384 @ <tr>
385 @ <td><td align="left">
386 @ <input type="submit" name="preview" value="Preview" />
387 @ </td>
388 @ <td align="left">See how the description will appear after formatting.</td>
389 @ </tr>
390 @
391 @ <th1>enable_output [info exists preview]</th1>
392 @ <tr>
393 @ <td><td align="left">
394 @ <input type="submit" name="submit" value="Submit" />
395 @ </td>
396 @ <td align="left">After filling in the information above, press this
397 @ button to create the new ticket</td>
398 @ </tr>
399 @ <th1>enable_output 1</th1>
400 @
401 @ <tr>
402 @ <td><td align="left">
403 @ <input type="submit" name="cancel" value="Cancel" />
404 @ </td>
405 @ <td>Abandon and forget this ticket</td>
@@ -477,11 +477,11 @@
477 @ </tr>
478 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
479 @ <td colspan="3" valign="top" class="tktDspValue">
480 @ $<foundin>
481 @ </td></tr>
482 @
483 @ <th1>
484 @ if {[info exists comment] && [string length $comment]>10} {
485 @ html {
486 @ <tr><td class="tktDspLabel">Description:</td></tr>
487 @ <tr><td colspan="5" class="tktDspValue">
@@ -577,55 +577,55 @@
577 @ </th1>
578 @ <table cellpadding="5">
579 @ <tr><td class="tktDspLabel">Title:</td><td>
580 @ <input type="text" name="title" value="$<title>" size="60" />
581 @ </td></tr>
582 @
583 @ <tr><td class="tktDspLabel">Status:</td><td>
584 @ <th1>combobox status $status_choices 1</th1>
585 @ </td></tr>
586 @
587 @ <tr><td class="tktDspLabel">Type:</td><td>
588 @ <th1>combobox type $type_choices 1</th1>
589 @ </td></tr>
590 @
591 @ <tr><td class="tktDspLabel">Severity:</td><td>
592 @ <th1>combobox severity $severity_choices 1</th1>
593 @ </td></tr>
594 @
595 @ <tr><td class="tktDspLabel">Priority:</td><td>
596 @ <th1>combobox priority $priority_choices 1</th1>
597 @ </td></tr>
598 @
599 @ <tr><td class="tktDspLabel">Resolution:</td><td>
600 @ <th1>combobox resolution $resolution_choices 1</th1>
601 @ </td></tr>
602 @
603 @ <tr><td class="tktDspLabel">Subsystem:</td><td>
604 @ <th1>combobox subsystem $subsystem_choices 1</th1>
605 @ </td></tr>
606 @
607 @ <th1>enable_output [hascap e]</th1>
608 @ <tr><td class="tktDspLabel">Contact:</td><td>
609 @ <input type="text" name="private_contact" size="40"
610 @ value="$<private_contact>" />
611 @ </td></tr>
612 @ <th1>enable_output 1</th1>
613 @
614 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
615 @ <input type="text" name="foundin" size="50" value="$<foundin>" />
616 @ </td></tr>
617 @
618 @ <tr><td colspan="2">
619 @ Append Remark with format
620 @ <th1>combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1</th1>
621 @ from
622 @ <input type="text" name="username" value="$<username>" size="30" />:<br />
623 @ <textarea name="icomment" cols="80" rows="15"
624 @ wrap="virtual" class="wikiedit">$<icomment></textarea>
625 @ </td></tr>
626 @
627 @ <th1>enable_output [info exists preview]</th1>
628 @ <tr><td colspan="2">
629 @ Description Preview:<br><hr>
630 @ <th1>
631 @ if {$mutype eq "Wiki"} {
@@ -641,34 +641,34 @@
641 @ }
642 @ </th1>
643 @ <hr>
644 @ </td></tr>
645 @ <th1>enable_output 1</th1>
646 @
647 @ <tr>
648 @ <td align="right">
649 @ <input type="submit" name="preview" value="Preview" />
650 @ </td>
651 @ <td align="left">See how the description will appear after formatting.</td>
652 @ </tr>
653 @
654 @ <th1>enable_output [info exists preview]</th1>
655 @ <tr>
656 @ <td align="right">
657 @ <input type="submit" name="submit" value="Submit" />
658 @ </td>
659 @ <td align="left">Apply the changes shown above</td>
660 @ </tr>
661 @ <th1>enable_output 1</th1>
662 @
663 @ <tr>
664 @ <td align="right">
665 @ <input type="submit" name="cancel" value="Cancel" />
666 @ </td>
667 @ <td>Abandon this edit</td>
668 @ </tr>
669 @
670 @ </table>
671 ;
672
673 /*
674 ** Return the code used to generate the edit ticket page
@@ -703,16 +703,16 @@
703 @ if {[hascap n]} {
704 @ html "<p>Enter a new ticket:</p>"
705 @ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
706 @ }
707 @ </th1>
708 @
709 @ <p>Choose a report format from the following list:</p>
710 @ <ol>
711 @ <th1>html $report_items</th1>
712 @ </ol>
713 @
714 @ <th1>
715 @ if {[hascap t q]} {
716 @ html "<p>Other options:</p>\n<ul>\n"
717 @ if {[hascap t]} {
718 @ html "<li><a href='rptnew'>New report format</a></li>\n"
@@ -750,11 +750,11 @@
750 }
751
752 /*
753 ** The default template ticket report format:
754 */
755 static char zDefaultReport[] =
756 @ SELECT
757 @ CASE WHEN status IN ('Open','Verified') THEN '#f2dcdc'
758 @ WHEN status='Review' THEN '#e8e8e8'
759 @ WHEN status='Fixed' THEN '#cfe8bd'
760 @ WHEN status='Tested' THEN '#bde5d6'
@@ -799,11 +799,11 @@
799 }
800
801 /*
802 ** The default template ticket key:
803 */
804 static const char zDefaultKey[] =
805 @ #ffffff Key:
806 @ #f2dcdc Active
807 @ #e8e8e8 Review
808 @ #cfe8bd Fixed
809 @ #bde5d6 Tested
@@ -880,7 +880,7 @@
880 @ <input type="submit" name="setup" value="Cancel" />
881 @ </p>
882 @ </div></form>
883 db_end_transaction(0);
884 style_footer();
885
886 }
887
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -115,11 +115,11 @@
115 void (*xRebuild)(void), /* Run after successful update */
116 int height /* Height of the edit box */
117 ){
118 const char *z;
119 int isSubmit;
120
121 login_check_credentials();
122 if( !g.perm.Setup ){
123 login_needed();
124 }
125 if( P("setup") ){
@@ -314,43 +314,43 @@
314 @ <td colspan="3">
315 @ Enter a one-line summary of the ticket:<br />
316 @ <input type="text" name="title" size="60" value="$<title>" />
317 @ </td>
318 @ </tr>
319 @
320 @ <tr>
321 @ <td align="right">Type:</td>
322 @ <td align="left"><th1>combobox type $type_choices 1</th1></td>
323 @ <td align="left">What type of ticket is this?</td>
324 @ </tr>
325 @
326 @ <tr>
327 @ <td align="right">Version:</td>
328 @ <td align="left">
329 @ <input type="text" name="foundin" size="20" value="$<foundin>" />
330 @ </td>
331 @ <td align="left">In what version or build number do you observe
332 @ the problem?</td>
333 @ </tr>
334 @
335 @ <tr>
336 @ <td align="right">Severity:</td>
337 @ <td align="left"><th1>combobox severity $severity_choices 1</th1></td>
338 @ <td align="left">How debilitating is the problem? How badly does the problem
339 @ affect the operation of the product?</td>
340 @ </tr>
341 @
342 @ <tr>
343 @ <td align="right">EMail:</td>
344 @ <td align="left">
345 @ <input type="text" name="private_contact" value="$<private_contact>"
346 @ size="30" />
347 @ </td>
348 @ <td align="left"><u>Not publicly visible</u>
349 @ Used by developers to contact you with questions.</td>
350 @ </tr>
351 @
352 @ <tr>
353 @ <td colspan="3">
354 @ Enter a detailed description of the problem.
355 @ For code defects, be sure to provide details on exactly how
356 @ the problem can be reproduced. Provide as much detail as
@@ -359,11 +359,11 @@
359 @ <br />
360 @ <th1>set nline [linecount $comment 50 10]</th1>
361 @ <textarea name="icomment" cols="80" rows="$nline"
362 @ wrap="virtual" class="wikiedit">$<icomment></textarea><br />
363 @ </tr>
364 @
365 @ <th1>enable_output [info exists preview]</th1>
366 @ <tr><td colspan="3">
367 @ Description Preview:<br /><hr />
368 @ <th1>
369 @ if {$mutype eq "Wiki"} {
@@ -378,28 +378,28 @@
378 @ wiki "<nowiki>$icomment\n</nowiki>"
379 @ }
380 @ </th1>
381 @ <hr /></td></tr>
382 @ <th1>enable_output 1</th1>
383 @
384 @ <tr>
385 @ <td><td align="left">
386 @ <input type="submit" name="preview" value="Preview" />
387 @ </td>
388 @ <td align="left">See how the description will appear after formatting.</td>
389 @ </tr>
390 @
391 @ <th1>enable_output [info exists preview]</th1>
392 @ <tr>
393 @ <td><td align="left">
394 @ <input type="submit" name="submit" value="Submit" />
395 @ </td>
396 @ <td align="left">After filling in the information above, press this
397 @ button to create the new ticket</td>
398 @ </tr>
399 @ <th1>enable_output 1</th1>
400 @
401 @ <tr>
402 @ <td><td align="left">
403 @ <input type="submit" name="cancel" value="Cancel" />
404 @ </td>
405 @ <td>Abandon and forget this ticket</td>
@@ -477,11 +477,11 @@
477 @ </tr>
478 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
479 @ <td colspan="3" valign="top" class="tktDspValue">
480 @ $<foundin>
481 @ </td></tr>
482 @
483 @ <th1>
484 @ if {[info exists comment] && [string length $comment]>10} {
485 @ html {
486 @ <tr><td class="tktDspLabel">Description:</td></tr>
487 @ <tr><td colspan="5" class="tktDspValue">
@@ -577,55 +577,55 @@
577 @ </th1>
578 @ <table cellpadding="5">
579 @ <tr><td class="tktDspLabel">Title:</td><td>
580 @ <input type="text" name="title" value="$<title>" size="60" />
581 @ </td></tr>
582 @
583 @ <tr><td class="tktDspLabel">Status:</td><td>
584 @ <th1>combobox status $status_choices 1</th1>
585 @ </td></tr>
586 @
587 @ <tr><td class="tktDspLabel">Type:</td><td>
588 @ <th1>combobox type $type_choices 1</th1>
589 @ </td></tr>
590 @
591 @ <tr><td class="tktDspLabel">Severity:</td><td>
592 @ <th1>combobox severity $severity_choices 1</th1>
593 @ </td></tr>
594 @
595 @ <tr><td class="tktDspLabel">Priority:</td><td>
596 @ <th1>combobox priority $priority_choices 1</th1>
597 @ </td></tr>
598 @
599 @ <tr><td class="tktDspLabel">Resolution:</td><td>
600 @ <th1>combobox resolution $resolution_choices 1</th1>
601 @ </td></tr>
602 @
603 @ <tr><td class="tktDspLabel">Subsystem:</td><td>
604 @ <th1>combobox subsystem $subsystem_choices 1</th1>
605 @ </td></tr>
606 @
607 @ <th1>enable_output [hascap e]</th1>
608 @ <tr><td class="tktDspLabel">Contact:</td><td>
609 @ <input type="text" name="private_contact" size="40"
610 @ value="$<private_contact>" />
611 @ </td></tr>
612 @ <th1>enable_output 1</th1>
613 @
614 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
615 @ <input type="text" name="foundin" size="50" value="$<foundin>" />
616 @ </td></tr>
617 @
618 @ <tr><td colspan="2">
619 @ Append Remark with format
620 @ <th1>combobox mutype {Wiki HTML {Plain Text} {[links only]}} 1</th1>
621 @ from
622 @ <input type="text" name="username" value="$<username>" size="30" />:<br />
623 @ <textarea name="icomment" cols="80" rows="15"
624 @ wrap="virtual" class="wikiedit">$<icomment></textarea>
625 @ </td></tr>
626 @
627 @ <th1>enable_output [info exists preview]</th1>
628 @ <tr><td colspan="2">
629 @ Description Preview:<br><hr>
630 @ <th1>
631 @ if {$mutype eq "Wiki"} {
@@ -641,34 +641,34 @@
641 @ }
642 @ </th1>
643 @ <hr>
644 @ </td></tr>
645 @ <th1>enable_output 1</th1>
646 @
647 @ <tr>
648 @ <td align="right">
649 @ <input type="submit" name="preview" value="Preview" />
650 @ </td>
651 @ <td align="left">See how the description will appear after formatting.</td>
652 @ </tr>
653 @
654 @ <th1>enable_output [info exists preview]</th1>
655 @ <tr>
656 @ <td align="right">
657 @ <input type="submit" name="submit" value="Submit" />
658 @ </td>
659 @ <td align="left">Apply the changes shown above</td>
660 @ </tr>
661 @ <th1>enable_output 1</th1>
662 @
663 @ <tr>
664 @ <td align="right">
665 @ <input type="submit" name="cancel" value="Cancel" />
666 @ </td>
667 @ <td>Abandon this edit</td>
668 @ </tr>
669 @
670 @ </table>
671 ;
672
673 /*
674 ** Return the code used to generate the edit ticket page
@@ -703,16 +703,16 @@
703 @ if {[hascap n]} {
704 @ html "<p>Enter a new ticket:</p>"
705 @ html "<ul><li><a href='tktnew'>New ticket</a></li></ul>"
706 @ }
707 @ </th1>
708 @
709 @ <p>Choose a report format from the following list:</p>
710 @ <ol>
711 @ <th1>html $report_items</th1>
712 @ </ol>
713 @
714 @ <th1>
715 @ if {[hascap t q]} {
716 @ html "<p>Other options:</p>\n<ul>\n"
717 @ if {[hascap t]} {
718 @ html "<li><a href='rptnew'>New report format</a></li>\n"
@@ -750,11 +750,11 @@
750 }
751
752 /*
753 ** The default template ticket report format:
754 */
755 static char zDefaultReport[] =
756 @ SELECT
757 @ CASE WHEN status IN ('Open','Verified') THEN '#f2dcdc'
758 @ WHEN status='Review' THEN '#e8e8e8'
759 @ WHEN status='Fixed' THEN '#cfe8bd'
760 @ WHEN status='Tested' THEN '#bde5d6'
@@ -799,11 +799,11 @@
799 }
800
801 /*
802 ** The default template ticket key:
803 */
804 static const char zDefaultKey[] =
805 @ #ffffff Key:
806 @ #f2dcdc Active
807 @ #e8e8e8 Review
808 @ #cfe8bd Fixed
809 @ #bde5d6 Tested
@@ -880,7 +880,7 @@
880 @ <input type="submit" name="setup" value="Cancel" />
881 @ </p>
882 @ </div></form>
883 db_end_transaction(0);
884 style_footer();
885
886 }
887
+24 -5
--- src/utf8.c
+++ src/utf8.c
@@ -190,11 +190,12 @@
190190
**
191191
*/
192192
void *fossil_utf8_to_filename(const char *zUtf8){
193193
#ifdef _WIN32
194194
int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195
- wchar_t *zUnicode = sqlite3_malloc( nChar * 2 );
195
+ /* Overallocate 6 chars, making some room for extended paths */
196
+ wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
196197
wchar_t *wUnicode = zUnicode;
197198
if( zUnicode==0 ){
198199
return 0;
199200
}
200201
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
@@ -207,17 +208,35 @@
207208
wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
208209
zUtf8 += 4;
209210
wUnicode += 4;
210211
}
211212
/*
212
- ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
213
- ** leave the ':' intact
214
- */
213
+ ** If there is no "\\?\" prefix but there is a drive or UNC
214
+ ** path prefix and the path is larger than MAX_PATH chars,
215
+ ** no Win32 API function can handle that unless it is
216
+ ** prefixed with the extended path prefix. See:
217
+ ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
218
+ **/
215219
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
216
- && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
220
+ && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){
221
+ if( wUnicode==zUnicode && nChar>MAX_PATH){
222
+ memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
223
+ memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
224
+ wUnicode += 4;
225
+ }
226
+ /*
227
+ ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
228
+ ** leave the ':' intact but translate the backslash to a slash.
229
+ */
217230
wUnicode[2] = '\\';
218231
wUnicode += 3;
232
+ }else if( wUnicode==zUnicode && nChar>MAX_PATH
233
+ && (zUtf8[0]=='\\' || zUtf8[0]=='/')
234
+ && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){
235
+ memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t));
236
+ memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t));
237
+ wUnicode += 7;
219238
}
220239
/*
221240
** In the remainder of the path, translate invalid characters to
222241
** characters in the Unicode private use area. This is what makes
223242
** Win32 fossil.exe work well in a Cygwin environment even when a
224243
--- src/utf8.c
+++ src/utf8.c
@@ -190,11 +190,12 @@
190 **
191 */
192 void *fossil_utf8_to_filename(const char *zUtf8){
193 #ifdef _WIN32
194 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195 wchar_t *zUnicode = sqlite3_malloc( nChar * 2 );
 
196 wchar_t *wUnicode = zUnicode;
197 if( zUnicode==0 ){
198 return 0;
199 }
200 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
@@ -207,17 +208,35 @@
207 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
208 zUtf8 += 4;
209 wUnicode += 4;
210 }
211 /*
212 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
213 ** leave the ':' intact
214 */
 
 
 
215 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
216 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
 
 
 
 
 
 
 
 
 
217 wUnicode[2] = '\\';
218 wUnicode += 3;
 
 
 
 
 
 
219 }
220 /*
221 ** In the remainder of the path, translate invalid characters to
222 ** characters in the Unicode private use area. This is what makes
223 ** Win32 fossil.exe work well in a Cygwin environment even when a
224
--- src/utf8.c
+++ src/utf8.c
@@ -190,11 +190,12 @@
190 **
191 */
192 void *fossil_utf8_to_filename(const char *zUtf8){
193 #ifdef _WIN32
194 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195 /* Overallocate 6 chars, making some room for extended paths */
196 wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
197 wchar_t *wUnicode = zUnicode;
198 if( zUnicode==0 ){
199 return 0;
200 }
201 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
@@ -207,17 +208,35 @@
208 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209 zUtf8 += 4;
210 wUnicode += 4;
211 }
212 /*
213 ** If there is no "\\?\" prefix but there is a drive or UNC
214 ** path prefix and the path is larger than MAX_PATH chars,
215 ** no Win32 API function can handle that unless it is
216 ** prefixed with the extended path prefix. See:
217 ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
218 **/
219 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
220 && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){
221 if( wUnicode==zUnicode && nChar>MAX_PATH){
222 memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
223 memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
224 wUnicode += 4;
225 }
226 /*
227 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
228 ** leave the ':' intact but translate the backslash to a slash.
229 */
230 wUnicode[2] = '\\';
231 wUnicode += 3;
232 }else if( wUnicode==zUnicode && nChar>MAX_PATH
233 && (zUtf8[0]=='\\' || zUtf8[0]=='/')
234 && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){
235 memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t));
236 memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t));
237 wUnicode += 7;
238 }
239 /*
240 ** In the remainder of the path, translate invalid characters to
241 ** characters in the Unicode private use area. This is what makes
242 ** Win32 fossil.exe work well in a Cygwin environment even when a
243
--- test/file1.test
+++ test/file1.test
@@ -33,5 +33,10 @@
3333
simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
3434
simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
3535
simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
3636
simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
3737
simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
38
+
39
+if {$::tcl_platform(os)=="Windows NT"} {
40
+ simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {}
41
+ simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {}
42
+}
3843
--- test/file1.test
+++ test/file1.test
@@ -33,5 +33,10 @@
33 simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
34 simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
35 simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
36 simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
37 simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
 
 
 
 
 
38
--- test/file1.test
+++ test/file1.test
@@ -33,5 +33,10 @@
33 simplify-name 103 a/b a/b /a/b /a/b a///b a/b ///a///b///// //a/b
34 simplify-name 104 a/b/../c/ a/c /a/b/../c /a/c /a/b//../c /a/c /a/b/..///c /a/c
35 simplify-name 105 a/b/../../x/y x/y /a/b/../../x/y /x/y
36 simplify-name 106 a/b/../../../x/y ../x/y /a/b/../../../x/y /../x/y
37 simplify-name 107 a/./b/.././../x/y x/y a//.//b//..//.//..//x//y/// x/y
38
39 if {$::tcl_platform(os)=="Windows NT"} {
40 simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {}
41 simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {}
42 }
43
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -89,11 +89,11 @@
8989
9090
# define the sqlite shell files, which need special flags on compile
9191
SQLITESHELLSRC=shell.c
9292
ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
9393
SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94
-SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
94
+SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=win32_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
9595
9696
# define the th scripting files, which need special flags on compile
9797
THSRC=th.c th_lang.c
9898
ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
9999
THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100100
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -89,11 +89,11 @@
89
90 # define the sqlite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94 SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
95
96 # define the th scripting files, which need special flags on compile
97 THSRC=th.c th_lang.c
98 ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
99 THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -89,11 +89,11 @@
89
90 # define the sqlite shell files, which need special flags on compile
91 SQLITESHELLSRC=shell.c
92 ORIGSQLITESHELLSRC=$(foreach sf,$(SQLITESHELLSRC),$(SRCDIR)$(sf))
93 SQLITESHELLOBJ=$(foreach sf,$(SQLITESHELLSRC),$(sf:.c=.obj))
94 SQLITESHELLDEFINES=-Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=win32_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
95
96 # define the th scripting files, which need special flags on compile
97 THSRC=th.c th_lang.c
98 ORIGTHSRC=$(foreach sf,$(THSRC),$(SRCDIR)$(sf))
99 THOBJ=$(foreach sf,$(THSRC),$(sf:.c=.obj))
100
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,11 +26,11 @@
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
2929
SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
3030
31
-SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
31
+SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=win32_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
3333
SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
3535
OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3636
3737
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,11 +26,11 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,11 +26,11 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=win32_access -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1704,18 +1704,19 @@
17041704
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
17051705
-DSQLITE_THREADSAFE=0 \
17061706
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
17071707
-DSQLITE_OMIT_DEPRECATED \
17081708
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709
- -D_HAVE_SQLITE_CONFIG_H \
1709
+ -D_HAVE__MINGW_H \
17101710
-DSQLITE_USE_MALLOC_H \
17111711
-DSQLITE_USE_MSIZE
17121712
17131713
SHELL_OPTIONS = -Dmain=sqlite3_shell \
17141714
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
17151715
-DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
17161716
-DSQLITE_SHELL_DBNAME_PROC=fossil_open \
1717
+ -Daccess=win32_access \
17171718
-Dgetenv=fossil_getenv \
17181719
-Dfopen=fossil_fopen
17191720
17201721
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw
17211722
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
17221723
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1704,18 +1704,19 @@
1704 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1705 -DSQLITE_THREADSAFE=0 \
1706 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1707 -DSQLITE_OMIT_DEPRECATED \
1708 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709 -D_HAVE_SQLITE_CONFIG_H \
1710 -DSQLITE_USE_MALLOC_H \
1711 -DSQLITE_USE_MSIZE
1712
1713 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1714 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1715 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
1716 -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
 
1717 -Dgetenv=fossil_getenv \
1718 -Dfopen=fossil_fopen
1719
1720 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw
1721 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1722
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -1704,18 +1704,19 @@
1704 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1705 -DSQLITE_THREADSAFE=0 \
1706 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1707 -DSQLITE_OMIT_DEPRECATED \
1708 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709 -D_HAVE__MINGW_H \
1710 -DSQLITE_USE_MALLOC_H \
1711 -DSQLITE_USE_MSIZE
1712
1713 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1714 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1715 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
1716 -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
1717 -Daccess=win32_access \
1718 -Dgetenv=fossil_getenv \
1719 -Dfopen=fossil_fopen
1720
1721 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw
1722 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1723
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -1704,16 +1704,19 @@
17041704
-DSQLITE_ENABLE_LOCKING_STYLE=0 \
17051705
-DSQLITE_THREADSAFE=0 \
17061706
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
17071707
-DSQLITE_OMIT_DEPRECATED \
17081708
-DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709
- -D_HAVE_SQLITE_CONFIG_H \
1709
+ -D_HAVE__MINGW_H \
17101710
-DSQLITE_USE_MALLOC_H \
17111711
-DSQLITE_USE_MSIZE
17121712
17131713
SHELL_OPTIONS = -Dmain=sqlite3_shell \
17141714
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
1715
+ -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
1716
+ -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
1717
+ -Daccess=win32_access \
17151718
-Dgetenv=fossil_getenv \
17161719
-Dfopen=fossil_fopen
17171720
17181721
$(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw.mistachkin
17191722
$(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
17201723
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -1704,16 +1704,19 @@
1704 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1705 -DSQLITE_THREADSAFE=0 \
1706 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1707 -DSQLITE_OMIT_DEPRECATED \
1708 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709 -D_HAVE_SQLITE_CONFIG_H \
1710 -DSQLITE_USE_MALLOC_H \
1711 -DSQLITE_USE_MSIZE
1712
1713 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1714 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
 
 
 
1715 -Dgetenv=fossil_getenv \
1716 -Dfopen=fossil_fopen
1717
1718 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw.mistachkin
1719 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1720
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -1704,16 +1704,19 @@
1704 -DSQLITE_ENABLE_LOCKING_STYLE=0 \
1705 -DSQLITE_THREADSAFE=0 \
1706 -DSQLITE_DEFAULT_FILE_FORMAT=4 \
1707 -DSQLITE_OMIT_DEPRECATED \
1708 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
1709 -D_HAVE__MINGW_H \
1710 -DSQLITE_USE_MALLOC_H \
1711 -DSQLITE_USE_MSIZE
1712
1713 SHELL_OPTIONS = -Dmain=sqlite3_shell \
1714 -DSQLITE_OMIT_LOAD_EXTENSION=1 \
1715 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
1716 -DSQLITE_SHELL_DBNAME_PROC=fossil_open \
1717 -Daccess=win32_access \
1718 -Dgetenv=fossil_getenv \
1719 -Dfopen=fossil_fopen
1720
1721 $(OBJDIR)/sqlite3.o: $(SRCDIR)/sqlite3.c $(SRCDIR)/../win/Makefile.mingw.mistachkin
1722 $(XTCC) $(SQLITE_OPTIONS) $(SQLITE_CFLAGS) -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1723
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -102,10 +102,11 @@
102102
103103
SHELL_OPTIONS = /Dmain=sqlite3_shell \
104104
/DSQLITE_OMIT_LOAD_EXTENSION=1 \
105105
/DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
106106
/DSQLITE_SHELL_DBNAME_PROC=fossil_open \
107
+ /Daccess=win32_access \
107108
/Dgetenv=fossil_getenv \
108109
/Dfopen=fossil_fopen
109110
110111
SRC = add_.c \
111112
allrepo_.c \
112113
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -102,10 +102,11 @@
102
103 SHELL_OPTIONS = /Dmain=sqlite3_shell \
104 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
105 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
106 /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
 
107 /Dgetenv=fossil_getenv \
108 /Dfopen=fossil_fopen
109
110 SRC = add_.c \
111 allrepo_.c \
112
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -102,10 +102,11 @@
102
103 SHELL_OPTIONS = /Dmain=sqlite3_shell \
104 /DSQLITE_OMIT_LOAD_EXTENSION=1 \
105 /DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) \
106 /DSQLITE_SHELL_DBNAME_PROC=fossil_open \
107 /Daccess=win32_access \
108 /Dgetenv=fossil_getenv \
109 /Dfopen=fossil_fopen
110
111 SRC = add_.c \
112 allrepo_.c \
113
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -189,10 +189,11 @@
189189
#define DT_DIR S_IFDIR
190190
#define DT_FIFO S_IFIFO
191191
#define DT_SOCK S_IFSOCK
192192
#define DT_CHR S_IFCHR
193193
#define DT_BLK S_IFBLK
194
+#define DT_LNK S_IFLNK
194195
195196
/* Macros for converting between st_mode and d_type */
196197
#define IFTODT(mode) ((mode) & S_IFMT)
197198
#define DTTOIF(type) (type)
198199
199200
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -189,10 +189,11 @@
189 #define DT_DIR S_IFDIR
190 #define DT_FIFO S_IFIFO
191 #define DT_SOCK S_IFSOCK
192 #define DT_CHR S_IFCHR
193 #define DT_BLK S_IFBLK
 
194
195 /* Macros for converting between st_mode and d_type */
196 #define IFTODT(mode) ((mode) & S_IFMT)
197 #define DTTOIF(type) (type)
198
199
--- win/include/dirent.h
+++ win/include/dirent.h
@@ -189,10 +189,11 @@
189 #define DT_DIR S_IFDIR
190 #define DT_FIFO S_IFIFO
191 #define DT_SOCK S_IFSOCK
192 #define DT_CHR S_IFCHR
193 #define DT_BLK S_IFBLK
194 #define DT_LNK S_IFLNK
195
196 /* Macros for converting between st_mode and d_type */
197 #define IFTODT(mode) ((mode) & S_IFMT)
198 #define DTTOIF(type) (type)
199
200
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,26 @@
11
<title>Change Log</title>
22
33
<h2>Changes For Version 1.29 (as yet unreleased)</h2>
44
* Add the ability to display content and diffs for UTF16 text files
55
in the web interface.
6
+ * Add the "SaveAs..." button to the graphical diff display that results
7
+ from using the --tk option with the [/help/diff | fossil diff] command.
68
* Honor timezones in imports from git.
79
* The [/reports] page now requires Read ("o") permissions. The "byweek"
810
report now properly propagates the selected year through the event type
911
filter links.
1012
* The [/help/info | info command] now shows leaf status of the checkout.
1113
* Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
1214
* Add option --empty to the "[/help?cmd=open | fossil open]" command.
15
+ * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter.
16
+ * Add --ignore-space-at-sol and --ignore-space-at-eol options to
17
+ [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame],
18
+ [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff].
19
+ The option -w activates both of them.
20
+ * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff
21
+ and /vdiff UI pages.
1322
1423
<h2>Changes For Version 1.28 (2014-01-27)</h2>
1524
* Enhance [/help?cmd=/reports | /reports] to support event type filtering.
1625
* When cloning a repository, the user name passed via the URL (if any)
1726
is now used as the default local admin user's name.
1827
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,26 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.29 (as yet unreleased)</h2>
4 * Add the ability to display content and diffs for UTF16 text files
5 in the web interface.
 
 
6 * Honor timezones in imports from git.
7 * The [/reports] page now requires Read ("o") permissions. The "byweek"
8 report now properly propagates the selected year through the event type
9 filter links.
10 * The [/help/info | info command] now shows leaf status of the checkout.
11 * Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
12 * Add option --empty to the "[/help?cmd=open | fossil open]" command.
 
 
 
 
 
 
 
13
14 <h2>Changes For Version 1.28 (2014-01-27)</h2>
15 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
16 * When cloning a repository, the user name passed via the URL (if any)
17 is now used as the default local admin user's name.
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,17 +1,26 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.29 (as yet unreleased)</h2>
4 * Add the ability to display content and diffs for UTF16 text files
5 in the web interface.
6 * Add the "SaveAs..." button to the graphical diff display that results
7 from using the --tk option with the [/help/diff | fossil diff] command.
8 * Honor timezones in imports from git.
9 * The [/reports] page now requires Read ("o") permissions. The "byweek"
10 report now properly propagates the selected year through the event type
11 filter links.
12 * The [/help/info | info command] now shows leaf status of the checkout.
13 * Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
14 * Add option --empty to the "[/help?cmd=open | fossil open]" command.
15 * Enhanced [/help?cmd=/fileage|the fileage page] to support a glob parameter.
16 * Add --ignore-space-at-sol and --ignore-space-at-eol options to
17 [/help?cmd=annotate|fossil annotate], [/help?cmd=blame|fossil blame],
18 [/help?cmd=diff|fossil (g)diff], [/help?cmd=stash|fossil stash diff].
19 The option -w activates both of them.
20 * Add button "Ignore Whitespace" to /annotate, /blame, /ci, /fdiff
21 and /vdiff UI pages.
22
23 <h2>Changes For Version 1.28 (2014-01-27)</h2>
24 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
25 * When cloning a repository, the user name passed via the URL (if any)
26 is now used as the default local admin user's name.
27

Keyboard Shortcuts

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