OLD | NEW |
1 /* | 1 /* |
2 ** 2008 March 19 | 2 ** 2008 March 19 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** Code for testing all sorts of SQLite interfaces. This code | 12 ** Code for testing all sorts of SQLite interfaces. This code |
13 ** implements new SQL functions used by the test scripts. | 13 ** implements new SQL functions used by the test scripts. |
14 */ | 14 */ |
15 #include "sqlite3.h" | 15 #include "sqlite3.h" |
16 #include "tcl.h" | 16 #include "tcl.h" |
17 #include <stdlib.h> | 17 #include <stdlib.h> |
18 #include <string.h> | 18 #include <string.h> |
19 #include <assert.h> | 19 #include <assert.h> |
20 | 20 |
| 21 #include "sqliteInt.h" |
| 22 #include "vdbeInt.h" |
| 23 |
21 | 24 |
22 /* | 25 /* |
23 ** Allocate nByte bytes of space using sqlite3_malloc(). If the | 26 ** Allocate nByte bytes of space using sqlite3_malloc(). If the |
24 ** allocation fails, call sqlite3_result_error_nomem() to notify | 27 ** allocation fails, call sqlite3_result_error_nomem() to notify |
25 ** the database handle that malloc() has failed. | 28 ** the database handle that malloc() has failed. |
26 */ | 29 */ |
27 static void *testContextMalloc(sqlite3_context *context, int nByte){ | 30 static void *testContextMalloc(sqlite3_context *context, int nByte){ |
28 char *z = sqlite3_malloc(nByte); | 31 char *z = sqlite3_malloc(nByte); |
29 if( !z && nByte>0 ){ | 32 if( !z && nByte>0 ){ |
30 sqlite3_result_error_nomem(context); | 33 sqlite3_result_error_nomem(context); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 char const *z = (char*)sqlite3_value_text(argv[i]); | 198 char const *z = (char*)sqlite3_value_text(argv[i]); |
196 if( z ){ | 199 if( z ){ |
197 int n; | 200 int n; |
198 char *zAux = sqlite3_get_auxdata(pCtx, i); | 201 char *zAux = sqlite3_get_auxdata(pCtx, i); |
199 if( zAux ){ | 202 if( zAux ){ |
200 zRet[i*2] = '1'; | 203 zRet[i*2] = '1'; |
201 assert( strcmp(zAux,z)==0 ); | 204 assert( strcmp(zAux,z)==0 ); |
202 }else { | 205 }else { |
203 zRet[i*2] = '0'; | 206 zRet[i*2] = '0'; |
204 } | 207 } |
205 n = strlen(z) + 1; | 208 n = (int)strlen(z) + 1; |
206 zAux = testContextMalloc(pCtx, n); | 209 zAux = testContextMalloc(pCtx, n); |
207 if( zAux ){ | 210 if( zAux ){ |
208 memcpy(zAux, z, n); | 211 memcpy(zAux, z, n); |
209 sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); | 212 sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); |
210 } | 213 } |
211 zRet[i*2+1] = ' '; | 214 zRet[i*2+1] = ' '; |
212 } | 215 } |
213 } | 216 } |
214 sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); | 217 sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); |
215 } | 218 } |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 zOut = sqlite3_malloc( n/2 ); | 418 zOut = sqlite3_malloc( n/2 ); |
416 if( zOut==0 ){ | 419 if( zOut==0 ){ |
417 sqlite3_result_error_nomem(pCtx); | 420 sqlite3_result_error_nomem(pCtx); |
418 }else{ | 421 }else{ |
419 testHexToBin(zIn, zOut); | 422 testHexToBin(zIn, zOut); |
420 sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); | 423 sqlite3_result_text16le(pCtx, zOut, n/2, sqlite3_free); |
421 } | 424 } |
422 } | 425 } |
423 #endif | 426 #endif |
424 | 427 |
| 428 /* |
| 429 ** SQL function: real2hex(X) |
| 430 ** |
| 431 ** If argument X is a real number, then convert it into a string which is |
| 432 ** the big-endian hexadecimal representation of the ieee754 encoding of |
| 433 ** that number. If X is not a real number, return NULL. |
| 434 */ |
| 435 static void real2hex( |
| 436 sqlite3_context *context, |
| 437 int argc, |
| 438 sqlite3_value **argv |
| 439 ){ |
| 440 union { |
| 441 sqlite3_uint64 i; |
| 442 double r; |
| 443 unsigned char x[8]; |
| 444 } v; |
| 445 char zOut[20]; |
| 446 int i; |
| 447 int bigEndian; |
| 448 v.i = 1; |
| 449 bigEndian = v.x[0]==0; |
| 450 v.r = sqlite3_value_double(argv[0]); |
| 451 for(i=0; i<8; i++){ |
| 452 if( bigEndian ){ |
| 453 zOut[i*2] = "0123456789abcdef"[v.x[i]>>4]; |
| 454 zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; |
| 455 }else{ |
| 456 zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4]; |
| 457 zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; |
| 458 } |
| 459 } |
| 460 zOut[16] = 0; |
| 461 sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); |
| 462 } |
| 463 |
| 464 /* |
| 465 ** tclcmd: test_extract(record, field) |
| 466 ** |
| 467 ** This function implements an SQL user-function that accepts a blob |
| 468 ** containing a formatted database record as the first argument. The |
| 469 ** second argument is the index of the field within that record to |
| 470 ** extract and return. |
| 471 */ |
| 472 static void test_extract( |
| 473 sqlite3_context *context, |
| 474 int argc, |
| 475 sqlite3_value **argv |
| 476 ){ |
| 477 sqlite3 *db = sqlite3_context_db_handle(context); |
| 478 u8 *pRec; |
| 479 u8 *pEndHdr; /* Points to one byte past record header */ |
| 480 u8 *pHdr; /* Current point in record header */ |
| 481 u8 *pBody; /* Current point in record data */ |
| 482 u64 nHdr; /* Bytes in record header */ |
| 483 int iIdx; /* Required field */ |
| 484 int iCurrent = 0; /* Current field */ |
| 485 |
| 486 assert( argc==2 ); |
| 487 pRec = (u8*)sqlite3_value_blob(argv[0]); |
| 488 iIdx = sqlite3_value_int(argv[1]); |
| 489 |
| 490 pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); |
| 491 pBody = pEndHdr = &pRec[nHdr]; |
| 492 |
| 493 for(iCurrent=0; pHdr<pEndHdr && iCurrent<=iIdx; iCurrent++){ |
| 494 u64 iSerialType; |
| 495 Mem mem; |
| 496 |
| 497 memset(&mem, 0, sizeof(mem)); |
| 498 mem.db = db; |
| 499 mem.enc = ENC(db); |
| 500 pHdr += sqlite3GetVarint(pHdr, &iSerialType); |
| 501 pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); |
| 502 |
| 503 if( iCurrent==iIdx ){ |
| 504 sqlite3_result_value(context, &mem); |
| 505 } |
| 506 |
| 507 if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc); |
| 508 } |
| 509 } |
| 510 |
| 511 /* |
| 512 ** tclcmd: test_decode(record) |
| 513 ** |
| 514 ** This function implements an SQL user-function that accepts a blob |
| 515 ** containing a formatted database record as its only argument. It returns |
| 516 ** a tcl list (type SQLITE_TEXT) containing each of the values stored |
| 517 ** in the record. |
| 518 */ |
| 519 static void test_decode( |
| 520 sqlite3_context *context, |
| 521 int argc, |
| 522 sqlite3_value **argv |
| 523 ){ |
| 524 sqlite3 *db = sqlite3_context_db_handle(context); |
| 525 u8 *pRec; |
| 526 u8 *pEndHdr; /* Points to one byte past record header */ |
| 527 u8 *pHdr; /* Current point in record header */ |
| 528 u8 *pBody; /* Current point in record data */ |
| 529 u64 nHdr; /* Bytes in record header */ |
| 530 Tcl_Obj *pRet; /* Return value */ |
| 531 |
| 532 pRet = Tcl_NewObj(); |
| 533 Tcl_IncrRefCount(pRet); |
| 534 |
| 535 assert( argc==1 ); |
| 536 pRec = (u8*)sqlite3_value_blob(argv[0]); |
| 537 |
| 538 pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); |
| 539 pBody = pEndHdr = &pRec[nHdr]; |
| 540 while( pHdr<pEndHdr ){ |
| 541 Tcl_Obj *pVal = 0; |
| 542 u64 iSerialType; |
| 543 Mem mem; |
| 544 |
| 545 memset(&mem, 0, sizeof(mem)); |
| 546 mem.db = db; |
| 547 mem.enc = ENC(db); |
| 548 pHdr += sqlite3GetVarint(pHdr, &iSerialType); |
| 549 pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); |
| 550 |
| 551 switch( sqlite3_value_type(&mem) ){ |
| 552 case SQLITE_TEXT: |
| 553 pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1); |
| 554 break; |
| 555 |
| 556 case SQLITE_BLOB: { |
| 557 char hexdigit[] = { |
| 558 '0', '1', '2', '3', '4', '5', '6', '7', |
| 559 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' |
| 560 }; |
| 561 int n = sqlite3_value_bytes(&mem); |
| 562 u8 *z = (u8*)sqlite3_value_blob(&mem); |
| 563 int i; |
| 564 pVal = Tcl_NewStringObj("x'", -1); |
| 565 for(i=0; i<n; i++){ |
| 566 char hex[3]; |
| 567 hex[0] = hexdigit[((z[i] >> 4) & 0x0F)]; |
| 568 hex[1] = hexdigit[(z[i] & 0x0F)]; |
| 569 hex[2] = '\0'; |
| 570 Tcl_AppendStringsToObj(pVal, hex, 0); |
| 571 } |
| 572 Tcl_AppendStringsToObj(pVal, "'", 0); |
| 573 break; |
| 574 } |
| 575 |
| 576 case SQLITE_FLOAT: |
| 577 pVal = Tcl_NewDoubleObj(sqlite3_value_double(&mem)); |
| 578 break; |
| 579 |
| 580 case SQLITE_INTEGER: |
| 581 pVal = Tcl_NewWideIntObj(sqlite3_value_int64(&mem)); |
| 582 break; |
| 583 |
| 584 case SQLITE_NULL: |
| 585 pVal = Tcl_NewStringObj("NULL", -1); |
| 586 break; |
| 587 |
| 588 default: |
| 589 assert( 0 ); |
| 590 } |
| 591 |
| 592 Tcl_ListObjAppendElement(0, pRet, pVal); |
| 593 |
| 594 if( mem.szMalloc ){ |
| 595 sqlite3DbFree(db, mem.zMalloc); |
| 596 } |
| 597 } |
| 598 |
| 599 sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
| 600 Tcl_DecrRefCount(pRet); |
| 601 } |
| 602 |
| 603 |
425 static int registerTestFunctions(sqlite3 *db){ | 604 static int registerTestFunctions(sqlite3 *db){ |
426 static const struct { | 605 static const struct { |
427 char *zName; | 606 char *zName; |
428 signed char nArg; | 607 signed char nArg; |
429 unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ | 608 unsigned char eTextRep; /* 1: UTF-16. 0: UTF-8 */ |
430 void (*xFunc)(sqlite3_context*,int,sqlite3_value **); | 609 void (*xFunc)(sqlite3_context*,int,sqlite3_value **); |
431 } aFuncs[] = { | 610 } aFuncs[] = { |
432 { "randstr", 2, SQLITE_UTF8, randStr }, | 611 { "randstr", 2, SQLITE_UTF8, randStr }, |
433 { "test_destructor", 1, SQLITE_UTF8, test_destructor}, | 612 { "test_destructor", 1, SQLITE_UTF8, test_destructor}, |
434 #ifndef SQLITE_OMIT_UTF16 | 613 #ifndef SQLITE_OMIT_UTF16 |
435 { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, | 614 { "test_destructor16", 1, SQLITE_UTF8, test_destructor16}, |
436 { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be}, | 615 { "hex_to_utf16be", 1, SQLITE_UTF8, testHexToUtf16be}, |
437 { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le}, | 616 { "hex_to_utf16le", 1, SQLITE_UTF8, testHexToUtf16le}, |
438 #endif | 617 #endif |
439 { "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8}, | 618 { "hex_to_utf8", 1, SQLITE_UTF8, testHexToUtf8}, |
440 { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, | 619 { "test_destructor_count", 0, SQLITE_UTF8, test_destructor_count}, |
441 { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, | 620 { "test_auxdata", -1, SQLITE_UTF8, test_auxdata}, |
442 { "test_error", 1, SQLITE_UTF8, test_error}, | 621 { "test_error", 1, SQLITE_UTF8, test_error}, |
443 { "test_error", 2, SQLITE_UTF8, test_error}, | 622 { "test_error", 2, SQLITE_UTF8, test_error}, |
444 { "test_eval", 1, SQLITE_UTF8, test_eval}, | 623 { "test_eval", 1, SQLITE_UTF8, test_eval}, |
445 { "test_isolation", 2, SQLITE_UTF8, test_isolation}, | 624 { "test_isolation", 2, SQLITE_UTF8, test_isolation}, |
446 { "test_counter", 1, SQLITE_UTF8, counterFunc}, | 625 { "test_counter", 1, SQLITE_UTF8, counterFunc}, |
| 626 { "real2hex", 1, SQLITE_UTF8, real2hex}, |
| 627 { "test_decode", 1, SQLITE_UTF8, test_decode}, |
| 628 { "test_extract", 2, SQLITE_UTF8, test_extract}, |
447 }; | 629 }; |
448 int i; | 630 int i; |
449 | 631 |
450 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ | 632 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ |
451 sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, | 633 sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, |
452 aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); | 634 aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); |
453 } | 635 } |
454 | 636 |
455 sqlite3_create_function(db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, 0, | 637 sqlite3_create_function(db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, 0, |
456 test_agg_errmsg16_step, test_agg_errmsg16_final); | 638 test_agg_errmsg16_step, test_agg_errmsg16_final); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 extern int Md5_Register(sqlite3*); | 756 extern int Md5_Register(sqlite3*); |
575 | 757 |
576 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ | 758 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
577 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); | 759 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); |
578 } | 760 } |
579 sqlite3_initialize(); | 761 sqlite3_initialize(); |
580 sqlite3_auto_extension((void*)registerTestFunctions); | 762 sqlite3_auto_extension((void*)registerTestFunctions); |
581 sqlite3_auto_extension((void*)Md5_Register); | 763 sqlite3_auto_extension((void*)Md5_Register); |
582 return TCL_OK; | 764 return TCL_OK; |
583 } | 765 } |
OLD | NEW |