Merge the latest trunk changes into the sessions branch.
FossilOrigin-Name: 110cfd6920cf3011aeaf7e586f8db867bfc69fbb
This commit is contained in:
@@ -38,6 +38,7 @@ run_test_suite pcache10
|
||||
run_test_suite pcache50
|
||||
run_test_suite pcache90
|
||||
run_test_suite pcache100
|
||||
run_test_suite prepare
|
||||
|
||||
if {$::tcl_platform(platform)=="unix"} {
|
||||
ifcapable !default_autovacuum {
|
||||
|
||||
@@ -137,6 +137,7 @@ do_test alter2-1.8 {
|
||||
do_test alter2-1.9 {
|
||||
# ALTER TABLE abc ADD COLUMN d;
|
||||
alter_table abc {CREATE TABLE abc(a, b, c, d);}
|
||||
if {[permutation] == "prepare"} { db cache flush }
|
||||
execsql { SELECT * FROM abc; }
|
||||
execsql {
|
||||
UPDATE abc SET d = 11 WHERE c IS NULL AND a<4;
|
||||
|
||||
@@ -248,4 +248,14 @@ do_execsql_test autoindex1-600 {
|
||||
0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?) (~8 rows)}
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test autoindex1-700 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t5 (~100000 rows)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+3
-3
@@ -57,17 +57,17 @@ do_test collate5-1.1 {
|
||||
execsql {
|
||||
SELECT DISTINCT a FROM collate5t1;
|
||||
}
|
||||
} {A B N}
|
||||
} {a b n}
|
||||
do_test collate5-1.2 {
|
||||
execsql {
|
||||
SELECT DISTINCT b FROM collate5t1;
|
||||
}
|
||||
} {{} Apple apple banana}
|
||||
} {apple Apple banana {}}
|
||||
do_test collate5-1.3 {
|
||||
execsql {
|
||||
SELECT DISTINCT a, b FROM collate5t1;
|
||||
}
|
||||
} {A Apple a apple B banana N {}}
|
||||
} {a apple A Apple b banana n {}}
|
||||
|
||||
# Ticket #3376
|
||||
#
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
# 2011 July 1
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is the DISTINCT modifier.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set testprefix distinct
|
||||
|
||||
|
||||
proc is_distinct_noop {sql} {
|
||||
set sql1 $sql
|
||||
set sql2 [string map {DISTINCT ""} $sql]
|
||||
|
||||
set program1 [list]
|
||||
set program2 [list]
|
||||
db eval "EXPLAIN $sql1" {
|
||||
if {$opcode != "Noop"} { lappend program1 $opcode }
|
||||
}
|
||||
db eval "EXPLAIN $sql2" {
|
||||
if {$opcode != "Noop"} { lappend program2 $opcode }
|
||||
}
|
||||
|
||||
return [expr {$program1==$program2}]
|
||||
}
|
||||
|
||||
proc do_distinct_noop_test {tn sql} {
|
||||
uplevel [list do_test $tn [list is_distinct_noop $sql] 1]
|
||||
}
|
||||
proc do_distinct_not_noop_test {tn sql} {
|
||||
uplevel [list do_test $tn [list is_distinct_noop $sql] 0]
|
||||
}
|
||||
|
||||
proc do_temptables_test {tn sql temptables} {
|
||||
uplevel [list do_test $tn [subst -novar {
|
||||
set ret ""
|
||||
db eval "EXPLAIN [set sql]" {
|
||||
if {$opcode == "OpenEphemeral"} {
|
||||
if {$p5 != "10" && $p5!="00"} { error "p5 = $p5" }
|
||||
if {$p5 == "10"} {
|
||||
lappend ret hash
|
||||
} else {
|
||||
lappend ret btree
|
||||
}
|
||||
}
|
||||
}
|
||||
set ret
|
||||
}] $temptables]
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - distinct-1.* - check that the planner correctly
|
||||
# detects cases where a UNIQUE index means that a DISTINCT clause is
|
||||
# redundant. Currently the planner only detects such cases when there
|
||||
# is a single table in the FROM clause.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c, d);
|
||||
CREATE UNIQUE INDEX i1 ON t1(b, c);
|
||||
CREATE UNIQUE INDEX i2 ON t1(d COLLATE nocase);
|
||||
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
|
||||
|
||||
CREATE TABLE t3(c1 PRIMARY KEY, c2);
|
||||
CREATE INDEX i3 ON t3(c2);
|
||||
}
|
||||
foreach {tn noop sql} {
|
||||
|
||||
1 1 "SELECT DISTINCT b, c FROM t1"
|
||||
2 1 "SELECT DISTINCT c FROM t1 WHERE b = ?"
|
||||
3 1 "SELECT DISTINCT rowid FROM t1"
|
||||
4 1 "SELECT DISTINCT rowid, a FROM t1"
|
||||
5 1 "SELECT DISTINCT x FROM t2"
|
||||
6 1 "SELECT DISTINCT * FROM t2"
|
||||
7 1 "SELECT DISTINCT * FROM (SELECT * FROM t2)"
|
||||
|
||||
8 1 "SELECT DISTINCT * FROM t1"
|
||||
|
||||
8 0 "SELECT DISTINCT a, b FROM t1"
|
||||
|
||||
9 0 "SELECT DISTINCT c FROM t1 WHERE b IN (1,2)"
|
||||
10 0 "SELECT DISTINCT c FROM t1"
|
||||
11 0 "SELECT DISTINCT b FROM t1"
|
||||
|
||||
12 0 "SELECT DISTINCT a, d FROM t1"
|
||||
13 0 "SELECT DISTINCT a, b, c COLLATE nocase FROM t1"
|
||||
14 1 "SELECT DISTINCT a, d COLLATE nocase FROM t1"
|
||||
15 0 "SELECT DISTINCT a, d COLLATE binary FROM t1"
|
||||
16 1 "SELECT DISTINCT a, b, c COLLATE binary FROM t1"
|
||||
|
||||
16 0 "SELECT DISTINCT t1.rowid FROM t1, t2"
|
||||
17 0 { /* Technically, it would be possible to detect that DISTINCT
|
||||
** is a no-op in cases like the following. But SQLite does not
|
||||
** do so. */
|
||||
SELECT DISTINCT t1.rowid FROM t1, t2 WHERE t1.rowid=t2.rowid }
|
||||
|
||||
18 1 "SELECT DISTINCT c1, c2 FROM t3"
|
||||
19 1 "SELECT DISTINCT c1 FROM t3"
|
||||
20 1 "SELECT DISTINCT * FROM t3"
|
||||
21 0 "SELECT DISTINCT c2 FROM t3"
|
||||
|
||||
22 0 "SELECT DISTINCT * FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
|
||||
23 1 "SELECT DISTINCT rowid FROM (SELECT 1, 2, 3 UNION SELECT 4, 5, 6)"
|
||||
|
||||
24 0 "SELECT DISTINCT rowid/2 FROM t1"
|
||||
25 1 "SELECT DISTINCT rowid/2, rowid FROM t1"
|
||||
26 1 "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?"
|
||||
} {
|
||||
if {$noop} {
|
||||
do_distinct_noop_test 1.$tn $sql
|
||||
} else {
|
||||
do_distinct_not_noop_test 1.$tn $sql
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests - distinct-2.* - test cases where an index is
|
||||
# used to deliver results in order of the DISTINCT expressions.
|
||||
#
|
||||
drop_all_tables
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
|
||||
CREATE INDEX i1 ON t1(a, b);
|
||||
CREATE INDEX i2 ON t1(b COLLATE nocase, c COLLATE nocase);
|
||||
|
||||
INSERT INTO t1 VALUES('a', 'b', 'c');
|
||||
INSERT INTO t1 VALUES('A', 'B', 'C');
|
||||
INSERT INTO t1 VALUES('a', 'b', 'c');
|
||||
INSERT INTO t1 VALUES('A', 'B', 'C');
|
||||
}
|
||||
|
||||
foreach {tn sql temptables res} {
|
||||
1 "a, b FROM t1" {} {A B a b}
|
||||
2 "b, a FROM t1" {} {B A b a}
|
||||
3 "a, b, c FROM t1" {hash} {a b c A B C}
|
||||
4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c}
|
||||
5 "b FROM t1 WHERE a = 'a'" {} {b}
|
||||
6 "b FROM t1" {hash} {b B}
|
||||
7 "a FROM t1" {} {A a}
|
||||
8 "b COLLATE nocase FROM t1" {} {b}
|
||||
9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {B}
|
||||
} {
|
||||
do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res
|
||||
do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables
|
||||
}
|
||||
|
||||
do_execsql_test 2.A {
|
||||
SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o;
|
||||
} {a A a A}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
+6
-6
@@ -1238,8 +1238,8 @@ do_select_tests e_select-5 {
|
||||
3.1 "SELECT x FROM h2" {One Two Three Four one two three four}
|
||||
3.2 "SELECT x FROM h1, h2 ON (x=b)" {One one Four four}
|
||||
|
||||
4.1 "SELECT DISTINCT x FROM h2" {four one three two}
|
||||
4.2 "SELECT DISTINCT x FROM h1, h2 ON (x=b)" {four one}
|
||||
4.1 "SELECT DISTINCT x FROM h2" {One Two Three Four}
|
||||
4.2 "SELECT DISTINCT x FROM h1, h2 ON (x=b)" {One Four}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-02054-15343 For the purposes of detecting duplicate
|
||||
@@ -1253,11 +1253,11 @@ do_select_tests e_select-5.5 {
|
||||
# sequence to compare text values with apply.
|
||||
#
|
||||
do_select_tests e_select-5.6 {
|
||||
1 "SELECT DISTINCT b FROM h1" {I IV four i iv one}
|
||||
2 "SELECT DISTINCT b COLLATE nocase FROM h1" {four i iv one}
|
||||
3 "SELECT DISTINCT x FROM h2" {four one three two}
|
||||
1 "SELECT DISTINCT b FROM h1" {one I i four IV iv}
|
||||
2 "SELECT DISTINCT b COLLATE nocase FROM h1" {one I four IV}
|
||||
3 "SELECT DISTINCT x FROM h2" {One Two Three Four}
|
||||
4 "SELECT DISTINCT x COLLATE binary FROM h2" {
|
||||
Four One Three Two four one three two
|
||||
One Two Three Four one two three four
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ foreach jm {rollback wal} {
|
||||
sql1 { DROP INDEX IF EXISTS i2 }
|
||||
sql2 { CREATE INDEX aux.i2 ON t2(x) }
|
||||
sql1 { DROP INDEX IF EXISTS i2 }
|
||||
sql2 { SELECT name FROM aux.sqlite_master WHERE type = 'index' }
|
||||
sql2 { SELECT * FROM aux.sqlite_master WHERE type = 'index' }
|
||||
} {}
|
||||
|
||||
# VIEW objects.
|
||||
|
||||
+49
-3
@@ -107,15 +107,17 @@ proc do_fts3query_test {tn args} {
|
||||
" $matchinfo_asc
|
||||
}
|
||||
|
||||
# fts3_make_deferrable TABLE TOKEN
|
||||
# fts3_make_deferrable TABLE TOKEN ?NROW?
|
||||
#
|
||||
proc fts3_make_deferrable {tbl token} {
|
||||
proc fts3_make_deferrable {tbl token {nRow 0}} {
|
||||
|
||||
set stmt [sqlite3_prepare db "SELECT * FROM $tbl" -1 dummy]
|
||||
set name [sqlite3_column_name $stmt 0]
|
||||
sqlite3_finalize $stmt
|
||||
|
||||
set nRow [db one "SELECT count(*) FROM $tbl"]
|
||||
if {$nRow==0} {
|
||||
set nRow [db one "SELECT count(*) FROM $tbl"]
|
||||
}
|
||||
set pgsz [db one "PRAGMA page_size"]
|
||||
execsql BEGIN
|
||||
for {set i 0} {$i < ($nRow * $pgsz * 1.2)/100} {incr i} {
|
||||
@@ -653,6 +655,50 @@ foreach {tn pending create} {
|
||||
catchsql { COMMIT }
|
||||
}
|
||||
|
||||
foreach {tn create} {
|
||||
1 "fts4(x)"
|
||||
2 "fts4(x, order=DESC)"
|
||||
} {
|
||||
execsql [subst {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE VIRTUAL TABLE t1 USING $create;
|
||||
}]
|
||||
|
||||
foreach {x} {
|
||||
"F E N O T K X V A X I E X A P G Q V H U"
|
||||
"R V A E T C V Q N I E L O N U G J K L U"
|
||||
"U Y I G W M V F J L X I D C H F P J Q B"
|
||||
"S G D Z X R P G S S Y B K A S G A I L L"
|
||||
"L S I C H T Z S R Q P R N K J X L F M J"
|
||||
"C C C D P X B Z C M A D A C X S B T X V"
|
||||
"W Y J M D R G V R K B X S A W R I T N C"
|
||||
"P K L W T M S P O Y Y V V O E H Q A I R"
|
||||
"C D Y I C Z F H J C O Y A Q F L S B D K"
|
||||
"P G S C Y C Y V I M B D S Z D D Y W I E"
|
||||
"Z K Z U E E S F Y X T U A L W O U J C Q"
|
||||
"P A T Z S W L P L Q V Y Y I P W U X S S"
|
||||
"I U I H U O F Z F R H R F T N D X A G M"
|
||||
"N A B M S H K X S O Y D T X S B R Y H Z"
|
||||
"L U D A S K I L S V Z J P U B E B Y H M"
|
||||
} {
|
||||
execsql { INSERT INTO t1 VALUES($x) }
|
||||
}
|
||||
|
||||
# Add extra documents to the database such that token "B" will be considered
|
||||
# deferrable if considering the other tokens means that 2 or fewer documents
|
||||
# will be loaded into memory.
|
||||
#
|
||||
fts3_make_deferrable t1 B 2
|
||||
|
||||
# B is not deferred in either of the first two tests below, since filtering
|
||||
# on "M" or "D" returns 10 documents or so. But filtering on "M * D" only
|
||||
# returns 2, so B is deferred in this case.
|
||||
#
|
||||
do_fts3query_test 7.$tn.1 t1 {"M B"}
|
||||
do_fts3query_test 7.$tn.2 t1 {"B D"}
|
||||
do_fts3query_test 7.$tn.3 -deferred B t1 {"M B D"}
|
||||
}
|
||||
|
||||
set sqlite_fts3_enable_parentheses $sfep
|
||||
finish_test
|
||||
|
||||
|
||||
+20
-18
@@ -17,24 +17,26 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
|
||||
do_test func3-1.1 {
|
||||
set destroyed 0
|
||||
proc destroy {} { set ::destroyed 1 }
|
||||
sqlite3_create_function_v2 db f2 -1 any -func f2 -destroy destroy
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.2 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf8 -func f2
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.3 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf16le -func f2
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.4 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf16be -func f2
|
||||
set destroyed
|
||||
} 1
|
||||
ifcapable utf16 {
|
||||
do_test func3-1.1 {
|
||||
set destroyed 0
|
||||
proc destroy {} { set ::destroyed 1 }
|
||||
sqlite3_create_function_v2 db f2 -1 any -func f2 -destroy destroy
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.2 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf8 -func f2
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.3 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf16le -func f2
|
||||
set destroyed
|
||||
} 0
|
||||
do_test func3-1.4 {
|
||||
sqlite3_create_function_v2 db f2 -1 utf16be -func f2
|
||||
set destroyed
|
||||
} 1
|
||||
}
|
||||
|
||||
do_test func3-2.1 {
|
||||
set destroyed 0
|
||||
|
||||
+1
-1
@@ -1376,7 +1376,7 @@ do_test fuzzer1-2.3 {
|
||||
AND f2.distance<=200
|
||||
AND streetname.n>=f2.word AND streetname.n<=(f2.word || x'F7BFBFBF')
|
||||
}
|
||||
} {steelewood tallia tallu talwyn taymouth thelema trailer {tyler finley}}
|
||||
} {{tyler finley} trailer taymouth steelewood tallia tallu talwyn thelema}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -35,6 +35,7 @@ do_malloc_test 1 -tclprep {
|
||||
}
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
fconfigure $::blob -translation binary
|
||||
set rc [catch {puts -nonewline $::blob $::data}]
|
||||
if {$rc} { error "out of memory" }
|
||||
}
|
||||
@@ -71,8 +72,7 @@ do_malloc_test 3 -tclprep {
|
||||
if {$rc} {
|
||||
error "out of memory"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
do_ioerr_test incrblob_err-4 -cksum 1 -sqlprep {
|
||||
CREATE TABLE blobs(k, v BLOB);
|
||||
@@ -87,6 +87,7 @@ do_ioerr_test incrblob_err-5 -cksum 1 -sqlprep {
|
||||
INSERT INTO blobs VALUES(1, zeroblob(length(CAST($::data AS BLOB))));
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
fconfigure $::blob -translation binary
|
||||
puts -nonewline $::blob $::data
|
||||
close $::blob
|
||||
}
|
||||
@@ -96,6 +97,7 @@ do_ioerr_test incrblob_err-6 -cksum 1 -sqlprep {
|
||||
INSERT INTO blobs VALUES(1, $::data || $::data || $::data);
|
||||
} -tclbody {
|
||||
set ::blob [db incrblob blobs v 1]
|
||||
fconfigure $::blob -translation binary
|
||||
seek $::blob -20 end
|
||||
puts -nonewline $::blob "12345678900987654321"
|
||||
close $::blob
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ do_test insert4-2.4.1 {
|
||||
INSERT INTO t3 SELECT DISTINCT * FROM t2;
|
||||
SELECT * FROM t3;
|
||||
}
|
||||
} {1 9 9 1}
|
||||
} {9 1 1 9}
|
||||
xferopt_test insert4-2.4.2 0
|
||||
do_test insert4-2.4.3 {
|
||||
catchsql {
|
||||
|
||||
+5
-2
@@ -70,12 +70,15 @@ do_test like-1.4 {
|
||||
}
|
||||
} {ABC abc}
|
||||
do_test like-1.5.1 {
|
||||
# Use sqlite3_exec() to verify fix for ticket [25ee81271091] 2011-06-26
|
||||
sqlite3_exec db {PRAGMA case_sensitive_like=on}
|
||||
} {0 {}}
|
||||
do_test like-1.5.2 {
|
||||
execsql {
|
||||
PRAGMA case_sensitive_like=on;
|
||||
SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
|
||||
}
|
||||
} {abc}
|
||||
do_test like-1.5.2 {
|
||||
do_test like-1.5.3 {
|
||||
execsql {
|
||||
PRAGMA case_sensitive_like; -- no argument; does not change setting
|
||||
SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
|
||||
|
||||
+1
-1
@@ -505,7 +505,7 @@ ifcapable subquery {
|
||||
)
|
||||
ORDER BY LOWER(artist) ASC;
|
||||
}
|
||||
} {one}
|
||||
} {two}
|
||||
}
|
||||
|
||||
# Ticket #1370. Do not overwrite small files (less than 1024 bytes)
|
||||
|
||||
+20
-63
@@ -49,6 +49,7 @@ proc multiplex_set {db name chunk_size max_chunks} {
|
||||
# and files with the chunk extension.
|
||||
proc multiplex_delete {name} {
|
||||
global g_max_chunks
|
||||
forcedelete $name
|
||||
for {set i 0} {$i<$g_max_chunks} {incr i} {
|
||||
forcedelete [multiplex_name $name $i]
|
||||
forcedelete [multiplex_name $name-journal $i]
|
||||
@@ -78,10 +79,9 @@ do_test multiplex-1.8 { sqlite3_multiplex_shutdown } {SQLITE_OK}
|
||||
do_test multiplex-1.9.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.2 { sqlite3 db test.db } {}
|
||||
do_test multiplex-1.9.3 { multiplex_set db main 32768 16 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_MISUSE}
|
||||
do_test multiplex-1.9.5 { multiplex_set db main -1 16 } {SQLITE_MISUSE}
|
||||
do_test multiplex-1.9.4 { multiplex_set db main 32768 -1 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.6 { multiplex_set db main 31 16 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_MISUSE}
|
||||
do_test multiplex-1.9.7 { multiplex_set db main 32768 100 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.8 { multiplex_set db main 1073741824 1 } {SQLITE_OK}
|
||||
do_test multiplex-1.9.9 { db close } {}
|
||||
do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
|
||||
@@ -89,10 +89,9 @@ do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
|
||||
do_test multiplex-1.10.1 { sqlite3_multiplex_initialize "" 1 } {SQLITE_OK}
|
||||
do_test multiplex-1.10.2 { sqlite3 db test.db } {}
|
||||
do_test multiplex-1.10.3 { lindex [ catchsql { SELECT multiplex_control(2, 32768); } ] 0 } {0}
|
||||
do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {1}
|
||||
do_test multiplex-1.10.5 { lindex [ catchsql { SELECT multiplex_control(2, -1); } ] 0 } {1}
|
||||
do_test multiplex-1.10.4 { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 } {0}
|
||||
do_test multiplex-1.10.6 { lindex [ catchsql { SELECT multiplex_control(2, 31); } ] 0 } {0}
|
||||
do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {1}
|
||||
do_test multiplex-1.10.7 { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 } {0}
|
||||
do_test multiplex-1.10.8 { lindex [ catchsql { SELECT multiplex_control(2, 1073741824); } ] 0 } {0}
|
||||
do_test multiplex-1.10.9 { db close } {}
|
||||
do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown } {SQLITE_OK}
|
||||
@@ -146,8 +145,9 @@ do_test multiplex-1.13.7 { sqlite3_multiplex_shutdown }
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
multiplex_set db main 32768 16
|
||||
|
||||
file delete -force test.x
|
||||
do_test multiplex-2.1.2 {
|
||||
sqlite3 db test.db
|
||||
sqlite3 db test.x
|
||||
execsql {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA auto_vacuum=OFF;
|
||||
@@ -159,7 +159,7 @@ do_test multiplex-2.1.2 {
|
||||
INSERT INTO t1 VALUES(2, randomblob(1100));
|
||||
}
|
||||
} {}
|
||||
do_test multiplex-2.1.3 { file size [multiplex_name test.db 0] } {4096}
|
||||
do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096}
|
||||
do_test multiplex-2.1.4 {
|
||||
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
|
||||
} {}
|
||||
@@ -167,10 +167,10 @@ do_test multiplex-2.1.4 {
|
||||
do_test multiplex-2.2.1 {
|
||||
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
|
||||
} {}
|
||||
do_test multiplex-2.2.3 { file size [multiplex_name test.db 0] } {6144}
|
||||
do_test multiplex-2.2.3 { file size [multiplex_name test.x 0] } {6144}
|
||||
|
||||
do_test multiplex-2.3.1 {
|
||||
sqlite3 db2 test2.db
|
||||
sqlite3 db2 test2.x
|
||||
db2 close
|
||||
} {}
|
||||
|
||||
@@ -181,7 +181,7 @@ do_test multiplex-2.4.1 {
|
||||
do_test multiplex-2.4.2 {
|
||||
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
|
||||
} {}
|
||||
do_test multiplex-2.4.4 { file size [multiplex_name test.db 0] } {7168}
|
||||
do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
|
||||
do_test multiplex-2.4.99 {
|
||||
db close
|
||||
sqlite3_multiplex_shutdown
|
||||
@@ -189,9 +189,9 @@ do_test multiplex-2.4.99 {
|
||||
|
||||
|
||||
do_test multiplex-2.5.1 {
|
||||
multiplex_delete test.db
|
||||
multiplex_delete test.x
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db test.db
|
||||
sqlite3 db test.x
|
||||
multiplex_set db main 4096 16
|
||||
} {SQLITE_OK}
|
||||
|
||||
@@ -236,8 +236,8 @@ do_test multiplex-2.5.8 {
|
||||
db eval {SELECT a,length(b) FROM t1 WHERE a=4}
|
||||
} {4 4000}
|
||||
|
||||
do_test multiplex-2.5.9 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
|
||||
do_test multiplex-2.5.10 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
|
||||
do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
|
||||
do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
|
||||
|
||||
do_test multiplex-2.5.99 {
|
||||
db close
|
||||
@@ -523,50 +523,6 @@ do_faultsim_test multiplex-5.5 -prep {
|
||||
multiplex_set db main 32768 16
|
||||
}
|
||||
|
||||
# test that mismatch filesize is detected
|
||||
#
|
||||
# Do not run this test if $::G(perm:presql) is set. If it is set, then the
|
||||
# expected IO error will occur within the Tcl [sqlite3] wrapper, not within
|
||||
# the first SQL statement executed below. This breaks the test case.
|
||||
#
|
||||
if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} {
|
||||
set all_journal_modes {delete persist truncate memory off}
|
||||
foreach jmode $all_journal_modes {
|
||||
do_test multiplex-5.6.1.$jmode {
|
||||
sqlite3_multiplex_shutdown
|
||||
multiplex_delete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size = 1024;
|
||||
PRAGMA auto_vacuum = off;
|
||||
}
|
||||
db eval "PRAGMA journal_mode = $jmode;"
|
||||
} $jmode
|
||||
do_test multiplex-5.6.2.$jmode {
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, randomblob(15000));
|
||||
INSERT INTO t1 VALUES(2, randomblob(15000));
|
||||
INSERT INTO t1 VALUES(3, randomblob(15000));
|
||||
INSERT INTO t1 VALUES(4, randomblob(15000));
|
||||
INSERT INTO t1 VALUES(5, randomblob(15000));
|
||||
}
|
||||
db close
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db test.db
|
||||
multiplex_set db main 4096 16
|
||||
} {SQLITE_OK}
|
||||
do_test multiplex-5.6.3.$jmode {
|
||||
catchsql {
|
||||
INSERT INTO t1 VALUES(6, randomblob(15000));
|
||||
}
|
||||
} {1 {disk I/O error}}
|
||||
do_test multiplex-5.6.4.$jmode {
|
||||
db close
|
||||
} {}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that you can vacuum a multiplex'ed DB.
|
||||
|
||||
@@ -575,8 +531,9 @@ ifcapable vacuum {
|
||||
sqlite3_multiplex_shutdown
|
||||
do_test multiplex-6.0.0 {
|
||||
multiplex_delete test.db
|
||||
multiplex_delete test.x
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db test.db
|
||||
sqlite3 db test.x
|
||||
multiplex_set db main 4096 16
|
||||
} {SQLITE_OK}
|
||||
|
||||
@@ -592,8 +549,8 @@ do_test multiplex-6.1.0 {
|
||||
INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
|
||||
}
|
||||
} {}
|
||||
do_test multiplex-6.2.1 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
|
||||
do_test multiplex-6.2.2 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
|
||||
do_test multiplex-6.2.1 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
|
||||
do_test multiplex-6.2.2 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
|
||||
|
||||
do_test multiplex-6.3.0 {
|
||||
execsql { VACUUM }
|
||||
@@ -601,7 +558,7 @@ do_test multiplex-6.3.0 {
|
||||
|
||||
do_test multiplex-6.99 {
|
||||
db close
|
||||
multiplex_delete test.db
|
||||
multiplex_delete test.x
|
||||
sqlite3_multiplex_shutdown
|
||||
} {SQLITE_OK}
|
||||
|
||||
|
||||
@@ -783,6 +783,15 @@ test_suite "no_optimization" -description {
|
||||
optimization_control $::dbhandle all 0
|
||||
}
|
||||
|
||||
test_suite "prepare" -description {
|
||||
Run tests with the db connection using sqlite3_prepare() instead of _v2().
|
||||
} -dbconfig {
|
||||
db_use_legacy_prepare $::dbhandle 1
|
||||
#$::dbhandle cache size 0
|
||||
} -files [
|
||||
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
|
||||
]
|
||||
|
||||
# End of tests
|
||||
#############################################################################
|
||||
|
||||
|
||||
@@ -155,10 +155,10 @@ array set ::Configs {
|
||||
|
||||
array set ::Platforms {
|
||||
Linux-x86_64 {
|
||||
"Debug-One" "checksymbols test"
|
||||
"Secure-Delete" test
|
||||
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
|
||||
"Update-Delete-Limit" test
|
||||
"Debug-One" test
|
||||
"Extra-Robustness" test
|
||||
"Device-Two" test
|
||||
"Ftrapv" test
|
||||
@@ -177,6 +177,7 @@ array set ::Platforms {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# End of configuration section.
|
||||
#########################################################################
|
||||
#########################################################################
|
||||
|
||||
+1
-1
@@ -355,7 +355,7 @@ for {set ii 3} {$ii <= 4} {incr ii} {
|
||||
SELECT DISTINCT (a/10) FROM t1 UNION ALL SELECT DISTINCT(d%2) FROM t2
|
||||
)
|
||||
}
|
||||
} {0 1 0 1}
|
||||
} {0 1 1 0}
|
||||
|
||||
do_test selectB-$ii.20 {
|
||||
execsql {
|
||||
|
||||
+12
-8
@@ -319,18 +319,22 @@ do_test sqllimits1-5.14.4 {
|
||||
catch {sqlite3_bind_text $::STMT 1 $::str1 -1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
do_test sqllimits1-5.14.5 {
|
||||
catch {sqlite3_bind_text16 $::STMT 1 $::str1 -1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
ifcapable utf16 {
|
||||
do_test sqllimits1-5.14.5 {
|
||||
catch {sqlite3_bind_text16 $::STMT 1 $::str1 -1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
}
|
||||
do_test sqllimits1-5.14.6 {
|
||||
catch {sqlite3_bind_text $::STMT 1 $::str1 $np1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
do_test sqllimits1-5.14.7 {
|
||||
catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
ifcapable utf16 {
|
||||
do_test sqllimits1-5.14.7 {
|
||||
catch {sqlite3_bind_text16 $::STMT 1 $::str1 $np1} res
|
||||
set res
|
||||
} {SQLITE_TOOBIG}
|
||||
}
|
||||
do_test sqllimits1-5.14.8 {
|
||||
set n [expr {$np1-1}]
|
||||
catch {sqlite3_bind_text $::STMT 1 $::str1 $n} res
|
||||
|
||||
@@ -292,6 +292,7 @@ do_test temptable-5.1 {
|
||||
execsql {
|
||||
CREATE TEMP TABLE mask(a,b,c)
|
||||
} db2
|
||||
if {[permutation]=="prepare"} { db2 cache flush }
|
||||
execsql {
|
||||
CREATE INDEX mask ON t2(x);
|
||||
SELECT * FROM t2;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# 2011 July 8
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing that bug [54844eea3f] has been fixed.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set ::testprefix tkt-54844eea3f
|
||||
|
||||
do_test 1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t1 VALUES(4);
|
||||
|
||||
CREATE TABLE t2(b INTEGER PRIMARY KEY);
|
||||
INSERT INTO t2 VALUES(1);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
INSERT INTO t2 SELECT b+2 FROM t2;
|
||||
INSERT INTO t2 SELECT b+4 FROM t2;
|
||||
INSERT INTO t2 SELECT b+8 FROM t2;
|
||||
INSERT INTO t2 SELECT b+16 FROM t2;
|
||||
|
||||
CREATE TABLE t3(c INTEGER PRIMARY KEY);
|
||||
INSERT INTO t3 VALUES(1);
|
||||
INSERT INTO t3 VALUES(2);
|
||||
INSERT INTO t3 VALUES(3);
|
||||
}
|
||||
} {}
|
||||
|
||||
do_test 1.1 {
|
||||
execsql {
|
||||
SELECT 'test-2', t3.c, (
|
||||
SELECT count(*)
|
||||
FROM t1 JOIN (SELECT DISTINCT t3.c AS p FROM t2) AS x ON t1.a=x.p
|
||||
)
|
||||
FROM t3;
|
||||
}
|
||||
} {test-2 1 1 test-2 2 0 test-2 3 0}
|
||||
|
||||
do_test 1.2 {
|
||||
execsql {
|
||||
CREATE TABLE t4(a, b, c);
|
||||
INSERT INTO t4 VALUES('a', 1, 'one');
|
||||
INSERT INTO t4 VALUES('a', 2, 'two');
|
||||
INSERT INTO t4 VALUES('b', 1, 'three');
|
||||
INSERT INTO t4 VALUES('b', 2, 'four');
|
||||
SELECT (
|
||||
SELECT c FROM (
|
||||
SELECT * FROM t4 WHERE a=out.a ORDER BY b LIMIT 10 OFFSET 1
|
||||
) WHERE b=out.b
|
||||
) FROM t4 AS out;
|
||||
}
|
||||
} {{} two {} four}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -14,6 +14,12 @@
|
||||
# the use of these columns in triggers will refer to the column and not
|
||||
# to the actual ROWID. Ticket [34d2ae1c6d08b5271ba5e5592936d4a1d913ffe3]
|
||||
#
|
||||
# Also, verify that triggers created like this:
|
||||
#
|
||||
# CREATE TRIGGER attached.trig AFTER INSERT ON attached.tab ...
|
||||
#
|
||||
# can be reparsed as a main database. Ticket [d6ddba6706353915ceedc56b4e3]
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -171,4 +177,43 @@ do_test triggerD-3.2 {
|
||||
} {10003 20004}
|
||||
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# Ticket [d6ddba6706353915ceedc56b4e3e72ecb4d77ba4]
|
||||
#
|
||||
# The following syntax really should not be allowed:
|
||||
#
|
||||
# CREATE TRIGGER xyz.trig BEFORE UPDATE ON xyz.tab BEGIN ...
|
||||
#
|
||||
# But a long-standing bug does allow it. And the "xyz.tab" slips into
|
||||
# the sqlite_master table. We cannot fix the bug simply by disallowing
|
||||
# "xyz.tab" since that could break legacy applications. We have to
|
||||
# fix the system so that the "xyz." on "xyz.tab" is ignored.
|
||||
# Verify that this is the case.
|
||||
#
|
||||
do_test triggerD-4.1 {
|
||||
db close
|
||||
file delete -force test.db test2.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
ATTACH 'test2.db' AS db2;
|
||||
CREATE TABLE db2.t2(y);
|
||||
CREATE TABLE db2.log(z);
|
||||
CREATE TRIGGER db2.trig AFTER INSERT ON db2.t2 BEGIN
|
||||
INSERT INTO log(z) VALUES(new.y);
|
||||
END;
|
||||
INSERT INTO t2 VALUES(123);
|
||||
SELECT * FROM log;
|
||||
}
|
||||
} {123}
|
||||
do_test triggerD-4.2 {
|
||||
sqlite3 db2 test2.db
|
||||
db2 eval {
|
||||
INSERT INTO t2 VALUES(234);
|
||||
SELECT * FROM log;
|
||||
}
|
||||
} {123 234}
|
||||
db2 close
|
||||
|
||||
finish_test
|
||||
|
||||
+1
-2
@@ -707,7 +707,7 @@ T delete
|
||||
# and continues.
|
||||
#
|
||||
set nConn 50
|
||||
if { [string match *BSD $tcl_platform(os)] } { set nConn 35 }
|
||||
if { [string match *BSD $tcl_platform(os)] } { set nConn 25 }
|
||||
do_test wal3-9.0 {
|
||||
file delete -force test.db test.db-journal test.db wal
|
||||
sqlite3 db test.db
|
||||
@@ -784,4 +784,3 @@ do_multiclient_test tn {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+2
-11
@@ -43,19 +43,11 @@ foreach jmode $all_journal_modes {
|
||||
} {1 2}
|
||||
|
||||
# Under Windows, you'll get an error trying to delete
|
||||
# a file this is already opened. For now, make sure
|
||||
# we get that error, then close the first connection
|
||||
# a file this is already opened. Close the first connection
|
||||
# so the other tests work.
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
if {$jmode=="persist" || $jmode=="truncate"} {
|
||||
do_test wal6-1.2.$jmode.win {
|
||||
sqlite3 db2 test.db
|
||||
catchsql {
|
||||
PRAGMA journal_mode=WAL;
|
||||
} db2
|
||||
} {1 {disk I/O error}}
|
||||
db2 close
|
||||
db close
|
||||
db close
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,4 +79,3 @@ if {$tcl_platform(platform)=="windows"} {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
# 2011 July 11
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is recovery from transient manditory locks
|
||||
# that sometimes appear on database files due to anti-virus software.
|
||||
#
|
||||
|
||||
if {$tcl_platform(platform)!="windows"} return
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
set testprefix win32lock
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log xLog
|
||||
proc xLog {error_code msg} {
|
||||
lappend ::log $msg
|
||||
}
|
||||
sqlite3 db test.db
|
||||
|
||||
do_test win32lock-1.1 {
|
||||
db eval {
|
||||
PRAGMA cache_size=10;
|
||||
CREATE TABLE t1(x,y);
|
||||
INSERT INTO t1 VALUES(1,randomblob(100000));
|
||||
INSERT INTO t1 VALUES(2,randomblob(50000));
|
||||
INSERT INTO t1 VALUES(3,randomblob(25000));
|
||||
INSERT INTO t1 VALUES(4,randomblob(12500));
|
||||
SELECT x, length(y) FROM t1 ORDER BY rowid;
|
||||
}
|
||||
} {1 100000 2 50000 3 25000 4 12500}
|
||||
|
||||
unset -nocomplain delay1 rc msg
|
||||
set delay1 50
|
||||
set rc 0
|
||||
set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000]
|
||||
while {1} {
|
||||
sqlite3_sleep 10
|
||||
lock_win32_file test.db 0 $::delay1
|
||||
set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
|
||||
if {$rc} {
|
||||
do_test win32lock-1.2-$delay1-fin {
|
||||
set ::msg
|
||||
} {disk I/O error}
|
||||
break
|
||||
} else {
|
||||
do_test win32lock-1.2-$delay1 {
|
||||
set ::msg
|
||||
} {1 100000 2 50000 3 25000 4 12500}
|
||||
if {$::log!=""} {
|
||||
do_test win32lock-1.2-$delay1-log1 {
|
||||
regsub {\d+} $::log # x
|
||||
set x
|
||||
} {{delayed #ms for lock/sharing conflict}}
|
||||
}
|
||||
incr delay1 50
|
||||
}
|
||||
set ::log {}
|
||||
}
|
||||
|
||||
do_test win32lock-2.0 {
|
||||
file_control_win32_av_retry db -1 -1
|
||||
} {0 10 25}
|
||||
do_test win32lock-2.1 {
|
||||
file_control_win32_av_retry db 1 1
|
||||
} {0 1 1}
|
||||
|
||||
set delay1 50
|
||||
while {1} {
|
||||
sqlite3_sleep 10
|
||||
lock_win32_file test.db 0 $::delay1
|
||||
set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg]
|
||||
if {$rc} {
|
||||
do_test win32lock-2.2-$delay1-fin {
|
||||
set ::msg
|
||||
} {disk I/O error}
|
||||
break
|
||||
} else {
|
||||
do_test win32lock-2.2-$delay1 {
|
||||
set ::msg
|
||||
} {1 100000 2 50000 3 25000 4 12500}
|
||||
if {$::log!=""} {
|
||||
do_test win32lock-2.2-$delay1-log1 {
|
||||
regsub {\d+} $::log # x
|
||||
set x
|
||||
} {{delayed #ms for lock/sharing conflict}}
|
||||
}
|
||||
incr delay1 50
|
||||
}
|
||||
set ::log {}
|
||||
}
|
||||
|
||||
file_control_win32_av_retry db 10 25
|
||||
sqlite3_test_control_pending_byte $old_pending_byte
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
Reference in New Issue
Block a user