In the CLI, if a command-line argument names a file and the filename ends
with .sql or .txt, then process that file as an SQL script. Use this feature for better testing. FossilOrigin-Name: 19cc0522e2255f21f6fb6af1442c2ba122fdd4deacd9ea2c181ce9e597b88770
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Back\sout\sthe\s--compat\soption\sfrom\sthe\sCLI.
|
||||
D 2025-12-13T00:13:40.858
|
||||
C In\sthe\sCLI,\sif\sa\scommand-line\sargument\snames\sa\sfile\sand\sthe\sfilename\sends\nwith\s.sql\sor\s.txt,\sthen\sprocess\sthat\sfile\sas\san\sSQL\sscript.\s\sUse\sthis\nfeature\sfor\sbetter\stesting.
|
||||
D 2025-12-13T21:11:49.724
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -737,7 +737,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 8d53771eb51a4ab5f970150c3a70969d8db79cd04a8774c2d296bbcf471a0dd0
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c 344518c1bba9c4636bf651b7642304abd2e7075ba35feb4bae42a51e5efe991f
|
||||
F src/shell.c.in 000a5c12e353b59b0a9276a7ff577804ba98f663528f818b91f8d25ea639fdee
|
||||
F src/shell.c.in e885e048418c366c5aa3252bb83bb0a61297054fdf829bc2283fb4fdd0e9bebb
|
||||
F src/sqlite.h.in 706cacea5308b0244fb6cec92e08310fb427a125375c64137cc1f878ae4cf5c0
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 5d5330f5f8461f5ce74960436ddcfa53ecd09c2b8b23901e22ae38aec3243998
|
||||
@@ -1038,7 +1038,7 @@ F test/dbfuzz.c fc566102f72c8af84ae8077b4faf7f056c571e6fa7a32e98b66e42b7505f47b6
|
||||
F test/dbfuzz001.test 6c9a4622029d69dc38926f115864b055cb2f39badd25ec22cbfb130c8ba8e9c3
|
||||
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
|
||||
F test/dbfuzz2.c 4b3c12de4d98b1b2d908ab03d217d4619e47c8b23d5e67f8a6f2b1bdee7cae23
|
||||
F test/dblwidth-a.sql eb4141518610e52f931a55a984310075e98dc31eee5a28ae806b1e35377be85a
|
||||
F test/dblwidth-a.sql 59dd59aa78ce8fd8ab631a3816516831f4e947b143039257e6fe132c3cea4171
|
||||
F test/dbpage.test 63fab1eb026bada121107e53436fa749bbf83281dc9dea17af422f7a5c0f289f
|
||||
F test/dbpagefault.test ea39de2ca86041a9c6df1135645180a76d0a8da93ac159e2fafe38e39636530b
|
||||
F test/dbstatus.test 4a4221a883025ffd39696b3d1b3910b928fb097d77e671351acb35f3aed42759
|
||||
@@ -1441,7 +1441,7 @@ F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
|
||||
F test/mmapcorrupt.test 470fb44fe92e99c1d23701d156f8c17865f5b027063c9119dcfdb842791f4465
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
|
||||
F test/modeA.clitest 2db42f2814ba45d5e886fead881360e689bc27346cfc37e6bb46f63334bebc61
|
||||
F test/modeA.sql a804e7db0f672007a54f5b890737de7376ac4d08c6e309347e1c93be5d533c5c w test/modeA.clitest
|
||||
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test fac575e0b1b852025575a6a8357701d80933e98b5d2fe6d35ddaa68f92f6a1f7
|
||||
@@ -1620,7 +1620,7 @@ F test/shell7.test 43fd8e511c533bab5232e95c7b4be93b243451709e89582600d4b6e67693d
|
||||
F test/shell8.test 641cf21a99c59404c24e3062923734951c4099a6b6b6520de00cf7a1249ee871
|
||||
F test/shell9.test 8742a5b390cdcef6369f5aa223e415aa4255a4129ef249b177887dc635a87209
|
||||
F test/shellA.test 05cdaafa1f79913654487ce3aefa038d4106245d58f52e02faf506140a76d480
|
||||
F test/shellB.test de879b1ea7c25daf1a06b2c882b45a5d002e6580c81c57169ce47084cc6afb6b
|
||||
F test/shellB.test 41730c85658e1caa7e421454deefb3837fbfcd68be13a2a2f3a1ed92342fb0a4
|
||||
F test/shmlock.test 9f1f729a7fe2c46c88b156af819ac9b72c0714ac6f7246638a73c5752b5fd13c
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
@@ -2184,8 +2184,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 1ca31e1a297c0d53d068afb658ce6602887cda0f3eaf42cd629c4d1b7204f0b0
|
||||
R cf0d7b71ff1f31fdee2bbe0931020fd5
|
||||
P 850d5dbfb0f1eacd1e5213759810ec7e5eba4fcc0b2718dabccd5b269b126f1c
|
||||
R 7d316ab9e616e989cd7843c90446decc
|
||||
U drh
|
||||
Z b8e82ce5183ee7bea000d8d3bf76900c
|
||||
Z 1fff9a15000a4bc11ad069c242a3fa0b
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
850d5dbfb0f1eacd1e5213759810ec7e5eba4fcc0b2718dabccd5b269b126f1c
|
||||
19cc0522e2255f21f6fb6af1442c2ba122fdd4deacd9ea2c181ce9e597b88770
|
||||
|
||||
+88
-13
@@ -4122,6 +4122,52 @@ static int session_filter(void *pCtx, const char *zTab){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the size of the named file in bytes. Or return a negative
|
||||
** number if the file does not exist.
|
||||
*/
|
||||
static sqlite3_int64 fileSize(const char *zFile){
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
struct _stat64 x;
|
||||
if( _stat64(zFile, &x)!=0 ) return -1;
|
||||
return (sqlite3_int64)x.st_size;
|
||||
#else
|
||||
struct stat x;
|
||||
if( stat(zFile, &x)!=0 ) return -1;
|
||||
return (sqlite3_int64)x.st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if zFile is an SQLite database.
|
||||
**
|
||||
** Algorithm:
|
||||
** * If the file does not exist -> return false
|
||||
** * If the size of the file is not a multiple of 512 -> return false
|
||||
** * If sqlite3_open() fails -> return false
|
||||
** * if sqlite3_prepare() or sqlite3_step() fails -> return false
|
||||
** * Otherwise -> return true
|
||||
*/
|
||||
static int isDatabaseFile(const char *zFile, int openFlags){
|
||||
sqlite3 *db = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc;
|
||||
sqlite3_int64 sz = fileSize(zFile);
|
||||
if( sz<512 || (sz%512)!=0 ) return 0;
|
||||
if( sqlite3_open_v2(zFile, &db, openFlags, 0)==SQLITE_OK
|
||||
&& sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
|
||||
==SQLITE_OK
|
||||
&& sqlite3_step(pStmt)==SQLITE_ROW
|
||||
){
|
||||
rc = 1;
|
||||
}else{
|
||||
rc = 0;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to deduce the type of file for zName based on its content. Return
|
||||
** one of the SHELL_OPEN_* constants.
|
||||
@@ -4134,20 +4180,12 @@ static int session_filter(void *pCtx, const char *zTab){
|
||||
int deduceDatabaseType(const char *zName, int dfltZip, int openFlags){
|
||||
FILE *f;
|
||||
size_t n;
|
||||
sqlite3 *db = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
int rc = SHELL_OPEN_UNSPEC;
|
||||
char zBuf[100];
|
||||
if( access(zName,0)!=0 ) goto database_type_by_name;
|
||||
if( sqlite3_open_v2(zName, &db, openFlags, 0)==SQLITE_OK
|
||||
&& sqlite3_prepare_v2(db,"SELECT count(*) FROM sqlite_schema",-1,&pStmt,0)
|
||||
==SQLITE_OK
|
||||
&& sqlite3_step(pStmt)==SQLITE_ROW
|
||||
){
|
||||
if( isDatabaseFile(zName, openFlags) ){
|
||||
rc = SHELL_OPEN_NORMAL;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
if( rc==SHELL_OPEN_NORMAL ) return SHELL_OPEN_NORMAL;
|
||||
f = sqlite3_fopen(zName, "rb");
|
||||
if( f==0 ) goto database_type_by_name;
|
||||
@@ -4182,6 +4220,33 @@ database_type_by_name:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the text in z[] is the name of a readable file and that file appears
|
||||
** to contain SQL text and/or dot-commands, then return true. If z[] is
|
||||
** not a file, or if the file is unreadable, or if the file is a database
|
||||
** or anything else that is not SQL text and dot-commands, then return false.
|
||||
**
|
||||
** If the bLeaveUninit flag is set, then be sure to leave SQLite in an
|
||||
** uninitialized state. This means invoking sqlite3_shutdown() after any
|
||||
** SQLite API is used.
|
||||
**
|
||||
** Some amount of guesswork is involved in this decision.
|
||||
*/
|
||||
static int isScriptFile(const char *z, int bLeaveUninit){
|
||||
sqlite3_int64 sz = fileSize(z);
|
||||
if( sz<=0 ) return 0;
|
||||
if( (sz%512)==0 ){
|
||||
int rc = isDatabaseFile(z, SQLITE_OPEN_READONLY);
|
||||
if( bLeaveUninit ){
|
||||
sqlite3_shutdown();
|
||||
}
|
||||
if( rc ) return 0; /* Is a database */
|
||||
}
|
||||
if( sqlite3_strlike("*.sql",z,0)==0 ) return 1;
|
||||
if( sqlite3_strlike("*.txt",z,0)==0 ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
||||
/*
|
||||
** Reconstruct an in-memory database using the output from the "dbtotxt"
|
||||
@@ -12635,7 +12700,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do an initial pass through the command-line argument to locate
|
||||
/* Do an initial pass through the command-line arguments to locate
|
||||
** the name of the database file, the name of the initialization file,
|
||||
** the size of the alternative malloc heap, options affecting commands
|
||||
** or SQL run from the command line, and the first command to execute.
|
||||
@@ -12647,7 +12712,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
char *z;
|
||||
z = argv[i];
|
||||
if( z[0]!='-' || i>nOptsEnd ){
|
||||
if( data.aAuxDb->zDbFilename==0 ){
|
||||
if( data.aAuxDb->zDbFilename==0 && !isScriptFile(z,1) ){
|
||||
data.aAuxDb->zDbFilename = z;
|
||||
}else{
|
||||
/* Excess arguments are interpreted as SQL (or dot-commands) and
|
||||
@@ -12882,7 +12947,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
*/
|
||||
if( !noInit ) process_sqliterc(&data,zInitFile);
|
||||
|
||||
/* Make a second pass through the command-line argument and set
|
||||
/* Make a second pass through the command-line arguments and set
|
||||
** options. This second pass is delayed until after the initialization
|
||||
** file is processed so that the command-line arguments will override
|
||||
** settings in the initialization file.
|
||||
@@ -13107,7 +13172,17 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
*/
|
||||
for(i=0; i<nCmd; i++){
|
||||
echo_group_input(&data, azCmd[i]);
|
||||
if( azCmd[i][0]=='.' ){
|
||||
if( isScriptFile(azCmd[i],0) ){
|
||||
FILE *inSaved = data.in;
|
||||
i64 savedLineno = data.lineno;
|
||||
int res = 1;
|
||||
if( (data.in = openChrSource(azCmd[i]))!=0 ){
|
||||
res = process_input(&data, azCmd[i]);
|
||||
}
|
||||
data.in = inSaved;
|
||||
data.lineno = savedLineno;
|
||||
if( res ) i = nCmd;
|
||||
}else if( azCmd[i][0]=='.' ){
|
||||
char *zErrCtx = malloc( 64 );
|
||||
shell_check_oom(zErrCtx);
|
||||
sqlite3_snprintf(64,zErrCtx,"argv[%i]:",aiCmd[i]);
|
||||
|
||||
+34
-4
@@ -1,20 +1,50 @@
|
||||
#!sqlite3
|
||||
/*
|
||||
** Run this script using "sqlite3" to confirm that the command-line
|
||||
** shell properly handles the output of double-width characters.
|
||||
**
|
||||
** https://sqlite.org/forum/forumpost/008ac80276
|
||||
*/
|
||||
.testcase 100
|
||||
.mode box
|
||||
CREATE TABLE data(word TEXT, description TEXT);
|
||||
INSERT INTO data VALUES('〈οὐκέτι〉','Greek without dblwidth <...>');
|
||||
.print .mode box
|
||||
SELECT * FROM data;
|
||||
.check <<END
|
||||
╭────────────┬──────────────────────────────╮
|
||||
│ word │ description │
|
||||
╞════════════╪══════════════════════════════╡
|
||||
│ 〈οὐκέτι〉 │ Greek without dblwidth <...> │
|
||||
╰────────────┴──────────────────────────────╯
|
||||
END
|
||||
|
||||
.testcase 200
|
||||
.mode table
|
||||
.print .mode table
|
||||
SELECT * FROM data;
|
||||
.check <<END
|
||||
+------------+------------------------------+
|
||||
| word | description |
|
||||
+------------+------------------------------+
|
||||
| 〈οὐκέτι〉 | Greek without dblwidth <...> |
|
||||
+------------+------------------------------+
|
||||
END
|
||||
|
||||
.testcase 300
|
||||
.mode qbox
|
||||
.print .mode qbox
|
||||
SELECT * FROM data;
|
||||
.check <<END
|
||||
╭──────────────┬────────────────────────────────╮
|
||||
│ word │ description │
|
||||
╞══════════════╪════════════════════════════════╡
|
||||
│ '〈οὐκέτι〉' │ 'Greek without dblwidth <...>' │
|
||||
╰──────────────┴────────────────────────────────╯
|
||||
END
|
||||
|
||||
.testcase 400
|
||||
.mode column
|
||||
.print .mode column
|
||||
SELECT * FROM data;
|
||||
.check <<END
|
||||
word description
|
||||
---------- ----------------------------
|
||||
〈οὐκέτι〉 Greek without dblwidth <...>
|
||||
END
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!sqlite3
|
||||
#
|
||||
# 2025-11-12
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
+2
-1
@@ -39,6 +39,7 @@ proc do_clitest {name} {
|
||||
do_test shellB-$name $script {error count: 0}
|
||||
}
|
||||
|
||||
do_clitest modeA.clitest
|
||||
do_clitest modeA.sql
|
||||
do_clitest dblwidth-a.sql
|
||||
|
||||
finish_test
|
||||
|
||||
Reference in New Issue
Block a user