Add the stmtrand() extension function for use in testing.

FossilOrigin-Name: 5c97a5b9d163b1c427e002f3734687ca0384bc0da6a90fc4bfd358c654d3a7b3
This commit is contained in:
drh 2024-05-24 14:16:06 +00:00
parent 7c492a250b
commit 31079226f7
9 changed files with 166 additions and 13 deletions

View File

@ -454,6 +454,7 @@ TESTSRC += \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/stmtrand.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c \

View File

@ -1596,6 +1596,7 @@ TESTEXT = \
$(TOP)\ext\misc\remember.c \
$(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\stmtrand.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\unionvtab.c \
$(TOP)\ext\misc\wholenumber.c \

97
ext/misc/stmtrand.c Normal file
View File

@ -0,0 +1,97 @@
/*
** 2024-05-24
**
** 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.
**
******************************************************************************
**
** An SQL function that return pseudo-random non-negative integers.
**
** SELECT stmtrand(123);
**
** A special feature of this function is that the same sequence of random
** integers is returned for each invocation of the statement. This makes
** the results repeatable, and hence useful for testing. The argument is
** an integer which is the seed for the random number sequence. The seed
** is used by the first invocation of this function only and is ignored
** for all subsequent calls within the same statement.
**
** Resetting a statement (sqlite3_reset()) also resets the random number
** sequence.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
/* State of the pseudo-random number generator */
typedef struct Stmtrand {
unsigned int x, y;
} Stmtrand;
/* auxdata key */
#define STMTRAND_KEY (-4418371)
/*
** Function: stmtrand(SEED)
**
** Return a pseudo-random number.
*/
static void stmtrandFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Stmtrand *p;
p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
if( p==0 ){
unsigned int seed;
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ){
sqlite3_result_error_nomem(context);
return;
}
if( argc>=1 ){
seed = (unsigned int)sqlite3_value_int(argv[0]);
}else{
seed = 0;
}
p->x = seed | 1;
p->y = seed;
sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
if( p==0 ){
sqlite3_result_error_nomem(context);
return;
}
}
p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
p->y = p->y*1103515245 + 12345;
sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_stmtrand_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "stmtrand", 1, SQLITE_UTF8, 0,
stmtrandFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
stmtrandFunc, 0, 0);
}
return rc;
}

View File

@ -364,6 +364,7 @@ TESTSRC += \
$(TOP)/ext/misc/remember.c \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/stmtrand.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c \

View File

@ -1,11 +1,11 @@
C Fix\san\s"ifcapable"\sexpression\sin\svalues.test.
D 2024-05-24T13:33:39.715
C Add\sthe\sstmtrand()\sextension\sfunction\sfor\suse\sin\stesting.
D 2024-05-24T14:16:06.243
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in 993a7874e3d3721df61846f03dda4a9ef7490da11953ae36ba1bb0c0346eaf4a
F Makefile.in 58c2cc5010aa5fd5e8eef6fe24d4ebcec7dc2e8c56f135d4f49e90a099bbc531
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc e64a52619310d3067f6c38f56eedd15918a82dade70954197d6da486ad99d7f4
F Makefile.msc 993f8addade63bcac7192416e7161ceee60edcee2376299ea48b2a74c66ac2d5
F README.md 6358805260a03ebead84e168bbf3740ddf3f683b477e478567186aa7afb490d3
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@ -418,6 +418,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd397dbea
F ext/misc/sqlar.c a6175790482328171da47095f87608b48a476d4fac78d8a9ff18b03a2454f634
F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
F ext/misc/stmtrand.c 59cffa5d8e158943ff1ce078956d8e208e8c04e67307e8f249dece2436dcb7fc
F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
F ext/misc/totype.c 75ed9827d19cc3b434fc2aeb60725d4d46e1534373615612a4d1cfdcc3d60922
F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
@ -674,7 +675,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk e5da4b6c13f2b15bba7f1efb0a47089dfdde0973e85a024785485655d59fd758
F main.mk 9541ffdce424ddddb463e2480c3f1cb4067bbd3a6d2c84b3f083cb128a2fa721
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@ -755,7 +756,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 22f1fa3423b377c02ae78d451cfeb1c2d96dcf0389c0642cbdcd19d3bfd7ae01
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 1a841c38974d45cf15a7611398479182b61ad4c187423c380741d8b1688fe607
F src/shell.c.in 885dafabb3f16d68bdb4576683afb0e39a1939f50985b162255bf656c470babf
F src/shell.c.in 31249f26684467e95e529915bf486961c535ae8288ed7e79890cc9ed3d781d8f
F src/sqlite.h.in c71d9ef76a6d32dc7ff2d373f2e57ce09056af26c1457bcadae5358b7628c7c3
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
@ -764,7 +765,7 @@ F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
F src/test1.c 310f43eb17a9252a7790726ca652e4ea3197da17c19eec93b8578863a49dc7b4
F src/test1.c 6bd203421934f2af4d4a4b673f609879f1e0c35164f7e21d0d6cdc0da2eeee8f
F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
@ -1664,6 +1665,7 @@ F test/startup.c 1beb5ca66fcc0fce95c3444db9d1674f90fc605499a574ae2434dcfc10d2280
F test/stat.test 123212a20ceb496893d5254a5f6c76442ce549fdc08d1702d8288a2bbaac8408
F test/statfault.test 064f43379e4992b5221b7d9ac887c313b3191f85cce605d78e416fc4045da64e
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
F test/stmtrand.test 340e2ea4841c5cdc02d36e33739769c5d907ab529b12bb535407def0e413ca17
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
F test/strict1.test 4d2b492152b984fd7e8196d23eb88e2ccb0ef9e46ca2f96c2ce7147ceef9d168
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
@ -2191,8 +2193,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 cec6bb3fc9932ea78ec8e63d9c2d4e56a4d94b8973b9ea46033cc4baa87c0476
R 203911405be61016c300aab6226a6699
U dan
Z 51255f9b31c7a540d78da0504b6db5c1
P b8442d2a6012b1f2e15381613267db0982e36bb4c748b15b56e668e0d0a3d0d2
R 01f61db2371d56efe0fc89de21914b9a
U drh
Z 5bafe7bbe2cfe723081ab4c42a45e0a5
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
b8442d2a6012b1f2e15381613267db0982e36bb4c748b15b56e668e0d0a3d0d2
5c97a5b9d163b1c427e002f3734687ca0384bc0da6a90fc4bfd358c654d3a7b3

View File

@ -1221,9 +1221,9 @@ INCLUDE ../ext/misc/sqlar.c
#endif
INCLUDE ../ext/expert/sqlite3expert.h
INCLUDE ../ext/expert/sqlite3expert.c
INCLUDE ../ext/intck/sqlite3intck.h
INCLUDE ../ext/intck/sqlite3intck.c
INCLUDE ../ext/misc/stmtrand.c
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
@ -5364,6 +5364,7 @@ static void open_db(ShellState *p, int openFlags){
#endif
sqlite3_shathree_init(p->db, 0, 0);
sqlite3_uint_init(p->db, 0, 0);
sqlite3_stmtrand_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_base64_init(p->db, 0, 0);
sqlite3_base85_init(p->db, 0, 0);

View File

@ -8174,6 +8174,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_stmtrand_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_unionvtab_init(sqlite3*,char**,const sqlite3_api_routines*);
@ -8207,6 +8208,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "remember", sqlite3_remember_init },
{ "series", sqlite3_series_init },
{ "spellfix", sqlite3_spellfix_init },
{ "stmtrand", sqlite3_stmtrand_init },
{ "totype", sqlite3_totype_init },
{ "unionvtab", sqlite3_unionvtab_init },
{ "wholenumber", sqlite3_wholenumber_init },

48
test/stmtrand.test Normal file
View File

@ -0,0 +1,48 @@
# 2024-05-24
#
# 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.
#
#***********************************************************************
#
# Verify that the stmtrand() extension function works.
#
# Stmtrand() is a pseudo-random number generator designed for testing.
# it has the property that it returns the same sequence of pseudo-random
# numbers for each SQL statement invocation. This makes it suitable for
# testing because the results are reproducible.
#
# The optional argument is the seed for the PRNG. The seed is only used
# on the first invocation. If the argument is omitted, a seed of 0 is
# used.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix stmtrand
load_static_extension db stmtrand
do_execsql_test 1.1 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<30)
SELECT stmtrand()%10 FROM c
} {4 1 8 3 6 1 4 9 2 1 2 1 0 1 8 1 4 7 6 1 8 7 0 3 0 9 4 5 9 9}
do_execsql_test 1.2 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<30)
SELECT stmtrand(0)%10 FROM c
} {4 1 8 3 6 1 4 9 2 1 2 1 0 1 8 1 4 7 6 1 8 7 0 3 0 9 4 5 9 9}
do_execsql_test 1.3 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<30)
SELECT stmtrand(1)%10 FROM c
} {3 8 9 4 7 2 3 8 5 2 7 0 3 0 7 2 5 6 1 8 5 6 7 8 7 2 9 6 8 0}
do_execsql_test 1.4 {
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<30)
SELECT stmtrand(x)%10 FROM c
} {3 8 9 4 7 2 3 8 5 2 7 0 3 0 7 2 5 6 1 8 5 6 7 8 7 2 9 6 8 0}
finish_test