Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4eb4201da9 | |||
| ed7ab43885 |
@@ -1,5 +1,5 @@
|
||||
C Enhance\sthe\s".stats"\scommand\sin\ssqlite3.exe\sto\sshow\sone-time\sstats\sinformation\nif\sinvoked\swith\sone\sargument.\s\sAlso\sshow\s/proc/PID/io\sinformation\sif\srun\son\nLinux.
|
||||
D 2016-02-27T17:12:36.918
|
||||
C More\scompact\simplementation\sof\sPRAGMA\sonconflict,\sand\ssome\stest\scases.
|
||||
D 2016-02-27T19:03:22.754
|
||||
F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079
|
||||
@@ -310,11 +310,11 @@ F src/global.c ded7b97efd16efda5062b65e857198e46c40e652
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 9ca97272e9f74ed0efddf3b4350ee12740cebbef
|
||||
F src/insert.c b42e0c7e81da4a56c664c3895c675662ac6469f4
|
||||
F src/journal.c fe3a3e2559ce3ce9d371afd30fbabbc074174575
|
||||
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
|
||||
F src/loadext.c 9e2a41adcaff16ebc1ebff1f336cbf33de55396f
|
||||
F src/main.c be9309f442ec291177642d2e48e82290e0951f4b
|
||||
F src/main.c 2bf81b968e8e1f9ce778eb5b61b389ab145f9497
|
||||
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
@@ -342,8 +342,8 @@ F src/parse.y c3ce2c4a7cbf0b699239be6b2a945c5cb51875e2
|
||||
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
|
||||
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
|
||||
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
|
||||
F src/pragma.c d6028d23a9495a8b55f2075e3244ec9a0485e03e
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/pragma.c b9d960d385968789ea79e28dd44a62ed57ad9208
|
||||
F src/pragma.h 0639ea9901f8a22433a94ca8b0f35921d6ac2306
|
||||
F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e
|
||||
F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
@@ -354,7 +354,7 @@ F src/shell.c f30efdd675007ec6006d51193fc47aabda2984a5
|
||||
F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
|
||||
F src/sqliteInt.h 63c0e1b5b5d608a1ba2303fe3a554b859a120406
|
||||
F src/sqliteInt.h eed052038018d543cd03ade7f3a69830ff302777
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
@@ -410,7 +410,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 3d338cdd00d916ce8a05c397001d64ed58e6fe1c
|
||||
F src/treeview.c c525282442111b3f61eb176784567cd6654db5dc
|
||||
F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280
|
||||
F src/update.c a7eeeaffad59c6506f01303a071dac11de8269ca
|
||||
F src/update.c 3c911431bcc7c6b5f996743d807ff0a9ef9e088a
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c 6ed9d7bdd3b0a30742027b6d8e8e1a9e2b14f373
|
||||
F src/vacuum.c feb1eabb20987983d9350cad98299b21fa811f52
|
||||
@@ -920,6 +920,7 @@ F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
|
||||
F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
|
||||
F test/onconflict1.test c03c755a2efda1c8d6e74e15f04e16ac14f0acba
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test 4d22a7c75f6a83fc1f188cc7bb5192285fdf2552
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
@@ -1391,7 +1392,7 @@ F tool/mkmsvcmin.tcl 2f12f7fa8858bbe61cf81820a2da96c79ed1ca8d
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 385c62d78c38b2d92146dcb5abd319dbbc33506d
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41
|
||||
F tool/mkpragmatab.tcl bf99a05342afb7baf04c7b18b151d5b55ae8588f
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835
|
||||
F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84
|
||||
@@ -1451,7 +1452,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P d1392c627934b89cdb86d82e73d56e8f76952b30
|
||||
R cc008a8c941c26feeb254cac8325586b
|
||||
P 3a0c347cca58fdaefd1b3644ba1649a5b4ebe91f
|
||||
R 58122bd2911f76c0eb3005cd77e413fa
|
||||
U drh
|
||||
Z 0f34ce71f4553990685c1f98cc5c169c
|
||||
Z eb55459b1b74d5d83abb570469162143
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3c36948f16b58fe8042c37d0df634308b4e48217
|
||||
3e5d38f5b37da08a3d4704c23a51399624e3ecab
|
||||
+9
-8
@@ -988,7 +988,7 @@ void sqlite3Insert(
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? db->dfltOnError : onError);
|
||||
sqlite3MayAbort(pParse);
|
||||
}else
|
||||
#endif
|
||||
@@ -1282,10 +1282,10 @@ void sqlite3GenerateConstraintChecks(
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = db->dfltOnError;
|
||||
}
|
||||
if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
|
||||
onError = OE_Abort;
|
||||
onError = db->dfltOnError;
|
||||
}
|
||||
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
||||
|| onError==OE_Ignore || onError==OE_Replace );
|
||||
@@ -1325,7 +1325,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
|
||||
ExprList *pCheck = pTab->pCheck;
|
||||
pParse->ckBase = regNewData+1;
|
||||
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
|
||||
onError = overrideError!=OE_Default ? overrideError : db->dfltOnError;
|
||||
for(i=0; i<pCheck->nExpr; i++){
|
||||
int allOk;
|
||||
Expr *pExpr = pCheck->a[i].pExpr;
|
||||
@@ -1337,7 +1337,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
}else{
|
||||
char *zName = pCheck->a[i].zName;
|
||||
if( zName==0 ) zName = pTab->zName;
|
||||
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
|
||||
if( onError==OE_Replace ) onError = db->dfltOnError; /* IMP: R-15569-63625 */
|
||||
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
|
||||
onError, zName, P4_TRANSIENT,
|
||||
P5_ConstraintCheck);
|
||||
@@ -1358,7 +1358,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = db->dfltOnError;
|
||||
}
|
||||
|
||||
if( isUpdate ){
|
||||
@@ -1390,6 +1390,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
VdbeCoverage(v);
|
||||
|
||||
/* Generate code that deals with a rowid collision */
|
||||
if( onError==OE_Default ) onError = db->dfltOnError;
|
||||
switch( onError ){
|
||||
default: {
|
||||
onError = OE_Abort;
|
||||
@@ -1532,7 +1533,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
if( overrideError!=OE_Default ){
|
||||
onError = overrideError;
|
||||
}else if( onError==OE_Default ){
|
||||
onError = OE_Abort;
|
||||
onError = db->dfltOnError;
|
||||
}
|
||||
|
||||
/* Check to see if the new index entry will be unique */
|
||||
@@ -1910,7 +1911,7 @@ static int xferOptimization(
|
||||
#endif
|
||||
if( onError==OE_Default ){
|
||||
if( pDest->iPKey>=0 ) onError = pDest->keyConf;
|
||||
if( onError==OE_Default ) onError = OE_Abort;
|
||||
if( onError==OE_Default ) onError = db->dfltOnError;
|
||||
}
|
||||
assert(pSelect->pSrc); /* allocated even if there is no FROM clause */
|
||||
if( pSelect->pSrc->nSrc!=1 ){
|
||||
|
||||
@@ -2779,6 +2779,7 @@ static int openDatabase(
|
||||
db->nDb = 2;
|
||||
db->magic = SQLITE_MAGIC_BUSY;
|
||||
db->aDb = db->aDbStatic;
|
||||
db->dfltOnError = OE_Abort;
|
||||
|
||||
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
|
||||
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
|
||||
|
||||
@@ -1894,6 +1894,27 @@ void sqlite3Pragma(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA onconflict
|
||||
** PRAGMA onconflict = FAIL
|
||||
** PRAGMA onconflict = ABORT
|
||||
** PRAGMA onconflict = ROLLBACK
|
||||
**
|
||||
** Set the default conflict handling algorithm.
|
||||
*/
|
||||
case PragTyp_ONCONFLICT: {
|
||||
static const char *azMode[] = { "ABORT", "FAIL", "ROLLBACK" };
|
||||
static const u8 aeMode[] = { OE_Abort, OE_Fail, OE_Rollback };
|
||||
const char *zRes = 0;
|
||||
int i;
|
||||
for(i=0; i<ArraySize(azMode); i++){
|
||||
if( sqlite3_stricmp(azMode[i], zRight)==0 ) db->dfltOnError = aeMode[i];
|
||||
if( db->dfltOnError==aeMode[i] ) zRes = azMode[i];
|
||||
}
|
||||
returnSingleText(v, "onconflict", zRes);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/*
|
||||
** Report the current state of file logs for all databases
|
||||
|
||||
+26
-19
@@ -28,24 +28,25 @@
|
||||
#define PragTyp_LOCKING_MODE 22
|
||||
#define PragTyp_PAGE_COUNT 23
|
||||
#define PragTyp_MMAP_SIZE 24
|
||||
#define PragTyp_PAGE_SIZE 25
|
||||
#define PragTyp_SECURE_DELETE 26
|
||||
#define PragTyp_SHRINK_MEMORY 27
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 28
|
||||
#define PragTyp_STATS 29
|
||||
#define PragTyp_SYNCHRONOUS 30
|
||||
#define PragTyp_TABLE_INFO 31
|
||||
#define PragTyp_TEMP_STORE 32
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 33
|
||||
#define PragTyp_THREADS 34
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 35
|
||||
#define PragTyp_WAL_CHECKPOINT 36
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 37
|
||||
#define PragTyp_HEXKEY 38
|
||||
#define PragTyp_KEY 39
|
||||
#define PragTyp_REKEY 40
|
||||
#define PragTyp_LOCK_STATUS 41
|
||||
#define PragTyp_PARSER_TRACE 42
|
||||
#define PragTyp_ONCONFLICT 25
|
||||
#define PragTyp_PAGE_SIZE 26
|
||||
#define PragTyp_SECURE_DELETE 27
|
||||
#define PragTyp_SHRINK_MEMORY 28
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 29
|
||||
#define PragTyp_STATS 30
|
||||
#define PragTyp_SYNCHRONOUS 31
|
||||
#define PragTyp_TABLE_INFO 32
|
||||
#define PragTyp_TEMP_STORE 33
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 34
|
||||
#define PragTyp_THREADS 35
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 36
|
||||
#define PragTyp_WAL_CHECKPOINT 37
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 38
|
||||
#define PragTyp_HEXKEY 39
|
||||
#define PragTyp_KEY 40
|
||||
#define PragTyp_REKEY 41
|
||||
#define PragTyp_LOCK_STATUS 42
|
||||
#define PragTyp_PARSER_TRACE 43
|
||||
#define PragFlag_NeedSchema 0x01
|
||||
#define PragFlag_ReadOnly 0x02
|
||||
static const struct sPragmaNames {
|
||||
@@ -299,6 +300,12 @@ static const struct sPragmaNames {
|
||||
/* ePragTyp: */ PragTyp_MMAP_SIZE,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
{ /* zName: */ "onconflict",
|
||||
/* ePragTyp: */ PragTyp_ONCONFLICT,
|
||||
/* ePragFlag: */ 0,
|
||||
/* iArg: */ 0 },
|
||||
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
||||
{ /* zName: */ "page_count",
|
||||
/* ePragTyp: */ PragTyp_PAGE_COUNT,
|
||||
/* ePragFlag: */ PragFlag_NeedSchema,
|
||||
@@ -461,4 +468,4 @@ static const struct sPragmaNames {
|
||||
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 60 on by default, 73 total. */
|
||||
/* Number of pragmas: 61 on by default, 74 total. */
|
||||
|
||||
@@ -1194,6 +1194,7 @@ struct sqlite3 {
|
||||
u8 suppressErr; /* Do not issue error messages if true */
|
||||
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
|
||||
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
|
||||
u8 dfltOnError; /* Default conflict handling. OE_Abort */
|
||||
int nextPagesize; /* Pagesize after VACUUM if >0 */
|
||||
u32 magic; /* Magic number for detect library misuse */
|
||||
int nChange; /* Value returned by sqlite3_changes() */
|
||||
|
||||
+1
-1
@@ -794,7 +794,7 @@ static void updateVirtualTable(
|
||||
}
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, nArg, regArg, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
|
||||
sqlite3VdbeChangeP5(v, onError==OE_Default ? db->dfltOnError : onError);
|
||||
sqlite3MayAbort(pParse);
|
||||
|
||||
/* End of the ephemeral table scan. Or, if using the onepass strategy,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# 2016-02-27
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# This file focuses on the PRAGMA onconflict statement.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix onconflict1
|
||||
|
||||
do_execsql_test 100 {
|
||||
PRAGMA onconflict;
|
||||
} {ABORT}
|
||||
do_execsql_test 110 {
|
||||
PRAGMA onconflict=Rollback;
|
||||
} {ROLLBACK}
|
||||
do_execsql_test 120 {
|
||||
PRAGMA onconflict=fail;
|
||||
} {FAIL}
|
||||
do_execsql_test 130 {
|
||||
PRAGMA onconflict=whatever;
|
||||
} {FAIL}
|
||||
do_execsql_test 140 {
|
||||
PRAGMA onconflict=abort;
|
||||
} {ABORT}
|
||||
|
||||
do_catchsql_test 200 {
|
||||
CREATE TABLE t1(a, b UNIQUE);
|
||||
INSERT INTO t1(a,b) VALUES(1,1),(2,2),(3,3),(98,98),(99,99);
|
||||
BEGIN;
|
||||
UPDATE t1 SET a=100 WHERE a=101;
|
||||
UPDATE t1 SET b=10;
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 201 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 1 2 2 3 3 98 98 99 99}
|
||||
|
||||
do_catchsql_test 210 {
|
||||
PRAGMA onconflict=FAIL;
|
||||
UPDATE t1 SET b=10;
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 211 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 10 2 2 3 3 98 98 99 99}
|
||||
|
||||
do_catchsql_test 220 {
|
||||
ROLLBACK;
|
||||
BEGIN;
|
||||
PRAGMA onconflict=ROLLBACK;
|
||||
UPDATE t1 SET b=10;
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 221 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 1 2 2 3 3 98 98 99 99}
|
||||
do_catchsql_test 222 {
|
||||
ROLLBACK
|
||||
} {1 {cannot rollback - no transaction is active}}
|
||||
|
||||
do_catchsql_test 300 {
|
||||
PRAGMA onconflict=ABORT;
|
||||
BEGIN;
|
||||
INSERT INTO t1(a,b) VALUES(4,4),(5,1),(6,6);
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 301 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 1 2 2 3 3 98 98 99 99}
|
||||
|
||||
do_catchsql_test 310 {
|
||||
PRAGMA onconflict=ROLLBACK;
|
||||
INSERT INTO t1(a,b) VALUES(4,4),(5,1),(6,6);
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 311 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 1 2 2 3 3 98 98 99 99}
|
||||
do_catchsql_test 312 {
|
||||
ROLLBACK
|
||||
} {1 {cannot rollback - no transaction is active}}
|
||||
|
||||
do_catchsql_test 320 {
|
||||
PRAGMA onconflict=FAIL;
|
||||
BEGIN;
|
||||
INSERT INTO t1(a,b) VALUES(4,4),(5,1),(6,6);
|
||||
} {1 {UNIQUE constraint failed: t1.b}}
|
||||
do_execsql_test 321 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
} {1 1 2 2 3 3 4 4 98 98 99 99}
|
||||
do_catchsql_test 322 {
|
||||
ROLLBACK
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
@@ -317,6 +317,8 @@ set pragma_def {
|
||||
NAME: soft_heap_limit
|
||||
|
||||
NAME: threads
|
||||
|
||||
NAME: onconflict
|
||||
}
|
||||
|
||||
# Open the output file
|
||||
|
||||
Reference in New Issue
Block a user