1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Merge the latest trunk enhancements into the begin-concurrent branch.

FossilOrigin-Name: cb5e024b6aed12cb109b481e87d2a5457b5f4f5fc090571e5eef2bd8cf04aaf7
This commit is contained in:
drh
2025-03-22 14:12:46 +00:00
32 changed files with 953 additions and 296 deletions

View File

@@ -183,6 +183,47 @@ do_execsql_test 4.3 {
do_execsql_test 4.4 {
SELECT * FROM t0 LEFT JOIN t1 LEFT JOIN t2 ON (b NOTNULL)==(c IN ()) WHERE c;
} {xyz {} 7.0}
reset_db
do_execsql_test 5.0 {
CREATE TABLE t1 (c1);
INSERT INTO t1 VALUES (101);
CREATE TABLE t2 ( x );
INSERT INTO t2 VALUES(404);
}
do_execsql_test 5.1 {
SELECT 'val' in (
select 'val' from ( select 'valueB' from t1 order by 1 )
union all
select 'val'
);
} {1}
do_execsql_test 5.2 {
select * from t2
where 'val' in (
select 'val' from ( select 'valueB' from t1 order by 1 )
union all
select 'val'
);
} {404}
do_execsql_test 5.3 {
SELECT subq_1.c_0 as c_0
FROM ( SELECT 0 as c_0) as subq_1
WHERE (subq_1.c_0) IN (
SELECT subq_2.c_0 as c_0
FROM (
SELECT 0 as c_0
FROM t1 as ref_1
WHERE (ref_1.c1) = (2)
ORDER BY c_0 desc
) as subq_2
UNION ALL
SELECT 0 as c_0
);
} {0}
finish_test

View File

@@ -391,6 +391,21 @@ static void renderDbSqlForCLI(
if( nSql>0 && zSql[nSql-1]!='\n' ) fprintf(out, "\n");
}
/*
** Find the tail (the last component) of a pathname.
*/
static const char *pathTail(const char *zPath){
const char *zTail = zPath;
while( zPath[0] ){
if( zPath[0]=='/' && zPath[1]!=0 ) zTail = &zPath[1];
#ifndef __unix__
if( zPath[0]=='\\' && zPath[1]!=0 ) zTail = &zPath[1];
#endif
zPath++;
}
return zTail;
}
/*
** Read the complete content of a file into memory. Add a 0x00 terminator
** and return a pointer to the result.
@@ -1847,6 +1862,7 @@ static void showHelp(void){
"Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
"each database, checking for crashes and memory leaks.\n"
"Options:\n"
" --brief Output only a summary of results at the end\n"
" --cell-size-check Set the PRAGMA cell_size_check=ON\n"
" --dbid M..N Use only the databases where dbid between M and N\n"
" \"M..\" for M and afterwards. Just \"M\" for M only\n"
@@ -1873,6 +1889,7 @@ static void showHelp(void){
" --result-trace Show the results of each SQL command\n"
" --script Output CLI script instead of running tests\n"
" --skip N Skip the first N test cases\n"
" --slice M N Run only the M-th out of each group of N tests\n"
" --spinner Use a spinner to show progress\n"
" --sqlid M..N Use only SQL where sqlid between M..N\n"
" \"M..\" for M and afterwards. Just \"M\" for M only\n"
@@ -1887,6 +1904,7 @@ static void showHelp(void){
int main(int argc, char **argv){
sqlite3_int64 iBegin; /* Start time of this program */
int quietFlag = 0; /* True if --quiet or -q */
int briefFlag = 0; /* Output summary report at the end */
int verboseFlag = 0; /* True if --verbose or -v */
char *zInsSql = 0; /* SQL statement for --load-db or --load-sql */
int iFirstInsArg = 0; /* First argv[] for --load-db or --load-sql */
@@ -1934,6 +1952,8 @@ int main(int argc, char **argv){
int nV; /* How much to increase verbosity with -vvvv */
sqlite3_int64 tmStart; /* Start of each test */
int iEstTime = 0; /* LPF for the time-to-go */
int iSliceSz = 0; /* Divide the test space into this many pieces */
int iSliceIdx = 0; /* Only run the piece with this index */
sqlite3_config(SQLITE_CONFIG_URI,1);
registerOomSimulator();
@@ -1954,6 +1974,12 @@ int main(int argc, char **argv){
if( z[0]=='-' ){
z++;
if( z[0]=='-' ) z++;
if( strcmp(z,"brief")==0 ){
briefFlag = 1;
quietFlag = 1;
verboseFlag = 1;
eVerbosity = 0;
}else
if( strcmp(z,"cell-size-check")==0 ){
cellSzCkFlag = 1;
}else
@@ -2044,6 +2070,7 @@ int main(int argc, char **argv){
g.uRandom = atoi(argv[++i]);
}else
if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
briefFlag = 0;
quietFlag = 1;
verboseFlag = 0;
eVerbosity = 0;
@@ -2062,12 +2089,19 @@ int main(int argc, char **argv){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
nSkip = atoi(argv[++i]);
}else
if( strcmp(z,"slice")==0 ){
if( i>=argc-2 ) fatalError("missing arguments on %s", argv[i]);
iSliceIdx = integerValue(argv[++i]);
iSliceSz = integerValue(argv[++i]);
/* --slice implices --brief */
briefFlag = 1;
quietFlag = 1;
verboseFlag = 1;
eVerbosity = 0;
}else
if( strcmp(z,"spinner")==0 ){
bSpinner = 1;
}else
if( strcmp(z,"timer")==0 ){
bTimer = 1;
}else
if( strcmp(z,"sqlid")==0 ){
const char *zDotDot;
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
@@ -2093,10 +2127,14 @@ int main(int argc, char **argv){
fatalError("timeout is not available on non-unix systems");
#endif
}else
if( strcmp(z,"timer")==0 ){
bTimer = 1;
}else
if( strcmp(z,"vdbe-debug")==0 ){
bVdbeDebug = 1;
}else
if( strcmp(z,"verbose")==0 ){
briefFlag = 0;
quietFlag = 0;
verboseFlag++;
eVerbosity++;
@@ -2163,6 +2201,12 @@ int main(int argc, char **argv){
fatalError("cannot import into more than one database");
}
}
if( iSliceSz<=iSliceIdx
|| iSliceSz<=0
|| iSliceIdx<0
){
iSliceSz = iSliceIdx = 0;
}
/* Process each source database separately */
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
@@ -2452,6 +2496,10 @@ int main(int argc, char **argv){
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
tmStart = timeOfDay();
if( isDbSql(pSql->a, pSql->sz) ){
if( iSliceSz>0 && (nTest%iSliceSz)!=iSliceIdx ){
nTest++;
continue;
}
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
if( bScript ){
/* No progress output */
@@ -2510,6 +2558,10 @@ int main(int argc, char **argv){
for(pDb=g.pFirstDb; pDb; pDb=pDb->pNext){
int openFlags;
const char *zVfs = "inmem";
if( iSliceSz>0 && (nTest%iSliceSz)!=iSliceIdx ){
nTest++;
continue;
}
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
pSql->id, pDb->id);
if( bScript ){
@@ -2616,7 +2668,20 @@ int main(int argc, char **argv){
}
}
}
if( bScript ){
if( briefFlag ){
sqlite3_int64 iElapse = timeOfDay() - iBegin;
if( iSliceSz>0 ){
printf("%s %s: slice %d/%d of %d tests, %d.%03d seconds\n",
pathTail(argv[0]), pathTail(g.zDbFile),
iSliceIdx, iSliceSz, nTest,
(int)(iElapse/1000), (int)(iElapse%1000));
}else{
printf("%s %s: 0 errors, %d tests, %d.%03d seconds\n",
pathTail(argv[0]), pathTail(g.zDbFile), nTest,
(int)(iElapse/1000), (int)(iElapse%1000));
}
iBegin = timeOfDay();
}else if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
@@ -2634,6 +2699,7 @@ int main(int argc, char **argv){
} /* End loop over all source databases */
if( !quietFlag && !bScript ){
sqlite3_int64 iElapse = timeOfDay() - iBegin;
if( g.nInvariant ){

Binary file not shown.

View File

@@ -1228,7 +1228,7 @@ do_test shell1-8.1 {
FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
}
} {0 47.49000000000000198951966012828052043914794921875}
do_test shell1-8.2 {
do_test_with_ansi_output shell1-8.2 {
catchcmd :memory: {
.mode box
SELECT ieee754(47.49) AS x;
@@ -1238,7 +1238,7 @@ SELECT ieee754(47.49) AS x;
├───────────────────────────────┤
│ ieee754(6683623321994527,-47) │
└───────────────────────────────┘}}
do_test shell1-8.3 {
do_test_with_ansi_output shell1-8.3 {
catchcmd ":memory: --box" {
select ieee754(6683623321994527,-47) as x;
}
@@ -1254,7 +1254,7 @@ do_test shell1-8.4 {
+------------------+-----+
| 6683623321994527 | -47 |
+------------------+-----+}}
do_test shell1-8.5 {
do_test_with_ansi_output shell1-8.5 {
catchcmd ":memory: --box" {
create table t(a text, b int);
insert into t values ('too long for one line', 1), ('shorter', NULL);

View File

@@ -224,24 +224,24 @@ do_test shell2-1.4.10 {
set res [catchcmd :memory: [string trim {
SELECT * FROM generate_series(9223372036854775807,9223372036854775807,1);
SELECT * FROM generate_series(9223372036854775807,9223372036854775807,-1);
SELECT avg(rowid),min(value),max(value) FROM generate_series(
SELECT avg(value),min(value),max(value) FROM generate_series(
-9223372036854775808,9223372036854775807,1085102592571150095);
SELECT * FROM generate_series(-9223372036854775808,9223372036854775807,
9223372036854775807);
SELECT value,rowid FROM generate_series(-4611686018427387904,
SELECT value FROM generate_series(-4611686018427387904,
4611686018427387904, 4611686018427387904) ORDER BY value DESC;
SELECT * FROM generate_series(0,-2,-1);
SELECT * FROM generate_series(0,-2);
SELECT * FROM generate_series(0,2) LIMIT 3;}]]
} {0 {9223372036854775807
9223372036854775807
9.5|-9223372036854775808|9223372036854775807
-0.5|-9223372036854775808|9223372036854775807
-9223372036854775808
-1
9223372036854775806
4611686018427387904|3
0|2
-4611686018427387904|1
4611686018427387904
0
-4611686018427387904
0
-1
-2

View File

@@ -140,7 +140,7 @@ do_test shell4-3.1 {
close $fd
exec $::CLI_ONLY :memory: --interactive ".read t1.txt"
} {squirrel}
do_test shell4-3.2 {
do_test_with_ansi_output shell4-3.2 {
set fd [open t1.txt wb]
puts $fd "SELECT 'pound: \302\243';"
close $fd

View File

@@ -553,7 +553,7 @@ Columns renamed during .import shell5.csv due to duplicates:
# Tests for preserving utf-8 that is not also ASCII.
#
do_test shell5-6.1 {
do_test_with_ansi_output shell5-6.1 {
set out [open shell5.csv w]
fconfigure $out -translation lf
puts $out {あい,うえお}
@@ -566,7 +566,7 @@ SELECT * FROM t1;}
} {0 { あい = 1
うえお = 2}}
do_test shell5-6.2 {
do_test_with_ansi_output shell5-6.2 {
set out [open shell5.csv w]
fconfigure $out -translation lf
puts $out {1,2}

View File

@@ -35,7 +35,7 @@ do_execsql_test shellA-1.0 {
# Initial verification that the database created correctly
# and that our calls to the CLI are working.
#
do_test shellA-1.2 {
do_test_with_ansi_output shellA-1.2 {
exec {*}$CLI test.db {.mode box --escape symbol} {SELECT * FROM t1;}
} {
┌───┬──────────────────────────┐
@@ -67,7 +67,7 @@ do_test shellA-1.3 {
} {
^[[31mVT-100 codes^[[0m
}
do_test shellA-1.4 {
do_test_with_ansi_output shellA-1.4 {
exec {*}$CLI test.db --escape symbol {SELECT x FROM t1 WHERE a=2;}
} {
␛[31mVT-100 codes␛[0m
@@ -77,7 +77,7 @@ do_test shellA-1.5 {
} {
^[[31mVT-100 codes^[[0m
}
do_test shellA-1.6 {
do_test_with_ansi_output shellA-1.6 {
exec {*}$CLI test.db {.mode list --escape symbol} {SELECT x FROM t1 WHERE a=2;}
} {
␛[31mVT-100 codes␛[0m
@@ -134,7 +134,7 @@ do_test shellA-2.4 {
# ".mode line"
#
do_test shellA-3.1 {
do_test_with_ansi_output shellA-3.1 {
exec {*}$CLI test.db --line --escape symbol \
{SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
} {
@@ -177,7 +177,7 @@ line
# ".mode box"
#
do_test shellA-4.1 {
do_test_with_ansi_output shellA-4.1 {
exec {*}$CLI test.db --box --escape ascii \
{SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
} {
@@ -196,7 +196,7 @@ do_test shellA-4.1 {
│ 8 │ last line │
└───┴──────────────────────────┘
}
do_test shellA-4.2 {
do_test_with_ansi_output shellA-4.2 {
exec {*}$CLI test.db {.mode qbox} {SELECT a, x FROM t1 WHERE a IN (1,2,6,7,8)}
} {
┌───┬───────────────────────────────────────────┐

View File

@@ -61,10 +61,10 @@ do_execsql_test tabfunc01-1.8 {
} {30 25 20 15 10 5 0}
do_execsql_test tabfunc01-1.9 {
SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC;
} {7 30 6 25 5 20 4 15 3 10 2 5 1 0}
} {30 30 25 25 20 20 15 15 10 10 5 5 0 0}
do_execsql_test tabfunc01-1.10 {
SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC;
} {7 30 6 25 5 20 4 15 3 10 2 5 1 0}
} {30 30 25 25 20 20 15 15 10 10 5 5 0 0}
do_execsql_test tabfunc01-1.20 {
CREATE VIEW v1(a,b) AS VALUES(1,2),(3,4);
@@ -383,7 +383,18 @@ do_execsql_test 1100 {
where (ref_3.value) in (select 1);
} {1}
# 2025-03-18 /forumpost/1e17219c88
# The generate_series() table-valued function is modified so that its
# rowid is always its value. That way it can be used on the RHS of a
# RIGHT JOIN.
#
do_execsql_test 1200 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(value INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT t1.value, t2.value
FROM t1 RIGHT JOIN generate_series(1,3,1) AS t2 USING(value);
} {1 1 2 2 3 3}
# Free up memory allocations
intarray_addr

View File

@@ -809,6 +809,15 @@ proc do_test {name cmd expected} {
flush stdout
}
# Like do_test except the test is not run in a slave interpreter
# on Windows because of issues with ANSI and UTF8 I/O on Win11.
#
proc do_test_with_ansi_output {name cmd expected} {
if {![info exists ::SLAVE] || $::tcl_platform(platform)!="windows"} {
uplevel 1 [list do_test $name $cmd $expected]
}
}
proc dumpbytes {s} {
set r ""
for {set i 0} {$i < [string length $s]} {incr i} {

19
test/vt100-a.sql Normal file
View File

@@ -0,0 +1,19 @@
/*
** Run this script using the "sqlite3" command-line shell
** test test formatting of output text that contains
** vt100 escape sequences.
*/
.mode box -escape off
CREATE TEMP TABLE t1(a,b,c);
INSERT INTO t1 VALUES
('one','twotwotwo','thirty-three'),
(unistr('\u001b[91mRED\u001b[0m'),'fourfour','fifty-five'),
('six','seven','eighty-eight');
.print With -escape off
SELECT * FROM t1;
.mode box -escape ascii
.print With -escape ascii
SELECT * FROM t1;
.mode box -escape symbol
.print With -escape symbol
SELECT * FROM t1;