wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | using i64 = System.Int64; |
||
6 | using u8 = System.Byte; |
||
7 | |||
8 | namespace Community.CsharpSqlite |
||
9 | { |
||
10 | #if TCLSH |
||
11 | using tcl.lang; |
||
12 | using sqlite3_stmt = Sqlite3.Vdbe; |
||
13 | using sqlite3_value = Sqlite3.Mem; |
||
14 | using Tcl_Interp = tcl.lang.Interp; |
||
15 | using Tcl_Obj = tcl.lang.TclObject; |
||
16 | |||
17 | public partial class Sqlite3 |
||
18 | { |
||
19 | /* |
||
20 | ** 2008 March 19 |
||
21 | ** |
||
22 | ** The author disclaims copyright to this source code. In place of |
||
23 | ** a legal notice, here is a blessing: |
||
24 | ** |
||
25 | ** May you do good and not evil. |
||
26 | ** May you find forgiveness for yourself and forgive others. |
||
27 | ** May you share freely, never taking more than you give. |
||
28 | ** |
||
29 | ************************************************************************* |
||
30 | ** Code for testing all sorts of SQLite interfaces. This code |
||
31 | ** implements new SQL functions used by the test scripts. |
||
32 | ************************************************************************* |
||
33 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
34 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
35 | ** |
||
36 | ** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e |
||
37 | ** |
||
38 | ************************************************************************* |
||
39 | */ |
||
40 | //#include "sqlite3.h" |
||
41 | //#include "tcl.h" |
||
42 | //#include <stdlib.h> |
||
43 | //#include <string.h> |
||
44 | //#include <assert.h> |
||
45 | |||
46 | |||
47 | /* |
||
48 | ** Allocate nByte bytes of space using sqlite3Malloc(). If the |
||
49 | ** allocation fails, call sqlite3_result_error_nomem() to notify |
||
50 | ** the database handle that malloc() has failed. |
||
51 | */ |
||
52 | static Object testContextMalloc( sqlite3_context context, int nByte ) |
||
53 | { |
||
54 | Object z = new Object();// sqlite3Malloc( nByte ); |
||
55 | if ( z == null && nByte > 0 ) |
||
56 | { |
||
57 | sqlite3_result_error_nomem( context ); |
||
58 | } |
||
59 | return z; |
||
60 | } |
||
61 | |||
62 | /* |
||
63 | ** This function generates a string of random characters. Used for |
||
64 | ** generating test data. |
||
65 | */ |
||
66 | static void randStr( sqlite3_context context, int argc, sqlite3_value[] argv ) |
||
67 | { |
||
68 | string zSrc = |
||
69 | "abcdefghijklmnopqrstuvwxyz" + |
||
70 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + |
||
71 | "0123456789" + |
||
72 | ".-!,:*^+=_|?/<> "; |
||
73 | int iMin, iMax, n, i; |
||
74 | i64 r = 0; |
||
75 | |||
76 | StringBuilder zBuf = new StringBuilder( 1000 ); |
||
77 | |||
78 | /* It used to be possible to call randstr() with any number of arguments, |
||
79 | ** but now it is registered with SQLite as requiring exactly 2. |
||
80 | */ |
||
81 | Debug.Assert( argc == 2 ); |
||
82 | |||
83 | iMin = sqlite3_value_int( argv[0] ); |
||
84 | if ( iMin < 0 ) |
||
85 | iMin = 0; |
||
86 | if ( iMin >= zBuf.Capacity ) |
||
87 | iMin = zBuf.Capacity - 1; |
||
88 | iMax = sqlite3_value_int( argv[1] ); |
||
89 | if ( iMax < iMin ) |
||
90 | iMax = iMin; |
||
91 | if ( iMax >= zBuf.Capacity ) |
||
92 | iMax = zBuf.Capacity - 1; |
||
93 | n = iMin; |
||
94 | if ( iMax > iMin ) |
||
95 | { |
||
96 | sqlite3_randomness( sizeof( i64 ), ref r ); |
||
97 | r &= 0x7fffffff; |
||
98 | n += (int)( r % ( iMax + 1 - iMin ) ); |
||
99 | } |
||
100 | Debug.Assert( n < zBuf.Capacity );//sizeof( zBuf ) ); |
||
101 | i64 zRan = 0; |
||
102 | for ( i = 0; i < n; i++ ) |
||
103 | { |
||
104 | sqlite3_randomness( 1, ref zRan ); |
||
105 | zBuf.Append( zSrc[(int)( Math.Abs( zRan ) % ( zSrc.Length - 1 ) )] ); |
||
106 | } |
||
107 | //zBuf[n] = 0; |
||
108 | sqlite3_result_text( context, zBuf, n, SQLITE_TRANSIENT ); |
||
109 | } |
||
110 | |||
111 | /* |
||
112 | ** The following two SQL functions are used to test returning a text |
||
113 | ** result with a destructor. Function 'test_destructor' takes one argument |
||
114 | ** and returns the same argument interpreted as TEXT. A destructor is |
||
115 | ** passed with the sqlite3_result_text() call. |
||
116 | ** |
||
117 | ** SQL function 'test_destructor_count' returns the number of outstanding |
||
118 | ** allocations made by 'test_destructor'; |
||
119 | ** |
||
120 | ** WARNING: Not threadsafe. |
||
121 | */ |
||
122 | static int test_destructor_count_var = 0; |
||
123 | static void destructor( ref string p ) |
||
124 | { |
||
125 | string zVal = p; |
||
126 | Debug.Assert( zVal != null ); |
||
127 | //zVal--; |
||
128 | sqlite3DbFree( null, ref zVal ); |
||
129 | test_destructor_count_var--; |
||
130 | } |
||
131 | static void test_destructor( |
||
132 | sqlite3_context pCtx, /* Function context */ |
||
133 | int nArg, /* Number of function arguments */ |
||
134 | sqlite3_value[] argv /* Values for all function arguments */ |
||
135 | ) |
||
136 | { |
||
137 | String zVal; |
||
138 | int len; |
||
139 | |||
140 | test_destructor_count_var++; |
||
141 | Debug.Assert( nArg == 1 ); |
||
142 | if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) |
||
143 | return; |
||
144 | len = sqlite3_value_bytes( argv[0] ); |
||
145 | zVal = "";//testContextMalloc( pCtx, len + 3 ); |
||
146 | if ( null == zVal ) |
||
147 | { |
||
148 | return; |
||
149 | } |
||
150 | //zVal[len+1] = 0; |
||
151 | //zVal[len+2] = 0; |
||
152 | //zVal++; |
||
153 | zVal = sqlite3_value_text( argv[0] );//memcpy(zVal, sqlite3_value_text(argv[0]), len); |
||
154 | |||
155 | sqlite3_result_text( pCtx, zVal, -1, destructor ); |
||
156 | } |
||
157 | #if !SQLITE_OMIT_UTF16 |
||
158 | static void test_destructor16( |
||
159 | //sqlite3_context pCtx, /* Function context */ |
||
160 | //int nArg, /* Number of function arguments */ |
||
161 | //sqlite3_value[] argv /* Values for all function arguments */ |
||
162 | ){ |
||
163 | string zVal; |
||
164 | int len; |
||
165 | |||
166 | test_destructor_count_var++; |
||
167 | Debug.Assert(nArg==1 ); |
||
168 | if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
||
169 | len = sqlite3_value_bytes16(argv[0]); |
||
170 | zVal = testContextMalloc(pCtx, len+3); |
||
171 | if( null==zVal ){ |
||
172 | return; |
||
173 | } |
||
174 | zVal[len+1] = 0; |
||
175 | zVal[len+2] = 0; |
||
176 | zVal++; |
||
177 | memcpy(zVal, sqlite3_value_text16(argv[0]), len); |
||
178 | sqlite3_result_text16(pCtx, zVal, -1, destructor); |
||
179 | } |
||
180 | #endif |
||
181 | |||
182 | static void test_destructor_count( |
||
183 | sqlite3_context pCtx, /* Function context */ |
||
184 | int nArg, /* Number of function arguments */ |
||
185 | sqlite3_value[] argv /* Values for all function arguments */ |
||
186 | ) |
||
187 | { |
||
188 | sqlite3_result_int( pCtx, test_destructor_count_var ); |
||
189 | } |
||
190 | |||
191 | /* |
||
192 | ** The following aggregate function, test_agg_errmsg16(), takes zero |
||
193 | ** arguments. It returns the text value returned by the sqlite3_errmsg16() |
||
194 | ** API function. |
||
195 | */ |
||
196 | #if SQLITE_OMIT_BUILTIN_TEST |
||
197 | //void sqlite3BeginBenignMalloc(void); |
||
198 | //void sqlite3EndBenignMalloc(void); |
||
199 | #else |
||
200 | //#define sqlite3BeginBenignMalloc() |
||
201 | //#define sqlite3EndBenignMalloc() |
||
202 | #endif |
||
203 | static void test_agg_errmsg16_step( sqlite3_context a, int b, sqlite3_value[] c ) |
||
204 | { |
||
205 | } |
||
206 | static void test_agg_errmsg16_final( sqlite3_context ctx ) |
||
207 | { |
||
208 | #if !SQLITE_OMIT_UTF16 |
||
209 | string z; |
||
210 | sqlite3 db = sqlite3_context_db_handle( ctx ); |
||
211 | sqlite3_aggregate_context( ctx, 2048 ); |
||
212 | sqlite3BeginBenignMalloc(); |
||
213 | z = sqlite3_errmsg16( db ); |
||
214 | sqlite3EndBenignMalloc(); |
||
215 | sqlite3_result_text16( ctx, z, -1, SQLITE_TRANSIENT ); |
||
216 | #endif |
||
217 | } |
||
218 | |||
219 | /* |
||
220 | ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() |
||
221 | ** interface. |
||
222 | ** |
||
223 | ** The test_auxdata() SQL function attempts to register each of its arguments |
||
224 | ** as auxiliary data. If there are no prior registrations of aux data for |
||
225 | ** that argument (meaning the argument is not a constant or this is its first |
||
226 | ** call) then the result for that argument is 0. If there is a prior |
||
227 | ** registration, the result for that argument is 1. The overall result |
||
228 | ** is the individual argument results separated by spaces. |
||
229 | */ |
||
230 | static void free_test_auxdata( ref string p ) |
||
231 | { |
||
232 | p = null; |
||
233 | sqlite3DbFree( null, ref p ); |
||
234 | } |
||
235 | static void test_auxdata( |
||
236 | sqlite3_context pCtx, /* Function context */ |
||
237 | int nArg, /* Number of function arguments */ |
||
238 | sqlite3_value[] argv /* Values for all function arguments */ |
||
239 | ) |
||
240 | { |
||
241 | int i; |
||
242 | StringBuilder zRet = new StringBuilder( nArg * 2 );//testContextMalloc( pCtx, nArg * 2 ); |
||
243 | if ( null == zRet ) |
||
244 | return; |
||
245 | //memset(zRet, 0, nArg*2); |
||
246 | for ( i = 0; i < nArg; i++ ) |
||
247 | { |
||
248 | string z = sqlite3_value_text( argv[i] ); |
||
249 | if ( z != null ) |
||
250 | { |
||
251 | int n; |
||
252 | string zAux = (string)sqlite3_get_auxdata( pCtx, i ); |
||
253 | if ( zAux != null ) |
||
254 | { |
||
255 | zRet.Append( '1' );//[i * 2] = '1'; |
||
256 | Debug.Assert( zAux == z );//strcmp( zAux, z ) == 0 ); |
||
257 | } |
||
258 | else |
||
259 | { |
||
260 | zRet.Append( '0' );//[i * 2] = '0'; |
||
261 | } |
||
262 | n = z.Length;// strlen( z ) + 1; |
||
263 | zAux = "";//testContextMalloc( pCtx, n ); |
||
264 | if ( zAux != null ) |
||
265 | { |
||
266 | zAux = z.Substring( 0, n );// memcpy( zAux, z, n ); |
||
267 | sqlite3_set_auxdata( pCtx, i, zAux ); |
||
268 | } |
||
269 | zRet.Append( ' ' );// zRet[i * 2 + 1] = ' '; |
||
270 | } |
||
271 | } |
||
272 | sqlite3_result_text( pCtx, zRet, 2 * nArg - 1, free_test_auxdata ); |
||
273 | } |
||
274 | |||
275 | /* |
||
276 | ** A function to test error reporting from user functions. This function |
||
277 | ** returns a copy of its first argument as the error message. If the |
||
278 | ** second argument exists, it becomes the error code. |
||
279 | */ |
||
280 | static void test_error( |
||
281 | sqlite3_context pCtx, /* Function context */ |
||
282 | int nArg, /* Number of function arguments */ |
||
283 | sqlite3_value[] argv /* Values for all function arguments */ |
||
284 | ) |
||
285 | { |
||
286 | sqlite3_result_error( pCtx, sqlite3_value_text( argv[0] ), -1 ); |
||
287 | if ( nArg == 2 ) |
||
288 | { |
||
289 | sqlite3_result_error_code( pCtx, sqlite3_value_int( argv[1] ) ); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | /* |
||
294 | ** Implementation of the counter(X) function. If X is an integer |
||
295 | ** constant, then the first invocation will return X. The second X+1. |
||
296 | ** and so forth. Can be used (for example) to provide a sequence number |
||
297 | ** in a result set. |
||
298 | */ |
||
299 | //static void counterFunc( |
||
300 | //sqlite3_context pCtx, /* Function context */ |
||
301 | //int nArg, /* Number of function arguments */ |
||
302 | //sqlite3_value[] argv /* Values for all function arguments */ |
||
303 | //){ |
||
304 | // int *pCounter = (int)sqlite3_get_auxdata(pCtx, 0); |
||
305 | // if( pCounter==0 ){ |
||
306 | // pCounter = sqlite3_malloc( sizeof(*pCounter) ); |
||
307 | // if( pCounter==0 ){ |
||
308 | // sqlite3_result_error_nomem(pCtx); |
||
309 | // return; |
||
310 | // } |
||
311 | // *pCounter = sqlite3_value_int(argv[0]); |
||
312 | // sqlite3_set_auxdata(pCtx, 0, pCounter, //sqlite3_free); |
||
313 | // }else{ |
||
314 | // ++*pCounter; |
||
315 | // } |
||
316 | // sqlite3_result_int(pCtx, *pCounter); |
||
317 | //} |
||
318 | // |
||
319 | // |
||
320 | |||
321 | /* |
||
322 | ** This function takes two arguments. It performance UTF-8/16 type |
||
323 | ** conversions on the first argument then returns a copy of the second |
||
324 | ** argument. |
||
325 | ** |
||
326 | ** This function is used in cases such as the following: |
||
327 | ** |
||
328 | ** SELECT test_isolation(x,x) FROM t1; |
||
329 | ** |
||
330 | ** We want to verify that the type conversions that occur on the |
||
331 | ** first argument do not invalidate the second argument. |
||
332 | */ |
||
333 | static void test_isolation( |
||
334 | sqlite3_context pCtx, /* Function context */ |
||
335 | int nArg, /* Number of function arguments */ |
||
336 | sqlite3_value[] argv /* Values for all function arguments */ |
||
337 | ) |
||
338 | { |
||
339 | #if !SQLITE_OMIT_UTF16 |
||
340 | sqlite3_value_text16(argv[0]); |
||
341 | sqlite3_value_text(argv[0]); |
||
342 | sqlite3_value_text16(argv[0]); |
||
343 | sqlite3_value_text(argv[0]); |
||
344 | #endif |
||
345 | sqlite3_result_value( pCtx, argv[1] ); |
||
346 | } |
||
347 | |||
348 | /* |
||
349 | ** Invoke an SQL statement recursively. The function result is the |
||
350 | ** first column of the first row of the result set. |
||
351 | */ |
||
352 | static void test_eval( |
||
353 | sqlite3_context pCtx, /* Function context */ |
||
354 | int nArg, /* Number of function arguments */ |
||
355 | sqlite3_value[] argv /* Values for all function arguments */ |
||
356 | ) |
||
357 | { |
||
358 | sqlite3_stmt pStmt = new sqlite3_stmt(); |
||
359 | int rc; |
||
360 | sqlite3 db = sqlite3_context_db_handle( pCtx ); |
||
361 | string zSql; |
||
362 | |||
363 | zSql = sqlite3_value_text( argv[0] ); |
||
364 | rc = sqlite3_prepare_v2( db, zSql, -1, ref pStmt, 0 ); |
||
365 | if ( rc == SQLITE_OK ) |
||
366 | { |
||
367 | rc = sqlite3_step( pStmt ); |
||
368 | if ( rc == SQLITE_ROW ) |
||
369 | { |
||
370 | sqlite3_result_value( pCtx, sqlite3_column_value( pStmt, 0 ) ); |
||
371 | } |
||
372 | rc = sqlite3_finalize( pStmt ); |
||
373 | } |
||
374 | if ( rc != 0 ) |
||
375 | { |
||
376 | string zErr; |
||
377 | Debug.Assert( pStmt == null ); |
||
378 | zErr = sqlite3_mprintf( "sqlite3_prepare_v2() error: %s", sqlite3_errmsg( db ) ); |
||
379 | sqlite3_result_text( pCtx, zErr, -1, null );//sqlite3_free ); |
||
380 | sqlite3_result_error_code( pCtx, rc ); |
||
381 | } |
||
382 | } |
||
383 | |||
384 | class _aFuncs |
||
385 | { |
||
386 | public string zName; |
||
387 | public int nArg; |
||
388 | public u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ |
||
389 | public dxFunc xFunc; |
||
390 | public _aFuncs( string zName, int nArg, u8 eTextRep, dxFunc xFunc ) |
||
391 | { |
||
392 | this.zName = zName; |
||
393 | this.nArg = nArg; |
||
394 | this.eTextRep = eTextRep; |
||
395 | this.xFunc = xFunc; |
||
396 | } |
||
397 | } |
||
398 | |||
399 | /* |
||
400 | ** convert one character from hex to binary |
||
401 | */ |
||
402 | static int testHexChar( char c ) |
||
403 | { |
||
404 | if ( c >= '0' && c <= '9' ) |
||
405 | { |
||
406 | return c - '0'; |
||
407 | } |
||
408 | else if ( c >= 'a' && c <= 'f' ) |
||
409 | { |
||
410 | return c - 'a' + 10; |
||
411 | } |
||
412 | else if ( c >= 'A' && c <= 'F' ) |
||
413 | { |
||
414 | return c - 'A' + 10; |
||
415 | } |
||
416 | return 0; |
||
417 | } |
||
418 | |||
419 | /* |
||
420 | ** Convert hex to binary. |
||
421 | */ |
||
422 | static void testHexToBin( string zIn, ref string zOut ) |
||
423 | { |
||
424 | for ( int zIx = 0; zIx < zIn.Length - 1; zIx += 2 )// zIn[0] && zIn[1] ) |
||
425 | { |
||
426 | //*(zOut++) = (testHexChar(zIn[0])<<4) + testHexChar(zIn[1]); |
||
427 | zOut += ( testHexChar( zIn[zIx] ) << 4 ) + testHexChar( zIn[zIx + 1] ); |
||
428 | //zIn += 2; |
||
429 | } |
||
430 | } |
||
431 | |||
432 | #if !SQLITE_OMIT_UTF16 |
||
433 | /* |
||
434 | ** hex_to_utf16be(HEX) |
||
435 | ** |
||
436 | ** Convert the input string from HEX into binary. Then return the |
||
437 | ** result using sqlite3_result_text16le(). |
||
438 | */ |
||
439 | static void testHexToUtf16be( |
||
440 | sqlite3_context *pCtx, |
||
441 | int nArg, |
||
442 | sqlite3_value **argv |
||
443 | ){ |
||
444 | int n; |
||
445 | string zIn; |
||
446 | string zOut; |
||
447 | Debug.Assert( nArg==1 ); |
||
448 | n = sqlite3_value_bytes(argv[0]); |
||
449 | zIn = (const char)sqlite3_value_text(argv[0]); |
||
450 | zOut = sqlite3_malloc( n/2 ); |
||
451 | if( zOut==0 ){ |
||
452 | sqlite3_result_error_nomem(pCtx); |
||
453 | }else{ |
||
454 | testHexToBin(zIn, zOut); |
||
455 | sqlite3_result_text16be(pCtx, zOut, n/2, sqlite3_free); |
||
456 | } |
||
457 | } |
||
458 | #endif |
||
459 | |||
460 | /* |
||
461 | ** hex_to_utf8(HEX) |
||
462 | ** |
||
463 | ** Convert the input string from HEX into binary. Then return the |
||
464 | ** result using sqlite3_result_text16le(). |
||
465 | */ |
||
466 | static void testHexToUtf8( |
||
467 | sqlite3_context pCtx, |
||
468 | int nArg, |
||
469 | sqlite3_value[] argv |
||
470 | ) |
||
471 | { |
||
472 | int n; |
||
473 | string zIn; |
||
474 | string zOut = ""; |
||
475 | Debug.Assert( nArg == 1 ); |
||
476 | n = sqlite3_value_bytes( argv[0] ); |
||
477 | zIn = sqlite3_value_text( argv[0] ); |
||
478 | //zOut = sqlite3_malloc( n/2 ); |
||
479 | //if( zOut==0 ){ |
||
480 | // sqlite3_result_error_nomem(pCtx); |
||
481 | //}else{ |
||
482 | testHexToBin( zIn, ref zOut ); |
||
483 | sqlite3_result_text( pCtx, zOut, n / 2, null );//sqlite3_free ); |
||
484 | //} |
||
485 | } |
||
486 | |||
487 | #if !SQLITE_OMIT_UTF16 |
||
488 | /* |
||
489 | ** hex_to_utf16le(HEX) |
||
490 | ** |
||
491 | ** Convert the input string from HEX into binary. Then return the |
||
492 | ** result using sqlite3_result_text16le(). |
||
493 | */ |
||
494 | static void testHexToUtf16le( |
||
495 | sqlite3_context *pCtx, |
||
496 | int nArg, |
||
497 | sqlite3_value **argv |
||
498 | ){ |
||
499 | int n; |
||
500 | string zIn; |
||
501 | string zOut; |
||
502 | Debug.Assert( nArg==1 ); |
||
503 | n = sqlite3_value_bytes(argv[0]); |
||
504 | zIn = (const char)sqlite3_value_text(argv[0]); |
||
505 | zOut = sqlite3_malloc( n/2 ); |
||
506 | if( zOut==0 ){ |
||
507 | sqlite3_result_error_nomem(pCtx); |
||
508 | }else{ |
||
509 | testHexToBin(zIn, zOut); |
||
510 | sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); |
||
511 | } |
||
512 | } |
||
513 | #endif |
||
514 | |||
515 | static int registerTestFunctions( sqlite3 db, ref string dummy1, sqlite3_api_routines dummy2 ) |
||
516 | { |
||
517 | _aFuncs[] aFuncs = new _aFuncs[] { |
||
518 | new _aFuncs( "randstr", 2, SQLITE_UTF8, randStr ), |
||
519 | new _aFuncs( "test_destructor", 1, SQLITE_UTF8, test_destructor), |
||
520 | #if !SQLITE_OMIT_UTF16 |
||
521 | { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, |
||
522 | { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be}, |
||
523 | { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le}, |
||
524 | #endif |
||
525 | new _aFuncs( "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8), |
||
526 | new _aFuncs( "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count), |
||
527 | new _aFuncs( "test_auxdata", -1, SQLITE_UTF8, test_auxdata), |
||
528 | new _aFuncs( "test_error", 1, SQLITE_UTF8, test_error), |
||
529 | new _aFuncs( "test_error", 2, SQLITE_UTF8, test_error), |
||
530 | new _aFuncs( "test_eval", 1, SQLITE_UTF8, test_eval), |
||
531 | new _aFuncs( "test_isolation", 2, SQLITE_UTF8, test_isolation), |
||
532 | //{ "test_counter", 2, SQLITE_UTF8, counterFunc}, |
||
533 | }; |
||
534 | int i; |
||
535 | |||
536 | for ( i = 0; i < aFuncs.Length; i++ ) |
||
537 | {//sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ |
||
538 | sqlite3_create_function( db, aFuncs[i].zName, aFuncs[i].nArg, |
||
539 | aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, null, null ); |
||
540 | } |
||
541 | |||
542 | sqlite3_create_function( db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, null, |
||
543 | test_agg_errmsg16_step, test_agg_errmsg16_final ); |
||
544 | |||
545 | return SQLITE_OK; |
||
546 | } |
||
547 | |||
548 | /* |
||
549 | ** TCLCMD: autoinstall_test_functions |
||
550 | ** |
||
551 | ** Invoke this TCL command to use sqlite3_auto_extension() to cause |
||
552 | ** the standard set of test functions to be loaded into each new |
||
553 | ** database connection. |
||
554 | */ |
||
555 | static int autoinstall_test_funcs( |
||
556 | object clientdata, |
||
557 | Tcl_Interp interp, |
||
558 | int objc, |
||
559 | Tcl_Obj[] objv |
||
560 | ) |
||
561 | { |
||
562 | //extern int Md5_Register(sqlite3); |
||
563 | int rc = sqlite3_auto_extension( (dxInit)registerTestFunctions ); |
||
564 | if ( rc == SQLITE_OK ) |
||
565 | { |
||
566 | rc = sqlite3_auto_extension( (dxInit)Md5_Register ); |
||
567 | } |
||
568 | TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( rc ) ); |
||
569 | return TCL.TCL_OK; |
||
570 | } |
||
571 | |||
572 | |||
573 | /* |
||
574 | ** A bogus step function and finalizer function. |
||
575 | */ |
||
576 | static void tStep( sqlite3_context a, int b, sqlite3_value[] c ) |
||
577 | { |
||
578 | } |
||
579 | static void tFinal( sqlite3_context a ) |
||
580 | { |
||
581 | } |
||
582 | |||
583 | |||
584 | /* |
||
585 | ** tclcmd: abuse_create_function |
||
586 | ** |
||
587 | ** Make various calls to sqlite3_create_function that do not have valid |
||
588 | ** parameters. Verify that the error condition is detected and reported. |
||
589 | */ |
||
590 | static int abuse_create_function( |
||
591 | object clientdata, |
||
592 | Tcl_Interp interp, |
||
593 | int objc, |
||
594 | Tcl_Obj[] objv |
||
595 | ) |
||
596 | { |
||
597 | //extern int getDbPointer(Tcl_Interp*, const char*, sqlite3*); |
||
598 | sqlite3 db = null; |
||
599 | int rc; |
||
600 | int mxArg; |
||
601 | |||
602 | if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) |
||
603 | return TCL.TCL_ERROR; |
||
604 | |||
605 | rc = sqlite3_create_function( db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, tFinal ); |
||
606 | if ( rc != SQLITE_MISUSE ) |
||
607 | goto abuse_err; |
||
608 | |||
609 | rc = sqlite3_create_function( db, "tx", 1, SQLITE_UTF8, 0, tStep, tStep, null ); |
||
610 | if ( rc != SQLITE_MISUSE ) |
||
611 | goto abuse_err; |
||
612 | |||
613 | rc = sqlite3_create_function( db, "tx", 1, SQLITE_UTF8, 0, tStep, null, tFinal ); |
||
614 | if ( rc != SQLITE_MISUSE ) |
||
615 | goto abuse_err; |
||
616 | |||
617 | rc = sqlite3_create_function( db, "tx", 1, SQLITE_UTF8, 0, null, null, tFinal ); |
||
618 | if ( rc != SQLITE_MISUSE ) |
||
619 | goto abuse_err; |
||
620 | |||
621 | rc = sqlite3_create_function( db, "tx", 1, SQLITE_UTF8, 0, null, tStep, null ); |
||
622 | if ( rc != SQLITE_MISUSE ) |
||
623 | goto abuse_err; |
||
624 | |||
625 | rc = sqlite3_create_function( db, "tx", -2, SQLITE_UTF8, 0, tStep, null, null ); |
||
626 | if ( rc != SQLITE_MISUSE ) |
||
627 | goto abuse_err; |
||
628 | |||
629 | rc = sqlite3_create_function( db, "tx", 128, SQLITE_UTF8, 0, tStep, null, null ); |
||
630 | if ( rc != SQLITE_MISUSE ) |
||
631 | goto abuse_err; |
||
632 | |||
633 | rc = sqlite3_create_function( db, "funcxx" + |
||
634 | "_123456789_123456789_123456789_123456789_123456789" + |
||
635 | "_123456789_123456789_123456789_123456789_123456789" + |
||
636 | "_123456789_123456789_123456789_123456789_123456789" + |
||
637 | "_123456789_123456789_123456789_123456789_123456789" + |
||
638 | "_123456789_123456789_123456789_123456789_123456789", |
||
639 | 1, SQLITE_UTF8, 0, tStep, null, null ); |
||
640 | if ( rc != SQLITE_MISUSE ) |
||
641 | goto abuse_err; |
||
642 | |||
643 | /* This last function registration should actually work. Generate |
||
644 | ** a no-op function (that always returns NULL) and which has the |
||
645 | ** maximum-length function name and the maximum number of parameters. |
||
646 | */ |
||
647 | sqlite3_limit( db, SQLITE_LIMIT_FUNCTION_ARG, 10000 ); |
||
648 | mxArg = sqlite3_limit( db, SQLITE_LIMIT_FUNCTION_ARG, -1 ); |
||
649 | rc = sqlite3_create_function( db, "nullx" + |
||
650 | "_123456789_123456789_123456789_123456789_123456789" + |
||
651 | "_123456789_123456789_123456789_123456789_123456789" + |
||
652 | "_123456789_123456789_123456789_123456789_123456789" + |
||
653 | "_123456789_123456789_123456789_123456789_123456789" + |
||
654 | "_123456789_123456789_123456789_123456789_123456789", |
||
655 | mxArg, SQLITE_UTF8, 0, tStep, null, null ); |
||
656 | if ( rc != SQLITE_OK ) |
||
657 | goto abuse_err; |
||
658 | |||
659 | return TCL.TCL_OK; |
||
660 | |||
661 | abuse_err: |
||
662 | TCL.Tcl_AppendResult( interp, "sqlite3_create_function abused test failed" |
||
663 | ); |
||
664 | return TCL.TCL_ERROR; |
||
665 | } |
||
666 | |||
667 | |||
668 | /* |
||
669 | ** Register commands with the TCL interpreter. |
||
670 | */ |
||
671 | public static int Sqlitetest_func_Init( Tcl_Interp interp ) |
||
672 | { |
||
673 | //static struct { |
||
674 | // string zName; |
||
675 | // Tcl_ObjCmdProc *xProc; |
||
676 | //} |
||
677 | _aObjCmd[] aObjCmd = new _aObjCmd[] { |
||
678 | new _aObjCmd( "autoinstall_test_functions", autoinstall_test_funcs ), |
||
679 | new _aObjCmd( "abuse_create_function", abuse_create_function ), |
||
680 | }; |
||
681 | int i; |
||
682 | //extern int Md5_Register(sqlite3); |
||
683 | |||
684 | for ( i = 0; i < aObjCmd.Length; i++ ) |
||
685 | {//sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
||
686 | TCL.Tcl_CreateObjCommand( interp, aObjCmd[i].zName, aObjCmd[i].xProc, null, null ); |
||
687 | } |
||
688 | sqlite3_initialize(); |
||
689 | sqlite3_auto_extension( (dxInit)registerTestFunctions ); |
||
690 | sqlite3_auto_extension( (dxInit)Md5_Register ); |
||
691 | return TCL.TCL_OK; |
||
692 | } |
||
693 | } |
||
694 | #endif |
||
695 | } |
||
696 |