public override bool TryGetValue(string keyword, out object value)
        {
            bool flag = base.TryGetValue(keyword, out value);

            if (this._properties.ContainsKey(keyword))
            {
                PropertyDescriptor descriptor = this._properties[keyword] as PropertyDescriptor;
                if (descriptor == null)
                {
                    return(flag);
                }
                if (flag)
                {
                    if (descriptor.PropertyType == typeof(bool))
                    {
                        value = SQLiteConvert.ToBoolean(value);
                        return(flag);
                    }
                    value = TypeDescriptor.GetConverter(descriptor.PropertyType).ConvertFrom(value);
                    return(flag);
                }
                DefaultValueAttribute attribute = descriptor.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
                if (attribute != null)
                {
                    value = attribute.Value;
                    flag  = true;
                }
            }
            return(flag);
        }
示例#2
0
        static SQLiteFactory()
        {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
            UnsafeNativeMethods.Initialize();
#endif

#if USE_INTEROP_DLL && INTEROP_LOG
            if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok)
            {
                UnsafeNativeMethods.sqlite3_log(
                    SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized."));
            }
#endif

            SQLiteLog.Initialize();

            string version =
#if NET_40 || NET_45 || NET_451 || NET_452 || NET_46 || NET_461
                "4.0.0.0";
#else
                "3.5.0.0";
#endif

            _dbProviderServicesType = Type.GetType(HelperMethods.StringFormat(CultureInfo.InvariantCulture, "System.Data.Common.DbProviderServices, System.Data.Entity, Version={0}, Culture=neutral, PublicKeyToken=b77a5c561934e089", version), false);
        }
示例#3
0
        /// <summary>
        /// Parses the connection string into component parts
        /// </summary>
        /// <param name="connectionString">The connection string to parse</param>
        /// <returns>An array of key-value pairs representing each parameter of the connection string</returns>
        internal static System.Collections.Generic.SortedList <string, string> ParseConnectionString(string connectionString)
        {
            string s = connectionString;
            int    n;
            SortedList <string, string> ls = new SortedList <string, string>(StringComparer.OrdinalIgnoreCase);

            // First split into semi-colon delimited values.  The Split() function of SQLiteBase accounts for and properly
            // skips semi-colons in quoted strings
            string[] arParts = SQLiteConvert.Split(s, ';');

            int x = arParts.Length;

            // For each semi-colon piece, split into key and value pairs by the presence of the = sign
            for (n = 0; n < x; n++)
            {
                int indexOf = arParts[n].IndexOf('=');

                if (indexOf != -1)
                {
                    ls.Add(arParts[n].Substring(0, indexOf), arParts[n].Substring(indexOf + 1));
                }
                else
                {
                    throw new ArgumentException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Invalid ConnectionString format for part \"{0}\"", arParts[n]));
                }
            }
            return(ls);
        }
        /// <summary>
        /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
        /// </summary>
        /// <param name="i">The index of the column to retrieve</param>
        /// <returns>A SQLiteType structure</returns>
        private SQLiteType GetSQLiteType(int i)
        {
            SQLiteType typ;

            // Initialize the field types array if not already initialized
            if (_fieldTypeArray == null)
            {
                _fieldTypeArray = new SQLiteType[VisibleFieldCount];
            }

            // Initialize this column's field type instance
            if (_fieldTypeArray[i] == null)
            {
                _fieldTypeArray[i] = new SQLiteType();
            }

            typ = _fieldTypeArray[i];

            // If not initialized, then fetch the declared column datatype and attempt to convert it
            // to a known DbType.
            if (typ.Affinity == TypeAffinity.Uninitialized)
            {
                typ.Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity));
            }
            else
            {
                typ.Affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i);
            }

            return(typ);
        }
示例#5
0
 public override Type GetFieldType(int i)
 {
     if ((i >= this.VisibleFieldCount) && (this._keyInfo != null))
     {
         return(this._keyInfo.GetFieldType(i - this.VisibleFieldCount));
     }
     return(SQLiteConvert.SQLiteTypeToType(this.GetSQLiteType(i)));
 }
示例#6
0
        ///////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Creates a <see cref="SQLiteBlob" /> object.  This will not work
        /// for tables that were created WITHOUT ROWID.
        /// </summary>
        /// <param name="connection">
        /// The connection to use when opening the blob object.
        /// </param>
        /// <param name="databaseName">
        /// The name of the database containing the blob object.
        /// </param>
        /// <param name="tableName">
        /// The name of the table containing the blob object.
        /// </param>
        /// <param name="columnName">
        /// The name of the column containing the blob object.
        /// </param>
        /// <param name="rowId">
        /// The integer identifier for the row associated with the desired
        /// blob object.
        /// </param>
        /// <param name="readOnly">
        /// Non-zero to open the blob object for read-only access.
        /// </param>
        /// <returns>
        /// The newly created <see cref="SQLiteBlob" /> instance -OR- null
        /// if an error occurs.
        /// </returns>
        public static SQLiteBlob Create(
            SQLiteConnection connection,
            string databaseName,
            string tableName,
            string columnName,
            long rowId,
            bool readOnly
            )
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            SQLite3 sqlite3 = connection._sql as SQLite3;

            if (sqlite3 == null)
            {
                throw new InvalidOperationException("Connection has no wrapper");
            }

            SQLiteConnectionHandle handle = sqlite3._sql;

            if (handle == null)
            {
                throw new InvalidOperationException("Connection has an invalid handle.");
            }

            SQLiteBlobHandle blob = null;

            try
            {
                // do nothing.
            }
            finally /* NOTE: Thread.Abort() protection. */
            {
                IntPtr ptrBlob = IntPtr.Zero;

                SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_blob_open(
                    handle, SQLiteConvert.ToUTF8(databaseName),
                    SQLiteConvert.ToUTF8(tableName), SQLiteConvert.ToUTF8(
                        columnName), rowId, readOnly ? 0 : 1, ref ptrBlob);

                if (rc != SQLiteErrorCode.Ok)
                {
                    throw new SQLiteException(rc, null);
                }

                blob = new SQLiteBlobHandle(handle, ptrBlob);
            }

            SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
                                           SQLiteConnectionEventType.NewCriticalHandle, null, null,
                                           null, null, blob, null, new object[] { typeof(SQLiteBlob),
                                                                                  databaseName, tableName, columnName, rowId, readOnly }));

            return(new SQLiteBlob(sqlite3, blob));
        }
        /// <summary>
        /// Returns the .NET type of a given column
        /// </summary>
        /// <param name="i">The index of the column to retrieve</param>
        /// <returns>Type</returns>
        public override Type GetFieldType(int i)
        {
            if (i >= VisibleFieldCount && _keyInfo != null)
            {
                return(_keyInfo.GetFieldType(i - VisibleFieldCount));
            }

            return(SQLiteConvert.SQLiteTypeToType(GetSQLiteType(i)));
        }
        /// <summary>
        /// Converts a SQLiteType to a .NET Type object
        /// </summary>
        /// <param name="t">The SQLiteType to convert</param>
        /// <returns>Returns a .NET Type object</returns>
        internal static Type SQLiteTypeToType(SQLiteType t)
        {
            if (t.Type != DbType.Object)
            {
                return(SQLiteConvert.DbTypeToType(t.Type));
            }

            return(_typeaffinities[(int)t.Affinity]);
        }
示例#9
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
        {
            byte[] buffer    = SQLiteConvert.ToUTF8(value);
            int    errorCode = UnsafeNativeMethods.sqlite3_bind_text((IntPtr)stmt._sqlite_stmt, index, buffer, buffer.Length - 1, (IntPtr)(-1));

            if (errorCode > 0)
            {
                throw new SQLiteException(errorCode, this.SQLiteLastError());
            }
        }
        /// <summary>
        /// Determines the data type of a column in a statement
        /// </summary>
        /// <param name="stmt">The statement to retrieve information for</param>
        /// <param name="i">The column to retrieve type information on</param>
        /// <param name="typ">The SQLiteType to receive the affinity for the given column</param>
        //    internal static void ColumnToType(SQLiteStatement stmt, int i, SQLiteType typ)
        //    {
        //      typ.Type = TypeNameToDbType(stmt._sql.ColumnType(stmt, i, out typ.Affinity));
        //    }

        /// <summary>
        /// Converts a SQLiteType to a .NET Type object
        /// </summary>
        /// <param name="t">The SQLiteType to convert</param>
        /// <returns>Returns a .NET Type object</returns>
        internal static Type SQLiteTypeToType(SQLiteType t)
        {
            if (t.Type == DbType.Object)
            {
                return(_affinitytotype[(int)t.Affinity]);
            }
            else
            {
                return(SQLiteConvert.DbTypeToType(t.Type));
            }
        }
        /// <summary>
        /// Retrieves the name of the back-end datatype of the column
        /// </summary>
        /// <param name="i">The index of the column to retrieve</param>
        /// <returns>string</returns>
        public override string GetDataTypeName(int i)
        {
            CheckClosed();
            SQLiteType typ = GetSQLiteType(i);

            if (typ.Type == DbType.Object)
            {
                return(SQLiteConvert.SQLiteTypeToType(typ).Name);
            }

            return(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity));
        }
示例#12
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence)
        {
            IntPtr ptr;
            int    num;
            int    errorCode = UnsafeNativeMethods.sqlite3_index_column_info_interop((IntPtr)this._sql, SQLiteConvert.ToUTF8(database), SQLiteConvert.ToUTF8(index), SQLiteConvert.ToUTF8(column), out sortMode, out onError, out ptr, out num);

            if (errorCode != 0)
            {
                throw new SQLiteException(errorCode, "");
            }
            collationSequence = SQLiteConvert.UTF8ToString(ptr, num);
        }
        /// <summary>
        /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
        /// </summary>
        /// <param name="i">The index of the column to retrieve</param>
        /// <returns>A SQLiteType structure</returns>
        private SQLiteType GetSQLiteType(int i)
        {
            if (_fieldTypeArray == null)
            {
                _fieldTypeArray = new SQLiteType[_fieldCount];
            }

            if (_fieldTypeArray[i].Affinity == TypeAffinity.Uninitialized || _fieldTypeArray[i].Affinity == TypeAffinity.Null)
            {
                _fieldTypeArray[i].Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, i, out _fieldTypeArray[i].Affinity));
            }
            return(_fieldTypeArray[i]);
        }
示例#14
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16)
        {
            int errorCode = UnsafeNativeMethods.sqlite3_create_collation((IntPtr)this._sql, SQLiteConvert.ToUTF8(strCollation), 2, IntPtr.Zero, func16);

            if (errorCode == 0)
            {
                UnsafeNativeMethods.sqlite3_create_collation((IntPtr)this._sql, SQLiteConvert.ToUTF8(strCollation), 1, IntPtr.Zero, func);
            }
            if (errorCode > 0)
            {
                throw new SQLiteException(errorCode, this.SQLiteLastError());
            }
        }
示例#15
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override CollationSequence GetCollationSequence(SQLiteFunction func, IntPtr context)
        {
            int num;
            int num2;
            int num3;
            CollationSequence sequence     = new CollationSequence();
            IntPtr            nativestring = UnsafeNativeMethods.sqlite3_context_collseq(context, out num2, out num3, out num);

            sequence.Name     = SQLiteConvert.UTF8ToString(nativestring, num);
            sequence.Type     = (CollationTypeEnum)num2;
            sequence._func    = func;
            sequence.Encoding = (CollationEncodingEnum)num3;
            return(sequence);
        }
示例#16
0
        public override string GetDataTypeName(int i)
        {
            if ((i >= this.VisibleFieldCount) && (this._keyInfo != null))
            {
                return(this._keyInfo.GetDataTypeName(i - this.VisibleFieldCount));
            }
            SQLiteType sQLiteType = this.GetSQLiteType(i);

            if (sQLiteType.Type == DbType.Object)
            {
                return(SQLiteConvert.SQLiteTypeToType(sQLiteType).Name);
            }
            return(this._activeStatement._sql.ColumnType(this._activeStatement, i, out sQLiteType.Affinity));
        }
示例#17
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override object GetValue(SQLiteStatement stmt, int index, SQLiteType typ)
        {
            if (this.IsNull(stmt, index))
            {
                return(DBNull.Value);
            }
            TypeAffinity affinity = typ.Affinity;
            Type         type     = null;

            if (typ.Type != DbType.Object)
            {
                type     = SQLiteConvert.SQLiteTypeToType(typ);
                affinity = SQLiteConvert.TypeToAffinity(type);
            }
            switch (affinity)
            {
            case TypeAffinity.Int64:
                if (type != null)
                {
                    return(Convert.ChangeType(this.GetInt64(stmt, index), type, null));
                }
                return(this.GetInt64(stmt, index));

            case TypeAffinity.Double:
                if (type != null)
                {
                    return(Convert.ChangeType(this.GetDouble(stmt, index), type, null));
                }
                return(this.GetDouble(stmt, index));

            case TypeAffinity.Blob:
                if ((typ.Type != DbType.Guid) || (typ.Affinity != TypeAffinity.Text))
                {
                    int    nLength = (int)this.GetBytes(stmt, index, 0, null, 0, 0);
                    byte[] bDest   = new byte[nLength];
                    this.GetBytes(stmt, index, 0, bDest, 0, nLength);
                    if ((typ.Type == DbType.Guid) && (nLength == 0x10))
                    {
                        return(new Guid(bDest));
                    }
                    return(bDest);
                }
                return(new Guid(this.GetText(stmt, index)));

            case TypeAffinity.DateTime:
                return(this.GetDateTime(stmt, index));
            }
            return(this.GetText(stmt, index));
        }
示例#18
0
        /// <summary>
        /// Retrieves the name of the back-end datatype of the column
        /// </summary>
        /// <param name="i">The index of the column to retrieve</param>
        /// <returns>string</returns>
        public override string GetDataTypeName(int i)
        {
            if (i >= VisibleFieldCount && _keyInfo != null)
            {
                return(_keyInfo.GetDataTypeName(i - VisibleFieldCount));
            }

            SQLiteType typ = GetSQLiteType(i);

            if (typ.Type == DbType.Object)
            {
                return(SQLiteConvert.SQLiteTypeToType(typ).Name);
            }
            return(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity));
        }
示例#19
0
文件: SQLiteBase.cs 项目: bdcliang/BD
 internal static void ResetConnection(SQLiteConnectionHandle db)
 {
     lock (_lock)
     {
         IntPtr zero = IntPtr.Zero;
         do
         {
             zero = UnsafeNativeMethods.sqlite3_next_stmt((IntPtr)db, zero);
             if (zero != IntPtr.Zero)
             {
                 UnsafeNativeMethods.sqlite3_reset_interop(zero);
             }
         }while (zero != IntPtr.Zero);
         UnsafeNativeMethods.sqlite3_exec((IntPtr)db, SQLiteConvert.ToUTF8("ROLLBACK"), IntPtr.Zero, IntPtr.Zero, out zero);
     }
 }
示例#20
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity)
        {
            int    num;
            IntPtr nativestring = UnsafeNativeMethods.sqlite3_column_decltype_interop((IntPtr)stmt._sqlite_stmt, index, out num);

            nAffinity = this.ColumnAffinity(stmt, index);
            if (nativestring != IntPtr.Zero)
            {
                return(SQLiteConvert.UTF8ToString(nativestring, num));
            }
            string[] typeDefinitions = stmt.TypeDefinitions;
            if (((typeDefinitions != null) && (index < typeDefinitions.Length)) && (typeDefinitions[index] != null))
            {
                return(typeDefinitions[index]);
            }
            return(string.Empty);
        }
示例#21
0
        /// <summary>
        /// Helper function to retrieve a column of data from an active statement.
        /// </summary>
        /// <param name="stmt">The statement being step()'d through</param>
        /// <param name="index">The column index to retrieve</param>
        /// <param name="typ">The type of data contained in the column.  If Uninitialized, this function will retrieve the datatype information.</param>
        /// <returns>Returns the data in the column</returns>
        internal virtual object   GetValue(SQLiteStatement stmt, int index, ref SQLiteType typ)
        {
            if (typ.Affinity == 0)
            {
                typ = SQLiteConvert.ColumnToType(stmt, index);
            }
            if (IsNull(stmt, index))
            {
                return(DBNull.Value);
            }

            Type t = SQLiteConvert.SQLiteTypeToType(typ);

            switch (TypeToAffinity(t))
            {
            case TypeAffinity.Blob:
                if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text)
                {
                    return(new Guid(GetText(stmt, index)));
                }

                int    n = (int)GetBytes(stmt, index, 0, null, 0, 0);
                byte[] b = new byte[n];
                GetBytes(stmt, index, 0, b, 0, n);

                if (typ.Type == DbType.Guid && n == 16)
                {
                    return(new Guid(b));
                }

                return(b);

            case TypeAffinity.DateTime:
                return(GetDateTime(stmt, index));

            case TypeAffinity.Double:
                return(Convert.ChangeType(GetDouble(stmt, index), t, null));

            case TypeAffinity.Int64:
                return(Convert.ChangeType(GetInt64(stmt, index), t, null));

            default:
                return(GetText(stmt, index));
            }
        }
示例#22
0
        private SQLiteType GetSQLiteType(int i)
        {
            if (this._fieldTypeArray == null)
            {
                this._fieldTypeArray = new SQLiteType[this.VisibleFieldCount];
            }
            if (this._fieldTypeArray[i] == null)
            {
                this._fieldTypeArray[i] = new SQLiteType();
            }
            SQLiteType type = this._fieldTypeArray[i];

            if (type.Affinity == TypeAffinity.Uninitialized)
            {
                type.Type = SQLiteConvert.TypeNameToDbType(this._activeStatement._sql.ColumnType(this._activeStatement, i, out type.Affinity));
                return(type);
            }
            type.Affinity = this._activeStatement._sql.ColumnAffinity(this._activeStatement, i);
            return(type);
        }
        /// <summary>
        /// Turn a datatable into a table in the temporary database for the connection
        /// </summary>
        /// <param name="cnn">The connection to make the temporary table in</param>
        /// <param name="table">The table to write out</param>
        /// <param name="dest">The temporary table name to write to</param>
        private void DataTableToTable(SQLiteConnection cnn, DataTable table, string dest)
        {
            StringBuilder        sql     = new StringBuilder();
            SQLiteCommandBuilder builder = new SQLiteCommandBuilder();

            using (SQLiteCommand cmd = cnn.CreateCommand())
                using (DataTable source = new DataTable())
                {
                    sql.AppendFormat(CultureInfo.InvariantCulture, "CREATE TEMP TABLE {0} (", builder.QuoteIdentifier(dest));
                    string separator            = String.Empty;
                    SQLiteConnectionFlags flags = cnn.Flags;
                    foreach (DataColumn dc in table.Columns)
                    {
                        DbType dbtypeName = SQLiteConvert.TypeToDbType(dc.DataType);
                        string typeName   = SQLiteConvert.DbTypeToTypeName(dbtypeName, flags);

                        sql.AppendFormat(CultureInfo.InvariantCulture, "{2}{0} {1} COLLATE NOCASE", builder.QuoteIdentifier(dc.ColumnName), typeName, separator);
                        separator = ", ";
                    }
                    sql.Append(")");

                    cmd.CommandText = sql.ToString();
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = String.Format("SELECT * FROM TEMP.{0} WHERE 1=2", builder.QuoteIdentifier(dest));
                    using (SQLiteDataAdapter adp = new SQLiteDataAdapter(cmd))
                    {
                        builder.DataAdapter = adp;

                        adp.Fill(source);

                        foreach (DataRow row in table.Rows)
                        {
                            object[] arr = row.ItemArray;

                            source.Rows.Add(arr);
                        }
                        adp.Update(source);
                    }
                }
        }
示例#24
0
文件: SQLite3.cs 项目: bdcliang/BD
        internal override void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement)
        {
            IntPtr ptr;
            IntPtr ptr2;
            int    num;
            int    num2;
            int    num3;
            int    num5;
            int    num6;
            int    errorCode = UnsafeNativeMethods.sqlite3_table_column_metadata_interop((IntPtr)this._sql, SQLiteConvert.ToUTF8(dataBase), SQLiteConvert.ToUTF8(table), SQLiteConvert.ToUTF8(column), out ptr, out ptr2, out num, out num2, out num3, out num5, out num6);

            if (errorCode > 0)
            {
                throw new SQLiteException(errorCode, this.SQLiteLastError());
            }
            dataType        = SQLiteConvert.UTF8ToString(ptr, num5);
            collateSequence = SQLiteConvert.UTF8ToString(ptr2, num6);
            notNull         = num == 1;
            primaryKey      = num2 == 1;
            autoIncrement   = num3 == 1;
        }
        /// <summary>
        /// Helper function for retrieving values from the connectionstring
        /// </summary>
        /// <param name="keyword">The keyword to retrieve settings for</param>
        /// <param name="value">The resulting parameter value</param>
        /// <returns>Returns true if the value was found and returned</returns>
        public override bool TryGetValue(string keyword, out object value)
        {
            bool b = base.TryGetValue(keyword, out value);

            if (!_properties.ContainsKey(keyword))
            {
                return(b);
            }

            PropertyDescriptor pd = _properties[keyword] as PropertyDescriptor;

            if (pd == null)
            {
                return(b);
            }

            // Attempt to coerce the value into something more solid
            if (b)
            {
                if (pd.PropertyType == typeof(Boolean))
                {
                    value = SQLiteConvert.ToBoolean(value);
                }
                else if (pd.PropertyType != typeof(byte[]))
                {
                    value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value);
                }
            }
            else
            {
                DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
                if (att != null)
                {
                    value = att.Value;
                    b     = true;
                }
            }
            return(b);
        }
示例#26
0
 internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
 {
     if (base._sql == null)
     {
         base._usePool = usePool;
         if (usePool)
         {
             base._fileName = strFilename;
             base._sql      = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out this._poolVersion);
         }
         if (base._sql == null)
         {
             IntPtr ptr;
             int    errorCode = UnsafeNativeMethods.sqlite3_open16_interop(SQLiteConvert.ToUTF8(strFilename), (int)flags, out ptr);
             if (errorCode > 0)
             {
                 throw new SQLiteException(errorCode, null);
             }
             base._sql = ptr;
         }
         base._functionsArray = SQLiteFunction.BindFunctions(this);
     }
 }
示例#27
0
        internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue)
        {
            this.CheckClosed();
            DataTable tbl    = new DataTable("SchemaTable");
            DataTable schema = null;
            string    str2   = "";
            string    str3   = "";
            string    str4   = "";

            tbl.Locale = CultureInfo.InvariantCulture;
            tbl.Columns.Add(SchemaTableColumn.ColumnName, typeof(string));
            tbl.Columns.Add(SchemaTableColumn.ColumnOrdinal, typeof(int));
            tbl.Columns.Add(SchemaTableColumn.ColumnSize, typeof(int));
            tbl.Columns.Add(SchemaTableColumn.NumericPrecision, typeof(short));
            tbl.Columns.Add(SchemaTableColumn.NumericScale, typeof(short));
            tbl.Columns.Add(SchemaTableColumn.IsUnique, typeof(bool));
            tbl.Columns.Add(SchemaTableColumn.IsKey, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.BaseServerName, typeof(string));
            tbl.Columns.Add(SchemaTableOptionalColumn.BaseCatalogName, typeof(string));
            tbl.Columns.Add(SchemaTableColumn.BaseColumnName, typeof(string));
            tbl.Columns.Add(SchemaTableColumn.BaseSchemaName, typeof(string));
            tbl.Columns.Add(SchemaTableColumn.BaseTableName, typeof(string));
            tbl.Columns.Add(SchemaTableColumn.DataType, typeof(Type));
            tbl.Columns.Add(SchemaTableColumn.AllowDBNull, typeof(bool));
            tbl.Columns.Add(SchemaTableColumn.ProviderType, typeof(int));
            tbl.Columns.Add(SchemaTableColumn.IsAliased, typeof(bool));
            tbl.Columns.Add(SchemaTableColumn.IsExpression, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.IsRowVersion, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.IsHidden, typeof(bool));
            tbl.Columns.Add(SchemaTableColumn.IsLong, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(bool));
            tbl.Columns.Add(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(Type));
            tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object));
            tbl.Columns.Add("DataTypeName", typeof(string));
            tbl.Columns.Add("CollationType", typeof(string));
            tbl.BeginLoadData();
            for (int i = 0; i < this._fieldCount; i++)
            {
                string  str6;
                bool    flag;
                bool    flag2;
                bool    flag3;
                DataRow row = tbl.NewRow();
                DbType  typ = this.GetSQLiteType(i).Type;
                row[SchemaTableColumn.ColumnName]           = this.GetName(i);
                row[SchemaTableColumn.ColumnOrdinal]        = i;
                row[SchemaTableColumn.ColumnSize]           = SQLiteConvert.DbTypeToColumnSize(typ);
                row[SchemaTableColumn.NumericPrecision]     = SQLiteConvert.DbTypeToNumericPrecision(typ);
                row[SchemaTableColumn.NumericScale]         = SQLiteConvert.DbTypeToNumericScale(typ);
                row[SchemaTableColumn.ProviderType]         = this.GetSQLiteType(i).Type;
                row[SchemaTableColumn.IsLong]               = false;
                row[SchemaTableColumn.AllowDBNull]          = true;
                row[SchemaTableOptionalColumn.IsReadOnly]   = false;
                row[SchemaTableOptionalColumn.IsRowVersion] = false;
                row[SchemaTableColumn.IsUnique]             = false;
                row[SchemaTableColumn.IsKey] = false;
                row[SchemaTableOptionalColumn.IsAutoIncrement] = false;
                row[SchemaTableColumn.DataType]         = this.GetFieldType(i);
                row[SchemaTableOptionalColumn.IsHidden] = false;
                str4 = this._command.Connection._sql.ColumnOriginalName(this._activeStatement, i);
                if (!string.IsNullOrEmpty(str4))
                {
                    row[SchemaTableColumn.BaseColumnName] = str4;
                }
                row[SchemaTableColumn.IsExpression] = string.IsNullOrEmpty(str4);
                row[SchemaTableColumn.IsAliased]    = string.Compare(this.GetName(i), str4, true, CultureInfo.InvariantCulture) != 0;
                string str = this._command.Connection._sql.ColumnTableName(this._activeStatement, i);
                if (!string.IsNullOrEmpty(str))
                {
                    row[SchemaTableColumn.BaseTableName] = str;
                }
                str = this._command.Connection._sql.ColumnDatabaseName(this._activeStatement, i);
                if (!string.IsNullOrEmpty(str))
                {
                    row[SchemaTableOptionalColumn.BaseCatalogName] = str;
                }
                string dataType = null;
                if (string.IsNullOrEmpty(str4))
                {
                    goto Label_09B7;
                }
                this._command.Connection._sql.ColumnMetaData((string)row[SchemaTableOptionalColumn.BaseCatalogName], (string)row[SchemaTableColumn.BaseTableName], str4, out dataType, out str6, out flag, out flag2, out flag3);
                if (flag || flag2)
                {
                    row[SchemaTableColumn.AllowDBNull] = false;
                }
                row[SchemaTableColumn.IsKey] = flag2;
                row[SchemaTableOptionalColumn.IsAutoIncrement] = flag3;
                row["CollationType"] = str6;
                string[] strArray = dataType.Split(new char[] { '(' });
                if (strArray.Length > 1)
                {
                    dataType = strArray[0];
                    strArray = strArray[1].Split(new char[] { ')' });
                    if (strArray.Length > 1)
                    {
                        strArray = strArray[0].Split(new char[] { ',', '.' });
                        if ((this.GetSQLiteType(i).Type == DbType.String) || (this.GetSQLiteType(i).Type == DbType.Binary))
                        {
                            row[SchemaTableColumn.ColumnSize] = Convert.ToInt32(strArray[0], CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            row[SchemaTableColumn.NumericPrecision] = Convert.ToInt32(strArray[0], CultureInfo.InvariantCulture);
                            if (strArray.Length > 1)
                            {
                                row[SchemaTableColumn.NumericScale] = Convert.ToInt32(strArray[1], CultureInfo.InvariantCulture);
                            }
                        }
                    }
                }
                if (wantDefaultValue)
                {
                    using (SQLiteCommand command = new SQLiteCommand(string.Format(CultureInfo.InvariantCulture, "PRAGMA [{0}].TABLE_INFO([{1}])", new object[] { row[SchemaTableOptionalColumn.BaseCatalogName], row[SchemaTableColumn.BaseTableName] }), this._command.Connection))
                    {
                        using (DbDataReader reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                if (string.Compare((string)row[SchemaTableColumn.BaseColumnName], reader.GetString(1), true, CultureInfo.InvariantCulture) == 0)
                                {
                                    if (!reader.IsDBNull(4))
                                    {
                                        row[SchemaTableOptionalColumn.DefaultValue] = reader[4];
                                    }
                                    goto Label_075E;
                                }
                            }
                        }
                    }
                }
Label_075E:
                if (wantUniqueInfo)
                {
                    if ((((string)row[SchemaTableOptionalColumn.BaseCatalogName]) != str2) || (((string)row[SchemaTableColumn.BaseTableName]) != str3))
                    {
                        str2 = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
                        str3 = (string)row[SchemaTableColumn.BaseTableName];
                        string[] restrictionValues = new string[4];
                        restrictionValues[0] = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
                        restrictionValues[2] = (string)row[SchemaTableColumn.BaseTableName];
                        schema = this._command.Connection.GetSchema("Indexes", restrictionValues);
                    }
                    foreach (DataRow row2 in schema.Rows)
                    {
                        string[] strArray3 = new string[5];
                        strArray3[0] = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
                        strArray3[2] = (string)row[SchemaTableColumn.BaseTableName];
                        strArray3[3] = (string)row2["INDEX_NAME"];
                        DataTable table3 = this._command.Connection.GetSchema("IndexColumns", strArray3);
                        foreach (DataRow row3 in table3.Rows)
                        {
                            if (string.Compare((string)row3["COLUMN_NAME"], str4, true, CultureInfo.InvariantCulture) == 0)
                            {
                                if ((table3.Rows.Count == 1) && !((bool)row[SchemaTableColumn.AllowDBNull]))
                                {
                                    row[SchemaTableColumn.IsUnique] = row2["UNIQUE"];
                                }
                                if (((table3.Rows.Count != 1) || !((bool)row2["PRIMARY_KEY"])) || (string.IsNullOrEmpty(dataType) || (string.Compare(dataType, "integer", true, CultureInfo.InvariantCulture) != 0)))
                                {
                                }
                                break;
                            }
                        }
                    }
                }
                if (string.IsNullOrEmpty(dataType))
                {
                    TypeAffinity affinity;
                    dataType = this._activeStatement._sql.ColumnType(this._activeStatement, i, out affinity);
                }
                if (!string.IsNullOrEmpty(dataType))
                {
                    row["DataTypeName"] = dataType;
                }
Label_09B7:
                tbl.Rows.Add(row);
            }
            if (this._keyInfo != null)
            {
                this._keyInfo.AppendSchemaTable(tbl);
            }
            tbl.AcceptChanges();
            tbl.EndLoadData();
            return(tbl);
        }
示例#28
0
        /// <summary>
        /// Perform the bind operation for an individual parameter
        /// </summary>
        /// <param name="index">The index of the parameter to bind</param>
        /// <param name="param">The parameter we're binding</param>
        private void BindParameter(int index, SQLiteParameter param)
        {
            if (param == null)
            {
                throw new SQLiteException("Insufficient parameters supplied to the command");
            }

            if (HelperMethods.HasFlags(
                    _flags, SQLiteConnectionFlags.UseConnectionBindValueCallbacks))
            {
                bool complete;

                InvokeBindValueCallback(index, param, out complete);

                if (complete)
                {
                    return;
                }
            }

            object obj     = param.Value;
            DbType objType = param.DbType;

            if ((obj != null) && (objType == DbType.Object))
            {
                objType = SQLiteConvert.TypeToDbType(obj.GetType());
            }

            if (SQLite3.ForceLogPrepare() || HelperMethods.LogPreBind(_flags))
            {
                IntPtr handle = _sqlite_stmt;

                SQLiteLog.LogMessage(HelperMethods.StringFormat(
                                         CultureInfo.CurrentCulture,
                                         "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...",
                                         handle, index, objType, obj));
            }

            if ((obj == null) || Convert.IsDBNull(obj))
            {
                _sql.Bind_Null(this, _flags, index);
                return;
            }

            CultureInfo invariantCultureInfo = CultureInfo.InvariantCulture;

            bool invariantText = HelperMethods.HasFlags(
                _flags, SQLiteConnectionFlags.BindInvariantText);

            CultureInfo cultureInfo = CultureInfo.CurrentCulture;

            if (HelperMethods.HasFlags(
                    _flags, SQLiteConnectionFlags.ConvertInvariantText))
            {
                cultureInfo = invariantCultureInfo;
            }

            if (HelperMethods.HasFlags(
                    _flags, SQLiteConnectionFlags.BindAllAsText))
            {
                if (obj is DateTime)
                {
                    _sql.Bind_DateTime(this, _flags, index, (DateTime)obj);
                }
                else
                {
                    _sql.Bind_Text(this, _flags, index, invariantText ?
                                   SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) :
                                   SQLiteConvert.ToStringWithProvider(obj, cultureInfo));
                }

                return;
            }

            bool invariantDecimal = HelperMethods.HasFlags(
                _flags, SQLiteConnectionFlags.BindInvariantDecimal);

            if (HelperMethods.HasFlags(
                    _flags, SQLiteConnectionFlags.BindDecimalAsText))
            {
                if (obj is Decimal)
                {
                    _sql.Bind_Text(this, _flags, index, invariantText || invariantDecimal ?
                                   SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) :
                                   SQLiteConvert.ToStringWithProvider(obj, cultureInfo));

                    return;
                }
            }

            switch (objType)
            {
            case DbType.Date:
            case DbType.Time:
            case DbType.DateTime:
                //
                // NOTE: The old method (commented below) does not honor the selected date format
                //       for the connection.
                // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, cultureInfo));
                _sql.Bind_DateTime(this, _flags, index, (obj is string) ?
                                   _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, cultureInfo));
                break;

            case DbType.Boolean:
                _sql.Bind_Boolean(this, _flags, index, SQLiteConvert.ToBoolean(obj, cultureInfo, true));
                break;

            case DbType.SByte:
                _sql.Bind_Int32(this, _flags, index, Convert.ToSByte(obj, cultureInfo));
                break;

            case DbType.Int16:
                _sql.Bind_Int32(this, _flags, index, Convert.ToInt16(obj, cultureInfo));
                break;

            case DbType.Int32:
                _sql.Bind_Int32(this, _flags, index, Convert.ToInt32(obj, cultureInfo));
                break;

            case DbType.Int64:
                _sql.Bind_Int64(this, _flags, index, Convert.ToInt64(obj, cultureInfo));
                break;

            case DbType.Byte:
                _sql.Bind_UInt32(this, _flags, index, Convert.ToByte(obj, cultureInfo));
                break;

            case DbType.UInt16:
                _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt16(obj, cultureInfo));
                break;

            case DbType.UInt32:
                _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt32(obj, cultureInfo));
                break;

            case DbType.UInt64:
                _sql.Bind_UInt64(this, _flags, index, Convert.ToUInt64(obj, cultureInfo));
                break;

            case DbType.Single:
            case DbType.Double:
            case DbType.Currency:
                _sql.Bind_Double(this, _flags, index, Convert.ToDouble(obj, cultureInfo));
                break;

            case DbType.Binary:
                _sql.Bind_Blob(this, _flags, index, (byte[])obj);
                break;

            case DbType.Guid:
                if (_command.Connection._binaryGuid == true)
                {
                    _sql.Bind_Blob(this, _flags, index, ((Guid)obj).ToByteArray());
                }
                else
                {
                    _sql.Bind_Text(this, _flags, index, invariantText ?
                                   SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) :
                                   SQLiteConvert.ToStringWithProvider(obj, cultureInfo));
                }
                break;

            case DbType.Decimal:     // Dont store decimal as double ... loses precision
                _sql.Bind_Text(this, _flags, index, invariantText || invariantDecimal ?
                               SQLiteConvert.ToStringWithProvider(Convert.ToDecimal(obj, cultureInfo), invariantCultureInfo) :
                               SQLiteConvert.ToStringWithProvider(Convert.ToDecimal(obj, cultureInfo), cultureInfo));
                break;

            default:
                _sql.Bind_Text(this, _flags, index, invariantText ?
                               SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) :
                               SQLiteConvert.ToStringWithProvider(obj, cultureInfo));
                break;
            }
        }
示例#29
0
        /// <summary>
        /// Invokes the parameter binding callback configured for the database
        /// type name associated with the specified column.  If no parameter
        /// binding callback is available for the database type name, do
        /// nothing.
        /// </summary>
        /// <param name="index">
        /// The index of the column being read.
        /// </param>
        /// <param name="parameter">
        /// The <see cref="SQLiteParameter" /> instance being bound to the
        /// command.
        /// </param>
        /// <param name="complete">
        /// Non-zero if the default handling for the parameter binding call
        /// should be skipped (i.e. the parameter should not be bound at all).
        /// Great care should be used when setting this to non-zero.
        /// </param>
        private void InvokeBindValueCallback(
            int index,
            SQLiteParameter parameter,
            out bool complete
            )
        {
            complete = false;
            SQLiteConnectionFlags oldFlags = _flags;

            _flags &= ~SQLiteConnectionFlags.UseConnectionBindValueCallbacks;

            try
            {
                if (parameter == null)
                {
                    return;
                }

                SQLiteConnection connection = GetConnection(this);

                if (connection == null)
                {
                    return;
                }

                //
                // NOTE: First, always look for an explicitly set database type
                //       name.
                //
                string typeName = parameter.TypeName;

                if (typeName == null)
                {
                    //
                    // NOTE: Are we allowed to fallback to using the parameter name
                    //       as the basis for looking up the binding callback?
                    //
                    if (HelperMethods.HasFlags(
                            _flags, SQLiteConnectionFlags.UseParameterNameForTypeName))
                    {
                        typeName = parameter.ParameterName;
                    }
                }

                if (typeName == null)
                {
                    //
                    // NOTE: Are we allowed to fallback to using the database type
                    //       name translated from the DbType as the basis for looking
                    //       up the binding callback?
                    //
                    if (HelperMethods.HasFlags(
                            _flags, SQLiteConnectionFlags.UseParameterDbTypeForTypeName))
                    {
                        typeName = SQLiteConvert.DbTypeToTypeName(
                            connection, parameter.DbType, _flags);
                    }
                }

                if (typeName == null)
                {
                    return;
                }

                SQLiteTypeCallbacks callbacks;

                if (!connection.TryGetTypeCallbacks(typeName, out callbacks) ||
                    (callbacks == null))
                {
                    return;
                }

                SQLiteBindValueCallback callback = callbacks.BindValueCallback;

                if (callback == null)
                {
                    return;
                }

                object userData = callbacks.BindValueUserData;

                callback(
                    _sql, _command, oldFlags, parameter, typeName, index,
                    userData, out complete); /* throw */
            }
            finally
            {
                _flags |= SQLiteConnectionFlags.UseConnectionBindValueCallbacks;
            }
        }
        /// <summary>
        /// This function does all the nasty work at determining what keys need to be returned for
        /// a given statement.
        /// </summary>
        /// <param name="cnn"></param>
        /// <param name="reader"></param>
        /// <param name="stmt"></param>
        internal SQLiteKeyReader(SQLiteConnection cnn, SQLiteDataReader reader, SQLiteStatement stmt)
        {
            Dictionary <string, int>            catalogs = new Dictionary <string, int>();
            Dictionary <string, List <string> > tables   = new Dictionary <string, List <string> >();
            List <string>    list;
            List <KeyInfo>   keys   = new List <KeyInfo>();
            List <RowIdInfo> rowIds = new List <RowIdInfo>();

            // Record the statement so we can use it later for sync'ing
            _stmt = stmt;

            // Fetch all the attached databases on this connection
            using (DataTable tbl = cnn.GetSchema("Catalogs"))
            {
                foreach (DataRow row in tbl.Rows)
                {
                    catalogs.Add((string)row["CATALOG_NAME"], Convert.ToInt32(row["ID"], CultureInfo.InvariantCulture));
                }
            }

            // Fetch all the unique tables and catalogs used by the current statement
            using (DataTable schema = reader.GetSchemaTable(false, false))
            {
                foreach (DataRow row in schema.Rows)
                {
                    // Check if column is backed to a table
                    if (row[SchemaTableOptionalColumn.BaseCatalogName] == DBNull.Value)
                    {
                        continue;
                    }

                    // Record the unique table so we can look up its keys
                    string catalog = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
                    string table   = (string)row[SchemaTableColumn.BaseTableName];

                    if (tables.ContainsKey(catalog) == false)
                    {
                        list = new List <string>();
                        tables.Add(catalog, list);
                    }
                    else
                    {
                        list = tables[catalog];
                    }

                    if (list.Contains(table) == false)
                    {
                        list.Add(table);
                    }
                }

                // For each catalog and each table, query the indexes for the table.
                // Find a primary key index if there is one.  If not, find a unique index instead
                foreach (KeyValuePair <string, List <string> > pair in tables)
                {
                    for (int i = 0; i < pair.Value.Count; i++)
                    {
                        string  table        = pair.Value[i];
                        DataRow preferredRow = null;
                        using (DataTable tbl = cnn.GetSchema("Indexes", new string[] { pair.Key, null, table }))
                        {
                            // Loop twice.  The first time looking for a primary key index,
                            // the second time looking for a unique index
                            for (int n = 0; n < 2 && preferredRow == null; n++)
                            {
                                foreach (DataRow row in tbl.Rows)
                                {
                                    if (n == 0 && (bool)row["PRIMARY_KEY"] == true)
                                    {
                                        preferredRow = row;
                                        break;
                                    }
                                    else if (n == 1 && (bool)row["UNIQUE"] == true)
                                    {
                                        preferredRow = row;
                                        break;
                                    }
                                }
                            }
                            if (preferredRow == null) // Unable to find any suitable index for this table so remove it
                            {
                                pair.Value.RemoveAt(i);
                                i--;
                            }
                            else // We found a usable index, so fetch the necessary table details
                            {
                                using (DataTable tblTables = cnn.GetSchema("Tables", new string[] { pair.Key, null, table }))
                                {
                                    // Find the root page of the table in the current statement and get the cursor that's iterating it
                                    int database = catalogs[pair.Key];
                                    int rootPage = Convert.ToInt32(tblTables.Rows[0]["TABLE_ROOTPAGE"], CultureInfo.InvariantCulture);
                                    int cursor   = stmt._sql.GetCursorForTable(stmt, database, rootPage);

                                    // Now enumerate the members of the index we're going to use
                                    using (DataTable indexColumns = cnn.GetSchema("IndexColumns", new string[] { pair.Key, null, table, (string)preferredRow["INDEX_NAME"] }))
                                    {
                                        //
                                        // NOTE: If this is actually a RowId (or alias), record that now.  There should
                                        //       be exactly one index column in that case.
                                        //
                                        bool     isRowId = (string)preferredRow["INDEX_NAME"] == "sqlite_master_PK_" + table;
                                        KeyQuery query   = null;

                                        List <string> cols = new List <string>();
                                        for (int x = 0; x < indexColumns.Rows.Count; x++)
                                        {
                                            string columnName = SQLiteConvert.GetStringOrNull(
                                                indexColumns.Rows[x]["COLUMN_NAME"]);

                                            bool addKey = true;
                                            // If the column in the index already appears in the query, skip it
                                            foreach (DataRow row in schema.Rows)
                                            {
                                                if (row.IsNull(SchemaTableColumn.BaseColumnName))
                                                {
                                                    continue;
                                                }

                                                if ((string)row[SchemaTableColumn.BaseColumnName] == columnName &&
                                                    (string)row[SchemaTableColumn.BaseTableName] == table &&
                                                    (string)row[SchemaTableOptionalColumn.BaseCatalogName] == pair.Key)
                                                {
                                                    if (isRowId)
                                                    {
                                                        RowIdInfo rowId = new RowIdInfo();

                                                        rowId.databaseName = pair.Key;
                                                        rowId.tableName    = table;
                                                        rowId.column       = (int)row[SchemaTableColumn.ColumnOrdinal];

                                                        rowIds.Add(rowId);
                                                    }
                                                    indexColumns.Rows.RemoveAt(x);
                                                    x--;
                                                    addKey = false;
                                                    break;
                                                }
                                            }
                                            if (addKey == true)
                                            {
                                                cols.Add(columnName);
                                            }
                                        }

                                        // If the index is not a rowid alias, record all the columns
                                        // needed to make up the unique index and construct a SQL query for it
                                        if (!isRowId)
                                        {
                                            // Whatever remains of the columns we need that make up the index that are not
                                            // already in the query need to be queried separately, so construct a subquery
                                            if (cols.Count > 0)
                                            {
                                                string[] querycols = new string[cols.Count];
                                                cols.CopyTo(querycols);
                                                query = new KeyQuery(cnn, pair.Key, table, querycols);
                                            }
                                        }

                                        // Create a KeyInfo struct for each column of the index
                                        for (int x = 0; x < indexColumns.Rows.Count; x++)
                                        {
                                            string  columnName = SQLiteConvert.GetStringOrNull(indexColumns.Rows[x]["COLUMN_NAME"]);
                                            KeyInfo key        = new KeyInfo();

                                            key.rootPage     = rootPage;
                                            key.cursor       = cursor;
                                            key.database     = database;
                                            key.databaseName = pair.Key;
                                            key.tableName    = table;
                                            key.columnName   = columnName;
                                            key.query        = query;
                                            key.column       = x;

                                            keys.Add(key);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Now we have all the additional columns we have to return in order to support
            // CommandBehavior.KeyInfo
            _keyInfo = new KeyInfo[keys.Count];
            keys.CopyTo(_keyInfo);

            _rowIdInfo = new RowIdInfo[rowIds.Count];
            rowIds.CopyTo(_rowIdInfo);
        }