Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add experimental support for interfacing with the authorizer callback mechanism in the SQLite core library. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
12c508890cd3486713263e359466636d |
User & Date: | mistachkin 2013-09-18 02:10:34.189 |
Context
2013-09-18
| ||
02:31 | Simplify and cleanup authorizer tests. Update version history docs. check-in: 441ccabcc6 user: mistachkin tags: trunk | |
02:10 | Add experimental support for interfacing with the authorizer callback mechanism in the SQLite core library. check-in: 12c508890c user: mistachkin tags: trunk | |
2013-09-17
| ||
08:00 | Add some simple tests of the new properties. check-in: 06c39db73a user: mistachkin tags: trunk | |
Changes
Changes to Setup/verify.lst.
︙ | |||
403 404 405 406 407 408 409 410 411 412 413 414 415 416 | 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | + | testlinq/Properties/ testlinq/Properties/AssemblyInfo.cs testlinq/testlinq.2008.csproj testlinq/testlinq.2010.csproj testlinq/testlinq.2012.csproj Tests/ Tests/all.eagle Tests/authorizer.eagle Tests/backup.eagle Tests/basic.eagle Tests/common.eagle Tests/empty.eagle Tests/installer.eagle Tests/Installer_Test_Vs2005.log Tests/Installer_Test_Vs2008.log |
︙ |
Changes to System.Data.SQLite/SQLite3.cs.
︙ | |||
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 | 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 | + + + + + | internal override void ChangePassword(byte[] newPasswordBytes) { SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_rekey(_sql, newPasswordBytes, (newPasswordBytes == null) ? 0 : newPasswordBytes.Length); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); } #endif internal override void SetAuthorizerHook(SQLiteAuthorizerCallback func) { UnsafeNativeMethods.sqlite3_set_authorizer(_sql, func, IntPtr.Zero); } internal override void SetUpdateHook(SQLiteUpdateCallback func) { UnsafeNativeMethods.sqlite3_update_hook(_sql, func, IntPtr.Zero); } internal override void SetCommitHook(SQLiteCommitCallback func) |
︙ |
Changes to System.Data.SQLite/SQLiteBase.cs.
︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | + | internal abstract void LogMessage(SQLiteErrorCode iErrCode, string zMessage); #if INTEROP_CODEC internal abstract void SetPassword(byte[] passwordBytes); internal abstract void ChangePassword(byte[] newPasswordBytes); #endif internal abstract void SetAuthorizerHook(SQLiteAuthorizerCallback func); internal abstract void SetUpdateHook(SQLiteUpdateCallback func); internal abstract void SetCommitHook(SQLiteCommitCallback func); internal abstract void SetTraceCallback(SQLiteTraceCallback func); internal abstract void SetRollbackHook(SQLiteRollbackCallback func); internal abstract SQLiteErrorCode SetLogCallback(SQLiteLogCallback func); /// <summary> |
︙ |
Changes to System.Data.SQLite/SQLiteConnection.cs.
︙ | |||
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | + + | /// </summary> private bool _parseViaFramework; internal bool _binaryGuid; internal long _version; private event SQLiteAuthorizerEventHandler _authorizerHandler; private event SQLiteUpdateEventHandler _updateHandler; private event SQLiteCommitHandler _commitHandler; private event SQLiteTraceEventHandler _traceHandler; private event EventHandler _rollbackHandler; private SQLiteAuthorizerCallback _authorizerCallback; private SQLiteUpdateCallback _updateCallback; private SQLiteCommitCallback _commitCallback; private SQLiteTraceCallback _traceCallback; private SQLiteRollbackCallback _rollbackCallback; #endregion /////////////////////////////////////////////////////////////////////////////////////////////// |
︙ | |||
2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 | + + + | { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA foreign_keys={0}", boolValue ? "ON" : "OFF"); cmd.ExecuteNonQuery(); } } } if (_authorizerHandler != null) _sql.SetAuthorizerHook(_authorizerCallback); if (_commitHandler != null) _sql.SetCommitHook(_commitCallback); if (_updateHandler != null) _sql.SetUpdateHook(_updateCallback); if (_rollbackHandler != null) |
︙ | |||
3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 | 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | } tbl.EndLoadData(); tbl.AcceptChanges(); return tbl; } /// <summary> /// This event is raised whenever SQLite encounters an action covered by the /// authorizer during query preparation. Changing the value of the /// <see cref="AuthorizerEventArgs.ReturnCode" /> property will determine if /// the specific action will be allowed, ignored, or denied. For the entire /// duration of the event, the associated connection and statement objects /// must not be modified, either directly or indirectly, by the called code. /// </summary> public event SQLiteAuthorizerEventHandler Authorize { add { CheckDisposed(); if (_authorizerHandler == null) { _authorizerCallback = new SQLiteAuthorizerCallback(AuthorizerCallback); if (_sql != null) _sql.SetAuthorizerHook(_authorizerCallback); } _authorizerHandler += value; } remove { CheckDisposed(); _authorizerHandler -= value; if (_authorizerHandler == null) { if (_sql != null) _sql.SetAuthorizerHook(null); _authorizerCallback = null; } } } /// <summary> /// This event is raised whenever SQLite makes an update/delete/insert into the database on /// this connection. It only applies to the given connection. /// </summary> public event SQLiteUpdateEventHandler Update { |
︙ | |||
3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 | 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 | + + + + + + + + + + + + + + + + + + + | if (_updateHandler == null) { if (_sql != null) _sql.SetUpdateHook(null); _updateCallback = null; } } } private SQLiteAuthorizerReturnCode AuthorizerCallback( IntPtr pUserData, SQLiteAuthorizerActionCode actionCode, IntPtr pArgument1, IntPtr pArgument2, IntPtr pDatabase, IntPtr pAuthContext) { AuthorizerEventArgs eventArgs = new AuthorizerEventArgs(pUserData, actionCode, SQLiteBase.UTF8ToString(pArgument1, -1), SQLiteBase.UTF8ToString(pArgument2, -1), SQLiteBase.UTF8ToString(pDatabase, -1), SQLiteBase.UTF8ToString(pAuthContext, -1), SQLiteAuthorizerReturnCode.Ok); if (_authorizerHandler != null) _authorizerHandler(this, eventArgs); return eventArgs.ReturnCode; } private void UpdateCallback(IntPtr puser, int type, IntPtr database, IntPtr table, Int64 rowid) { _updateHandler(this, new UpdateEventArgs( SQLiteBase.UTF8ToString(database, -1), SQLiteBase.UTF8ToString(table, -1), (UpdateEventType)type, |
︙ | |||
4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 | 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 | + + + + + + + + + + + + + + + + + + + + + | /// Use the default operating system's file flushing, SQLite does not explicitly flush the file buffers after writing /// </summary> Off = 2, } #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif internal delegate SQLiteAuthorizerReturnCode SQLiteAuthorizerCallback( IntPtr pUserData, SQLiteAuthorizerActionCode actionCode, IntPtr pArgument1, IntPtr pArgument2, IntPtr pDatabase, IntPtr pAuthContext ); #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif internal delegate void SQLiteUpdateCallback(IntPtr puser, int type, IntPtr database, IntPtr table, Int64 rowid); #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif internal delegate int SQLiteCommitCallback(IntPtr puser); #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif internal delegate void SQLiteTraceCallback(IntPtr puser, IntPtr statement); #if !PLATFORM_COMPACTFRAMEWORK [UnmanagedFunctionPointer(CallingConvention.Cdecl)] #endif internal delegate void SQLiteRollbackCallback(IntPtr puser); /// <summary> /// Raised when authorization is required to perform an action contained /// within a SQL query. /// </summary> /// <param name="sender">The connection performing the action.</param> /// <param name="e">A <see cref="AuthorizerEventArgs" /> that contains the /// event data.</param> public delegate void SQLiteAuthorizerEventHandler(object sender, AuthorizerEventArgs e); /// <summary> /// Raised when a transaction is about to be committed. To roll back a transaction, set the /// rollbackTrans boolean value to true. /// </summary> /// <param name="sender">The connection committing the transaction</param> /// <param name="e">Event arguments on the transaction</param> public delegate void SQLiteCommitHandler(object sender, CommitEventArgs e); |
︙ | |||
4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 | 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | string destinationName, int pages, int remainingPages, int totalPages, bool retry ); #endregion /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// The data associated with a call into the authorizer. /// </summary> public class AuthorizerEventArgs : EventArgs { /// <summary> /// The user-defined native data associated with this event. Currently, /// this will always contain the value of <see cref="IntPtr.Zero" />. /// </summary> public readonly IntPtr UserData; /// <summary> /// The action code responsible for the current call into the authorizer. /// </summary> public readonly SQLiteAuthorizerActionCode ActionCode; /// <summary> /// The first string argument for the current call into the authorizer. /// The exact value will vary based on the action code, see the /// <see cref="SQLiteAuthorizerActionCode" /> enumeration for possible /// values. /// </summary> public readonly string Argument1; /// <summary> /// The second string argument for the current call into the authorizer. /// The exact value will vary based on the action code, see the /// <see cref="SQLiteAuthorizerActionCode" /> enumeration for possible /// values. /// </summary> public readonly string Argument2; /// <summary> /// The database name for the current call into the authorizer, if /// applicable. /// </summary> public readonly string Database; /// <summary> /// The name of the inner-most trigger or view that is responsible for /// the access attempt or a null value if this access attempt is directly /// from top-level SQL code. /// </summary> public readonly string Context; /// <summary> /// The return code for the current call into the authorizer. /// </summary> public SQLiteAuthorizerReturnCode ReturnCode; /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs an instance of this class with default property values. /// </summary> private AuthorizerEventArgs() { this.UserData = IntPtr.Zero; this.ActionCode = SQLiteAuthorizerActionCode.None; this.Argument1 = null; this.Argument2 = null; this.Database = null; this.Context = null; this.ReturnCode = SQLiteAuthorizerReturnCode.Ok; } /////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs an instance of this class with specific property values. /// </summary> /// <param name="pUserData"> /// The user-defined native data associated with this event. /// </param> /// <param name="actionCode"> /// The authorizer action code. /// </param> /// <param name="argument1"> /// The first authorizer argument. /// </param> /// <param name="argument2"> /// The second authorizer argument. /// </param> /// <param name="database"> /// The database name, if applicable. /// </param> /// <param name="context"> /// The name of the inner-most trigger or view that is responsible for /// the access attempt or a null value if this access attempt is directly /// from top-level SQL code. /// </param> /// <param name="returnCode"> /// The authorizer return code. /// </param> internal AuthorizerEventArgs( IntPtr pUserData, SQLiteAuthorizerActionCode actionCode, string argument1, string argument2, string database, string context, SQLiteAuthorizerReturnCode returnCode ) : this() { this.UserData = pUserData; this.ActionCode = actionCode; this.Argument1 = argument1; this.Argument2 = argument2; this.Database = database; this.Context = context; this.ReturnCode = returnCode; } } /////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Whenever an update event is triggered on a connection, this enum will indicate /// exactly what type of operation is being performed. /// </summary> |
︙ |
Changes to System.Data.SQLite/SQLiteConvert.cs.
︙ | |||
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 | 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 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 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 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 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | /// <summary> /// Use the default command execution type. Using this value is the same /// as using the <see cref="SQLiteExecuteType.NonQuery" /> value. /// </summary> Default = NonQuery /* TODO: Good default? */ } /// <summary> /// The action code responsible for the current call into the authorizer. /// </summary> public enum SQLiteAuthorizerActionCode { /// <summary> /// No action is being performed. This value should not be used from /// external code. /// </summary> None = -1, /// <summary> /// No longer used. /// </summary> Copy = 0, /// <summary> /// An index will be created. The action-specific arguments are the /// index name and the table name. /// /// </summary> CreateIndex = 1, /// <summary> /// A table will be created. The action-specific arguments are the /// table name and a null value. /// </summary> CreateTable = 2, /// <summary> /// A temporary index will be created. The action-specific arguments /// are the index name and the table name. /// </summary> CreateTempIndex = 3, /// <summary> /// A temporary table will be created. The action-specific arguments /// are the table name and a null value. /// </summary> CreateTempTable = 4, /// <summary> /// A temporary trigger will be created. The action-specific arguments /// are the trigger name and the table name. /// </summary> CreateTempTrigger = 5, /// <summary> /// A temporary view will be created. The action-specific arguments are /// the view name and a null value. /// </summary> CreateTempView = 6, /// <summary> /// A trigger will be created. The action-specific arguments are the /// trigger name and the table name. /// </summary> CreateTrigger = 7, /// <summary> /// A view will be created. The action-specific arguments are the view /// name and a null value. /// </summary> CreateView = 8, /// <summary> /// A DELETE statement will be executed. The action-specific arguments /// are the table name and a null value. /// </summary> Delete = 9, /// <summary> /// An index will be dropped. The action-specific arguments are the /// index name and the table name. /// </summary> DropIndex = 10, /// <summary> /// A table will be dropped. The action-specific arguments are the tables /// name and a null value. /// </summary> DropTable = 11, /// <summary> /// A temporary index will be dropped. The action-specific arguments are /// the index name and the table name. /// </summary> DropTempIndex = 12, /// <summary> /// A temporary table will be dropped. The action-specific arguments are /// the table name and a null value. /// </summary> DropTempTable = 13, /// <summary> /// A temporary trigger will be dropped. The action-specific arguments /// are the trigger name and the table name. /// </summary> DropTempTrigger = 14, /// <summary> /// A temporary view will be dropped. The action-specific arguments are /// the view name and a null value. /// </summary> DropTempView = 15, /// <summary> /// A trigger will be dropped. The action-specific arguments are the /// trigger name and the table name. /// </summary> DropTrigger = 16, /// <summary> /// A view will be dropped. The action-specific arguments are the view /// name and a null value. /// </summary> DropView = 17, /// <summary> /// An INSERT statement will be executed. The action-specific arguments /// are the table name and a null value. /// </summary> Insert = 18, /// <summary> /// A PRAGMA statement will be executed. The action-specific arguments /// are the name of the PRAGMA and the new value or a null value. /// </summary> Pragma = 19, /// <summary> /// A table column will be read. The action-specific arguments are the /// table name and the column name. /// </summary> Read = 20, /// <summary> /// A SELECT statement will be executed. The action-specific arguments /// are both null values. /// </summary> Select = 21, /// <summary> /// A transaction will be started, committed, or rolled back. The /// action-specific arguments are the name of the operation (BEGIN, /// COMMIT, or ROLLBACK) and a null value. /// </summary> Transaction = 22, /// <summary> /// An UPDATE statement will be executed. The action-specific arguments /// are the table name and the column name. /// </summary> Update = 23, /// <summary> /// A database will be attached to the connection. The action-specific /// arguments are the database file name and a null value. /// </summary> Attach = 24, /// <summary> /// A database will be detached from the connection. The action-specific /// arguments are the database name and a null value. /// </summary> Detach = 25, /// <summary> /// The schema of a table will be altered. The action-specific arguments /// are the database name and the table name. /// </summary> AlterTable = 26, /// <summary> /// An index will be deleted and then recreated. The action-specific /// arguments are the index name and a null value. /// </summary> Reindex = 27, /// <summary> /// A table will be analyzed to gathers statistics about it. The /// action-specific arguments are the table name and a null value. /// </summary> Analyze = 28, /// <summary> /// A virtual table will be created. The action-specific arguments are /// the table name and the module name. /// </summary> CreateVtable = 29, /// <summary> /// A virtual table will be dropped. The action-specific arguments are /// the table name and the module name. /// </summary> DropVtable = 30, /// <summary> /// A SQL function will be called. The action-specific arguments are a /// null value and the function name. /// </summary> Function = 31, /// <summary> /// A savepoint will be created, released, or rolled back. The /// action-specific arguments are the name of the operation (BEGIN, /// RELEASE, or ROLLBACK) and the savepoint name. /// </summary> Savepoint = 32 } /// <summary> /// The return code for the current call into the authorizer. /// </summary> public enum SQLiteAuthorizerReturnCode { /// <summary> /// The action will be allowed. /// </summary> Ok = 0, /// <summary> /// The overall action will be disallowed and an error message will be /// returned from the query preparation method. /// </summary> Deny = 1, /// <summary> /// The specific action will be disallowed; however, the overall action /// will continue. The exact effects of this return code vary depending /// on the specific action, please refer to the SQLite core library /// documentation for futher details. /// </summary> Ignore = 2 } /// <summary> /// Class used internally to determine the datatype of a column in a resultset /// </summary> internal sealed class SQLiteType { /// <summary> |
︙ |
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
︙ | |||
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 | 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 | + + + + + + + | [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern SQLiteErrorCode sqlite3_rekey(IntPtr db, byte[] key, int keylen); #endif #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_set_authorizer(IntPtr db, SQLiteAuthorizerCallback func, IntPtr pvUser); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_update_hook(IntPtr db, SQLiteUpdateCallback func, IntPtr pvUser); |
︙ |
Added Tests/authorizer.eagle.