|
1 /* |
|
2 ** 2008 March 19 |
|
3 ** |
|
4 ** The author disclaims copyright to this source code. In place of |
|
5 ** a legal notice, here is a blessing: |
|
6 ** |
|
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. |
|
10 ** |
|
11 ************************************************************************* |
|
12 ** Code for testing all sorts of SQLite interfaces. This code |
|
13 ** implements new SQL functions used by the test scripts. |
|
14 ** |
|
15 ** $Id: test_func.c,v 1.13 2008/08/28 02:26:07 drh Exp $ |
|
16 */ |
|
17 #include "sqlite3.h" |
|
18 #include "tcl.h" |
|
19 #include <stdlib.h> |
|
20 #include <string.h> |
|
21 #include <assert.h> |
|
22 |
|
23 |
|
24 /* |
|
25 ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
|
26 ** allocation fails, call sqlite3_result_error_nomem() to notify |
|
27 ** the database handle that malloc() has failed. |
|
28 */ |
|
29 static void *testContextMalloc(sqlite3_context *context, int nByte){ |
|
30 char *z = sqlite3_malloc(nByte); |
|
31 if( !z && nByte>0 ){ |
|
32 sqlite3_result_error_nomem(context); |
|
33 } |
|
34 return z; |
|
35 } |
|
36 |
|
37 /* |
|
38 ** This function generates a string of random characters. Used for |
|
39 ** generating test data. |
|
40 */ |
|
41 static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ |
|
42 static const unsigned char zSrc[] = |
|
43 "abcdefghijklmnopqrstuvwxyz" |
|
44 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
|
45 "0123456789" |
|
46 ".-!,:*^+=_|?/<> "; |
|
47 int iMin, iMax, n, r, i; |
|
48 unsigned char zBuf[1000]; |
|
49 |
|
50 /* It used to be possible to call randstr() with any number of arguments, |
|
51 ** but now it is registered with SQLite as requiring exactly 2. |
|
52 */ |
|
53 assert(argc==2); |
|
54 |
|
55 iMin = sqlite3_value_int(argv[0]); |
|
56 if( iMin<0 ) iMin = 0; |
|
57 if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; |
|
58 iMax = sqlite3_value_int(argv[1]); |
|
59 if( iMax<iMin ) iMax = iMin; |
|
60 if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; |
|
61 n = iMin; |
|
62 if( iMax>iMin ){ |
|
63 sqlite3_randomness(sizeof(r), &r); |
|
64 r &= 0x7fffffff; |
|
65 n += r%(iMax + 1 - iMin); |
|
66 } |
|
67 assert( n<sizeof(zBuf) ); |
|
68 sqlite3_randomness(n, zBuf); |
|
69 for(i=0; i<n; i++){ |
|
70 zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; |
|
71 } |
|
72 zBuf[n] = 0; |
|
73 sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT); |
|
74 } |
|
75 |
|
76 /* |
|
77 ** The following two SQL functions are used to test returning a text |
|
78 ** result with a destructor. Function 'test_destructor' takes one argument |
|
79 ** and returns the same argument interpreted as TEXT. A destructor is |
|
80 ** passed with the sqlite3_result_text() call. |
|
81 ** |
|
82 ** SQL function 'test_destructor_count' returns the number of outstanding |
|
83 ** allocations made by 'test_destructor'; |
|
84 ** |
|
85 ** WARNING: Not threadsafe. |
|
86 */ |
|
87 static int test_destructor_count_var = 0; |
|
88 static void destructor(void *p){ |
|
89 char *zVal = (char *)p; |
|
90 assert(zVal); |
|
91 zVal--; |
|
92 sqlite3_free(zVal); |
|
93 test_destructor_count_var--; |
|
94 } |
|
95 static void test_destructor( |
|
96 sqlite3_context *pCtx, |
|
97 int nArg, |
|
98 sqlite3_value **argv |
|
99 ){ |
|
100 char *zVal; |
|
101 int len; |
|
102 |
|
103 test_destructor_count_var++; |
|
104 assert( nArg==1 ); |
|
105 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
|
106 len = sqlite3_value_bytes(argv[0]); |
|
107 zVal = testContextMalloc(pCtx, len+3); |
|
108 if( !zVal ){ |
|
109 return; |
|
110 } |
|
111 zVal[len+1] = 0; |
|
112 zVal[len+2] = 0; |
|
113 zVal++; |
|
114 memcpy(zVal, sqlite3_value_text(argv[0]), len); |
|
115 sqlite3_result_text(pCtx, zVal, -1, destructor); |
|
116 } |
|
117 #ifndef SQLITE_OMIT_UTF16 |
|
118 static void test_destructor16( |
|
119 sqlite3_context *pCtx, |
|
120 int nArg, |
|
121 sqlite3_value **argv |
|
122 ){ |
|
123 char *zVal; |
|
124 int len; |
|
125 |
|
126 test_destructor_count_var++; |
|
127 assert( nArg==1 ); |
|
128 if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
|
129 len = sqlite3_value_bytes16(argv[0]); |
|
130 zVal = testContextMalloc(pCtx, len+3); |
|
131 if( !zVal ){ |
|
132 return; |
|
133 } |
|
134 zVal[len+1] = 0; |
|
135 zVal[len+2] = 0; |
|
136 zVal++; |
|
137 memcpy(zVal, sqlite3_value_text16(argv[0]), len); |
|
138 sqlite3_result_text16(pCtx, zVal, -1, destructor); |
|
139 } |
|
140 #endif |
|
141 static void test_destructor_count( |
|
142 sqlite3_context *pCtx, |
|
143 int nArg, |
|
144 sqlite3_value **argv |
|
145 ){ |
|
146 sqlite3_result_int(pCtx, test_destructor_count_var); |
|
147 } |
|
148 |
|
149 /* |
|
150 ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() |
|
151 ** interface. |
|
152 ** |
|
153 ** The test_auxdata() SQL function attempts to register each of its arguments |
|
154 ** as auxiliary data. If there are no prior registrations of aux data for |
|
155 ** that argument (meaning the argument is not a constant or this is its first |
|
156 ** call) then the result for that argument is 0. If there is a prior |
|
157 ** registration, the result for that argument is 1. The overall result |
|
158 ** is the individual argument results separated by spaces. |
|
159 */ |
|
160 static void free_test_auxdata(void *p) {sqlite3_free(p);} |
|
161 static void test_auxdata( |
|
162 sqlite3_context *pCtx, |
|
163 int nArg, |
|
164 sqlite3_value **argv |
|
165 ){ |
|
166 int i; |
|
167 char *zRet = testContextMalloc(pCtx, nArg*2); |
|
168 if( !zRet ) return; |
|
169 memset(zRet, 0, nArg*2); |
|
170 for(i=0; i<nArg; i++){ |
|
171 char const *z = (char*)sqlite3_value_text(argv[i]); |
|
172 if( z ){ |
|
173 int n; |
|
174 char *zAux = sqlite3_get_auxdata(pCtx, i); |
|
175 if( zAux ){ |
|
176 zRet[i*2] = '1'; |
|
177 assert( strcmp(zAux,z)==0 ); |
|
178 }else { |
|
179 zRet[i*2] = '0'; |
|
180 } |
|
181 n = strlen(z) + 1; |
|
182 zAux = testContextMalloc(pCtx, n); |
|
183 if( zAux ){ |
|
184 memcpy(zAux, z, n); |
|
185 sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); |
|
186 } |
|
187 zRet[i*2+1] = ' '; |
|
188 } |
|
189 } |
|
190 sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); |
|
191 } |
|
192 |
|
193 /* |
|
194 ** A function to test error reporting from user functions. This function |
|
195 ** returns a copy of its first argument as the error message. If the |
|
196 ** second argument exists, it becomes the error code. |
|
197 */ |
|
198 static void test_error( |
|
199 sqlite3_context *pCtx, |
|
200 int nArg, |
|
201 sqlite3_value **argv |
|
202 ){ |
|
203 sqlite3_result_error(pCtx, (char*)sqlite3_value_text(argv[0]), -1); |
|
204 if( nArg==2 ){ |
|
205 sqlite3_result_error_code(pCtx, sqlite3_value_int(argv[1])); |
|
206 } |
|
207 } |
|
208 |
|
209 /* |
|
210 ** Implementation of the counter(X) function. If X is an integer |
|
211 ** constant, then the first invocation will return X. The second X+1. |
|
212 ** and so forth. Can be used (for example) to provide a sequence number |
|
213 ** in a result set. |
|
214 */ |
|
215 static void counterFunc( |
|
216 sqlite3_context *pCtx, /* Function context */ |
|
217 int nArg, /* Number of function arguments */ |
|
218 sqlite3_value **argv /* Values for all function arguments */ |
|
219 ){ |
|
220 int *pCounter = (int*)sqlite3_get_auxdata(pCtx, 0); |
|
221 if( pCounter==0 ){ |
|
222 pCounter = sqlite3_malloc( sizeof(*pCounter) ); |
|
223 if( pCounter==0 ){ |
|
224 sqlite3_result_error_nomem(pCtx); |
|
225 return; |
|
226 } |
|
227 *pCounter = sqlite3_value_int(argv[0]); |
|
228 sqlite3_set_auxdata(pCtx, 0, pCounter, sqlite3_free); |
|
229 }else{ |
|
230 ++*pCounter; |
|
231 } |
|
232 sqlite3_result_int(pCtx, *pCounter); |
|
233 } |
|
234 |
|
235 |
|
236 /* |
|
237 ** This function takes two arguments. It performance UTF-8/16 type |
|
238 ** conversions on the first argument then returns a copy of the second |
|
239 ** argument. |
|
240 ** |
|
241 ** This function is used in cases such as the following: |
|
242 ** |
|
243 ** SELECT test_isolation(x,x) FROM t1; |
|
244 ** |
|
245 ** We want to verify that the type conversions that occur on the |
|
246 ** first argument do not invalidate the second argument. |
|
247 */ |
|
248 static void test_isolation( |
|
249 sqlite3_context *pCtx, |
|
250 int nArg, |
|
251 sqlite3_value **argv |
|
252 ){ |
|
253 #ifndef SQLITE_OMIT_UTF16 |
|
254 sqlite3_value_text16(argv[0]); |
|
255 sqlite3_value_text(argv[0]); |
|
256 sqlite3_value_text16(argv[0]); |
|
257 sqlite3_value_text(argv[0]); |
|
258 #endif |
|
259 sqlite3_result_value(pCtx, argv[1]); |
|
260 } |
|
261 |
|
262 /* |
|
263 ** Invoke an SQL statement recursively. The function result is the |
|
264 ** first column of the first row of the result set. |
|
265 */ |
|
266 static void test_eval( |
|
267 sqlite3_context *pCtx, |
|
268 int nArg, |
|
269 sqlite3_value **argv |
|
270 ){ |
|
271 sqlite3_stmt *pStmt; |
|
272 int rc; |
|
273 sqlite3 *db = sqlite3_context_db_handle(pCtx); |
|
274 const char *zSql; |
|
275 |
|
276 zSql = (char*)sqlite3_value_text(argv[0]); |
|
277 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
|
278 if( rc==SQLITE_OK ){ |
|
279 rc = sqlite3_step(pStmt); |
|
280 if( rc==SQLITE_ROW ){ |
|
281 sqlite3_result_value(pCtx, sqlite3_column_value(pStmt, 0)); |
|
282 } |
|
283 rc = sqlite3_finalize(pStmt); |
|
284 } |
|
285 if( rc ){ |
|
286 char *zErr; |
|
287 assert( pStmt==0 ); |
|
288 zErr = sqlite3_mprintf("sqlite3_prepare_v2() error: %s",sqlite3_errmsg(db)); |
|
289 sqlite3_result_text(pCtx, zErr, -1, sqlite3_free); |
|
290 sqlite3_result_error_code(pCtx, rc); |
|
291 } |
|
292 } |
|
293 |
|
294 |
|
295 static int registerTestFunctions(sqlite3 *db){ |
|
296 static const struct { |
|
297 char *zName; |
|
298 signed char nArg; |
|
299 unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ |
|
300 void (*xFunc)(sqlite3_context*,int,sqlite3_value **); |
|
301 } aFuncs[] = { |
|
302 { "randstr", 2, SQLITE_UTF8, randStr }, |
|
303 { "test_destructor", 1, SQLITE_UTF8, test_destructor}, |
|
304 #ifndef SQLITE_OMIT_UTF16 |
|
305 { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, |
|
306 #endif |
|
307 { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, |
|
308 { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, |
|
309 { "test_error", 1, SQLITE_UTF8, test_error}, |
|
310 { "test_error", 2, SQLITE_UTF8, test_error}, |
|
311 { "test_eval", 1, SQLITE_UTF8, test_eval}, |
|
312 { "test_isolation", 2, SQLITE_UTF8, test_isolation}, |
|
313 { "test_counter", 1, SQLITE_UTF8, counterFunc}, |
|
314 }; |
|
315 int i; |
|
316 |
|
317 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ |
|
318 sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, |
|
319 aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); |
|
320 } |
|
321 return SQLITE_OK; |
|
322 } |
|
323 |
|
324 /* |
|
325 ** TCLCMD: autoinstall_test_functions |
|
326 ** |
|
327 ** Invoke this TCL command to use sqlite3_auto_extension() to cause |
|
328 ** the standard set of test functions to be loaded into each new |
|
329 ** database connection. |
|
330 */ |
|
331 static int autoinstall_test_funcs( |
|
332 void * clientData, |
|
333 Tcl_Interp *interp, |
|
334 int objc, |
|
335 Tcl_Obj *CONST objv[] |
|
336 ){ |
|
337 extern int Md5_Register(sqlite3*); |
|
338 int rc = sqlite3_auto_extension((void*)registerTestFunctions); |
|
339 if( rc==SQLITE_OK ){ |
|
340 rc = sqlite3_auto_extension((void*)Md5_Register); |
|
341 } |
|
342 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |
|
343 return TCL_OK; |
|
344 } |
|
345 |
|
346 /* |
|
347 ** A bogus step function and finalizer function. |
|
348 */ |
|
349 static void tStep(sqlite3_context *a, int b, sqlite3_value **c){} |
|
350 static void tFinal(sqlite3_context *a){} |
|
351 |
|
352 |
|
353 /* |
|
354 ** tclcmd: abuse_create_function |
|
355 ** |
|
356 ** Make various calls to sqlite3_create_function that do not have valid |
|
357 ** parameters. Verify that the error condition is detected and reported. |
|
358 */ |
|
359 static int abuse_create_function( |
|
360 void * clientData, |
|
361 Tcl_Interp *interp, |
|
362 int objc, |
|
363 Tcl_Obj *CONST objv[] |
|
364 ){ |
|
365 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**); |
|
366 sqlite3 *db; |
|
367 int rc; |
|
368 int mxArg; |
|
369 |
|
370 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; |
|
371 |
|
372 rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep,tStep,tFinal); |
|
373 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
374 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
375 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
376 |
|
377 rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, 0); |
|
378 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
379 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
380 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
381 |
|
382 rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, tStep, 0, tFinal); |
|
383 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
384 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
385 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
386 |
|
387 rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, 0, tFinal); |
|
388 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
389 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
390 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
391 |
|
392 rc = sqlite3_create_function(db, "tx", 1, SQLITE_UTF8, 0, 0, tStep, 0); |
|
393 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
394 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
395 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
396 |
|
397 rc = sqlite3_create_function(db, "tx", -2, SQLITE_UTF8, 0, tStep, 0, 0); |
|
398 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
399 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
400 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
401 |
|
402 rc = sqlite3_create_function(db, "tx", 128, SQLITE_UTF8, 0, tStep, 0, 0); |
|
403 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
404 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
405 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
406 |
|
407 rc = sqlite3_create_function(db, "funcxx" |
|
408 "_123456789_123456789_123456789_123456789_123456789" |
|
409 "_123456789_123456789_123456789_123456789_123456789" |
|
410 "_123456789_123456789_123456789_123456789_123456789" |
|
411 "_123456789_123456789_123456789_123456789_123456789" |
|
412 "_123456789_123456789_123456789_123456789_123456789", |
|
413 1, SQLITE_UTF8, 0, tStep, 0, 0); |
|
414 if( rc!=SQLITE_ERROR ) goto abuse_err; |
|
415 if( sqlite3_errcode(db)!=SQLITE_ERROR ) goto abuse_err; |
|
416 if( strcmp(sqlite3_errmsg(db), "bad parameters")!=0 ) goto abuse_err; |
|
417 |
|
418 /* This last function registration should actually work. Generate |
|
419 ** a no-op function (that always returns NULL) and which has the |
|
420 ** maximum-length function name and the maximum number of parameters. |
|
421 */ |
|
422 sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, 10000); |
|
423 mxArg = sqlite3_limit(db, SQLITE_LIMIT_FUNCTION_ARG, -1); |
|
424 rc = sqlite3_create_function(db, "nullx" |
|
425 "_123456789_123456789_123456789_123456789_123456789" |
|
426 "_123456789_123456789_123456789_123456789_123456789" |
|
427 "_123456789_123456789_123456789_123456789_123456789" |
|
428 "_123456789_123456789_123456789_123456789_123456789" |
|
429 "_123456789_123456789_123456789_123456789_123456789", |
|
430 mxArg, SQLITE_UTF8, 0, tStep, 0, 0); |
|
431 if( rc!=SQLITE_OK ) goto abuse_err; |
|
432 |
|
433 return TCL_OK; |
|
434 |
|
435 abuse_err: |
|
436 Tcl_AppendResult(interp, "sqlite3_create_function abused test failed", |
|
437 (char*)0); |
|
438 return TCL_ERROR; |
|
439 } |
|
440 |
|
441 |
|
442 |
|
443 /* |
|
444 ** Register commands with the TCL interpreter. |
|
445 */ |
|
446 int Sqlitetest_func_Init(Tcl_Interp *interp){ |
|
447 static struct { |
|
448 char *zName; |
|
449 Tcl_ObjCmdProc *xProc; |
|
450 } aObjCmd[] = { |
|
451 { "autoinstall_test_functions", autoinstall_test_funcs }, |
|
452 { "abuse_create_function", abuse_create_function }, |
|
453 }; |
|
454 int i; |
|
455 extern int Md5_Register(sqlite3*); |
|
456 |
|
457 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
|
458 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); |
|
459 } |
|
460 sqlite3_initialize(); |
|
461 sqlite3_auto_extension((void*)registerTestFunctions); |
|
462 sqlite3_auto_extension((void*)Md5_Register); |
|
463 return TCL_OK; |
|
464 } |