System.Data.SQLite
Check-in [cb9c3d67aa]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Permit an existing registered function to be replaced. Fix for [2556655d1b].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb9c3d67aa3a32d7219097d9d6d19d65329239b7
User & Date: mistachkin 2015-10-15 19:38:44
References
2015-10-15
19:39 Closed ticket [2556655d1b]: SQLiteFunction.RegisterFunction ArgumentException plus 4 other changes artifact: 52d1f361f4 user: mistachkin
Context
2015-10-15
19:51
Add SQLITE_ENABLE_API_ARMOR to the interop assembly. check-in: 53a3809160 user: mistachkin tags: trunk
19:38
Permit an existing registered function to be replaced. Fix for [2556655d1b]. check-in: cb9c3d67aa user: mistachkin tags: trunk
18:56
Fix a test constraint to make sure the recent .NET Frameworks are included. check-in: a2a5cbfc95 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/SQLiteFunction.cs.

708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
...
790
791
792
793
794
795
796







































797


798
799
800
801
802
803
804
            int u = arAtt.Length;
            for (int y = 0; y < u; y++)
            {
              at = arAtt[y] as SQLiteFunctionAttribute;
              if (at != null)
              {
                at.InstanceType = arTypes[x];
                _registeredFunctions.Add(at, null);
              }
            }
          }
        }
#endif
      }
      catch // SQLite provider can continue without being able to find built-in functions
................................................................................
        SQLiteFunctionAttribute at = new SQLiteFunctionAttribute(
            name, argumentCount, functionType);

        at.InstanceType = instanceType;
        at.Callback1 = callback1;
        at.Callback2 = callback2;








































        _registeredFunctions.Add(at, null);


    }

    /// <summary>
    /// Creates a <see cref="SQLiteFunction" /> instance based on the specified
    /// <see cref="SQLiteFunctionAttribute" />.
    /// </summary>
    /// <param name="functionAttribute">







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>







708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
...
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
            int u = arAtt.Length;
            for (int y = 0; y < u; y++)
            {
              at = arAtt[y] as SQLiteFunctionAttribute;
              if (at != null)
              {
                at.InstanceType = arTypes[x];
                ReplaceFunction(at, null);
              }
            }
          }
        }
#endif
      }
      catch // SQLite provider can continue without being able to find built-in functions
................................................................................
        SQLiteFunctionAttribute at = new SQLiteFunctionAttribute(
            name, argumentCount, functionType);

        at.InstanceType = instanceType;
        at.Callback1 = callback1;
        at.Callback2 = callback2;

        ReplaceFunction(at, null);
    }

    /// <summary>
    /// Replaces a registered function, disposing of the associated (old)
    /// value if necessary.
    /// </summary>
    /// <param name="at">
    /// The attribute that describes the function to replace.
    /// </param>
    /// <param name="newValue">
    /// The new value to use.
    /// </param>
    /// <returns>
    /// Non-zero if an existing registered function was replaced; otherwise,
    /// zero.
    /// </returns>
    private static bool ReplaceFunction(
        SQLiteFunctionAttribute at,
        object newValue
        )
    {
        object oldValue;

        if (_registeredFunctions.TryGetValue(at, out oldValue))
        {
            IDisposable disposable = oldValue as IDisposable;

            if (disposable != null)
            {
                disposable.Dispose();
                disposable = null;
            }

            _registeredFunctions[at] = newValue;
            return true;
        }
        else
        {
            _registeredFunctions.Add(at, newValue);
            return false;
        }
    }

    /// <summary>
    /// Creates a <see cref="SQLiteFunction" /> instance based on the specified
    /// <see cref="SQLiteFunctionAttribute" />.
    /// </summary>
    /// <param name="functionAttribute">

Added Tests/tkt-2556655d1b.eagle.

























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
###############################################################################
#
# tkt-2556655d1b.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require Eagle.Library
package require Eagle.Test

runTestPrologue

###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################

###############################################################################

runTest {test tkt-2556655d1b-1.1 {duplicate functions} -setup {
  set fileName tkt-2556655d1b-1.1.db
} -body {
  set id [object invoke Interpreter.GetActive NextId]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;

    namespace _Dynamic${id}
    {
      \[SQLiteFunction(Name = "Base64", FuncType = FunctionType.Scalar)\]
      public class Test${id} : SQLiteFunction
      {
        public override object Invoke(
          object\[\] args
          )
        {
          if (args == null)
            return null;

          if (args.Length != 1)
            return new ArgumentException(String.Format(
              "need exactly one argument, got {0}", args.Length));

          object arg = args\[0\];

          if (arg == null)
            return String.Empty;

          Type type = arg.GetType();

          if (type == typeof(DBNull))
            return String.Empty;

          if (type != typeof(byte\[\]))
            return new ArgumentException(String.Format(
              "argument must be byte array, got {0}", type));

          return Convert.ToBase64String((byte\[\]) arg);
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          SQLiteFunction.RegisterFunction(typeof(Test${id}));
          SQLiteFunction.RegisterFunction(typeof(Test${id}));
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  #
  # NOTE: Compile the C# code (above) to register the custom SQLite function
  #       and then open the database for this test case and attempt to execute
  #       the function.  Normally, we would open the database in the test setup
  #       phase; however, that will not work correctly because newly registered
  #       functions are only picked up and used by databases opened after they
  #       have been registered.
  #
  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result [setupDb $fileName] \
      [sql execute -execute scalar $db "SELECT Base64(CAST(NULL AS BLOB));"] \
      [sql execute -execute scalar $db "SELECT Base64(CAST('' AS BLOB));"] \
      [sql execute -execute scalar $db "SELECT Base64(CAST('foo' AS BLOB));"]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors id db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite compileCSharp} -match regexp -result {^Ok\
System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{\}\
System#Data#SQLite#SQLiteConnection#\d+ \{\} \{\} Zm9v$}}

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue