Index: System.Data.SQLite/SQLiteModule.cs ================================================================== --- System.Data.SQLite/SQLiteModule.cs +++ System.Data.SQLite/SQLiteModule.cs @@ -329,11 +329,11 @@ } #endregion /////////////////////////////////////////////////////////////////////// - #region Internal Methods + #region Internal Marshal Helper Methods /// /// Converts a logical array of native pointers to native sqlite3_value /// structures into a managed array of /// object instances. /// @@ -1074,10 +1074,176 @@ { inputs = new SQLiteIndexInputs(nConstraint, nOrderBy); outputs = new SQLiteIndexOutputs(nConstraint); } #endregion + + /////////////////////////////////////////////////////////////////////// + + #region Internal Marshal Helper Methods + /// + /// Converts a native pointer to a native sqlite3_index_info structure + /// into a new object instance. + /// + /// + /// The native pointer to the native sqlite3_index_info structure to + /// convert. + /// + /// + /// Upon success, this parameter will be modified to contain the newly + /// created object instance. + /// + internal static void FromIntPtr( + IntPtr pIndex, + ref SQLiteIndex index + ) + { + if (pIndex == IntPtr.Zero) + return; + + int offset = 0; + + int nConstraint = SQLiteMarshal.ReadInt32(pIndex, offset); + + offset += sizeof(int); + + IntPtr pConstraint = SQLiteMarshal.ReadIntPtr(pIndex, offset); + + offset += IntPtr.Size; + + int nOrderBy = SQLiteMarshal.ReadInt32(pIndex, offset); + + offset += sizeof(int); + + IntPtr pOrderBy = SQLiteMarshal.ReadIntPtr(pIndex, offset); + + index = new SQLiteIndex(nConstraint, nOrderBy); + + int sizeOfConstraintType = Marshal.SizeOf(typeof( + UnsafeNativeMethods.sqlite3_index_constraint)); + + for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++) + { + UnsafeNativeMethods.sqlite3_index_constraint constraint = + new UnsafeNativeMethods.sqlite3_index_constraint(); + + Marshal.PtrToStructure(SQLiteMarshal.IntPtrForOffset( + pConstraint, iConstraint * sizeOfConstraintType), + constraint); + + index.Inputs.Constraints[iConstraint] = + new SQLiteIndexConstraint(constraint); + } + + int sizeOfOrderByType = Marshal.SizeOf(typeof( + UnsafeNativeMethods.sqlite3_index_orderby)); + + for (int iOrderBy = 0; iOrderBy < nOrderBy; iOrderBy++) + { + UnsafeNativeMethods.sqlite3_index_orderby orderBy = + new UnsafeNativeMethods.sqlite3_index_orderby(); + + Marshal.PtrToStructure(SQLiteMarshal.IntPtrForOffset( + pOrderBy, iOrderBy * sizeOfOrderByType), orderBy); + + index.Inputs.OrderBys[iOrderBy] = + new SQLiteIndexOrderBy(orderBy); + } + } + + /////////////////////////////////////////////////////////////////////// + + /// + /// Populates the outputs of a pre-allocated native sqlite3_index_info + /// structure using an existing object + /// instance. + /// + /// + /// The existing object instance containing + /// the output data to use. + /// + /// + /// The native pointer to the pre-allocated native sqlite3_index_info + /// structure. + /// + internal static void ToIntPtr( + SQLiteIndex index, + IntPtr pIndex + ) + { + if ((index == null) || (index.Inputs == null) || + (index.Inputs.Constraints == null) || + (index.Outputs == null) || + (index.Outputs.ConstraintUsages == null)) + { + return; + } + + if (pIndex == IntPtr.Zero) + return; + + int offset = 0; + + int nConstraint = SQLiteMarshal.ReadInt32(pIndex, offset); + + if (nConstraint != index.Inputs.Constraints.Length) + return; + + if (nConstraint != index.Outputs.ConstraintUsages.Length) + return; + + offset += sizeof(int) + IntPtr.Size + sizeof(int) + IntPtr.Size; + + IntPtr pConstraintUsage = SQLiteMarshal.ReadIntPtr(pIndex, offset); + + int sizeOfConstraintUsageType = Marshal.SizeOf(typeof( + UnsafeNativeMethods.sqlite3_index_constraint_usage)); + + for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++) + { + UnsafeNativeMethods.sqlite3_index_constraint_usage constraintUsage = + new UnsafeNativeMethods.sqlite3_index_constraint_usage( + index.Outputs.ConstraintUsages[iConstraint]); + + Marshal.StructureToPtr( + constraintUsage, SQLiteMarshal.IntPtrForOffset( + pConstraintUsage, iConstraint * sizeOfConstraintUsageType), + false); + + index.Outputs.ConstraintUsages[iConstraint] = + new SQLiteIndexConstraintUsage(constraintUsage); + } + + offset += IntPtr.Size; + + SQLiteMarshal.WriteInt32(pIndex, offset, + index.Outputs.IndexNumber); + + offset += sizeof(int); + + SQLiteMarshal.WriteIntPtr(pIndex, offset, + SQLiteString.Utf8IntPtrFromString(index.Outputs.IndexString)); + + offset += IntPtr.Size; + + // + // NOTE: We just allocated the IndexString field; therefore, we + // need to set the NeedToFreeIndexString field to non-zero. + // + SQLiteMarshal.WriteInt32(pIndex, offset, 1); + + offset += sizeof(int); + + SQLiteMarshal.WriteInt32(pIndex, offset, + index.Outputs.OrderByConsumed); + + offset += sizeof(int); + + SQLiteMarshal.WriteDouble(pIndex, offset, + index.Outputs.EstimatedCost); + } + #endregion /////////////////////////////////////////////////////////////////////// #region Public Properties private SQLiteIndexInputs inputs; @@ -4125,167 +4291,10 @@ #else Marshal.WriteIntPtr(IntPtrForOffset(pointer, offset), value); #endif } #endregion - - /////////////////////////////////////////////////////////////////////// - - #region SQLiteIndex Helper Methods - /// - /// Converts a native pointer to a native sqlite3_index_info structure - /// into a new object instance. - /// - /// - /// The native pointer to the native sqlite3_index_info structure to - /// convert. - /// - /// - /// Upon success, this parameter will be modified to contain the newly - /// created object instance. - /// - public static void IndexFromIntPtr( - IntPtr pIndex, - ref SQLiteIndex index - ) - { - if (pIndex == IntPtr.Zero) - return; - - int offset = 0; - - int nConstraint = ReadInt32(pIndex, offset); - - offset += sizeof(int); - - IntPtr pConstraint = ReadIntPtr(pIndex, offset); - - offset += IntPtr.Size; - - int nOrderBy = ReadInt32(pIndex, offset); - - offset += sizeof(int); - - IntPtr pOrderBy = ReadIntPtr(pIndex, offset); - - index = new SQLiteIndex(nConstraint, nOrderBy); - - int sizeOfConstraintType = Marshal.SizeOf(typeof( - UnsafeNativeMethods.sqlite3_index_constraint)); - - for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++) - { - UnsafeNativeMethods.sqlite3_index_constraint constraint = - new UnsafeNativeMethods.sqlite3_index_constraint(); - - Marshal.PtrToStructure(IntPtrForOffset(pConstraint, - iConstraint * sizeOfConstraintType), constraint); - - index.Inputs.Constraints[iConstraint] = - new SQLiteIndexConstraint(constraint); - } - - int sizeOfOrderByType = Marshal.SizeOf(typeof( - UnsafeNativeMethods.sqlite3_index_orderby)); - - for (int iOrderBy = 0; iOrderBy < nOrderBy; iOrderBy++) - { - UnsafeNativeMethods.sqlite3_index_orderby orderBy = - new UnsafeNativeMethods.sqlite3_index_orderby(); - - Marshal.PtrToStructure(IntPtrForOffset(pOrderBy, - iOrderBy * sizeOfOrderByType), orderBy); - - index.Inputs.OrderBys[iOrderBy] = - new SQLiteIndexOrderBy(orderBy); - } - } - - /////////////////////////////////////////////////////////////////////// - - /// - /// Populates the outputs of a pre-allocated native sqlite3_index_info - /// structure using an existing object - /// instance. - /// - /// - /// The existing object instance containing - /// the output data to use. - /// - /// - /// The native pointer to the pre-allocated native sqlite3_index_info - /// structure. - /// - public static void IndexToIntPtr( - SQLiteIndex index, - IntPtr pIndex - ) - { - if ((index == null) || (index.Inputs == null) || - (index.Inputs.Constraints == null) || - (index.Outputs == null) || - (index.Outputs.ConstraintUsages == null)) - { - return; - } - - if (pIndex == IntPtr.Zero) - return; - - int offset = 0; - - int nConstraint = ReadInt32(pIndex, offset); - - if (nConstraint != index.Inputs.Constraints.Length) - return; - - if (nConstraint != index.Outputs.ConstraintUsages.Length) - return; - - offset += sizeof(int) + IntPtr.Size + sizeof(int) + IntPtr.Size; - - IntPtr pConstraintUsage = ReadIntPtr(pIndex, offset); - - int sizeOfConstraintUsageType = Marshal.SizeOf(typeof( - UnsafeNativeMethods.sqlite3_index_constraint_usage)); - - for (int iConstraint = 0; iConstraint < nConstraint; iConstraint++) - { - UnsafeNativeMethods.sqlite3_index_constraint_usage constraintUsage = - new UnsafeNativeMethods.sqlite3_index_constraint_usage( - index.Outputs.ConstraintUsages[iConstraint]); - - Marshal.StructureToPtr( - constraintUsage, IntPtrForOffset(pConstraintUsage, - iConstraint * sizeOfConstraintUsageType), false); - - index.Outputs.ConstraintUsages[iConstraint] = - new SQLiteIndexConstraintUsage(constraintUsage); - } - - offset += IntPtr.Size; - - WriteInt32(pIndex, offset, index.Outputs.IndexNumber); - - offset += sizeof(int); - - WriteIntPtr(pIndex, offset, SQLiteString.Utf8IntPtrFromString( - index.Outputs.IndexString)); - - offset += IntPtr.Size; - - WriteInt32(pIndex, offset, 1); /* NOTE: We just allocated it. */ - - offset += sizeof(int); - - WriteInt32(pIndex, offset, index.Outputs.OrderByConsumed); - - offset += sizeof(int); - - WriteDouble(pIndex, offset, index.Outputs.EstimatedCost); - } - #endregion } #endregion /////////////////////////////////////////////////////////////////////////// @@ -6662,15 +6671,15 @@ if (table != null) { SQLiteIndex index = null; - SQLiteMarshal.IndexFromIntPtr(pIndex, ref index); + SQLiteIndex.FromIntPtr(pIndex, ref index); if (BestIndex(table, index) == SQLiteErrorCode.Ok) { - SQLiteMarshal.IndexToIntPtr(index, pIndex); + SQLiteIndex.ToIntPtr(index, pIndex); return SQLiteErrorCode.Ok; } } } catch (Exception e) /* NOTE: Must catch ALL. */