1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-01-06 08:01:16 +03:00

Change .echo on effect so that SQL is echoed before prepare. This slightly alters echoed output when multiple SQL statements are submitted at once. Also sync with trunk.

FossilOrigin-Name: c1eff632c41809214edea2850a93852fff66da3ca0dc393e8fe55e0976d422fd
This commit is contained in:
larrybr
2022-05-11 19:59:31 +00:00
19 changed files with 278 additions and 249 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sa\sstale\srequirement\smark.
D 2022-05-10T17:42:55.876
C Change\s.echo\son\seffect\sso\sthat\sSQL\sis\sechoed\sbefore\sprepare.\sThis\sslightly\salters\sechoed\soutput\swhen\smultiple\sSQL\sstatements\sare\ssubmitted\sat\sonce.\sAlso\ssync\swith\strunk.
D 2022-05-11T19:59:31.774
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -534,10 +534,10 @@ F src/mutex_unix.c dd2b3f1cc1863079bc1349ac0fec395a500090c4fe4e11ab775310a49f2f9
F src/mutex_w32.c caa50e1c0258ac4443f52e00fe8aaea73b6d0728bd8856bedfff822cae418541
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
F src/os.c b1c4f2d485961e9a5b6b648c36687d25047c252222e9660b7cc25a6e1ea436ab
F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 1f71ec8c87621f75c9c5ea973f5e8ce2f1d23fe760c01ed2814fe4b98b639825
F src/os_unix.c 02becb87c58245d2831f10f4f1a9108a465f8091cc598b2a9c78976f51a4e446
F src/os_win.c a8ea80037e81127ca01959daa87387cc135f325c88dc745376c4f760de852a10
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 42120492784fc9bcd9082b5c9b5e329b7318c357f9f3574a1bbfcf7418910356
@@ -553,8 +553,8 @@ F src/printf.c 512574910a45341c8ad244bd3d4939968ebdfde215645b676fff01cc46e90757
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c e9ee235c4151d2b7fa47435a219bfd30bf516a804d2f004639858087ebf3137b
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c cd17de0cab436f0efc4cfeeeef1b8e03c41c40335ec757eff68e341e6a3f763f
F src/shell.c.in af2e55dbd1b3d1ea5b8c677f815ec8180aefef22299996f8ae64090d02d51aca
F src/select.c 5096a2e8ab0511a413e7f5e45453fea4102d99c5636c46792581ae67899a76d7
F src/shell.c.in cf90e67622f3d1a1874a4080ac1ab6b9393a09ca4cf7d820b45a62ff2429a6c0
F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e
@@ -641,7 +641,7 @@ F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
F src/where.c aa585b89bd65a81e44bdfb871b55f65bf8fda88e1bc85efda6c236fe8d2bd788
F src/whereInt.h 4db5a877a9d1f38b5c928c1c84297c07f30b9a3bc1f5f66214cf1a8ef90a0556
F src/whereInt.h 8da918f392bf202ccc0ee61291455b33ad171d209445f1ff3eaf62e0b6f6b363
F src/wherecode.c 72f8eeed5527450c8e2258160a7bd04534a76c161230d100da0f43a86c6e29ac
F src/whereexpr.c e036477ac8424de50ae5b36a71103405d3f86b33ba11125ec7a2a99d501b0622
F src/window.c fff1b51757438c664e471d5184634e48dcdf8ea34b640f3b1b0810b1e06de18c
@@ -1141,14 +1141,14 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
F test/join.test e5f165dfd84fd46406ddae6614b0122c3bfa23a26ef62966442e1503c40d96aa
F test/join.test edeaff6edc1c1a2bcfebee343744e04d000f861c3d67cb653114f88565f8c955
F test/join2.test 466b07233820f5deee66a6c3bf6e4500c8bbf7b83649e67606f5f649c07928c0
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test d22b6cba8fb59ab3f1c82701434c360705eb12d4ce200c449f37b018fc47681a
F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/join7.test 8e72de4b45e5e930d18c305c7efe86015fb2552731e4e03ea226353036b0dab0
F test/join8.test 68f5ec206cd88610c19ab8edb4789a174a55cdb1732619a95db8fd33dbb13783
F test/join8.test fef259c42d56bbe150b777726b185b0bc060d4290daf9f879abc68321f8ad6db
F test/join9.test 9056ddd3b0c0f4f9d658f4521038d9a37dc23ead8ca9a505d0b0db2b6a471e05
F test/joinA.test 7eab225dc1c1ab258a5e62513a4ed7cabbd3db971d59d5d92f4fb6fa14c12f6a
F test/joinB.test 1b2ba3fc8568b49411787fccbf540570c148e9b6a53a30f80691cb6268098ded
@@ -1294,7 +1294,7 @@ F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035c
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 68b6dcd2667acdc643140d502c0b6c503abe444495cf5d16aa3a4f0391604020
F test/permutations.test cf5f31bab83a452288b2a050880152cdf99d62e9aab71948268d549debcc6942
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
F test/pragma.test cae534c12a033a5c319ccc94f50b32811acdef9f67bf19a82ff42697caccd69f
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@ -1397,14 +1397,14 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test eb2a7b768a1a20d70a8a205b11a8e3fd94b7f8d98d45aa9fb90433202609b0c3
F test/shell2.test 7a3a23a9f57b99453f1679b1fe8072cb30e382a622874c0c4d97695fadb0a787
F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c
F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759
F test/shell5.test 78a7a8516b1e7de560748881424f621321549023d3e5f7ed2e1c56497f64c06c
F test/shell1.test e4b4de56f454708e0747b52915135baa2cbfec4965406d6eaf02a4a5c22a9880
F test/shell2.test c536c2aab4852608f8a606262330797abc4d964a4c2c782a7760f54ea1f17a6a
F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
F test/shell4.test 7dc8a515705bc093d8ffe381670e8fa7a969661e8ed177c35c847e3c6dfc35e2
F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae
F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54915
F test/shmlock.test 3dbf017d34ab0c60abe6a44e447d3552154bd0c87b41eaf5ceacd408dd13fda5
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1482,7 +1482,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
F test/tester.tcl 18448c7801d44cc5f2690f54f803da49ed994b3968f73a393cff329e55926679
F test/tester.tcl 76771269dcc20b2c2d1d6f1175dd50d1eebddc004aebac865483f1829a5cd398
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1719,7 +1719,7 @@ F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c840
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
F test/vtab6.test fa609a4af96da30beceefa3cb624abe9be38c4747ab373d98179b24027d6b798
F test/vtab6.test 2525a2fe2e44ccbed1d758cb2977fb8ab8f07d5312ed8d8799d3529647d11f2f
F test/vtab7.test 70c6f4a1d6177144a8236e4172d5fba92e683440374664ad1f04851fbb335d3c
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
@@ -1777,7 +1777,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
F test/walvfs.test bccb3e0d235ef85e276f491d34db32c9ada1ea67be8d9f10aabe7b30319ec656
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
F test/where.test 8c6bbd0cae8feae142a7946e3484a802fa566bacf38452b1c3e48cb77321f9a4
F test/where.test d13cd7c24e80009d2b54e2f7a8893c457afa49c64f99359c9eb3fe668ba1d9d4
F test/where2.test 03c21a11e7b90e2845fc3c8b4002fc44cc2797fa74c86ee47d70bd7ea4f29ed6
F test/where3.test 5b4ffc0ac2ea0fe92f02b1244b7531522fe4d7bccf6fa8741d54e82c10e67753
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
@@ -1953,8 +1953,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P b7285f92bb9bfd8471e51ee5b6dbd7030b1f731683876e8ecca4a8c033688736
R 72fca0ee51c12a7f90dd5313ccb28616
U drh
Z 747367051d653b31d41a6b7e7bda4d15
P 3eda4030f73384abf18b97cd8a4606e10b23e382d1b72dff7526aebfde23e0af d55273e36e312336b8fc77dc771657d3b2c3437fbbd79f3be37701982560d634
R aa68945421e08aa1a970b0abab882c1b
U larrybr
Z c1c6d0984d4c87f2c4cc513f1bf72524
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
3eda4030f73384abf18b97cd8a4606e10b23e382d1b72dff7526aebfde23e0af
c1eff632c41809214edea2850a93852fff66da3ca0dc393e8fe55e0976d422fd

View File

@@ -39,6 +39,13 @@
# define SQLITE_MAX_PATHLEN FILENAME_MAX
#endif
/* Maximum number of symlinks that will be resolved while trying to
** expand a filename in xFullPathname() in the VFS.
*/
#ifndef SQLITE_MAX_SYMLINK
# define SQLITE_MAX_SYMLINK 200
#endif
/*
** The default size of a disk sector
*/

View File

@@ -6423,86 +6423,99 @@ static int unixAccess(
}
/*
** If the last component of the pathname in z[0]..z[j-1] is something
** other than ".." then back it out and return true. If the last
** component is empty or if it is ".." then return false.
** A pathname under construction
*/
static int unixBackupDir(const char *z, int *pJ){
int j = *pJ;
int i;
if( j<=0 ) return 0;
for(i=j-1; i>0 && z[i-1]!='/'; i--){}
if( i==0 ) return 0;
if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
*pJ = i-1;
return 1;
typedef struct DbPath DbPath;
struct DbPath {
int rc; /* Non-zero following any error */
int nSymlink; /* Number of symlinks resolved */
char *zOut; /* Write the pathname here */
int nOut; /* Bytes of space available to zOut[] */
int nUsed; /* Bytes of zOut[] currently being used */
};
/* Forward reference */
static void appendAllPathElements(DbPath*,const char*);
/*
** Append a single path element to the DbPath under construction
*/
static void appendOnePathElement(
DbPath *pPath, /* Path under construction, to which to append zName */
const char *zName, /* Name to append to pPath. Not zero-terminated */
int nName /* Number of significant bytes in zName */
){
assert( nName>0 );
assert( zName!=0 );
if( zName[0]=='.' ){
if( nName==1 ) return;
if( zName[1]=='.' && nName==2 ){
if( pPath->nUsed<=1 ){
pPath->rc = SQLITE_ERROR;
return;
}
assert( pPath->zOut[0]=='/' );
while( pPath->zOut[--pPath->nUsed]!='/' ){}
return;
}
}
if( pPath->nUsed + nName + 2 >= pPath->nOut ){
pPath->rc = SQLITE_ERROR;
return;
}
pPath->zOut[pPath->nUsed++] = '/';
memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
pPath->nUsed += nName;
#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
if( pPath->rc==SQLITE_OK ){
const char *zIn;
struct stat buf;
pPath->zOut[pPath->nUsed] = 0;
zIn = pPath->zOut;
if( osLstat(zIn, &buf)!=0 ){
if( errno!=ENOENT ){
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
}
}else if( S_ISLNK(buf.st_mode) ){
ssize_t got;
char zLnk[SQLITE_MAX_PATHLEN+2];
if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
pPath->rc = SQLITE_CANTOPEN_BKPT;
return;
}
got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
if( got<=0 || got>=sizeof(zLnk)-2 ){
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
return;
}
zLnk[got] = 0;
if( zLnk[0]=='/' ){
pPath->nUsed = 0;
}else{
pPath->nUsed -= nName + 1;
}
appendAllPathElements(pPath, zLnk);
}
}
#endif
}
/*
** Convert a relative pathname into a full pathname. Also
** simplify the pathname as follows:
**
** Remove all instances of /./
** Remove all isntances of /X/../ for any X
** Append all path elements in zPath to the DbPath under construction.
*/
static int mkFullPathname(
const char *zPath, /* Input path */
char *zOut, /* Output buffer */
int nOut /* Allocated size of buffer zOut */
static void appendAllPathElements(
DbPath *pPath, /* Path under construction, to which to append zName */
const char *zPath /* Path to append to pPath. Is zero-terminated */
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
int i, j;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
int i = 0;
int j = 0;
do{
while( zPath[i] && zPath[i]!='/' ){ i++; }
if( i>j ){
appendOnePathElement(pPath, &zPath[j], i-j);
}
iOff = sqlite3Strlen30(zOut);
zOut[iOff++] = '/';
}
if( (iOff+nPath+1)>nOut ){
/* SQLite assumes that xFullPathname() nul-terminates the output buffer
** even if it returns an error. */
zOut[iOff] = '\0';
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
/* Remove duplicate '/' characters. Except, two // at the beginning
** of a pathname is allowed since this is important on windows. */
for(i=j=1; zOut[i]; i++){
zOut[j++] = zOut[i];
while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
}
zOut[j] = 0;
assert( zOut[0]=='/' );
for(i=j=0; zOut[i]; i++){
if( zOut[i]=='/' ){
/* Skip over internal "/." directory components */
if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
i += 1;
continue;
}
/* If this is a "/.." directory component then back out the
** previous term of the directory if it is something other than "..".
*/
if( zOut[i+1]=='.'
&& zOut[i+2]=='.'
&& zOut[i+3]=='/'
&& unixBackupDir(zOut, &j)
){
i += 2;
continue;
}
}
if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
j++;
}
if( NEVER(j==0) ) zOut[j++] = '/';
zOut[j] = 0;
return SQLITE_OK;
j = i+1;
}while( zPath[i++] );
}
/*
@@ -6520,86 +6533,26 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
return mkFullPathname(zPath, zOut, nOut);
#else
int rc = SQLITE_OK;
int nByte;
int nLink = 0; /* Number of symbolic links followed so far */
const char *zIn = zPath; /* Input path for each iteration of loop */
char *zDel = 0;
assert( pVfs->mxPathname==MAX_PATHNAME );
UNUSED_PARAMETER(pVfs);
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
** function failing. This function could fail if, for example, the
** current working directory has been unlinked.
*/
SimulateIOError( return SQLITE_ERROR );
do {
/* Call stat() on path zIn. Set bLink to true if the path is a symbolic
** link, or false otherwise. */
int bLink = 0;
struct stat buf;
if( osLstat(zIn, &buf)!=0 ){
if( errno!=ENOENT ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
}
}else{
bLink = S_ISLNK(buf.st_mode);
DbPath path;
path.rc = 0;
path.nUsed = 0;
path.nSymlink = 0;
path.nOut = nOut;
path.zOut = zOut;
if( zPath[0]!='/' ){
char zPwd[SQLITE_MAX_PATHLEN+2];
if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
if( bLink ){
nLink++;
if( zDel==0 ){
zDel = sqlite3_malloc(nOut);
if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
}else if( nLink>=SQLITE_MAX_SYMLINKS ){
rc = SQLITE_CANTOPEN_BKPT;
}
if( rc==SQLITE_OK ){
nByte = osReadlink(zIn, zDel, nOut-1);
if( nByte<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
}else{
if( zDel[0]!='/' ){
int n;
for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
if( nByte+n+1>nOut ){
rc = SQLITE_CANTOPEN_BKPT;
}else{
memmove(&zDel[n], zDel, nByte+1);
memcpy(zDel, zIn, n);
nByte += n;
}
}
zDel[nByte] = '\0';
}
}
zIn = zDel;
}
assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
if( rc==SQLITE_OK && zIn!=zOut ){
rc = mkFullPathname(zIn, zOut, nOut);
}
if( bLink==0 ) break;
zIn = zOut;
}while( rc==SQLITE_OK );
sqlite3_free(zDel);
if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
return rc;
#endif /* HAVE_READLINK && HAVE_LSTAT */
appendAllPathElements(&path, zPwd);
}
appendAllPathElements(&path, zPath);
zOut[path.nUsed] = 0;
if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
if( path.nSymlink ) return SQLITE_OK_SYMLINK;
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points

View File

@@ -7707,7 +7707,7 @@ int sqlite3Select(
eDist = sqlite3WhereIsDistinct(pWInfo);
updateAccumulator(pParse, regAcc, pAggInfo, eDist);
if( eDist!=WHERE_DISTINCT_NOOP ){
struct AggInfo_func *pF = &pAggInfo->aFunc[0];
struct AggInfo_func *pF = pAggInfo->aFunc;
if( pF ){
fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
}

View File

@@ -1192,10 +1192,9 @@ struct ShellState {
#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */
#define SHFLG_EchoSql 0x00000080 /* .echo sql, before prepare */
#define SHFLG_HeaderSet 0x00000100 /* showHeader has been specified */
#define SHFLG_DumpDataOnly 0x00000200 /* .dump show data only */
#define SHFLG_DumpNoSys 0x00000400 /* .dump omits system tables */
#define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */
#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
/*
** Macros for testing and setting shellFlgs
@@ -3797,11 +3796,6 @@ static int shell_exec(
}
#endif
/* Echo the sql statement(s) if echoing SQL early (before prepare.) */
if( pArg && ShellHasFlag(pArg, SHFLG_EchoSql) ){
utf8_printf(pArg->out, "%s\n", zSql);
}
while( zSql[0] && (SQLITE_OK == rc) ){
static const char *zStmtSql;
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
@@ -3826,10 +3820,6 @@ static int shell_exec(
pArg->cnt = 0;
}
/* echo the sql statement if echo on */
if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
}
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
sqlite3_stmt *pExplain;
@@ -8443,7 +8433,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int savedShowHeader = p->showHeader;
int savedShellFlags = p->shellFlgs;
ShellClearFlag(p,
SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo|SHFLG_EchoSql
SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
|SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
@@ -8550,14 +8540,9 @@ static int do_meta_command(char *zLine, ShellState *p){
if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
if( nArg==2 ){
ShellClearFlag(p,(SHFLG_Echo|SHFLG_EchoSql));
if( strcmp(azArg[1],"sql")==0 ){
ShellSetFlag(p,(SHFLG_EchoSql));
}else{
setOrClearFlag(p, SHFLG_Echo, azArg[1]);
}
setOrClearFlag(p, SHFLG_Echo, azArg[1]);
}else{
raw_printf(stderr, "Usage: .echo on|off|sql\n");
raw_printf(stderr, "Usage: .echo on|off\n");
rc = 1;
}
}else
@@ -8872,16 +8857,12 @@ static int do_meta_command(char *zLine, ShellState *p){
failIfSafeMode(p, "cannot run .import in safe mode");
memset(&sCtx, 0, sizeof(sCtx));
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
if( p->mode==MODE_Ascii ){
xRead = ascii_read_one_field;
}else{
xRead = csv_read_one_field;
}
rc = 1;
for(i=1; i<nArg; i++){
char *z = azArg[i];
if( z[0]=='-' && z[1]=='-' ) z++;
@@ -8893,7 +8874,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
showHelp(p->out, "import");
rc = 1;
goto meta_command_exit;
}
}else if( strcmp(z,"-v")==0 ){
@@ -8915,7 +8895,6 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
showHelp(p->out, "import");
rc = 1;
goto meta_command_exit;
}
}
@@ -8923,7 +8902,6 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
zFile==0 ? "FILE" : "TABLE");
showHelp(p->out, "import");
rc = 1;
goto meta_command_exit;
}
seenInterrupt = 0;
@@ -8935,21 +8913,18 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nSep==0 ){
raw_printf(stderr,
"Error: non-null column separator required for import\n");
rc = 1;
goto meta_command_exit;
}
if( nSep>1 ){
raw_printf(stderr,
raw_printf(stderr,
"Error: multi-character column separators not allowed"
" for import\n");
rc = 1;
goto meta_command_exit;
}
nSep = strlen30(p->rowSeparator);
if( nSep==0 ){
raw_printf(stderr,
"Error: non-null row separator required for import\n");
rc = 1;
goto meta_command_exit;
}
if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
@@ -8963,7 +8938,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( nSep>1 ){
raw_printf(stderr, "Error: multi-character row separators not allowed"
" for import\n");
rc = 1;
goto meta_command_exit;
}
sCtx.cColSep = p->colSeparator[0];
@@ -8974,7 +8948,6 @@ static int do_meta_command(char *zLine, ShellState *p){
if( sCtx.zFile[0]=='|' ){
#ifdef SQLITE_OMIT_POPEN
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
rc = 1;
goto meta_command_exit;
#else
sCtx.in = popen(sCtx.zFile+1, "r");
@@ -8987,10 +8960,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
if( sCtx.in==0 ){
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
rc = 1;
import_cleanup(&sCtx);
goto meta_command_exit;
}
rc = 0;
if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
char zSep[2];
zSep[1] = 0;
@@ -9002,6 +8974,11 @@ static int do_meta_command(char *zLine, ShellState *p){
output_c_string(p->out, zSep);
utf8_printf(p->out, "\n");
}
sCtx.z = sqlite3_malloc64(120);
if( sCtx.z==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
}
/* Below, resources must be freed before exit. */
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
@@ -9677,7 +9654,7 @@ static int do_meta_command(char *zLine, ShellState *p){
if( eMode=='x' ){
/* spreadsheet mode. Output as CSV. */
newTempFile(p, "csv");
ShellClearFlag(p, SHFLG_Echo|SHFLG_EchoSql);
ShellClearFlag(p, SHFLG_Echo);
p->mode = MODE_Csv;
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
@@ -10639,8 +10616,7 @@ static int do_meta_command(char *zLine, ShellState *p){
goto meta_command_exit;
}
utf8_printf(p->out, "%12.12s: %s\n","echo",
(ShellHasFlag(p, SHFLG_EchoSql))
? "sql" : azBool[ShellHasFlag(p, SHFLG_Echo)]);
azBool[ShellHasFlag(p, SHFLG_Echo)]);
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
utf8_printf(p->out, "%12.12s: %s\n","explain",
p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
@@ -11488,6 +11464,9 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
return 0;
}
static void echo_group_input(ShellState *p, const char *zDo){
if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
}
/*
** Read input from *in and process it. If *in==0 then input
@@ -11537,14 +11516,13 @@ static int process_input(ShellState *p){
}
qss = quickscan(zLine, qss);
if( QSS_PLAINWHITE(qss) && nSql==0 ){
if( ShellHasFlag(p, SHFLG_Echo) )
printf("%s\n", zLine);
/* Just swallow single-line whitespace */
echo_group_input(p, zLine);
qss = QSS_Start;
continue;
}
if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
echo_group_input(p, zLine);
if( zLine[0]=='.' ){
rc = do_meta_command(zLine, p);
if( rc==2 ){ /* exit requested */
@@ -11577,6 +11555,7 @@ static int process_input(ShellState *p){
nSql += nLine;
}
if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
echo_group_input(p, zSql);
errCnt += runOneSqlLine(p, zSql, p->in, startline);
nSql = 0;
if( p->outCount ){
@@ -11588,13 +11567,14 @@ static int process_input(ShellState *p){
p->bSafeMode = p->bSafeModePersist;
qss = QSS_Start;
}else if( nSql && QSS_PLAINWHITE(qss) ){
if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
echo_group_input(p, zSql);
nSql = 0;
qss = QSS_Start;
}
}
if( nSql ){
/* This may be incomplete. Let the SQL parser deal with that. */
echo_group_input(p, zSql);
errCnt += runOneSqlLine(p, zSql, p->in, startline);
}
free(zSql);
@@ -11875,6 +11855,9 @@ int SQLITE_CDECL main(int argc, char **argv){
#else
int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
char **argv;
#endif
#ifdef SQLITE_DEBUG
sqlite3_uint64 mem_main_enter = sqlite3_memory_used();
#endif
char *zErrMsg = 0;
ShellState data;
@@ -12241,11 +12224,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.showHeader = 0;
ShellSetFlag(&data, SHFLG_HeaderSet);
}else if( strcmp(z,"-echo")==0 ){
ShellClearFlag(&data, SHFLG_EchoSql);
ShellSetFlag(&data, SHFLG_Echo);
}else if( strcmp(z,"-echo-sql")==0 ){
ShellClearFlag(&data, SHFLG_Echo);
ShellSetFlag(&data, SHFLG_EchoSql);
}else if( strcmp(z,"-eqp")==0 ){
data.autoEQP = AUTOEQP_on;
}else if( strcmp(z,"-eqpfull")==0 ){
@@ -12446,5 +12425,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
/* Clear the global data structure so that valgrind will detect memory
** leaks */
memset(&data, 0, sizeof(data));
#ifdef SQLITE_DEBUG
if( sqlite3_memory_used()>mem_main_enter ){
utf8_printf(stderr, "Memory leaked: %u bytes\n",
(unsigned int)(sqlite3_memory_used()-mem_main_enter));
}
#endif
return rc;
}

View File

@@ -41,7 +41,7 @@ typedef struct WhereRightJoin WhereRightJoin;
*/
struct WhereMemBlock {
WhereMemBlock *pNext; /* Next block in the chain */
u8 sz; /* Bytes of space */
u64 sz; /* Bytes of space */
};
/*

View File

@@ -250,6 +250,19 @@ do_test join-2.1 {
}
} {1 2 3 4 2 3 4 5 3 4 5 {}}
# EVIDENCE-OF: R-52129-05406 you can say things like "OUTER LEFT NATURAL
# JOIN" which means the same as "NATURAL LEFT OUTER JOIN".
do_test join-2.1b {
execsql {
SELECT * FROM t1 OUTER LEFT NATURAL JOIN t2;
}
} {1 2 3 4 2 3 4 5 3 4 5 {}}
do_test join-2.1c {
execsql {
SELECT * FROM t1 NATURAL LEFT OUTER JOIN t2;
}
} {1 2 3 4 2 3 4 5 3 4 5 {}}
# ticket #3522
do_test join-2.1.1 {
execsql2 {
@@ -328,6 +341,9 @@ do_test join-3.6 {
SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
}
} {1 {no such column: t3.a}}
# EVIDENCE-OF: R-47973-48020 you cannot say "INNER OUTER JOIN", because
# that would be contradictory.
do_test join-3.7 {
catchsql {
SELECT * FROM t1 INNER OUTER JOIN t2;

View File

@@ -20,6 +20,8 @@ ifcapable !vtab {
}
db null NULL
# EVIDENCE-OF: R-33754-02880 you can say "LEFT RIGHT JOIN" which is the
# same as "FULL JOIN".
do_execsql_test join8-10 {
CREATE TABLE t1(a,b,c);
CREATE TABLE t2(x,y);
@@ -226,6 +228,27 @@ do_execsql_test join8-7010 {
- - - - - - - - 305 5
- - - - - - - - 310 10
}
# EVIDENCE-OF: R-33754-02880 you can say "LEFT RIGHT JOIN" which is the
# same as "FULL JOIN".
do_execsql_test join8-7011 {
WITH t0 AS MATERIALIZED (
SELECT t1.*, t2.*, t3.*
FROM t1 INNER JOIN t2 ON t1.b=t2.b AND t2.x>0
RIGHT JOIN t3 ON t1.c=t3.c AND t3.y>0
)
SELECT * FROM t0 LEFT RIGHT JOIN t4 ON t0.a=t4.d AND t4.z>0
ORDER BY coalesce(t0.a, t0.y+200, t4.d);
} {
6 106 206 306 106 6 206 6 - -
- - - - - - 200 0 - -
- - - - - - 203 3 - -
- - - - - - 209 9 - -
- - - - - - - - 300 0
- - - - - - - - 305 5
- - - - - - - - 310 10
}
do_execsql_test join8-7020 {
EXPLAIN QUERY PLAN
WITH t0 AS MATERIALIZED (

View File

@@ -217,7 +217,8 @@ test_suite "valgrind" -prefix "" -description {
fail under valgrind) omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* *_err* wal.test \
shell*.test crash8.test atof1.test selectG.test \
shell2.test shell6.test shell7.test \
crash8.test atof1.test selectG.test \
tkt-fc62af4523.test numindex1.test corruptK.test
] -initialize {
set ::G(valgrind) 1

View File

@@ -23,7 +23,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
@@ -313,7 +313,7 @@ do_test shell1-3.4.2 {
# .echo ON|OFF Turn command echo on or off
do_test shell1-3.5.1 {
catchcmd "test.db" ".echo"
} {1 {Usage: .echo on|off|sql}}
} {1 {Usage: .echo on|off}}
do_test shell1-3.5.2 {
catchcmd "test.db" ".echo ON"
} {0 {}}
@@ -323,7 +323,7 @@ do_test shell1-3.5.3 {
do_test shell1-3.5.4 {
# too many arguments
catchcmd "test.db" ".echo OFF BAD"
} {1 {Usage: .echo on|off|sql}}
} {1 {Usage: .echo on|off}}
# .exit Exit this program
do_test shell1-3.6.1 {

View File

@@ -136,16 +136,13 @@ SELECT * FROM foo1; SELECT * FROM foo2;
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
1
SELECT * FROM foo2;
1
INSERT INTO foo1(a) VALUES(2);
INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1;
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1; SELECT * FROM foo2;
1
2
SELECT * FROM foo2;
1
2
}}
@@ -170,19 +167,16 @@ CREATE TABLE foo1(a);
INSERT INTO foo1(a) VALUES(1);
CREATE TABLE foo2(b);
INSERT INTO foo2(b) VALUES(1);
SELECT * FROM foo1;
SELECT * FROM foo1; SELECT * FROM foo2;
a
1
SELECT * FROM foo2;
b
1
INSERT INTO foo1(a) VALUES(2);
INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1;
INSERT INTO foo1(a) VALUES(2); INSERT INTO foo2(b) VALUES(2);
SELECT * FROM foo1; SELECT * FROM foo2;
a
1
2
SELECT * FROM foo2;
b
1
2

View File

@@ -22,7 +22,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db

View File

@@ -23,7 +23,8 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
set CLI_ONLY [test_find_cli]
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
@@ -130,13 +131,13 @@ do_test shell4-3.1 {
set fd [open t1.txt wb]
puts $fd "SELECT 'squirrel';"
close $fd
exec $::CLI :memory: --interactive ".read t1.txt"
exec $::CLI_ONLY :memory: --interactive ".read t1.txt"
} {squirrel}
do_test shell4-3.2 {
set fd [open t1.txt wb]
puts $fd "SELECT 'pound: \302\243';"
close $fd
exec $::CLI :memory: --interactive ".read t1.txt"
exec $::CLI_ONLY :memory: --interactive ".read t1.txt"
} {pound: £}
do_test shell4-4.1 {

View File

@@ -21,7 +21,7 @@
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set CLI [test_find_cli]
set CLI [test_cli_invocation]
db close
forcedelete test.db test.db-journal test.db-wal

View File

@@ -19,7 +19,7 @@ set testprefix shell8
ifcapable !vtab {
finish_test; return
}
set CLI [test_find_cli]
set CLI [test_cli_invocation]
# Check to make sure the shell has been compiled with ".archive" support.
#

View File

@@ -184,7 +184,7 @@ proc get_pwd {} {
set comSpec {C:\Windows\system32\cmd.exe}
}
return [string map [list \\ /] \
[string trim [exec -- $comSpec /c echo %CD%]]]
[string trim [exec -- $comSpec /c CD]]]
} else {
return [pwd]
}
@@ -2478,7 +2478,7 @@ proc test_find_binary {nm} {
}
# Find the name of the 'shell' executable (e.g. "sqlite3.exe") to use for
# the tests in shell[1-5].test. If no such executable can be found, invoke
# the tests in shell*.test. If no such executable can be found, invoke
# [finish_test ; return] in the callers context.
#
proc test_find_cli {} {
@@ -2487,6 +2487,37 @@ proc test_find_cli {} {
return $prog
}
# Find invocation of the 'shell' executable (e.g. "sqlite3.exe") to use
# for the tests in shell*.test with optional valgrind prefix when the
# environment variable SQLITE_CLI_VALGRIND_OPT is set. The set value
# operates as follows:
# empty or 0 => no valgrind prefix;
# 1 => valgrind options for memory leak check;
# other => use value as valgrind options.
# If shell not found, invoke [finish_test ; return] in callers context.
#
proc test_cli_invocation {} {
set prog [test_find_binary sqlite3]
if {$prog==""} { return -code return }
set vgrun [expr {[permutation]=="valgrind"}]
if {$vgrun || [info exists ::env(SQLITE_CLI_VALGRIND_OPT)]} {
if {$vgrun} {
set vgo "--quiet"
} else {
set vgo $::env(SQLITE_CLI_VALGRIND_OPT)
}
if {$vgo == 0 || $vgo eq ""} {
return $prog
} elseif {$vgo == 1} {
return "valgrind --quiet --leak-check=yes $prog"
} else {
return "valgrind $vgo $prog"
}
} else {
return $prog
}
}
# Find the name of the 'sqldiff' executable (e.g. "sqlite3.exe") to use for
# the tests in sqldiff tests. If no such executable can be found, invoke
# [finish_test ; return] in the callers context.

View File

@@ -277,11 +277,15 @@ do_test vtab6-3.6 {
SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
}
} {1 {no such column: t3.a}}
# EVIDENCE-OF: R-47973-48020 you cannot say "INNER OUTER JOIN", because
# that would be contradictory.
do_test vtab6-3.7 {
catchsql {
SELECT * FROM t1 INNER OUTER JOIN t2;
}
} {1 {unknown join type: INNER OUTER}}
do_test vtab6-3.7 {
catchsql {
SELECT * FROM t1 LEFT BOGUS JOIN t2;

View File

@@ -11,7 +11,6 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the use of indices in WHERE clases.
#
# $Id: where.test,v 1.50 2008/11/03 09:06:06 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -1603,4 +1602,19 @@ if {[permutation]!="valgrind"} {
} {0}
}
# 2022-05-10 dbsqlfuzz 4c5e3e89bc251d28378be88233f531b84ec66901
#
reset_db
do_execsql_test where-28.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
CREATE INDEX t1b ON t1(b,b,b,b,b,b,b,b,b,b,b,b,b);
INSERT INTO t1(a,b) VALUES(1,1),(15,2),(19,5);
UPDATE t1 SET b=999 WHERE a IN (SELECT 15) AND b IN (1,2);
SELECT * FROM t1;
} {
1 1
15 999
19 5
}
finish_test