mirror of
https://github.com/tursodatabase/libsql.git
synced 2025-07-04 16:03:39 +00:00
.cargo
.github
bindings
bottomless
bottomless-cli
bottomless2
docker-compose
docs
libsql
libsql-ffi
libsql-hrana
libsql-replication
libsql-server
libsql-shell
libsql-sqlite3
art
autoconf
contrib
crates
doc
ext
async
crr
expert
fts3
fts5
icu
jni
libsql-wasi
lsm1
misc
README.md
amatch.c
anycollseq.c
appendvfs.c
base64.c
base85.c
basexx.c
blobio.c
btreeinfo.c
carray.c
carray.h
cksumvfs.c
closure.c
completion.c
compress.c
csv.c
dbdump.c
decimal.c
eval.c
explain.c
fileio.c
fossildelta.c
fuzzer.c
ieee754.c
memstat.c
memtrace.c
memvfs.c
mmapwarm.c
nextchar.c
noop.c
normalize.c
pcachetrace.c
percentile.c
prefixes.c
qpvtab.c
randomjson.c
regexp.c
remember.c
rot13.c
scrub.c
series.c
sha1.c
shathree.c
showauth.c
spellfix.c
sqlar.c
stmt.c
templatevtab.c
totype.c
uint.c
unionvtab.c
urifuncs.c
uuid.c
vfslog.c
vfsstat.c
vtablog.c
vtshim.c
wholenumber.c
zipfile.c
zorder.c
rbu
recover
repair
rtree
session
udf
userauth
vwal
wasi
wasm
README.md
mptest
src
test
tool
vsixtest
.gitignore
Dockerfile-wasm-udf
LIBSQL_VERSION
LICENSE.md
Makefile.in
Makefile.linux-gcc
Makefile.msc
README-SQLite.md
VERSION
aclocal.m4
config.guess
config.sub
configure
configure.ac
install-sh
libsql.pc.in
ltmain.sh
magic.txt
main.mk
manifest
manifest.uuid
spec.template
sqlite.pc.in
sqlite3.1
sqlite3.pc.in
sqlite_cfg.h.in
libsql-sys
libsql-wal
tools
vendored
xtask
.dockerignore
.env
.gitignore
.gitmodules
CODE_OF_CONDUCT.md
Cargo.lock
Cargo.toml
Dockerfile
Dockerfile.dev
LICENSE.md
README-libsql.md
README.md
docker-entrypoint.sh
fly.toml
rust-toolchain.toml
203 lines
6.1 KiB
C
203 lines
6.1 KiB
C
/*
|
|
** 2023-04-28
|
|
**
|
|
** 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 SQLite extension implements a the random_json(SEED) and
|
|
** random_json5(SEED) functions. Given a numeric SEED value, these
|
|
** routines generate pseudo-random JSON or JSON5, respectively. The
|
|
** same value is always generated for the same seed.
|
|
**
|
|
** These SQL functions are intended for testing. They do not have any
|
|
** practical real-world use, that we know of.
|
|
**
|
|
** COMPILE:
|
|
**
|
|
** gcc --shared -fPIC -o randomjson.so -I. ext/misc/randomjson.c
|
|
**
|
|
** USING FROM THE CLI:
|
|
**
|
|
** .load ./randomjson
|
|
** SELECT random_json(1);
|
|
*/
|
|
#include "sqlite3ext.h"
|
|
SQLITE_EXTENSION_INIT1
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
/* Pseudo-random number generator */
|
|
typedef struct Prng {
|
|
unsigned int x, y;
|
|
} Prng;
|
|
|
|
/* Reseed the PRNG */
|
|
static void prngSeed(Prng *p, unsigned int iSeed){
|
|
p->x = iSeed | 1;
|
|
p->y = iSeed;
|
|
}
|
|
|
|
/* Extract a random number */
|
|
static unsigned int prngInt(Prng *p){
|
|
p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
|
|
p->y = p->y*1103515245 + 12345;
|
|
return p->x ^ p->y;
|
|
}
|
|
|
|
static const char *azJsonAtoms[] = {
|
|
/* JSON /* JSON-5 */
|
|
"0", "0",
|
|
"1", "1",
|
|
"-1", "-1",
|
|
"2", "+2",
|
|
"3", "3",
|
|
"2.5", "2.5",
|
|
"0.75", ".75",
|
|
"-4.0e2", "-4.e2",
|
|
"5.0e-3", "+5e-3",
|
|
"0", "0x0",
|
|
"512", "0x200",
|
|
"256", "+0x100",
|
|
"-2748", "-0xabc",
|
|
"true", "true",
|
|
"false", "false",
|
|
"null", "null",
|
|
"9.0e999", "Infinity",
|
|
"-9.0e999", "-Infinity",
|
|
"9.0e999", "+Infinity",
|
|
"null", "NaN",
|
|
"-0.0005123", "-0.0005123",
|
|
"4.35e-3", "+4.35e-3",
|
|
"\"gem\\\"hay\"", "\"gem\\\"hay\"",
|
|
"\"icy'joy\"", "'icy\\'joy\'",
|
|
"\"keylog\"", "\"key\\\nlog\"",
|
|
"\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
|
|
"{}", "{}",
|
|
"[]", "[]",
|
|
"[]", "[/*empty*/]",
|
|
"{}", "{//empty\n}",
|
|
"\"ask\"", "\"ask\"",
|
|
"\"bag\"", "\"bag\"",
|
|
"\"can\"", "\"can\"",
|
|
"\"day\"", "\"day\"",
|
|
"\"end\"", "'end'",
|
|
"\"fly\"", "\"fly\"",
|
|
"\"\"", "\"\"",
|
|
};
|
|
static const char *azJsonTemplate[] = {
|
|
/* JSON JSON-5 */
|
|
"{\"a\":%,\"b\":%,\"c\":%}", "{a:%,b:%,c:%}",
|
|
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
|
|
"{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,\"\":%}",
|
|
"{\"d\":%}", "{d:%}",
|
|
"{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
|
|
"{\"$g\":%,\"_h_\":%}", "{$g:%,_h_:%,}",
|
|
"{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
|
|
"{\"a b c d\":%,\"e\":%,\"f\":%,\"x\":%,\"y\":%}",
|
|
"{\"a b c d\":%,e:%,f:%,x:%,y:%}",
|
|
"{\"Z\":%}", "{Z:%,}",
|
|
"[%]", "[%,]",
|
|
"[%,%]", "[%,%]",
|
|
"[%,%,%]", "[%,%,%,]",
|
|
"[%,%,%,%]", "[%,%,%,%]",
|
|
"[%,%,%,%,%]", "[%,%,%,%,%]",
|
|
};
|
|
|
|
#define count(X) (sizeof(X)/sizeof(X[0]))
|
|
|
|
#define STRSZ 10000
|
|
|
|
static void jsonExpand(
|
|
const char *zSrc,
|
|
char *zDest,
|
|
Prng *p,
|
|
int eType, /* 0 for JSON, 1 for JSON5 */
|
|
unsigned int r /* Growth probability 0..1000. 0 means no growth */
|
|
){
|
|
unsigned int i, j, k;
|
|
const char *z;
|
|
size_t n;
|
|
|
|
j = 0;
|
|
if( zSrc==0 ){
|
|
k = prngInt(p)%(count(azJsonTemplate)/2);
|
|
k = k*2 + eType;
|
|
zSrc = azJsonTemplate[k];
|
|
}
|
|
if( strlen(zSrc)>=STRSZ/10 ) r = 0;
|
|
for(i=0; zSrc[i]; i++){
|
|
if( zSrc[i]!='%' ){
|
|
if( j<STRSZ ) zDest[j++] = zSrc[i];
|
|
continue;
|
|
}
|
|
if( r==0 || (r<1000 && (prngInt(p)%1000)<=r) ){
|
|
/* Fill in without values without any new % */
|
|
k = prngInt(p)%(count(azJsonAtoms)/2);
|
|
k = k*2 + eType;
|
|
z = azJsonAtoms[k];
|
|
}else{
|
|
/* Add new % terms */
|
|
k = prngInt(p)%(count(azJsonTemplate)/2);
|
|
k = k*2 + eType;
|
|
z = azJsonTemplate[k];
|
|
}
|
|
n = strlen(z);
|
|
if( j+n<STRSZ ){
|
|
memcpy(&zDest[j], z, n);
|
|
j += n;
|
|
}
|
|
}
|
|
zDest[STRSZ-1] = 0;
|
|
if( j<STRSZ ) zDest[j] = 0;
|
|
}
|
|
|
|
static void randJsonFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
unsigned int iSeed;
|
|
int eType = *(int*)sqlite3_user_data(context);
|
|
Prng prng;
|
|
char z1[STRSZ+1], z2[STRSZ+1];
|
|
|
|
iSeed = (unsigned int)sqlite3_value_int(argv[0]);
|
|
prngSeed(&prng, iSeed);
|
|
jsonExpand(0, z2, &prng, eType, 1000);
|
|
jsonExpand(z2, z1, &prng, eType, 1000);
|
|
jsonExpand(z1, z2, &prng, eType, 100);
|
|
jsonExpand(z2, z1, &prng, eType, 0);
|
|
sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
__declspec(dllexport)
|
|
#endif
|
|
int sqlite3_randomjson_init(
|
|
sqlite3 *db,
|
|
char **pzErrMsg,
|
|
const sqlite3_api_routines *pApi
|
|
){
|
|
static int cOne = 1;
|
|
static int cZero = 0;
|
|
int rc = SQLITE_OK;
|
|
SQLITE_EXTENSION_INIT2(pApi);
|
|
(void)pzErrMsg; /* Unused parameter */
|
|
rc = sqlite3_create_function(db, "random_json", 1,
|
|
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
|
&cZero, randJsonFunc, 0, 0);
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3_create_function(db, "random_json5", 1,
|
|
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
|
|
&cOne, randJsonFunc, 0, 0);
|
|
}
|
|
return rc;
|
|
}
|