Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Refactor previous commit to remove the new delegates as they are not strictly required. Also, remove superfluous newData local variable in the StepCallback method. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | logBind |
Files: | files | file ages | folders |
SHA1: |
c43fca0ae614eb03eeb5238beea29adc |
User & Date: | mistachkin 2012-02-19 08:34:17 |
Context
2012-02-19
| ||
13:22 | When converting a DateTime instance of an 'Unspecified' kind to a string, use the same kind as the connection, if available. Also, cleanup handling of the default formats for UTC and local time. Closed-Leaf check-in: dbdf2561a4 user: mistachkin tags: logBind | |
08:34 | Refactor previous commit to remove the new delegates as they are not strictly required. Also, remove superfluous newData local variable in the StepCallback method. check-in: c43fca0ae6 user: mistachkin tags: logBind | |
08:11 | Make sure that exceptions are never thrown back to native code from user-provided function and collation implementations. Also, log all such caught callback exceptions if the appropriate connection flag is set. Fix for ticket [8a426d12eb]. Pass connection flags into SQLiteFunction binding method and refactor internal interfaces to support this. Change type of _contextDataList (SQLiteFunction) dictionary keys from long to IntPtr. check-in: 6136a92dc5 user: mistachkin tags: logBind | |
Changes
Changes to System.Data.SQLite/SQLiteFunction.cs.
44 44 /// code. 45 45 /// </summary> 46 46 private const int COR_E_EXCEPTION = unchecked((int)0x80131500); 47 47 #endregion 48 48 49 49 ///////////////////////////////////////////////////////////////////////// 50 50 51 - #region Private Delegate Types 52 - /// <summary> 53 - /// See the Invoke method of this class. 54 - /// </summary> 55 - /// <param name="args"> 56 - /// See the Invoke method of this class. 57 - /// </param> 58 - /// <returns> 59 - /// See the Invoke method of this class. 60 - /// </returns> 61 - private delegate object SQLiteFunctionInvokeCallback( 62 - object[] args 63 - ); 64 - 65 - ///////////////////////////////////////////////////////////////////////// 66 - 67 - /// <summary> 68 - /// See the Step method of this class. 69 - /// </summary> 70 - /// <param name="args"> 71 - /// See the Step method of this class. 72 - /// </param> 73 - /// <param name="stepNumber"> 74 - /// See the Step method of this class. 75 - /// </param> 76 - /// <param name="contextData"> 77 - /// See the Step method of this class. 78 - /// </param> 79 - private delegate void SQLiteFunctionStepCallback( 80 - object[] args, 81 - int stepNumber, 82 - ref object contextData 83 - ); 84 - 85 - ///////////////////////////////////////////////////////////////////////// 86 - 87 - /// <summary> 88 - /// See the Final method of this class. 89 - /// </summary> 90 - /// <param name="contextData"> 91 - /// See the Final method of this class. 92 - /// </param> 93 - /// <returns> 94 - /// See the Final method of this class. 95 - /// </returns> 96 - private delegate object SQLiteFunctionFinalCallback( 97 - object contextData 98 - ); 99 - 100 - ///////////////////////////////////////////////////////////////////////// 101 - 102 - /// <summary> 103 - /// See the Compare method of this class. 104 - /// </summary> 105 - /// <param name="param1"> 106 - /// See the Compare method of this class. 107 - /// </param> 108 - /// <param name="param2"> 109 - /// See the Compare method of this class. 110 - /// </param> 111 - /// <returns> 112 - /// See the Compare method of this class. 113 - /// </returns> 114 - private delegate int SQLiteCollationCompareCallback( 115 - string param1, 116 - string param2 117 - ); 118 - #endregion 119 - 120 - ///////////////////////////////////////////////////////////////////////// 121 - 122 51 /// <summary> 123 52 /// The base connection this function is attached to 124 53 /// </summary> 125 54 internal SQLiteBase _base; 126 55 127 56 /// <summary> 128 57 /// Internal array used to keep track of aggregate function context data ................................................................................ 131 60 132 61 /// <summary> 133 62 /// The connection flags associated with this object (this should be the 134 63 /// same value as the flags associated with the parent connection object). 135 64 /// </summary> 136 65 private SQLiteConnectionFlags _flags; 137 66 138 - /// <summary> 139 - /// The private instance of the SQLiteFunctionInvokeCallback delegate 140 - /// associated with this object. 141 - /// </summary> 142 - private SQLiteFunctionInvokeCallback _invokeCallback; 143 - 144 - /// <summary> 145 - /// The private instance of the SQLiteFunctionStepCallback delegate 146 - /// associated with this object. 147 - /// </summary> 148 - private SQLiteFunctionStepCallback _stepCallback; 149 - 150 - /// <summary> 151 - /// The private instance of the SQLiteFunctionFinalCallback delegate 152 - /// associated with this object. 153 - /// </summary> 154 - private SQLiteFunctionFinalCallback _finalCallback; 155 - 156 - /// <summary> 157 - /// The private instance of the SQLiteCollationCompareCallback delegate 158 - /// associated with this object. 159 - /// </summary> 160 - private SQLiteCollationCompareCallback _compareCallback; 161 - 162 67 /// <summary> 163 68 /// Holds a reference to the callback function for user functions 164 69 /// </summary> 165 70 private SQLiteCallback _InvokeFunc; 166 71 /// <summary> 167 72 /// Holds a reference to the callbakc function for stepping in an aggregate function 168 73 /// </summary> ................................................................................ 246 151 if (disp != null) 247 152 disp.Dispose(); 248 153 } 249 154 _contextDataList.Clear(); 250 155 _contextDataList = null; 251 156 252 157 _flags = SQLiteConnectionFlags.None; 253 - _invokeCallback = null; 254 - _stepCallback = null; 255 - _finalCallback = null; 256 - _compareCallback = null; 257 158 258 159 _InvokeFunc = null; 259 160 _StepFunc = null; 260 161 _FinalFunc = null; 261 162 _CompareFunc = null; 262 163 _base = null; 263 164 } ................................................................................ 465 366 _base.ReturnBlob(context, (byte[])returnValue); 466 367 return; 467 368 } 468 369 } 469 370 470 371 /// <summary> 471 372 /// Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method. 472 - /// Does nothing if there is no invoke callback configured. WARNING: Must not throw exceptions. 373 + /// WARNING: Must not throw exceptions. 473 374 /// </summary> 474 375 /// <param name="context">A raw context pointer</param> 475 376 /// <param name="nArgs">Number of arguments passed in</param> 476 377 /// <param name="argsptr">A pointer to the array of arguments</param> 477 378 internal void ScalarCallback(IntPtr context, int nArgs, IntPtr argsptr) 478 379 { 479 - if (_invokeCallback != null) 380 + try 381 + { 382 + _context = context; 383 + SetReturnValue(context, 384 + Invoke(ConvertParams(nArgs, argsptr))); /* throw */ 385 + } 386 +#if !PLATFORM_COMPACTFRAMEWORK 387 + catch (Exception e) /* NOTE: Must catch ALL. */ 480 388 { 481 389 try 482 390 { 483 - _context = context; 484 - SetReturnValue(context, 485 - _invokeCallback(ConvertParams(nArgs, argsptr))); /* throw */ 486 - } 487 -#if !PLATFORM_COMPACTFRAMEWORK 488 - catch (Exception e) /* NOTE: Must catch ALL. */ 489 - { 490 - try 391 + if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 392 + SQLiteConnectionFlags.LogCallbackException) 491 393 { 492 - if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 493 - SQLiteConnectionFlags.LogCallbackException) 494 - { 495 - SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 496 - "Caught exception in {0} callback: {1}", 497 - typeof(SQLiteFunctionInvokeCallback), e)); /* throw */ 498 - } 499 - } 500 - catch 501 - { 502 - // do nothing. 394 + SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 395 + "Caught exception in \"Invoke\" method: {0}", 396 + e)); /* throw */ 503 397 } 504 398 } 399 + catch 400 + { 401 + // do nothing. 402 + } 403 + } 505 404 #else 506 - catch /* NOTE: Must catch ALL. */ 507 - { 508 - // do nothing (Windows CE). 509 - } 405 + catch /* NOTE: Must catch ALL. */ 406 + { 407 + // do nothing (Windows CE). 408 + } 510 409 #endif 511 - } 512 410 } 513 411 514 412 /// <summary> 515 413 /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. 516 - /// Does nothing and returns zero if there is no compare callback configured. WARNING: Must not throw exceptions. 414 + /// WARNING: Must not throw exceptions. 517 415 /// </summary> 518 416 /// <param name="ptr">Not used</param> 519 417 /// <param name="len1">Length of the string pv1</param> 520 418 /// <param name="ptr1">Pointer to the first string to compare</param> 521 419 /// <param name="len2">Length of the string pv2</param> 522 420 /// <param name="ptr2">Pointer to the second string to compare</param> 523 421 /// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater 524 - /// than the second. Returns 0 if there is no callback wrapper configured or an exception is caught.</returns> 422 + /// than the second. Returns 0 if an exception is caught.</returns> 525 423 internal int CompareCallback(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) 526 424 { 527 - if (_compareCallback != null) 425 + try 426 + { 427 + return Compare(SQLiteConvert.UTF8ToString(ptr1, len1), 428 + SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */ 429 + } 430 +#if !PLATFORM_COMPACTFRAMEWORK 431 + catch (Exception e) /* NOTE: Must catch ALL. */ 528 432 { 529 433 try 530 434 { 531 - return _compareCallback(SQLiteConvert.UTF8ToString(ptr1, len1), 532 - SQLiteConvert.UTF8ToString(ptr2, len2)); /* throw */ 533 - } 534 -#if !PLATFORM_COMPACTFRAMEWORK 535 - catch (Exception e) /* NOTE: Must catch ALL. */ 536 - { 537 - try 435 + if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 436 + SQLiteConnectionFlags.LogCallbackException) 538 437 { 539 - if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 540 - SQLiteConnectionFlags.LogCallbackException) 541 - { 542 - SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 543 - "Caught exception in {0} callback: {1}", 544 - typeof(SQLiteCollationCompareCallback), e)); /* throw */ 545 - } 546 - } 547 - catch 548 - { 549 - // do nothing. 438 + SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 439 + "Caught exception in \"Compare\" method: {0}", 440 + e)); /* throw */ 550 441 } 551 442 } 443 + catch 444 + { 445 + // do nothing. 446 + } 447 + } 552 448 #else 553 - catch /* NOTE: Must catch ALL. */ 554 - { 555 - // do nothing (Windows CE). 556 - } 449 + catch /* NOTE: Must catch ALL. */ 450 + { 451 + // do nothing (Windows CE). 452 + } 557 453 #endif 558 - } 559 454 560 455 return 0; 561 456 } 562 457 563 458 /// <summary> 564 459 /// Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. 565 - /// Does nothing and returns zero if there is no compare callback configured. WARNING: Must not throw exceptions. 460 + /// WARNING: Must not throw exceptions. 566 461 /// </summary> 567 462 /// <param name="ptr">Not used</param> 568 463 /// <param name="len1">Length of the string pv1</param> 569 464 /// <param name="ptr1">Pointer to the first string to compare</param> 570 465 /// <param name="len2">Length of the string pv2</param> 571 466 /// <param name="ptr2">Pointer to the second string to compare</param> 572 467 /// <returns>Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater 573 - /// than the second. Returns 0 if there is no callback wrapper configured or an exception is caught.</returns> 468 + /// than the second. Returns 0 if an exception is caught.</returns> 574 469 internal int CompareCallback16(IntPtr ptr, int len1, IntPtr ptr1, int len2, IntPtr ptr2) 575 470 { 576 - if (_compareCallback != null) 471 + try 472 + { 473 + return Compare(SQLite3_UTF16.UTF16ToString(ptr1, len1), 474 + SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */ 475 + } 476 +#if !PLATFORM_COMPACTFRAMEWORK 477 + catch (Exception e) /* NOTE: Must catch ALL. */ 577 478 { 578 479 try 579 480 { 580 - return _compareCallback(SQLite3_UTF16.UTF16ToString(ptr1, len1), 581 - SQLite3_UTF16.UTF16ToString(ptr2, len2)); /* throw */ 582 - } 583 -#if !PLATFORM_COMPACTFRAMEWORK 584 - catch (Exception e) /* NOTE: Must catch ALL. */ 585 - { 586 - try 481 + if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 482 + SQLiteConnectionFlags.LogCallbackException) 587 483 { 588 - if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 589 - SQLiteConnectionFlags.LogCallbackException) 590 - { 591 - SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 592 - "Caught exception in {0} callback: {1}", 593 - typeof(SQLiteCollationCompareCallback), e)); /* throw */ 594 - } 595 - } 596 - catch 597 - { 598 - // do nothing. 484 + SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 485 + "Caught exception in \"Compare\" method: {0}", 486 + e)); /* throw */ 599 487 } 600 488 } 489 + catch 490 + { 491 + // do nothing. 492 + } 493 + } 601 494 #else 602 - catch /* NOTE: Must catch ALL. */ 603 - { 604 - // do nothing (Windows CE). 605 - } 606 -#endif 495 + catch /* NOTE: Must catch ALL. */ 496 + { 497 + // do nothing (Windows CE). 607 498 } 499 +#endif 608 500 609 501 return 0; 610 502 } 611 503 612 504 /// <summary> 613 505 /// The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method. 614 - /// Does nothing if there is no step callback configured. WARNING: Must not throw exceptions. 506 + /// WARNING: Must not throw exceptions. 615 507 /// </summary> 616 508 /// <remarks> 617 509 /// This function takes care of doing the lookups and getting the important information put together to call the Step() function. 618 510 /// That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so 619 511 /// binary searches can be done to find the data. 620 512 /// </remarks> 621 513 /// <param name="context">A raw context pointer</param> 622 514 /// <param name="nArgs">Number of arguments passed in</param> 623 515 /// <param name="argsptr">A pointer to the array of arguments</param> 624 516 internal void StepCallback(IntPtr context, int nArgs, IntPtr argsptr) 625 517 { 626 - if (_stepCallback != null) 518 + try 519 + { 520 + AggregateData data = null; 521 + 522 + if (_base != null) 523 + { 524 + IntPtr nAux = _base.AggregateContext(context); 525 + 526 + if ((_contextDataList != null) && 527 + !_contextDataList.TryGetValue(nAux, out data)) 528 + { 529 + data = new AggregateData(); 530 + _contextDataList[nAux] = data; 531 + } 532 + } 533 + 534 + if (data == null) 535 + data = new AggregateData(); 536 + 537 + try 538 + { 539 + _context = context; 540 + Step(ConvertParams(nArgs, argsptr), 541 + data._count, ref data._data); /* throw */ 542 + } 543 + finally 544 + { 545 + data._count++; 546 + } 547 + } 548 +#if !PLATFORM_COMPACTFRAMEWORK 549 + catch (Exception e) /* NOTE: Must catch ALL. */ 627 550 { 628 551 try 629 552 { 630 - AggregateData data = null; 631 - 632 - if (_base != null) 553 + if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 554 + SQLiteConnectionFlags.LogCallbackException) 633 555 { 634 - IntPtr nAux = _base.AggregateContext(context); 635 - 636 - if ((_contextDataList != null) && 637 - !_contextDataList.TryGetValue(nAux, out data)) 638 - { 639 - data = new AggregateData(); 640 - _contextDataList[nAux] = data; 641 - } 642 - } 643 - 644 - AggregateData newData = (data != null) ? data : new AggregateData(); 645 - 646 - try 647 - { 648 - _context = context; 649 - _stepCallback(ConvertParams(nArgs, argsptr), 650 - newData._count, ref newData._data); /* throw */ 651 - } 652 - finally 653 - { 654 - newData._count++; 556 + SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 557 + "Caught exception in \"Step\" method: {1}", 558 + e)); /* throw */ 655 559 } 656 560 } 657 -#if !PLATFORM_COMPACTFRAMEWORK 658 - catch (Exception e) /* NOTE: Must catch ALL. */ 561 + catch 659 562 { 660 - try 661 - { 662 - if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 663 - SQLiteConnectionFlags.LogCallbackException) 664 - { 665 - SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 666 - "Caught exception in {0} callback: {1}", 667 - typeof(SQLiteFunctionStepCallback), e)); /* throw */ 668 - } 669 - } 670 - catch 671 - { 672 - // do nothing. 673 - } 563 + // do nothing. 674 564 } 565 + } 675 566 #else 676 - catch /* NOTE: Must catch ALL. */ 677 - { 678 - // do nothing (Windows CE). 679 - } 680 -#endif 567 + catch /* NOTE: Must catch ALL. */ 568 + { 569 + // do nothing (Windows CE). 681 570 } 571 +#endif 682 572 } 683 573 684 574 /// <summary> 685 575 /// An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. 686 - /// Does nothing if there is no final callback configured. WARNING: Must not throw exceptions. 576 + /// WARNING: Must not throw exceptions. 687 577 /// </summary> 688 578 /// <param name="context">A raw context pointer</param> 689 579 internal void FinalCallback(IntPtr context) 690 580 { 691 - if (_finalCallback != null) 581 + try 582 + { 583 + object obj = null; 584 + 585 + if (_base != null) 586 + { 587 + IntPtr n = _base.AggregateContext(context); 588 + AggregateData aggData; 589 + 590 + if ((_contextDataList != null) && 591 + _contextDataList.TryGetValue(n, out aggData)) 592 + { 593 + obj = aggData._data; 594 + _contextDataList.Remove(n); 595 + } 596 + } 597 + 598 + try 599 + { 600 + _context = context; 601 + SetReturnValue(context, Final(obj)); /* throw */ 602 + } 603 + finally 604 + { 605 + IDisposable disp = obj as IDisposable; 606 + if (disp != null) disp.Dispose(); /* throw */ 607 + } 608 + } 609 +#if !PLATFORM_COMPACTFRAMEWORK 610 + catch (Exception e) /* NOTE: Must catch ALL. */ 692 611 { 693 612 try 694 613 { 695 - object obj = null; 696 - 697 - if (_base != null) 614 + if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 615 + SQLiteConnectionFlags.LogCallbackException) 698 616 { 699 - IntPtr n = _base.AggregateContext(context); 700 - AggregateData aggData; 701 - 702 - if ((_contextDataList != null) && 703 - _contextDataList.TryGetValue(n, out aggData)) 704 - { 705 - obj = aggData._data; 706 - _contextDataList.Remove(n); 707 - } 708 - } 709 - 710 - try 711 - { 712 - _context = context; 713 - SetReturnValue(context, _finalCallback(obj)); /* throw */ 714 - } 715 - finally 716 - { 717 - IDisposable disp = obj as IDisposable; 718 - if (disp != null) disp.Dispose(); /* throw */ 617 + SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 618 + "Caught exception in \"Final\" method: {1}", 619 + e)); /* throw */ 719 620 } 720 621 } 721 -#if !PLATFORM_COMPACTFRAMEWORK 722 - catch (Exception e) /* NOTE: Must catch ALL. */ 622 + catch 723 623 { 724 - try 725 - { 726 - if ((_flags & SQLiteConnectionFlags.LogCallbackException) == 727 - SQLiteConnectionFlags.LogCallbackException) 728 - { 729 - SQLiteLog.LogMessage(COR_E_EXCEPTION, String.Format( 730 - "Caught exception in {0} callback: {1}", 731 - typeof(SQLiteFunctionFinalCallback), e)); /* throw */ 732 - } 733 - } 734 - catch 735 - { 736 - // do nothing. 737 - } 624 + // do nothing. 738 625 } 626 + } 739 627 #else 740 - catch /* NOTE: Must catch ALL. */ 741 - { 742 - // do nothing (Windows CE). 743 - } 744 -#endif 628 + catch /* NOTE: Must catch ALL. */ 629 + { 630 + // do nothing (Windows CE). 745 631 } 632 +#endif 746 633 } 747 634 748 635 /// <summary> 749 636 /// Using reflection, enumerate all assemblies in the current appdomain looking for classes that 750 637 /// have a SQLiteFunctionAttribute attribute, and registering them accordingly. 751 638 /// </summary> 752 639 #if !PLATFORM_COMPACTFRAMEWORK ................................................................................ 858 745 859 746 foreach (SQLiteFunctionAttribute pr in _registeredFunctions) 860 747 { 861 748 f = (SQLiteFunction)Activator.CreateInstance(pr._instanceType); 862 749 863 750 f._base = sqlbase; 864 751 f._flags = flags; 865 - f._invokeCallback = f.Invoke; 866 - f._stepCallback = f.Step; 867 - f._finalCallback = f.Final; 868 - f._compareCallback = f.Compare; 869 752 f._InvokeFunc = (pr.FuncType == FunctionType.Scalar) ? new SQLiteCallback(f.ScalarCallback) : null; 870 753 f._StepFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteCallback(f.StepCallback) : null; 871 754 f._FinalFunc = (pr.FuncType == FunctionType.Aggregate) ? new SQLiteFinalCallback(f.FinalCallback) : null; 872 755 f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback) : null; 873 756 f._CompareFunc16 = (pr.FuncType == FunctionType.Collation) ? new SQLiteCollation(f.CompareCallback16) : null; 874 757 875 758 if (pr.FuncType != FunctionType.Collation)