wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
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