System.Data.SQLite
Changes On Branch vtabFixes
Not logged in

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

Changes In Branch vtabFixes Excluding Merge-Ins

This is equivalent to a diff from d5792024ef to 8408226315

2015-12-04
20:24
Fix virtual table handling of sqlite3_index_info members not available with older versions of the SQLite core library. check-in: bc75151c63 user: mistachkin tags: trunk
20:23
Update version history docs. Closed-Leaf check-in: 8408226315 user: mistachkin tags: vtabFixes
20:07
Update SQLite core library to the latest trunk code. Adapt the interop assembly code to deal with the changes. Closed-Leaf check-in: 7536d45bed user: mistachkin tags: core310
20:05
Enhance new vtab test. Style and naming tweaks. check-in: 605ba3f2e2 user: mistachkin tags: vtabFixes
06:14
More fixes to the optional field handling for the virtual table interface. check-in: 496499d755 user: mistachkin tags: vtabFixes
02:04
Add missing checks for NET_452 and NET_461 compile-time defines. check-in: d5792024ef user: mistachkin tags: trunk
01:52
Add preliminary support for the .NET Framework 4.6.1. check-in: e357378801 user: mistachkin tags: trunk

Changes to Doc/Extra/Provider/version.html.

    42     42       </div>
    43     43       <div id="mainSection">
    44     44       <div id="mainBody">
    45     45       <h1 class="heading">Version History</h1>
    46     46       <p><b>1.0.99.0 - December XX, 2015 <font color="red">(release scheduled)</font></b></p>
    47     47       <ul>
    48     48         <li>Updated to <a href="https://www.sqlite.org/releaselog/3_9_2.html">SQLite 3.9.2</a>.</li>
           49  +      <li>Add preliminary support for the .NET Framework 4.6.1.</li>
           50  +      <li>Fix virtual table handling of sqlite3_index_info members not available with older versions of the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    49     51         <li>Update and improve documentation comments for the native virtual table methods.</li>
    50     52         <li>Permit an existing registered function to be replaced. Fix for <a href="https://system.data.sqlite.org/index.html/info/2556655d1b">[2556655d1b]</a>.</li>
    51     53         <li>Make GetValue work for boolean columns with textual &quot;True&quot; and &quot;False&quot; values. Fix for <a href="https://system.data.sqlite.org/index.html/info/7714b60d61">[7714b60d61]</a>.</li>
    52     54         <li>Add Reset method to the SQLiteCommand class.</li>
    53     55         <li>Add FileName property to the SQLiteConnection class.</li>
    54     56         <li>Add experimental support for the native json1 and fts5 extensions.</li>
    55     57         <li>Add GetDatabaseName, GetTableName, and GetOriginalName methods to the SQLiteDataReader class.</li>

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

  1041   1041           ///////////////////////////////////////////////////////////////////////
  1042   1042   
  1043   1043           /// <summary>
  1044   1044           /// Determines if the native flags field can be used, based on the
  1045   1045           /// available version of the SQLite core library.
  1046   1046           /// </summary>
  1047   1047           /// <returns>
  1048         -        /// Non-zero if the <see cref="IdxFlags" /> property is supported by
         1048  +        /// Non-zero if the <see cref="IndexFlags" /> property is supported by
  1049   1049           /// the SQLite core library.
  1050   1050           /// </returns>
  1051         -        public bool CanUseIdxFlags()
         1051  +        public bool CanUseIndexFlags()
  1052   1052           {
  1053   1053               if (UnsafeNativeMethods.sqlite3_libversion_number() >= 3009000)
  1054   1054                   return true;
  1055   1055   
  1056   1056               return false;
  1057   1057           }
  1058   1058   
................................................................................
  1059   1059           ///////////////////////////////////////////////////////////////////////
  1060   1060   
  1061   1061           /// <summary>
  1062   1062           /// Determines if the native flags field can be used, based on the
  1063   1063           /// available version of the SQLite core library.
  1064   1064           /// </summary>
  1065   1065           /// <returns>
  1066         -        /// Non-zero if the <see cref="ColUsed" /> property is supported by
         1066  +        /// Non-zero if the <see cref="ColumnsUsed" /> property is supported by
  1067   1067           /// the SQLite core library.
  1068   1068           /// </returns>
  1069         -        public bool CanUseColUsed()
         1069  +        public bool CanUseColumnsUsed()
  1070   1070           {
  1071   1071               if (UnsafeNativeMethods.sqlite3_libversion_number() >= 3010000)
  1072   1072                   return true;
  1073   1073   
  1074   1074               return false;
  1075   1075           }
  1076   1076   
................................................................................
  1167   1167           {
  1168   1168               get { return estimatedRows; }
  1169   1169               set { estimatedRows = value; }
  1170   1170           }
  1171   1171   
  1172   1172           ///////////////////////////////////////////////////////////////////////
  1173   1173   
  1174         -        private SQLiteIndexFlags? idxFlags;
         1174  +        private SQLiteIndexFlags? indexFlags;
  1175   1175           /// <summary>
  1176   1176           /// The flags that should be used with this index.  Using a null value
  1177   1177           /// here indicates that a default flags value should be used.  This
  1178   1178           /// property has no effect if the SQLite core library is not at least
  1179   1179           /// version 3.9.0.
  1180   1180           /// </summary>
  1181         -        public SQLiteIndexFlags? IdxFlags
  1182         -        {
  1183         -            get { return idxFlags; }
  1184         -            set { idxFlags = value; }
  1185         -        }
  1186         -
  1187         -        ///////////////////////////////////////////////////////////////////////
  1188         -
  1189         -        private long? colUsed;
  1190         -        /// <summary>
  1191         -        /// The colUsed field indicates which columns of the virtual table
  1192         -        /// may be required by the current scan.  Virtual table columns are
  1193         -        /// numbered from zero in the order in which they appear within the
  1194         -        /// CREATE TABLE statement passed to sqlite3_declare_vtab().  For the
  1195         -        /// first 63 columns (columns 0-62), the corresponding bit is set
  1196         -        /// within the colUsed mask if the column may be required by SQLite.
  1197         -        /// If the table has at least 64 columns and any column to the right
  1198         -        /// of the first 63 is required, then bit 63 of colUsed is also set.
  1199         -        /// In other words, column iCol may be required if the expression
  1200         -        /// (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol)))
         1181  +        public SQLiteIndexFlags? IndexFlags
         1182  +        {
         1183  +            get { return indexFlags; }
         1184  +            set { indexFlags = value; }
         1185  +        }
         1186  +
         1187  +        ///////////////////////////////////////////////////////////////////////
         1188  +
         1189  +        private long? columnsUsed;
         1190  +        /// <summary>
         1191  +        /// <para>
         1192  +        /// Indicates which columns of the virtual table may be required by the
         1193  +        /// current scan.  Virtual table columns are numbered from zero in the
         1194  +        /// order in which they appear within the CREATE TABLE statement passed
         1195  +        /// to sqlite3_declare_vtab().  For the first 63 columns (columns 0-62),
         1196  +        /// the corresponding bit is set within the bit mask if the column may
         1197  +        /// be required by SQLite.  If the table has at least 64 columns and
         1198  +        /// any column to the right of the first 63 is required, then bit 63 of
         1199  +        /// colUsed is also set.  In other words, column iCol may be required
         1200  +        /// if the expression
         1201  +        /// </para>
         1202  +        /// <para><code>
         1203  +        /// (colUsed &amp; ((sqlite3_uint64)1 &lt;&lt; (iCol&gt;=63 ? 63 : iCol)))
         1204  +        /// </code></para>
         1205  +        /// <para>
  1201   1206           /// evaluates to non-zero.  Using a null value here indicates that a
  1202         -        /// default flags value should be used.  This property has no effect
  1203         -        /// if the SQLite core library is not at least version 3.10.0.
         1207  +        /// default flags value should be used.  This property has no effect if
         1208  +        /// the SQLite core library is not at least version 3.10.0.
         1209  +        /// </para>
  1204   1210           /// </summary>
  1205         -        public long? ColUsed
         1211  +        public long? ColumnsUsed
  1206   1212           {
  1207         -            get { return colUsed; }
  1208         -            set { colUsed = value; }
         1213  +            get { return columnsUsed; }
         1214  +            set { columnsUsed = value; }
  1209   1215           }
  1210   1216           #endregion
  1211   1217       }
  1212   1218       #endregion
  1213   1219   
  1214   1220       ///////////////////////////////////////////////////////////////////////////
  1215   1221   
................................................................................
  1241   1247               inputs = new SQLiteIndexInputs(nConstraint, nOrderBy);
  1242   1248               outputs = new SQLiteIndexOutputs(nConstraint);
  1243   1249           }
  1244   1250           #endregion
  1245   1251   
  1246   1252           ///////////////////////////////////////////////////////////////////////
  1247   1253   
         1254  +        #region Private Marshal Helper Methods (For Test Use Only)
         1255  +        /// <summary>
         1256  +        /// Attempts to determine the structure sizes needed to create and
         1257  +        /// populate a native
         1258  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_info" />
         1259  +        /// structure.
         1260  +        /// </summary>
         1261  +        /// <param name="sizeOfInfoType">
         1262  +        /// The size of the native
         1263  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_info" />
         1264  +        /// structure is stored here.
         1265  +        /// </param>
         1266  +        /// <param name="sizeOfConstraintType">
         1267  +        /// The size of the native
         1268  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_constraint" />
         1269  +        /// structure is stored here.
         1270  +        /// </param>
         1271  +        /// <param name="sizeOfOrderByType">
         1272  +        /// The size of the native
         1273  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_orderby" />
         1274  +        /// structure is stored here.
         1275  +        /// </param>
         1276  +        /// <param name="sizeOfConstraintUsageType">
         1277  +        /// The size of the native
         1278  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_constraint_usage" />
         1279  +        /// structure is stored here.
         1280  +        /// </param>
         1281  +        private static void SizeOfNative(
         1282  +            out int sizeOfInfoType,
         1283  +            out int sizeOfConstraintType,
         1284  +            out int sizeOfOrderByType,
         1285  +            out int sizeOfConstraintUsageType
         1286  +            )
         1287  +        {
         1288  +            sizeOfInfoType = Marshal.SizeOf(typeof(
         1289  +                UnsafeNativeMethods.sqlite3_index_info));
         1290  +
         1291  +            sizeOfConstraintType = Marshal.SizeOf(typeof(
         1292  +                UnsafeNativeMethods.sqlite3_index_constraint));
         1293  +
         1294  +            sizeOfOrderByType = Marshal.SizeOf(typeof(
         1295  +                UnsafeNativeMethods.sqlite3_index_orderby));
         1296  +
         1297  +            sizeOfConstraintUsageType = Marshal.SizeOf(typeof(
         1298  +                UnsafeNativeMethods.sqlite3_index_constraint_usage));
         1299  +        }
         1300  +
         1301  +        ///////////////////////////////////////////////////////////////////////
         1302  +
         1303  +        /// <summary>
         1304  +        /// Attempts to allocate and initialize a native
         1305  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_info" />
         1306  +        /// structure.
         1307  +        /// </summary>
         1308  +        /// <param name="nConstraint">
         1309  +        /// The number of <see cref="SQLiteIndexConstraint" /> instances to
         1310  +        /// pre-allocate space for.
         1311  +        /// </param>
         1312  +        /// <param name="nOrderBy">
         1313  +        /// The number of <see cref="SQLiteIndexOrderBy" /> instances to
         1314  +        /// pre-allocate space for.
         1315  +        /// </param>
         1316  +        /// <returns>
         1317  +        /// The newly allocated native
         1318  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_info" /> structure
         1319  +        /// -OR- <see cref="IntPtr.Zero" /> if it could not be fully allocated.
         1320  +        /// </returns>
         1321  +        private static IntPtr AllocateAndInitializeNative(
         1322  +            int nConstraint,
         1323  +            int nOrderBy
         1324  +            )
         1325  +        {
         1326  +            IntPtr pIndex = IntPtr.Zero;
         1327  +            IntPtr pInfo = IntPtr.Zero;
         1328  +            IntPtr pConstraint = IntPtr.Zero;
         1329  +            IntPtr pOrderBy = IntPtr.Zero;
         1330  +            IntPtr pConstraintUsage = IntPtr.Zero;
         1331  +
         1332  +            try
         1333  +            {
         1334  +                int sizeOfInfoType;
         1335  +                int sizeOfOrderByType;
         1336  +                int sizeOfConstraintType;
         1337  +                int sizeOfConstraintUsageType;
         1338  +
         1339  +                SizeOfNative(out sizeOfInfoType, out sizeOfConstraintType,
         1340  +                    out sizeOfOrderByType, out sizeOfConstraintUsageType);
         1341  +
         1342  +                if ((sizeOfInfoType > 0) &&
         1343  +                    (sizeOfConstraintType > 0) &&
         1344  +                    (sizeOfOrderByType > 0) &&
         1345  +                    (sizeOfConstraintUsageType > 0))
         1346  +                {
         1347  +                    pInfo = SQLiteMemory.Allocate(sizeOfInfoType);
         1348  +
         1349  +                    pConstraint = SQLiteMemory.Allocate(
         1350  +                        sizeOfConstraintType * nConstraint);
         1351  +
         1352  +                    pOrderBy = SQLiteMemory.Allocate(
         1353  +                        sizeOfOrderByType * nOrderBy);
         1354  +
         1355  +                    pConstraintUsage = SQLiteMemory.Allocate(
         1356  +                        sizeOfConstraintUsageType * nConstraint);
         1357  +
         1358  +                    if ((pInfo != IntPtr.Zero) &&
         1359  +                        (pConstraint != IntPtr.Zero) &&
         1360  +                        (pOrderBy != IntPtr.Zero) &&
         1361  +                        (pConstraintUsage != IntPtr.Zero))
         1362  +                    {
         1363  +                        int offset = 0;
         1364  +
         1365  +                        SQLiteMarshal.WriteInt32(
         1366  +                            pInfo, offset, nConstraint);
         1367  +
         1368  +                        offset = SQLiteMarshal.NextOffsetOf(
         1369  +                            offset, sizeof(int), IntPtr.Size);
         1370  +
         1371  +                        SQLiteMarshal.WriteIntPtr(
         1372  +                            pInfo, offset, pConstraint);
         1373  +
         1374  +                        offset = SQLiteMarshal.NextOffsetOf(
         1375  +                            offset, IntPtr.Size, sizeof(int));
         1376  +
         1377  +                        SQLiteMarshal.WriteInt32(
         1378  +                            pInfo, offset, nOrderBy);
         1379  +
         1380  +                        offset = SQLiteMarshal.NextOffsetOf(
         1381  +                            offset, sizeof(int), IntPtr.Size);
         1382  +
         1383  +                        SQLiteMarshal.WriteIntPtr(
         1384  +                            pInfo, offset, pOrderBy);
         1385  +
         1386  +                        offset = SQLiteMarshal.NextOffsetOf(
         1387  +                            offset, IntPtr.Size, IntPtr.Size);
         1388  +
         1389  +                        SQLiteMarshal.WriteIntPtr(
         1390  +                            pInfo, offset, pConstraintUsage);
         1391  +
         1392  +                        pIndex = pInfo; /* NOTE: Success. */
         1393  +                    }
         1394  +                }
         1395  +            }
         1396  +            finally
         1397  +            {
         1398  +                if (pIndex == IntPtr.Zero) /* NOTE: Failure? */
         1399  +                {
         1400  +                    if (pConstraintUsage != IntPtr.Zero)
         1401  +                    {
         1402  +                        SQLiteMemory.Free(pConstraintUsage);
         1403  +                        pConstraintUsage = IntPtr.Zero;
         1404  +                    }
         1405  +
         1406  +                    if (pOrderBy != IntPtr.Zero)
         1407  +                    {
         1408  +                        SQLiteMemory.Free(pOrderBy);
         1409  +                        pOrderBy = IntPtr.Zero;
         1410  +                    }
         1411  +
         1412  +                    if (pConstraint != IntPtr.Zero)
         1413  +                    {
         1414  +                        SQLiteMemory.Free(pConstraint);
         1415  +                        pConstraint = IntPtr.Zero;
         1416  +                    }
         1417  +
         1418  +                    if (pInfo != IntPtr.Zero)
         1419  +                    {
         1420  +                        SQLiteMemory.Free(pInfo);
         1421  +                        pInfo = IntPtr.Zero;
         1422  +                    }
         1423  +                }
         1424  +            }
         1425  +
         1426  +            return pIndex;
         1427  +        }
         1428  +
         1429  +        ///////////////////////////////////////////////////////////////////////
         1430  +
         1431  +        /// <summary>
         1432  +        /// Frees all the memory associated with a native
         1433  +        /// <see cref="UnsafeNativeMethods.sqlite3_index_info" />
         1434  +        /// structure.
         1435  +        /// </summary>
         1436  +        /// <param name="pIndex">
         1437  +        /// The native pointer to the native sqlite3_index_info structure to
         1438  +        /// free.
         1439  +        /// </param>
         1440  +        private static void FreeNative(
         1441  +            IntPtr pIndex
         1442  +            )
         1443  +        {
         1444  +            if (pIndex == IntPtr.Zero)
         1445  +                return;
         1446  +
         1447  +            int offset = 0;
         1448  +
         1449  +            offset = SQLiteMarshal.NextOffsetOf(
         1450  +                offset, sizeof(int), IntPtr.Size);
         1451  +
         1452  +            IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(
         1453  +                pIndex, offset);
         1454  +
         1455  +            offset = SQLiteMarshal.NextOffsetOf(
         1456  +                offset, IntPtr.Size, sizeof(int));
         1457  +
         1458  +            offset = SQLiteMarshal.NextOffsetOf(
         1459  +                offset, sizeof(int), IntPtr.Size);
         1460  +
         1461  +            IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(
         1462  +                pIndex, offset);
         1463  +
         1464  +            offset = SQLiteMarshal.NextOffsetOf(
         1465  +                offset, IntPtr.Size, IntPtr.Size);
         1466  +
         1467  +            IntPtr pConstraintUsage = SQLiteMarshal.ReadIntPtr(
         1468  +                pIndex, offset);
         1469  +
         1470  +            if (pConstraintUsage != IntPtr.Zero)
         1471  +            {
         1472  +                SQLiteMemory.Free(pConstraintUsage);
         1473  +                pConstraintUsage = IntPtr.Zero;
         1474  +            }
         1475  +
         1476  +            if (pOrderBy != IntPtr.Zero)
         1477  +            {
         1478  +                SQLiteMemory.Free(pOrderBy);
         1479  +                pOrderBy = IntPtr.Zero;
         1480  +            }
         1481  +
         1482  +            if (pConstraint != IntPtr.Zero)
         1483  +            {
         1484  +                SQLiteMemory.Free(pConstraint);
         1485  +                pConstraint = IntPtr.Zero;
         1486  +            }
         1487  +
         1488  +            if (pIndex != IntPtr.Zero)
         1489  +            {
         1490  +                SQLiteMemory.Free(pIndex);
         1491  +                pIndex = IntPtr.Zero;
         1492  +            }
         1493  +        }
         1494  +        #endregion
         1495  +
         1496  +        ///////////////////////////////////////////////////////////////////////
         1497  +
  1248   1498           #region Internal Marshal Helper Methods
  1249   1499           /// <summary>
  1250   1500           /// Converts a native pointer to a native sqlite3_index_info structure
  1251   1501           /// into a new <see cref="SQLiteIndex" /> object instance.
  1252   1502           /// </summary>
  1253   1503           /// <param name="pIndex">
  1254   1504           /// The native pointer to the native sqlite3_index_info structure to
  1255   1505           /// convert.
  1256   1506           /// </param>
         1507  +        /// <param name="includeOutput">
         1508  +        /// Non-zero to include fields from the outputs portion of the native
         1509  +        /// structure; otherwise, the "output" fields will not be read.
         1510  +        /// </param>
  1257   1511           /// <param name="index">
  1258   1512           /// Upon success, this parameter will be modified to contain the newly
  1259   1513           /// created <see cref="SQLiteIndex" /> object instance.
  1260   1514           /// </param>
  1261   1515           internal static void FromIntPtr(
  1262   1516               IntPtr pIndex,
         1517  +            bool includeOutput,
  1263   1518               ref SQLiteIndex index
  1264   1519               )
  1265   1520           {
  1266   1521               if (pIndex == IntPtr.Zero)
  1267   1522                   return;
  1268   1523   
  1269   1524               int offset = 0;
  1270   1525   
  1271         -            int nConstraint = SQLiteMarshal.ReadInt32(pIndex, offset);
  1272         -
  1273         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1274         -                IntPtr.Size);
  1275         -
  1276         -            IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(pIndex, offset);
  1277         -
  1278         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  1279         -                sizeof(int));
  1280         -
  1281         -            int nOrderBy = SQLiteMarshal.ReadInt32(pIndex, offset);
  1282         -
  1283         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1284         -                IntPtr.Size);
  1285         -
  1286         -            IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(pIndex, offset);
         1526  +            int nConstraint = SQLiteMarshal.ReadInt32(
         1527  +                pIndex, offset);
         1528  +
         1529  +            offset = SQLiteMarshal.NextOffsetOf(
         1530  +                offset, sizeof(int), IntPtr.Size);
         1531  +
         1532  +            IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(
         1533  +                pIndex, offset);
         1534  +
         1535  +            offset = SQLiteMarshal.NextOffsetOf(
         1536  +                offset, IntPtr.Size, sizeof(int));
         1537  +
         1538  +            int nOrderBy = SQLiteMarshal.ReadInt32(
         1539  +                pIndex, offset);
         1540  +
         1541  +            offset = SQLiteMarshal.NextOffsetOf(
         1542  +                offset, sizeof(int), IntPtr.Size);
         1543  +
         1544  +            IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(
         1545  +                pIndex, offset);
         1546  +
         1547  +            IntPtr pConstraintUsage = IntPtr.Zero;
         1548  +
         1549  +            if (includeOutput)
         1550  +            {
         1551  +                offset = SQLiteMarshal.NextOffsetOf(
         1552  +                    offset, IntPtr.Size, IntPtr.Size);
         1553  +
         1554  +                pConstraintUsage = SQLiteMarshal.ReadIntPtr(
         1555  +                    pIndex, offset);
         1556  +            }
  1287   1557   
  1288   1558               index = new SQLiteIndex(nConstraint, nOrderBy);
         1559  +            SQLiteIndexInputs inputs = index.Inputs;
  1289   1560   
  1290         -            Type indexConstraintType = typeof(
         1561  +            if (inputs == null)
         1562  +                return;
         1563  +
         1564  +            SQLiteIndexConstraint[] constraints = inputs.Constraints;
         1565  +
         1566  +            if (constraints == null)
         1567  +                return;
         1568  +
         1569  +            SQLiteIndexOrderBy[] orderBys = inputs.OrderBys;
         1570  +
         1571  +            if (orderBys == null)
         1572  +                return;
         1573  +
         1574  +            Type constraintType = typeof(
  1291   1575                   UnsafeNativeMethods.sqlite3_index_constraint);
  1292   1576   
  1293         -            int sizeOfConstraintType = Marshal.SizeOf(indexConstraintType);
         1577  +            int sizeOfConstraintType = Marshal.SizeOf(
         1578  +                constraintType);
  1294   1579   
  1295   1580               for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
  1296   1581               {
  1297   1582                   IntPtr pOffset = SQLiteMarshal.IntPtrForOffset(
  1298   1583                       pConstraint, iConstraint * sizeOfConstraintType);
  1299   1584   
  1300   1585                   UnsafeNativeMethods.sqlite3_index_constraint constraint =
  1301   1586                       (UnsafeNativeMethods.sqlite3_index_constraint)
  1302         -                        Marshal.PtrToStructure(pOffset, indexConstraintType);
         1587  +                        Marshal.PtrToStructure(pOffset, constraintType);
  1303   1588   
  1304         -                index.Inputs.Constraints[iConstraint] =
  1305         -                    new SQLiteIndexConstraint(constraint);
         1589  +                constraints[iConstraint] = new SQLiteIndexConstraint(
         1590  +                    constraint);
  1306   1591               }
  1307   1592   
  1308         -            Type indexOrderByType = typeof(
         1593  +            Type orderByType = typeof(
  1309   1594                   UnsafeNativeMethods.sqlite3_index_orderby);
  1310   1595   
  1311         -            int sizeOfOrderByType = Marshal.SizeOf(indexOrderByType);
         1596  +            int sizeOfOrderByType = Marshal.SizeOf(orderByType);
  1312   1597   
  1313   1598               for (int iOrderBy = 0; iOrderBy < nOrderBy; iOrderBy++)
  1314   1599               {
  1315   1600                   IntPtr pOffset = SQLiteMarshal.IntPtrForOffset(
  1316   1601                       pOrderBy, iOrderBy * sizeOfOrderByType);
  1317   1602   
  1318   1603                   UnsafeNativeMethods.sqlite3_index_orderby orderBy =
  1319   1604                       (UnsafeNativeMethods.sqlite3_index_orderby)
  1320         -                        Marshal.PtrToStructure(pOffset, indexOrderByType);
         1605  +                        Marshal.PtrToStructure(pOffset, orderByType);
  1321   1606   
  1322         -                index.Inputs.OrderBys[iOrderBy] =
  1323         -                    new SQLiteIndexOrderBy(orderBy);
         1607  +                orderBys[iOrderBy] = new SQLiteIndexOrderBy(orderBy);
         1608  +            }
         1609  +
         1610  +            if (includeOutput)
         1611  +            {
         1612  +                SQLiteIndexOutputs outputs = index.Outputs;
         1613  +
         1614  +                if (outputs == null)
         1615  +                    return;
         1616  +
         1617  +                SQLiteIndexConstraintUsage[] constraintUsages =
         1618  +                    outputs.ConstraintUsages;
         1619  +
         1620  +                if (constraintUsages == null)
         1621  +                    return;
         1622  +
         1623  +                Type constraintUsageType = typeof(
         1624  +                    UnsafeNativeMethods.sqlite3_index_constraint_usage);
         1625  +
         1626  +                int sizeOfConstraintUsageType = Marshal.SizeOf(
         1627  +                    constraintUsageType);
         1628  +
         1629  +                for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
         1630  +                {
         1631  +                    IntPtr pOffset = SQLiteMarshal.IntPtrForOffset(
         1632  +                        pConstraintUsage, iConstraint * sizeOfConstraintUsageType);
         1633  +
         1634  +                    UnsafeNativeMethods.sqlite3_index_constraint_usage constraintUsage =
         1635  +                        (UnsafeNativeMethods.sqlite3_index_constraint_usage)
         1636  +                            Marshal.PtrToStructure(pOffset, constraintUsageType);
         1637  +
         1638  +                    constraintUsages[iConstraint] = new SQLiteIndexConstraintUsage(
         1639  +                        constraintUsage);
         1640  +                }
         1641  +
         1642  +                offset = SQLiteMarshal.NextOffsetOf(
         1643  +                    offset, IntPtr.Size, sizeof(int));
         1644  +
         1645  +                outputs.IndexNumber = SQLiteMarshal.ReadInt32(
         1646  +                    pIndex, offset);
         1647  +
         1648  +                offset = SQLiteMarshal.NextOffsetOf(
         1649  +                    offset, sizeof(int), IntPtr.Size);
         1650  +
         1651  +                outputs.IndexString = SQLiteString.StringFromUtf8IntPtr(
         1652  +                    SQLiteMarshal.ReadIntPtr(pIndex, offset));
         1653  +
         1654  +                offset = SQLiteMarshal.NextOffsetOf(
         1655  +                    offset, IntPtr.Size, sizeof(int));
         1656  +
         1657  +                outputs.NeedToFreeIndexString = SQLiteMarshal.ReadInt32(
         1658  +                    pIndex, offset);
         1659  +
         1660  +                offset = SQLiteMarshal.NextOffsetOf(
         1661  +                    offset, sizeof(int), sizeof(int));
         1662  +
         1663  +                outputs.OrderByConsumed = SQLiteMarshal.ReadInt32(
         1664  +                    pIndex, offset);
         1665  +
         1666  +                offset = SQLiteMarshal.NextOffsetOf(
         1667  +                    offset, sizeof(int), sizeof(double));
         1668  +
         1669  +                outputs.EstimatedCost = SQLiteMarshal.ReadDouble(
         1670  +                    pIndex, offset);
         1671  +
         1672  +                offset = SQLiteMarshal.NextOffsetOf(
         1673  +                    offset, sizeof(double), sizeof(long));
         1674  +
         1675  +                if (outputs.CanUseEstimatedRows())
         1676  +                {
         1677  +                    outputs.EstimatedRows = SQLiteMarshal.ReadInt64(
         1678  +                        pIndex, offset);
         1679  +                }
         1680  +
         1681  +                offset = SQLiteMarshal.NextOffsetOf(
         1682  +                    offset, sizeof(long), sizeof(int));
         1683  +
         1684  +                if (outputs.CanUseIndexFlags())
         1685  +                {
         1686  +                    outputs.IndexFlags = (SQLiteIndexFlags)
         1687  +                        SQLiteMarshal.ReadInt32(pIndex, offset);
         1688  +                }
         1689  +
         1690  +                offset = SQLiteMarshal.NextOffsetOf(
         1691  +                    offset, sizeof(int), sizeof(long));
         1692  +
         1693  +                if (outputs.CanUseColumnsUsed())
         1694  +                {
         1695  +                    outputs.ColumnsUsed = SQLiteMarshal.ReadInt64(
         1696  +                        pIndex, offset);
         1697  +                }
  1324   1698               }
  1325   1699           }
  1326   1700   
  1327   1701           ///////////////////////////////////////////////////////////////////////
  1328   1702   
  1329   1703           /// <summary>
  1330   1704           /// Populates the outputs of a pre-allocated native sqlite3_index_info
................................................................................
  1335   1709           /// The existing <see cref="SQLiteIndex" /> object instance containing
  1336   1710           /// the output data to use.
  1337   1711           /// </param>
  1338   1712           /// <param name="pIndex">
  1339   1713           /// The native pointer to the pre-allocated native sqlite3_index_info
  1340   1714           /// structure.
  1341   1715           /// </param>
         1716  +        /// <param name="includeInput">
         1717  +        /// Non-zero to include fields from the inputs portion of the native
         1718  +        /// structure; otherwise, the "input" fields will not be written.
         1719  +        /// </param>
  1342   1720           internal static void ToIntPtr(
  1343   1721               SQLiteIndex index,
  1344         -            IntPtr pIndex
         1722  +            IntPtr pIndex,
         1723  +            bool includeInput
  1345   1724               )
  1346   1725           {
  1347         -            if ((index == null) || (index.Inputs == null) ||
  1348         -                (index.Inputs.Constraints == null) ||
  1349         -                (index.Outputs == null) ||
  1350         -                (index.Outputs.ConstraintUsages == null))
  1351         -            {
         1726  +            if (index == null)
         1727  +                return;
         1728  +
         1729  +            SQLiteIndexOutputs outputs = index.Outputs;
         1730  +
         1731  +            if (outputs == null)
         1732  +                return;
         1733  +
         1734  +            SQLiteIndexConstraintUsage[] constraintUsages =
         1735  +                outputs.ConstraintUsages;
         1736  +
         1737  +            if (constraintUsages == null)
  1352   1738                   return;
         1739  +
         1740  +            SQLiteIndexInputs inputs = null;
         1741  +            SQLiteIndexConstraint[] constraints = null;
         1742  +            SQLiteIndexOrderBy[] orderBys = null;
         1743  +
         1744  +            if (includeInput)
         1745  +            {
         1746  +                inputs = index.Inputs;
         1747  +
         1748  +                if (inputs == null)
         1749  +                    return;
         1750  +
         1751  +                constraints = inputs.Constraints;
         1752  +
         1753  +                if (constraints == null)
         1754  +                    return;
         1755  +
         1756  +                orderBys = inputs.OrderBys;
         1757  +
         1758  +                if (orderBys == null)
         1759  +                    return;
  1353   1760               }
  1354   1761   
  1355   1762               if (pIndex == IntPtr.Zero)
  1356   1763                   return;
  1357   1764   
  1358   1765               int offset = 0;
  1359   1766   
  1360   1767               int nConstraint = SQLiteMarshal.ReadInt32(pIndex, offset);
  1361   1768   
  1362         -            if (nConstraint != index.Inputs.Constraints.Length)
         1769  +            if (includeInput && (nConstraint != constraints.Length))
         1770  +                return;
         1771  +
         1772  +            if (nConstraint != constraintUsages.Length)
  1363   1773                   return;
  1364   1774   
  1365         -            if (nConstraint != index.Outputs.ConstraintUsages.Length)
         1775  +            offset = SQLiteMarshal.NextOffsetOf(
         1776  +                offset, sizeof(int), IntPtr.Size);
         1777  +
         1778  +            if (includeInput)
         1779  +            {
         1780  +                IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(
         1781  +                    pIndex, offset);
         1782  +
         1783  +                int sizeOfConstraintType = Marshal.SizeOf(typeof(
         1784  +                    UnsafeNativeMethods.sqlite3_index_constraint));
         1785  +
         1786  +                for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
         1787  +                {
         1788  +                    UnsafeNativeMethods.sqlite3_index_constraint constraint =
         1789  +                        new UnsafeNativeMethods.sqlite3_index_constraint(
         1790  +                            constraints[iConstraint]);
         1791  +
         1792  +                    Marshal.StructureToPtr(
         1793  +                        constraint, SQLiteMarshal.IntPtrForOffset(
         1794  +                        pConstraint, iConstraint * sizeOfConstraintType),
         1795  +                        false);
         1796  +                }
         1797  +            }
         1798  +
         1799  +            offset = SQLiteMarshal.NextOffsetOf(
         1800  +                offset, IntPtr.Size, sizeof(int));
         1801  +
         1802  +            int nOrderBy = includeInput ?
         1803  +                SQLiteMarshal.ReadInt32(pIndex, offset) : 0;
         1804  +
         1805  +            if (includeInput && (nOrderBy != orderBys.Length))
  1366   1806                   return;
  1367   1807   
  1368         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1369         -                IntPtr.Size);
         1808  +            offset = SQLiteMarshal.NextOffsetOf(
         1809  +                offset, sizeof(int), IntPtr.Size);
  1370   1810   
  1371         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  1372         -                sizeof(int));
         1811  +            if (includeInput)
         1812  +            {
         1813  +                IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(pIndex, offset);
  1373   1814   
  1374         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1375         -                IntPtr.Size);
         1815  +                int sizeOfOrderByType = Marshal.SizeOf(typeof(
         1816  +                    UnsafeNativeMethods.sqlite3_index_orderby));
  1376   1817   
  1377         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  1378         -                sizeof(int));
         1818  +                for (int iOrderBy = 0; iOrderBy < nOrderBy; iOrderBy++)
         1819  +                {
         1820  +                    UnsafeNativeMethods.sqlite3_index_orderby orderBy =
         1821  +                        new UnsafeNativeMethods.sqlite3_index_orderby(
         1822  +                            orderBys[iOrderBy]);
  1379   1823   
  1380         -            IntPtr pConstraintUsage = SQLiteMarshal.ReadIntPtr(pIndex, offset);
         1824  +                    Marshal.StructureToPtr(
         1825  +                        orderBy, SQLiteMarshal.IntPtrForOffset(
         1826  +                        pOrderBy, iOrderBy * sizeOfOrderByType),
         1827  +                        false);
         1828  +                }
         1829  +            }
         1830  +
         1831  +            offset = SQLiteMarshal.NextOffsetOf(
         1832  +                offset, IntPtr.Size, IntPtr.Size);
         1833  +
         1834  +            IntPtr pConstraintUsage = SQLiteMarshal.ReadIntPtr(
         1835  +                pIndex, offset);
  1381   1836   
  1382   1837               int sizeOfConstraintUsageType = Marshal.SizeOf(typeof(
  1383   1838                   UnsafeNativeMethods.sqlite3_index_constraint_usage));
  1384   1839   
  1385   1840               for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++)
  1386   1841               {
  1387   1842                   UnsafeNativeMethods.sqlite3_index_constraint_usage constraintUsage =
  1388   1843                       new UnsafeNativeMethods.sqlite3_index_constraint_usage(
  1389         -                        index.Outputs.ConstraintUsages[iConstraint]);
         1844  +                        constraintUsages[iConstraint]);
  1390   1845   
  1391   1846                   Marshal.StructureToPtr(
  1392   1847                       constraintUsage, SQLiteMarshal.IntPtrForOffset(
  1393   1848                       pConstraintUsage, iConstraint * sizeOfConstraintUsageType),
  1394   1849                       false);
  1395   1850               }
  1396   1851   
  1397         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  1398         -                sizeof(int));
         1852  +            offset = SQLiteMarshal.NextOffsetOf(
         1853  +                offset, IntPtr.Size, sizeof(int));
  1399   1854   
  1400   1855               SQLiteMarshal.WriteInt32(pIndex, offset,
  1401         -                index.Outputs.IndexNumber);
         1856  +                outputs.IndexNumber);
  1402   1857   
  1403         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1404         -                IntPtr.Size);
         1858  +            offset = SQLiteMarshal.NextOffsetOf(
         1859  +                offset, sizeof(int), IntPtr.Size);
  1405   1860   
  1406   1861               SQLiteMarshal.WriteIntPtr(pIndex, offset,
  1407         -                SQLiteString.Utf8IntPtrFromString(index.Outputs.IndexString));
         1862  +                SQLiteString.Utf8IntPtrFromString(outputs.IndexString));
  1408   1863   
  1409         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  1410         -                sizeof(int));
         1864  +            offset = SQLiteMarshal.NextOffsetOf(
         1865  +                offset, IntPtr.Size, sizeof(int));
  1411   1866   
  1412   1867               //
  1413   1868               // NOTE: We just allocated the IndexString field; therefore, we
  1414         -            //       need to set the NeedToFreeIndexString field to non-zero.
         1869  +            //       need to set make sure the NeedToFreeIndexString field
         1870  +            //       is non-zero; however, we are not picky about the exact
         1871  +            //       value.
  1415   1872               //
  1416         -            SQLiteMarshal.WriteInt32(pIndex, offset, 1);
         1873  +            int needToFreeIndexString = outputs.NeedToFreeIndexString != 0 ?
         1874  +                outputs.NeedToFreeIndexString : 1;
  1417   1875   
  1418         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1419         -                sizeof(int));
         1876  +            SQLiteMarshal.WriteInt32(pIndex, offset,
         1877  +                needToFreeIndexString);
         1878  +
         1879  +            offset = SQLiteMarshal.NextOffsetOf(
         1880  +                offset, sizeof(int), sizeof(int));
  1420   1881   
  1421   1882               SQLiteMarshal.WriteInt32(pIndex, offset,
  1422         -                index.Outputs.OrderByConsumed);
         1883  +                outputs.OrderByConsumed);
  1423   1884   
  1424         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1425         -                sizeof(double));
         1885  +            offset = SQLiteMarshal.NextOffsetOf(
         1886  +                offset, sizeof(int), sizeof(double));
  1426   1887   
  1427         -            if (index.Outputs.EstimatedCost.HasValue)
         1888  +            if (outputs.EstimatedCost.HasValue)
  1428   1889               {
  1429   1890                   SQLiteMarshal.WriteDouble(pIndex, offset,
  1430         -                    index.Outputs.EstimatedCost.GetValueOrDefault());
         1891  +                    outputs.EstimatedCost.GetValueOrDefault());
  1431   1892               }
  1432   1893   
  1433         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(double),
  1434         -                sizeof(long));
         1894  +            offset = SQLiteMarshal.NextOffsetOf(
         1895  +                offset, sizeof(double), sizeof(long));
  1435   1896   
  1436         -            if (index.Outputs.CanUseEstimatedRows() &&
  1437         -                index.Outputs.EstimatedRows.HasValue)
         1897  +            if (outputs.CanUseEstimatedRows() &&
         1898  +                outputs.EstimatedRows.HasValue)
  1438   1899               {
  1439   1900                   SQLiteMarshal.WriteInt64(pIndex, offset,
  1440         -                    index.Outputs.EstimatedRows.GetValueOrDefault());
         1901  +                    outputs.EstimatedRows.GetValueOrDefault());
  1441   1902               }
  1442   1903   
  1443         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(long),
  1444         -                sizeof(int));
         1904  +            offset = SQLiteMarshal.NextOffsetOf(
         1905  +                offset, sizeof(long), sizeof(int));
  1445   1906   
  1446         -            if (index.Outputs.CanUseIdxFlags() &&
  1447         -                index.Outputs.IdxFlags.HasValue)
         1907  +            if (outputs.CanUseIndexFlags() &&
         1908  +                outputs.IndexFlags.HasValue)
  1448   1909               {
  1449   1910                   SQLiteMarshal.WriteInt32(pIndex, offset,
  1450         -                   (int)index.Outputs.IdxFlags.GetValueOrDefault());
         1911  +                   (int)outputs.IndexFlags.GetValueOrDefault());
  1451   1912               }
  1452   1913   
  1453         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  1454         -                sizeof(long));
         1914  +            offset = SQLiteMarshal.NextOffsetOf(
         1915  +                offset, sizeof(int), sizeof(long));
  1455   1916   
  1456         -            if (index.Outputs.CanUseColUsed() &&
  1457         -                index.Outputs.ColUsed.HasValue)
         1917  +            if (outputs.CanUseColumnsUsed() &&
         1918  +                outputs.ColumnsUsed.HasValue)
  1458   1919               {
  1459   1920                   SQLiteMarshal.WriteInt64(pIndex, offset,
  1460         -                    index.Outputs.ColUsed.GetValueOrDefault());
         1921  +                    outputs.ColumnsUsed.GetValueOrDefault());
  1461   1922               }
  1462   1923           }
  1463   1924           #endregion
  1464   1925   
  1465   1926           ///////////////////////////////////////////////////////////////////////
  1466   1927   
  1467   1928           #region Public Properties
................................................................................
  3277   3738           {
  3278   3739   #if !PLATFORM_COMPACTFRAMEWORK
  3279   3740               return Marshal.ReadInt32(pointer, offset);
  3280   3741   #else
  3281   3742               return Marshal.ReadInt32(IntPtrForOffset(pointer, offset));
  3282   3743   #endif
  3283   3744           }
         3745  +
         3746  +        ///////////////////////////////////////////////////////////////////////
         3747  +
         3748  +        /// <summary>
         3749  +        /// Reads a <see cref="Int64" /> value from the specified memory
         3750  +        /// location.
         3751  +        /// </summary>
         3752  +        /// <param name="pointer">
         3753  +        /// The <see cref="IntPtr" /> object instance representing the base
         3754  +        /// memory location.
         3755  +        /// </param>
         3756  +        /// <param name="offset">
         3757  +        /// The integer offset from the base memory location where the
         3758  +        /// <see cref="Int64" /> value to be read is located.
         3759  +        /// </param>
         3760  +        /// <returns>
         3761  +        /// The <see cref="Int64" /> value at the specified memory location.
         3762  +        /// </returns>
         3763  +        public static long ReadInt64(
         3764  +            IntPtr pointer,
         3765  +            int offset
         3766  +            )
         3767  +        {
         3768  +#if !PLATFORM_COMPACTFRAMEWORK
         3769  +            return Marshal.ReadInt64(pointer, offset);
         3770  +#else
         3771  +            return Marshal.ReadInt64(IntPtrForOffset(pointer, offset));
         3772  +#endif
         3773  +        }
  3284   3774   
  3285   3775           ///////////////////////////////////////////////////////////////////////
  3286   3776   
  3287   3777           /// <summary>
  3288   3778           /// Reads a <see cref="Double" /> value from the specified memory
  3289   3779           /// location.
  3290   3780           /// </summary>
................................................................................
  5139   5629               try
  5140   5630               {
  5141   5631                   if (pVtab == IntPtr.Zero)
  5142   5632                       return false;
  5143   5633   
  5144   5634                   int offset = 0;
  5145   5635   
  5146         -                offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  5147         -                    sizeof(int));
         5636  +                offset = SQLiteMarshal.NextOffsetOf(
         5637  +                    offset, IntPtr.Size, sizeof(int));
  5148   5638   
  5149         -                offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  5150         -                    IntPtr.Size);
         5639  +                offset = SQLiteMarshal.NextOffsetOf(
         5640  +                    offset, sizeof(int), IntPtr.Size);
  5151   5641   
  5152   5642                   IntPtr pOldError = SQLiteMarshal.ReadIntPtr(pVtab, offset);
  5153   5643   
  5154   5644                   if (pOldError != IntPtr.Zero)
  5155   5645                   {
  5156   5646                       SQLiteMemory.Free(pOldError); pOldError = IntPtr.Zero;
  5157   5647                       SQLiteMarshal.WriteIntPtr(pVtab, offset, pOldError);
................................................................................
  5417   5907               if (pVtab == IntPtr.Zero)
  5418   5908                   return;
  5419   5909   
  5420   5910               int offset = 0;
  5421   5911   
  5422   5912               SQLiteMarshal.WriteIntPtr(pVtab, offset, IntPtr.Zero);
  5423   5913   
  5424         -            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
  5425         -                sizeof(int));
         5914  +            offset = SQLiteMarshal.NextOffsetOf(
         5915  +                offset, IntPtr.Size, sizeof(int));
  5426   5916   
  5427   5917               SQLiteMarshal.WriteInt32(pVtab, offset, 0);
  5428   5918   
  5429         -            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
  5430         -                IntPtr.Size);
         5919  +            offset = SQLiteMarshal.NextOffsetOf(
         5920  +                offset, sizeof(int), IntPtr.Size);
  5431   5921   
  5432   5922               SQLiteMarshal.WriteIntPtr(pVtab, offset, IntPtr.Zero);
  5433   5923           }
  5434   5924   
  5435   5925           ///////////////////////////////////////////////////////////////////////
  5436   5926   
  5437   5927           /// <summary>
................................................................................
  6079   6569           /// <summary>
  6080   6570           /// Modifies the specified <see cref="SQLiteIndex" /> object instance
  6081   6571           /// to contain the specified flags.
  6082   6572           /// </summary>
  6083   6573           /// <param name="index">
  6084   6574           /// The <see cref="SQLiteIndex" /> object instance to modify.
  6085   6575           /// </param>
  6086         -        /// <param name="idxFlags">
         6576  +        /// <param name="indexFlags">
  6087   6577           /// The index flags value to use.  Using a null value means that the
  6088   6578           /// default value provided by the SQLite core library should be used.
  6089   6579           /// </param>
  6090   6580           /// <returns>
  6091   6581           /// Non-zero upon success.
  6092   6582           /// </returns>
  6093         -        protected virtual bool SetIdxFlags(
         6583  +        protected virtual bool SetIndexFlags(
  6094   6584               SQLiteIndex index,
  6095         -            SQLiteIndexFlags? idxFlags
         6585  +            SQLiteIndexFlags? indexFlags
  6096   6586               )
  6097   6587           {
  6098   6588               if ((index == null) || (index.Outputs == null))
  6099   6589                   return false;
  6100   6590   
  6101         -            index.Outputs.IdxFlags = idxFlags;
         6591  +            index.Outputs.IndexFlags = indexFlags;
  6102   6592               return true;
  6103   6593           }
  6104   6594   
  6105   6595           ///////////////////////////////////////////////////////////////////////
  6106   6596   
  6107   6597           /// <summary>
  6108   6598           /// Modifies the specified <see cref="SQLiteIndex" /> object instance
................................................................................
  6110   6600           /// </summary>
  6111   6601           /// <param name="index">
  6112   6602           /// The <see cref="SQLiteIndex" /> object instance to modify.
  6113   6603           /// </param>
  6114   6604           /// <returns>
  6115   6605           /// Non-zero upon success.
  6116   6606           /// </returns>
  6117         -        protected virtual bool SetIdxFlags(
         6607  +        protected virtual bool SetIndexFlags(
  6118   6608               SQLiteIndex index
  6119   6609               )
  6120   6610           {
  6121         -            return SetIdxFlags(index, null);
         6611  +            return SetIndexFlags(index, null);
  6122   6612           }
  6123   6613           #endregion
  6124   6614           #endregion
  6125   6615   
  6126   6616           ///////////////////////////////////////////////////////////////////////
  6127   6617   
  6128   6618           #region Public Properties
................................................................................
  6255   6745               {
  6256   6746                   SQLiteVirtualTable table = TableFromIntPtr(pVtab);
  6257   6747   
  6258   6748                   if (table != null)
  6259   6749                   {
  6260   6750                       SQLiteIndex index = null;
  6261   6751   
  6262         -                    SQLiteIndex.FromIntPtr(pIndex, ref index);
         6752  +                    SQLiteIndex.FromIntPtr(pIndex, true, ref index);
  6263   6753   
  6264   6754                       if (BestIndex(table, index) == SQLiteErrorCode.Ok)
  6265   6755                       {
  6266         -                        SQLiteIndex.ToIntPtr(index, pIndex);
         6756  +                        SQLiteIndex.ToIntPtr(index, pIndex, true);
  6267   6757                           return SQLiteErrorCode.Ok;
  6268   6758                       }
  6269   6759                   }
  6270   6760               }
  6271   6761               catch (Exception e) /* NOTE: Must catch ALL. */
  6272   6762               {
  6273   6763                   SetTableError(pVtab, e.ToString());

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

  2851   2851   
  2852   2852       [StructLayout(LayoutKind.Sequential)]
  2853   2853       internal struct sqlite3_index_info
  2854   2854       {
  2855   2855           /* Inputs */
  2856   2856           public int nConstraint; /* Number of entries in aConstraint */
  2857   2857           public IntPtr aConstraint;
  2858         -        public int nOrderBy;
         2858  +        public int nOrderBy;    /* Number of entries in aOrderBy */
  2859   2859           public IntPtr aOrderBy;
  2860   2860           /* Outputs */
  2861   2861           public IntPtr aConstraintUsage;
  2862   2862           public int idxNum;           /* Number used to identify the index */
  2863   2863           public string idxStr;        /* String, possibly obtained from sqlite3_malloc */
  2864   2864           public int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
  2865   2865           public int orderByConsumed;  /* True if output is already ordered */
  2866   2866           public double estimatedCost; /* Estimated cost of using this index */
         2867  +        public long estimatedRows;   /* Estimated number of rows returned */
         2868  +        public SQLiteIndexFlags idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
         2869  +        public long colUsed;         /* Input: Mask of columns used by statement */
  2867   2870       }
  2868   2871   #endif
  2869   2872       #endregion
  2870   2873     }
  2871   2874   
  2872   2875     /////////////////////////////////////////////////////////////////////////////
  2873   2876   

Changes to Tests/vtab.eagle.

  1771   1771   
  1772   1772     unset -nocomplain result code results errors sql dataSource id fileName
  1773   1773   } -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
  1774   1774   System.Data.SQLite defineConstant.System.Data.SQLite.INTEROP_VIRTUAL_TABLE\
  1775   1775   compileCSharp} -match regexp -result [string map [list \n \r\n] {^Ok\
  1776   1776   System#CodeDom#Compiler#CompilerResults#\d+ \{\} 0 \{-?\d+ one -?\d+ two -?\d+\
  1777   1777   three -?\d+ 4 -?\d+ 5\.0\}$}]}
         1778  +
         1779  +###############################################################################
         1780  +
         1781  +runTest {test vtab-1.12 {SQLiteIndex managed-to-native-to-managed} -setup {
         1782  +  set nConstraint 3; set nOrderBy 3
         1783  +} -body {
         1784  +  set index(1) [object create -alias -flags +NonPublic \
         1785  +      System.Data.SQLite.SQLiteIndex $nConstraint $nOrderBy]
         1786  +
         1787  +  for {set iConstraint 0} {$iConstraint < $nConstraint} {incr iConstraint} {
         1788  +    set constraint(1) [object create -alias -flags +NonPublic \
         1789  +        System.Data.SQLite.SQLiteIndexConstraint 0 0 0 0]
         1790  +
         1791  +    $index(1) Inputs.Constraints.SetValue $constraint(1) $iConstraint
         1792  +
         1793  +    $constraint(1) iColumn [expr {int(0x01234567 + $iConstraint)}]
         1794  +    $constraint(1) op [expr {0xFF - $iConstraint}]
         1795  +    $constraint(1) usable [expr {0xCC + $iConstraint}]
         1796  +    $constraint(1) iTermOffset [expr {int(0x89ABCDEF + $iConstraint)}]
         1797  +  }
         1798  +
         1799  +  for {set iOrderBy 0} {$iOrderBy < $nOrderBy} {incr iOrderBy} {
         1800  +    set orderBy(1) [object create -alias -flags +NonPublic \
         1801  +        System.Data.SQLite.SQLiteIndexOrderBy 0 0]
         1802  +
         1803  +    $index(1) Inputs.OrderBys.SetValue $orderBy(1) $iOrderBy
         1804  +
         1805  +    $orderBy(1) iColumn [expr {int(0x23016745 + $iOrderBy)}]
         1806  +    $orderBy(1) desc [expr {0xFF - $iOrderBy}]
         1807  +  }
         1808  +
         1809  +  for {set iConstraint 0} {$iConstraint < $nConstraint} {incr iConstraint} {
         1810  +    set constraintUsage(1) [object create -alias -flags +NonPublic \
         1811  +        System.Data.SQLite.SQLiteIndexConstraintUsage 0 0]
         1812  +
         1813  +    $index(1) Outputs.ConstraintUsages.SetValue $constraintUsage(1) \
         1814  +        $iConstraint
         1815  +
         1816  +    $constraintUsage(1) argvIndex [expr {int(0xAB89EFCD + $iConstraint)}]
         1817  +    $constraintUsage(1) omit [expr {0xCC + $iConstraint}]
         1818  +  }
         1819  +
         1820  +  $index(1) Outputs.IndexNumber [expr {int(0xAAAAAAAA)}]
         1821  +  $index(1) Outputs.IndexString "\x01test index string.\xFF"
         1822  +  $index(1) Outputs.NeedToFreeIndexString [expr {int(0x55555555)}]
         1823  +  $index(1) Outputs.OrderByConsumed [expr {int(0x33333333)}]
         1824  +  $index(1) Outputs.EstimatedCost 1.0
         1825  +
         1826  +  if {[$index(1) Outputs.CanUseEstimatedRows]} then {
         1827  +    $index(1) Outputs.EstimatedRows [expr {int(0xCCCCCCCC)}]
         1828  +  }
         1829  +
         1830  +  if {[$index(1) Outputs.CanUseIndexFlags]} then {
         1831  +    $index(1) Outputs.IndexFlags [expr {int(0xEEEEEEEE)}]
         1832  +  }
         1833  +
         1834  +  if {[$index(1) Outputs.CanUseColumnsUsed]} then {
         1835  +    $index(1) Outputs.ColumnsUsed [expr {wide(0xBADC0FFEE875621A)}]
         1836  +  }
         1837  +
         1838  +  set pIndex(1) [object invoke -create -flags +NonPublic \
         1839  +      System.Data.SQLite.SQLiteIndex AllocateAndInitializeNative \
         1840  +      $nConstraint $nOrderBy]
         1841  +
         1842  +  object invoke -flags +NonPublic \
         1843  +      System.Data.SQLite.SQLiteIndex ToIntPtr $index(1) $pIndex(1) true
         1844  +
         1845  +  set index(2) [object create -alias -flags +NonPublic \
         1846  +      System.Data.SQLite.SQLiteIndex $nConstraint $nOrderBy]
         1847  +
         1848  +  object invoke -alias -flags +NonPublic \
         1849  +      System.Data.SQLite.SQLiteIndex FromIntPtr $pIndex(1) true index(2)
         1850  +
         1851  +  for {set iConstraint 0} {$iConstraint < $nConstraint} {incr iConstraint} {
         1852  +    set constraint(1) [$index(1) \
         1853  +        -alias Inputs.Constraints.GetValue $iConstraint]
         1854  +
         1855  +    set constraint(2) [$index(2) \
         1856  +        -alias Inputs.Constraints.GetValue $iConstraint]
         1857  +
         1858  +    if {[$constraint(1) iColumn] != [$constraint(2) iColumn]} then {
         1859  +      error [appendArgs \
         1860  +          "iColumn at index " $iConstraint " does not match"]
         1861  +    }
         1862  +
         1863  +    if {[$constraint(1) op] != [$constraint(2) op]} then {
         1864  +      error [appendArgs \
         1865  +          "op at index " $iConstraint " does not match"]
         1866  +    }
         1867  +
         1868  +    if {[$constraint(1) usable] != [$constraint(2) usable]} then {
         1869  +      error [appendArgs \
         1870  +          "usable at index " $iConstraint " does not match"]
         1871  +    }
         1872  +
         1873  +    if {[$constraint(1) iTermOffset] != [$constraint(2) iTermOffset]} then {
         1874  +      error [appendArgs \
         1875  +          "iTermOffset at index " $iConstraint " does not match"]
         1876  +    }
         1877  +  }
         1878  +
         1879  +  for {set iOrderBy 0} {$iOrderBy < $nOrderBy} {incr iOrderBy} {
         1880  +    set orderBy(1) [$index(1) \
         1881  +        -alias Inputs.OrderBys.GetValue $iOrderBy]
         1882  +
         1883  +    set orderBy(2) [$index(2) \
         1884  +        -alias Inputs.OrderBys.GetValue $iOrderBy]
         1885  +
         1886  +    if {[$orderBy(1) iColumn] != [$orderBy(2) iColumn]} then {
         1887  +      error [appendArgs \
         1888  +          "iColumn at index " $iOrderBy " does not match"]
         1889  +    }
         1890  +
         1891  +    if {[$orderBy(1) desc] != [$orderBy(2) desc]} then {
         1892  +      error [appendArgs \
         1893  +          "desc at index " $iOrderBy " does not match"]
         1894  +    }
         1895  +  }
         1896  +
         1897  +  for {set iConstraint 0} {$iConstraint < $nConstraint} {incr iConstraint} {
         1898  +    set constraintUsage(1) [$index(1) \
         1899  +        -alias Outputs.ConstraintUsages.GetValue $iConstraint]
         1900  +
         1901  +    set constraintUsage(2) [$index(2) \
         1902  +        -alias Outputs.ConstraintUsages.GetValue $iConstraint]
         1903  +
         1904  +    if {[$constraintUsage(1) argvIndex] != \
         1905  +        [$constraintUsage(2) argvIndex]} then {
         1906  +      error [appendArgs \
         1907  +          "argvIndex at index " $iConstraint " does not match"]
         1908  +    }
         1909  +
         1910  +    if {[$constraintUsage(1) omit] != [$constraintUsage(2) omit]} then {
         1911  +      error [appendArgs \
         1912  +          "omit at index " $iConstraint " does not match"]
         1913  +    }
         1914  +  }
         1915  +
         1916  +  if {[$index(1) Outputs.IndexNumber] != \
         1917  +      [$index(2) Outputs.IndexNumber]} then {
         1918  +    error "IndexNumber does not match"
         1919  +  }
         1920  +
         1921  +  if {[$index(1) Outputs.IndexString] ne \
         1922  +      [$index(2) Outputs.IndexString]} then {
         1923  +    error "IndexString does not match"
         1924  +  }
         1925  +
         1926  +  if {[$index(1) Outputs.NeedToFreeIndexString] != \
         1927  +      [$index(2) Outputs.NeedToFreeIndexString]} then {
         1928  +    error "NeedToFreeIndexString does not match"
         1929  +  }
         1930  +
         1931  +  if {[$index(1) Outputs.OrderByConsumed] != \
         1932  +      [$index(2) Outputs.OrderByConsumed]} then {
         1933  +    error "OrderByConsumed does not match"
         1934  +  }
         1935  +
         1936  +  if {[$index(1) Outputs.EstimatedCost] != \
         1937  +      [$index(2) Outputs.EstimatedCost]} then {
         1938  +    error "EstimatedCost does not match"
         1939  +  }
         1940  +
         1941  +  if {[$index(1) Outputs.CanUseEstimatedRows] && \
         1942  +      [$index(2) Outputs.CanUseEstimatedRows]} then {
         1943  +    if {[$index(1) Outputs.EstimatedRows] != \
         1944  +        [$index(2) Outputs.EstimatedRows]} then {
         1945  +      error "EstimatedRows does not match"
         1946  +    }
         1947  +
         1948  +    tputs $test_channel "---- checked EstimatedRows property\n"
         1949  +  }
         1950  +
         1951  +  if {[$index(1) Outputs.CanUseIndexFlags] && \
         1952  +      [$index(2) Outputs.CanUseIndexFlags]} then {
         1953  +    if {[$index(1) Outputs.IndexFlags] != \
         1954  +        [$index(2) Outputs.IndexFlags]} then {
         1955  +      error "IndexFlags does not match"
         1956  +    }
         1957  +
         1958  +    tputs $test_channel "---- checked IndexFlags property\n"
         1959  +  }
         1960  +
         1961  +  if {[$index(1) Outputs.CanUseColumnsUsed] && \
         1962  +      [$index(2) Outputs.CanUseColumnsUsed]} then {
         1963  +    if {[$index(1) Outputs.ColumnsUsed] != \
         1964  +        [$index(2) Outputs.ColumnsUsed]} then {
         1965  +      error "ColumnsUsed does not match"
         1966  +    }
         1967  +
         1968  +    tputs $test_channel "---- checked ColumnsUsed property\n"
         1969  +  }
         1970  +} -cleanup {
         1971  +  catch {
         1972  +    object invoke -flags +NonPublic \
         1973  +        System.Data.SQLite.SQLiteIndex FreeNative $pIndex(1)
         1974  +  }
         1975  +
         1976  +  unset -nocomplain constraintUsage
         1977  +  unset -nocomplain orderBy nOrderBy iOrderBy
         1978  +  unset -nocomplain constraint nConstraint iConstraint
         1979  +  unset -nocomplain pIndex index
         1980  +} -constraints {eagle command.object System.Data.SQLite\
         1981  +defineConstant.System.Data.SQLite.INTEROP_VIRTUAL_TABLE} -result {}}
  1778   1982   
  1779   1983   ###############################################################################
  1780   1984   
  1781   1985   runSQLiteTestEpilogue
  1782   1986   runTestEpilogue

Changes to readme.htm.

   209    209   <h2><b>Version History</b></h2>
   210    210   
   211    211   <p>
   212    212       <b>1.0.99.0 - December XX, 2015 <font color="red">(release scheduled)</font></b>
   213    213   </p>
   214    214   <ul>
   215    215       <li>Updated to <a href="https://www.sqlite.org/releaselog/3_9_2.html">SQLite 3.9.2</a>.</li>
          216  +    <li>Add preliminary support for the .NET Framework 4.6.1.</li>
          217  +    <li>Fix virtual table handling of sqlite3_index_info members not available with older versions of the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
   216    218       <li>Update and improve documentation comments for the native virtual table methods.</li>
   217    219       <li>Permit an existing registered function to be replaced. Fix for [2556655d1b].</li>
   218    220       <li>Make GetValue work for boolean columns with textual &quot;True&quot; and &quot;False&quot; values. Fix for [7714b60d61].</li>
   219    221       <li>Add Reset method to the SQLiteCommand class.</li>
   220    222       <li>Add FileName property to the SQLiteConnection class.</li>
   221    223       <li>Add experimental support for the native json1 and fts5 extensions.</li>
   222    224       <li>Add GetDatabaseName, GetTableName, and GetOriginalName methods to the SQLiteDataReader class.</li>

Changes to www/news.wiki.

     3      3   <b>Version History</b>
     4      4   
     5      5   <p>
     6      6       <b>1.0.99.0 - December XX, 2015 <font color="red">(release scheduled)</font></b>
     7      7   </p>
     8      8   <ul>
     9      9       <li>Updated to [https://www.sqlite.org/releaselog/3_9_2.html|SQLite 3.9.2].</li>
           10  +    <li>Add preliminary support for the .NET Framework 4.6.1.</li>
           11  +    <li>Fix virtual table handling of sqlite3_index_info members not available with older versions of the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    10     12       <li>Update and improve documentation comments for the native virtual table methods.</li>
    11     13       <li>Permit an existing registered function to be replaced. Fix for [2556655d1b].</li>
    12     14       <li>Make GetValue work for boolean columns with textual &quot;True&quot; and &quot;False&quot; values. Fix for [7714b60d61].</li>
    13     15       <li>Add Reset method to the SQLiteCommand class.</li>
    14     16       <li>Add FileName property to the SQLiteConnection class.</li>
    15     17       <li>Add experimental support for the native json1 and fts5 extensions.</li>
    16     18       <li>Add GetDatabaseName, GetTableName, and GetOriginalName methods to the SQLiteDataReader class.</li>