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

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

Overview
Comment:More work in progress fine-tuning the implementation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | delegateFunction
Files: files | file ages | folders
SHA1:ef7ebd64694b042d9dbf7f764a9b5c7f66987cd8
User & Date: mistachkin 2015-08-14 23:20:14
Context
2015-08-15
03:48
Refactor SQLiteDelegateFunction constructor to accept two delegates, not one. Use early-bound delegates by default. Get tests passing. check-in: 3c25655a66 user: mistachkin tags: delegateFunction
2015-08-14
23:20
More work in progress fine-tuning the implementation. check-in: ef7ebd6469 user: mistachkin tags: delegateFunction
2015-08-05
00:57
Work in progress on tests. Not yet working. check-in: 56469328f7 user: mistachkin tags: delegateFunction
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
....
1077
1078
1079
1080
1081
1082
1083

1084





























































































1085
1086
1087
1088
1089
1090
1091
....
1150
1151
1152
1153
1154
1155
1156




1157
1158
1159
1160
1161

1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
....
1189
1190
1191
1192
1193
1194
1195




1196
1197
1198
1199
1200
1201
1202

1203
1204
1205
1206

1207
1208

1209
1210
1211
1212
1213
1214
1215
1216
1217
1218



1219




















1220


1221
1222
1223










1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235




1236
1237
1238
1239
1240

1241
1242
1243





1244
1245
1246
1247
1248
1249
1250
....
1252
1253
1254
1255
1256
1257
1258




1259
1260
1261
1262
1263
1264

1265
1266
1267





1268
1269
1270
1271
1272
1273
1274
....
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309









1310


1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
....
1335
1336
1337
1338
1339
1340
1341









1342

1343
1344
1345
1346
1347


1348
1349
1350
1351
1352
1353
1354
....
1364
1365
1366
1367
1368
1369
1370








1371


1372
1373
1374
1375
1376
1377
1378
....
1395
1396
1397
1398
1399
1400
1401
1402








1403

1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
      CheckDisposed();
      return null;
    }

    /// <summary>
    /// User-defined collating sequences override this method to provide a custom string sorting algorithm.
    /// </summary>
    /// <param name="param1">The first string to compare</param>
    /// <param name="param2">The second strnig to compare</param>
    /// <returns>1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2</returns>
    public virtual int Compare(string param1, string param2)
    {
      CheckDisposed();
      return 0;
    }

    /// <summary>
................................................................................
        {
            return sqliteBase.CreateCollation(
                name, null, null, false) == SQLiteErrorCode.Ok;
        }
    }
  }

































































































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

  /// <summary>
  /// This class implements a SQLite function using a <see cref="Delegate" />.
  /// All the virtual methods of the <see cref="SQLiteFunction" /> class are
  /// implemented using calls to the <see cref="Delegate.DynamicInvoke" />
................................................................................
      /// Returns the list of arguments for the <see cref="Invoke" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
      /// argument is always the literal string "Invoke".
      /// </summary>
      /// <param name="args">
      /// The original arguments received by the <see cref="Invoke" /> method.
      /// </param>




      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetInvokeArgs(
          object[] args

          ) /* CANNOT RETURN NULL */
      {
          if (args == null)
              return new object[] { "Invoke" };

          int length = args.Length;
          object[] newArgs = new object[length + 1];

          newArgs[0] = "Invoke";

          for (int index = 0; index < length; index++)
              newArgs[index + 1] = args[index];

          return newArgs;
      }

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

      /// <summary>
................................................................................
      /// The step number (one based).  This is incrememted each time the
      /// <see cref="Step" /> method is called.
      /// </param>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
      /// to the current context.
      /// </param>




      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetStepArgs(
          object[] args,
          int stepNumber,
          object contextData

          ) /* CANNOT RETURN NULL */
      {
          int length = 0;


          if (args != null)
              length = args.Length;


          int newLength = length + 3; /* "Step", stepNumber, contextData */
          object[] newArgs = new object[newLength];

          newArgs[0] = "Step";

          if (args != null)
              for (int index = 0; index < length; index++)
                  newArgs[index + 1] = args[index];




          newArgs[newLength - 2] = stepNumber;




















          newArgs[newLength - 1] = contextData;



          return newArgs;
      }











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

      /// <summary>
      /// Returns the list of arguments for the <see cref="Final" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
      /// argument is always the literal string "Final".
      /// </summary>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
      /// to the current context.
      /// </param>




      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetFinalArgs(
          object contextData

          ) /* CANNOT RETURN NULL */
      {
          return new object[] { "Final", contextData };





      }

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

      /// <summary>
      /// Returns the list of arguments for the <see cref="Compare" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
................................................................................
      /// </summary>
      /// <param name="param1">
      /// The first string to compare.
      /// </param>
      /// <param name="param2">
      /// The second strnig to compare.
      /// </param>




      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetCompareArgs(
          string param1,
          string param2

          ) /* CANNOT RETURN NULL */
      {
          return new object[] { "Compare", param1, param2 };





      }
      #endregion

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

      #region Public Properties
      private Delegate callback;
................................................................................
      #region System.Data.SQLite.SQLiteFunction Overrides
      /// <summary>
      /// This virtual method is the implementation for scalar functions.
      /// See the <see cref="SQLiteFunction.Invoke" /> method for more
      /// details.
      /// </summary>
      /// <param name="args">
      /// The arguments for the scalar function.  The first argument is always
      /// the literal string "Invoke".  The remaining arguments, if any, are
      /// passed exactly as they are received.
      /// </param>
      /// <returns>
      /// The result of the scalar function.
      /// </returns>
      public override object Invoke(
          object[] args /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);










          return callback.DynamicInvoke(GetInvokeArgs(args)); /* throw */


      }

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

      /// <summary>
      /// This virtual method is part of the implementation for aggregate
      /// functions.  See the <see cref="SQLiteFunction.Step" /> method
      /// for more details.
      /// </summary>
      /// <param name="args">
      /// The arguments for the aggregate function.  The first argument is
      /// always the literal string "Step".  The remaining arguments, if
      /// any, are passed exactly as they are received.
      /// </param>
      /// <param name="stepNumber">
      /// The step number (one based).  This is incrememted each time the
      /// <see cref="Step" /> method is called.
      /// </param>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
................................................................................
          int stepNumber,        /* in */
          ref object contextData /* in, out */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);










          object[] newArgs = GetStepArgs(args, stepNumber, contextData);


          /* IGNORED */
          callback.DynamicInvoke(newArgs); /* throw */

          contextData = newArgs[newArgs.Length - 1]; /* out */


      }

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

      /// <summary>
      /// This virtual method is part of the implementation for aggregate
      /// functions.  See the <see cref="SQLiteFunction.Final" /> method
................................................................................
      public override object Final(
          object contextData /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);









          return callback.DynamicInvoke(GetFinalArgs(contextData)); /* throw */


      }

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

      /// <summary>
      /// This virtual method is part of the implementation for collating
      /// sequences.  See the <see cref="SQLiteFunction.Compare" /> method
................................................................................
          string param1, /* in */
          string param2  /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);

          object[] newArgs = GetCompareArgs(param1, param2);








          object result = callback.DynamicInvoke(newArgs); /* throw */


          if (result is int)
              return (int)result;

          throw new InvalidOperationException(String.Format(
              ResultInt32Error, newArgs[0]));

      }
      #endregion
  }

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

  /// <summary>







|
|
|







 







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>




|
>


<
|

|
|
<
<
<
<
<







 







>
>
>
>






|
>


<
<
>
|
<
>

|
|

|
|
<
<
<

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












>
>
>
>




|
>


|
>
>
>
>
>







 







>
>
>
>





|
>


|
>
>
>
>
>







 







|
<
<











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










|
<
<







 







>
>
>
>
>
>
>
>
>
|
>

|
|

<
>
>







 







>
>
>
>
>
>
>
>
|
>
>







 







|
>
>
>
>
>
>
>
>
|
>

|
|

|
|
>







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
....
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
....
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266





1267
1268
1269
1270
1271
1272
1273
....
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302


1303
1304

1305
1306
1307
1308
1309
1310
1311



1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
....
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
....
1438
1439
1440
1441
1442
1443
1444
1445


1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479


1480
1481
1482
1483
1484
1485
1486
....
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512

1513
1514
1515
1516
1517
1518
1519
1520
1521
....
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
....
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
      CheckDisposed();
      return null;
    }

    /// <summary>
    /// User-defined collating sequences override this method to provide a custom string sorting algorithm.
    /// </summary>
    /// <param name="param1">The first string to compare.</param>
    /// <param name="param2">The second strnig to compare.</param>
    /// <returns>1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2.</returns>
    public virtual int Compare(string param1, string param2)
    {
      CheckDisposed();
      return 0;
    }

    /// <summary>
................................................................................
        {
            return sqliteBase.CreateCollation(
                name, null, null, false) == SQLiteErrorCode.Ok;
        }
    }
  }

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

  /// <summary>
  /// This <see cref="Delegate" /> type is used with the
  /// <see cref="SQLiteDelegateFunction.Invoke" /> method.
  /// </summary>
  /// <param name="param0">
  /// This is always the string literal "Invoke".
  /// </param>
  /// <param name="args">
  /// The arguments for the scalar function.
  /// </param>
  /// <returns>
  /// The result of the scalar function.
  /// </returns>
  public delegate object SQLiteInvokeDelegate(
    string param0,
    object[] args
  );

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

  /// <summary>
  /// This <see cref="Delegate" /> type is used with the
  /// <see cref="SQLiteDelegateFunction.Step" /> method.
  /// </summary>
  /// <param name="param0">
  /// This is always the string literal "Step".
  /// </param>
  /// <param name="args">
  /// The arguments for the aggregate function.
  /// </param>
  /// <param name="stepNumber">
  /// The step number (one based).  This is incrememted each time the
  /// <see cref="SQLiteDelegateFunction.Step" /> method is called.
  /// </param>
  /// <param name="contextData">
  /// A placeholder for implementers to store contextual data pertaining
  /// to the current context.
  /// </param>
  public delegate void SQLiteStepDelegate(
    string param0,
    object[] args,
    int stepNumber,
    ref object contextData
  );

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

  /// <summary>
  /// This <see cref="Delegate" /> type is used with the
  /// <see cref="SQLiteDelegateFunction.Final" /> method.
  /// </summary>
  /// <param name="param0">
  /// This is always the string literal "Final".
  /// </param>
  /// <param name="contextData">
  /// A placeholder for implementers to store contextual data pertaining
  /// to the current context.
  /// </param>
  /// <returns>
  /// The result of the aggregate function.
  /// </returns>
  public delegate object SQLiteFinalDelegate(
    string param0,
    object contextData
  );

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

  /// <summary>
  /// This <see cref="Delegate" /> type is used with the
  /// <see cref="SQLiteDelegateFunction.Compare" /> method.
  /// </summary>
  /// <param name="param0">
  /// This is always the string literal "Compare".
  /// </param>
  /// <param name="param1">
  /// The first string to compare.
  /// </param>
  /// <param name="param2">
  /// The second strnig to compare.
  /// </param>
  /// <returns>
  /// A positive integer if the <paramref name="param1" /> parameter is
  /// greater than the <paramref name="param2" /> parameter, a negative
  /// integer if the <paramref name="param1" /> parameter is less than
  /// the <paramref name="param2" /> parameter, or zero if they are
  /// equal.
  /// </returns>
  public delegate int SQLiteCompareDelegate(
    string param0,
    string param1,
    string param2
  );

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

  /// <summary>
  /// This class implements a SQLite function using a <see cref="Delegate" />.
  /// All the virtual methods of the <see cref="SQLiteFunction" /> class are
  /// implemented using calls to the <see cref="Delegate.DynamicInvoke" />
................................................................................
      /// Returns the list of arguments for the <see cref="Invoke" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
      /// argument is always the literal string "Invoke".
      /// </summary>
      /// <param name="args">
      /// The original arguments received by the <see cref="Invoke" /> method.
      /// </param>
      /// <param name="earlyBound">
      /// Non-zero if the returned arguments are going to be used with the
      /// <see cref="SQLiteInvokeDelegate" /> type; otherwise, zero.
      /// </param>
      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetInvokeArgs(
          object[] args,
          bool earlyBound
          ) /* CANNOT RETURN NULL */
      {

          object[] newArgs = new object[] { "Invoke", args };

          if (!earlyBound)
              newArgs = new object[] { newArgs }; // WRAP






          return newArgs;
      }

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

      /// <summary>
................................................................................
      /// The step number (one based).  This is incrememted each time the
      /// <see cref="Step" /> method is called.
      /// </param>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
      /// to the current context.
      /// </param>
      /// <param name="earlyBound">
      /// Non-zero if the returned arguments are going to be used with the
      /// <see cref="SQLiteStepDelegate" /> type; otherwise, zero.
      /// </param>
      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetStepArgs(
          object[] args,
          int stepNumber,
          object contextData,
          bool earlyBound
          ) /* CANNOT RETURN NULL */
      {


          object[] newArgs = new object[] {
              "Step", args, stepNumber, contextData

          };

          if (!earlyBound)
              newArgs = new object[] { newArgs }; // WRAP

          return newArgs;
      }




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

      /// <summary>
      /// Updates the output arguments for the <see cref="Step" /> method,
      /// using an <see cref="Array" /> of <see cref="Object" />.  The first
      /// argument is always the literal string "Step".  Currently, only the
      /// <paramref name="contextData" /> parameter is updated.
      /// </summary>
      /// <param name="args">
      /// The original arguments received by the <see cref="Step" /> method.
      /// </param>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
      /// to the current context.
      /// </param>
      /// <param name="earlyBound">
      /// Non-zero if the returned arguments are going to be used with the
      /// <see cref="SQLiteStepDelegate" /> type; otherwise, zero.
      /// </param>
      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual void UpdateStepArgs(
          object[] args,
          ref object contextData,
          bool earlyBound
          ) /* CANNOT RETURN NULL */
      {
          object[] newArgs;

          if (earlyBound)
              newArgs = args;
          else
              newArgs = args[0] as object[];

          if (newArgs == null)
              return;

          contextData = newArgs[newArgs.Length - 1];
      }

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

      /// <summary>
      /// Returns the list of arguments for the <see cref="Final" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
      /// argument is always the literal string "Final".
      /// </summary>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
      /// to the current context.
      /// </param>
      /// <param name="earlyBound">
      /// Non-zero if the returned arguments are going to be used with the
      /// <see cref="SQLiteFinalDelegate" /> type; otherwise, zero.
      /// </param>
      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetFinalArgs(
          object contextData,
          bool earlyBound
          ) /* CANNOT RETURN NULL */
      {
          object[] newArgs = new object[] { "Final", contextData };

          if (!earlyBound)
              newArgs = new object[] { newArgs }; // WRAP

          return newArgs;
      }

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

      /// <summary>
      /// Returns the list of arguments for the <see cref="Compare" /> method,
      /// as an <see cref="Array" /> of <see cref="Object" />.  The first
................................................................................
      /// </summary>
      /// <param name="param1">
      /// The first string to compare.
      /// </param>
      /// <param name="param2">
      /// The second strnig to compare.
      /// </param>
      /// <param name="earlyBound">
      /// Non-zero if the returned arguments are going to be used with the
      /// <see cref="SQLiteCompareDelegate" /> type; otherwise, zero.
      /// </param>
      /// <returns>
      /// The arguments to pass to the configured <see cref="Delegate" />.
      /// </returns>
      protected virtual object[] GetCompareArgs(
          string param1,
          string param2,
          bool earlyBound
          ) /* CANNOT RETURN NULL */
      {
          object[] newArgs = new object[] { "Compare", param1, param2 };

          if (!earlyBound)
              newArgs = new object[] { newArgs }; // WRAP

          return newArgs;
      }
      #endregion

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

      #region Public Properties
      private Delegate callback;
................................................................................
      #region System.Data.SQLite.SQLiteFunction Overrides
      /// <summary>
      /// This virtual method is the implementation for scalar functions.
      /// See the <see cref="SQLiteFunction.Invoke" /> method for more
      /// details.
      /// </summary>
      /// <param name="args">
      /// The arguments for the scalar function.


      /// </param>
      /// <returns>
      /// The result of the scalar function.
      /// </returns>
      public override object Invoke(
          object[] args /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);

          SQLiteInvokeDelegate invokeDelegate =
              callback as SQLiteInvokeDelegate;

          if (invokeDelegate != null)
          {
              return invokeDelegate.Invoke("Invoke", args); /* throw */
          }
          else
          {
              return callback.DynamicInvoke(
                  GetInvokeArgs(args, false)); /* throw */
          }
      }

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

      /// <summary>
      /// This virtual method is part of the implementation for aggregate
      /// functions.  See the <see cref="SQLiteFunction.Step" /> method
      /// for more details.
      /// </summary>
      /// <param name="args">
      /// The arguments for the aggregate function.


      /// </param>
      /// <param name="stepNumber">
      /// The step number (one based).  This is incrememted each time the
      /// <see cref="Step" /> method is called.
      /// </param>
      /// <param name="contextData">
      /// A placeholder for implementers to store contextual data pertaining
................................................................................
          int stepNumber,        /* in */
          ref object contextData /* in, out */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);

          SQLiteStepDelegate stepDelegate = callback as SQLiteStepDelegate;

          if (stepDelegate != null)
          {
              stepDelegate.Invoke(
                  "Step", args, stepNumber, ref contextData); /* throw */
          }
          else
          {
              object[] newArgs = GetStepArgs(
                  args, stepNumber, contextData, false);

              /* IGNORED */
              callback.DynamicInvoke(newArgs); /* throw */


              UpdateStepArgs(newArgs, ref contextData, false);
          }
      }

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

      /// <summary>
      /// This virtual method is part of the implementation for aggregate
      /// functions.  See the <see cref="SQLiteFunction.Final" /> method
................................................................................
      public override object Final(
          object contextData /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);

          SQLiteFinalDelegate finalDelegate = callback as SQLiteFinalDelegate;

          if (finalDelegate != null)
          {
              return finalDelegate.Invoke("Final", contextData);
          }
          else
          {
              return callback.DynamicInvoke(GetFinalArgs(
                  contextData, callback is SQLiteFinalDelegate)); /* throw */
          }
      }

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

      /// <summary>
      /// This virtual method is part of the implementation for collating
      /// sequences.  See the <see cref="SQLiteFunction.Compare" /> method
................................................................................
          string param1, /* in */
          string param2  /* in */
          )
      {
          if (callback == null)
              throw new InvalidOperationException(NoCallbackError);

          SQLiteCompareDelegate compareDelegate =
              callback as SQLiteCompareDelegate;

          if (compareDelegate != null)
          {
              return compareDelegate.Invoke("Compare", param1, param2);
          }
          else
          {
              object result = callback.DynamicInvoke(GetCompareArgs(
                  param1, param2, false)); /* throw */

              if (result is int)
                  return (int)result;

              throw new InvalidOperationException(String.Format(
                  ResultInt32Error, "Compare"));
          }
      }
      #endregion
  }

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

  /// <summary>