4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This SQLite extension implements a the random_json(SEED) and
14 ** random_json5(SEED) functions. Given a numeric SEED value, these
15 ** routines generate pseudo-random JSON or JSON5, respectively. The
16 ** same value is always generated for the same seed.
18 ** These SQL functions are intended for testing. They do not have any
19 ** practical real-world use, that we know of.
23 ** gcc --shared -fPIC -o randomjson.so -I. ext/misc/randomjson.c
25 ** USING FROM THE CLI:
28 ** SELECT random_json(1);
29 ** SELECT random_json5(1);
31 #ifdef SQLITE_STATIC_RANDOMJSON
34 # include "sqlite3ext.h"
35 SQLITE_EXTENSION_INIT1
41 /* Pseudo-random number generator */
47 static void prngSeed(Prng
*p
, unsigned int iSeed
){
52 /* Extract a random number */
53 static unsigned int prngInt(Prng
*p
){
54 p
->x
= (p
->x
>>1) ^ ((1+~(p
->x
&1)) & 0xd0000001);
55 p
->y
= p
->y
*1103515245 + 12345;
59 static char *azJsonAtoms
[] = {
70 "6.DDe+0DD", "6.DDe+0DD",
78 "9.0e999", "Infinity",
79 "-9.0e999", "-Infinity",
80 "9.0e999", "+Infinity",
82 "-0.0005DD", "-0.0005DD",
83 "4.35e-3", "+4.35e-3",
84 "\"gem\\\"hay\"", "\"gem\\\"hay\"",
85 "\"icy'joy\"", "'icy\\'joy\'",
86 "\"keylog\"", "\"key\\\nlog\"",
87 "\"mix\\\\\\tnet\"", "\"mix\\\\\\tnet\"",
88 "\"oat\\r\\n\"", "\"oat\\r\\n\"",
89 "\"\\fpan\\b\"", "\"\\fpan\\b\"",
100 "\"\\u00XX\\u00XX\"", "\"\\xXX\\xXX\"",
101 "\"y\\uXXXXz\"", "\"y\\uXXXXz\"",
104 static char *azJsonTemplate
[] = {
106 "{\"a\":%,\"b\":%,\"cDD\":%}", "{a:%,b:%,cDD:%}",
107 "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"e\":%}", "{a:%,b:%,c:%,d:%,e:%}",
108 "{\"a\":%,\"b\":%,\"c\":%,\"d\":%,\"\":%}", "{a:%,b:%,c:%,d:%,'':%}",
109 "{\"d\":%}", "{d:%}",
110 "{\"eeee\":%, \"ffff\":%}", "{eeee:% /*and*/, ffff:%}",
111 "{\"$g\":%,\"_h_\":%,\"a b c d\":%}", "{$g:%,_h_:%,\"a b c d\":%}",
112 "{\"x\":%,\n \"y\":%}", "{\"x\":%,\n \"y\":%}",
113 "{\"\\u00XX\":%,\"\\uXXXX\":%}", "{\"\\xXX\":%,\"\\uXXXX\":%}",
114 "{\"Z\":%}", "{Z:%,}",
117 "[%,%,%]", "[%,%,%,]",
118 "[%,%,%,%]", "[%,%,%,%]",
119 "[%,%,%,%,%]", "[%,%,%,%,%]",
122 #define count(X) (sizeof(X)/sizeof(X[0]))
126 static void jsonExpand(
130 int eType
, /* 0 for JSON, 1 for JSON5 */
131 unsigned int r
/* Growth probability 0..1000. 0 means no growth */
133 unsigned int i
, j
, k
;
140 if( zSrc
==0 ) zSrc
= "%";
141 if( strlen(zSrc
)>=STRSZ
/10 ) r
= 0;
142 for(i
=0; zSrc
[i
]; i
++){
144 if( j
<STRSZ
) zDest
[j
++] = zSrc
[i
];
147 if( r
==0 || (r
<1000 && (prngInt(p
)%1000)<=r
) ){
148 /* Fill in without values without any new % */
149 k
= prngInt(p
)%(count(azJsonAtoms
)/2);
153 /* Add new % terms */
154 k
= prngInt(p
)%(count(azJsonTemplate
)/2);
156 z
= azJsonTemplate
[k
];
159 if( (zX
= strstr(z
,"XX"))!=0 ){
160 unsigned int y
= prngInt(p
);
161 if( (y
&0xff)==((y
>>8)&0xff) ) y
+= 0x100;
162 while( (y
&0xff)==((y
>>16)&0xff) || ((y
>>8)&0xff)==((y
>>16)&0xff) ){
165 memcpy(zBuf
, z
, n
+1);
169 zX
[0] = "0123456789abcdef"[y
%16]; y
/= 16;
170 zX
[1] = "0123456789abcdef"[y
%16]; y
/= 16;
171 zX
= strstr(zX
, "XX");
173 }else if( (zX
= strstr(z
,"DD"))!=0 ){
174 unsigned int y
= prngInt(p
);
175 memcpy(zBuf
, z
, n
+1);
179 zX
[0] = "0123456789"[y
%10]; y
/= 10;
180 zX
[1] = "0123456789"[y
%10]; y
/= 10;
181 zX
= strstr(zX
, "DD");
184 assert( strstr(z
, "XX")==0 );
185 assert( strstr(z
, "DD")==0 );
187 memcpy(&zDest
[j
], z
, n
);
192 if( j
<STRSZ
) zDest
[j
] = 0;
195 static void randJsonFunc(
196 sqlite3_context
*context
,
201 int eType
= *(int*)sqlite3_user_data(context
);
203 char z1
[STRSZ
+1], z2
[STRSZ
+1];
205 iSeed
= (unsigned int)sqlite3_value_int(argv
[0]);
206 prngSeed(&prng
, iSeed
);
207 jsonExpand(0, z2
, &prng
, eType
, 1000);
208 jsonExpand(z2
, z1
, &prng
, eType
, 1000);
209 jsonExpand(z1
, z2
, &prng
, eType
, 100);
210 jsonExpand(z2
, z1
, &prng
, eType
, 0);
211 sqlite3_result_text(context
, z1
, -1, SQLITE_TRANSIENT
);
215 __declspec(dllexport
)
217 int sqlite3_randomjson_init(
220 const sqlite3_api_routines
*pApi
223 static int cZero
= 0;
225 #ifdef SQLITE_STATIC_RANDOMJSON
226 (void)pApi
; /* Unused parameter */
228 SQLITE_EXTENSION_INIT2(pApi
);
230 (void)pzErrMsg
; /* Unused parameter */
231 rc
= sqlite3_create_function(db
, "random_json", 1,
232 SQLITE_UTF8
|SQLITE_INNOCUOUS
|SQLITE_DETERMINISTIC
,
233 &cZero
, randJsonFunc
, 0, 0);
235 rc
= sqlite3_create_function(db
, "random_json5", 1,
236 SQLITE_UTF8
|SQLITE_INNOCUOUS
|SQLITE_DETERMINISTIC
,
237 &cOne
, randJsonFunc
, 0, 0);