Index: SQLite.Designer/Design/Index.cs ================================================================== --- SQLite.Designer/Design/Index.cs +++ SQLite.Designer/Design/Index.cs @@ -391,11 +391,15 @@ internal IndexColumn(Index parent, DataRow row) { _parent = parent; if (row != null) { - _column = row["COLUMN_NAME"].ToString(); + if (!row.IsNull("COLUMN_NAME")) + _column = row["COLUMN_NAME"].ToString(); + else + _column = null; + if (row.IsNull("SORT_MODE") == false && (string)row["SORT_MODE"] != "ASC") _mode = ColumnSortMode.Descending; if (row.IsNull("COLLATION_NAME") == false) _collate = row["COLLATION_NAME"].ToString().ToUpperInvariant(); Index: Setup/data/verify.lst ================================================================== --- Setup/data/verify.lst +++ Setup/data/verify.lst @@ -790,10 +790,11 @@ Tests/tkt-448d663d11.eagle Tests/tkt-47c6fa04d3.eagle Tests/tkt-47f4bac575.eagle Tests/tkt-48a6b8e4ca.eagle Tests/tkt-4a791e70ab.eagle + Tests/tkt-5251bd0878.eagle Tests/tkt-544dba0a2f.eagle Tests/tkt-56b42d99c1.eagle Tests/tkt-58ed318f2f.eagle Tests/tkt-59edc1018b.eagle Tests/tkt-6434e23a0f.eagle Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -4755,33 +4755,37 @@ using (SQLiteCommand cmdIndex = new SQLiteCommand(UnsafeNativeMethods.StringFormat(CultureInfo.InvariantCulture, "PRAGMA [{0}].index_info([{1}])", strCatalog, rdIndexes.GetString(1)), this)) using (SQLiteDataReader rdIndex = cmdIndex.ExecuteReader()) { while (rdIndex.Read()) { + string columnName = rdIndex.IsDBNull(2) ? null : rdIndex.GetString(2); + row = tbl.NewRow(); row["CONSTRAINT_CATALOG"] = strCatalog; row["CONSTRAINT_NAME"] = rdIndexes.GetString(1); row["TABLE_CATALOG"] = strCatalog; row["TABLE_NAME"] = rdIndexes.GetString(2); - row["COLUMN_NAME"] = rdIndex.GetString(2); + row["COLUMN_NAME"] = columnName; row["INDEX_NAME"] = rdIndexes.GetString(1); row["ORDINAL_POSITION"] = ordinal; // rdIndex.GetInt32(1); string collationSequence = null; int sortMode = 0; int onError = 0; - _sql.GetIndexColumnExtendedInfo(strCatalog, rdIndexes.GetString(1), rdIndex.GetString(2), ref sortMode, ref onError, ref collationSequence); + + if (columnName != null) + _sql.GetIndexColumnExtendedInfo(strCatalog, rdIndexes.GetString(1), columnName, ref sortMode, ref onError, ref collationSequence); if (String.IsNullOrEmpty(collationSequence) == false) row["COLLATION_NAME"] = collationSequence; row["SORT_MODE"] = (sortMode == 0) ? "ASC" : "DESC"; row["CONFLICT_OPTION"] = onError; ordinal++; - if (String.IsNullOrEmpty(strColumn) || String.Compare(strColumn, row["COLUMN_NAME"].ToString(), StringComparison.OrdinalIgnoreCase) == 0) + if ((strColumn == null) || String.Compare(strColumn, columnName, StringComparison.OrdinalIgnoreCase) == 0) tbl.Rows.Add(row); } } } catch (SQLiteException) Index: System.Data.SQLite/SQLiteConvert.cs ================================================================== --- System.Data.SQLite/SQLiteConvert.cs +++ System.Data.SQLite/SQLiteConvert.cs @@ -1828,10 +1828,40 @@ { if (!found && (connection != null)) connection.SetCachedSetting(name, value); } } + + /// + /// Converts the object value, which is assumed to have originated + /// from a , to a string value. + /// + /// + /// The value to be converted to a string. + /// + /// + /// A null value will be returned if the original value is null -OR- + /// the original value is . Otherwise, + /// the original value will be converted to a string, using its + /// (possibly overridden) method and + /// then returned. + /// + public static string GetStringOrNull( + object value + ) + { + if (value == null) + return null; + + if (value is string) + return (string)value; + + if (value == DBNull.Value) + return null; + + return value.ToString(); + } /// /// Determines if the specified textual value appears to be a /// value. /// Index: System.Data.SQLite/SQLiteDataReader.cs ================================================================== --- System.Data.SQLite/SQLiteDataReader.cs +++ System.Data.SQLite/SQLiteDataReader.cs @@ -1170,11 +1170,11 @@ (string)rowIndexes["INDEX_NAME"], null }); foreach (DataRow rowColumnIndex in tblIndexColumns.Rows) { - if (String.Compare((string)rowColumnIndex["COLUMN_NAME"], strColumn, StringComparison.OrdinalIgnoreCase) == 0) + if (String.Compare(SQLiteConvert.GetStringOrNull(rowColumnIndex["COLUMN_NAME"]), strColumn, StringComparison.OrdinalIgnoreCase) == 0) { // // BUGFIX: Make sure that we only flag this column as "unique" // if we are not processing of some kind of multi-table // construct (i.e. a join) because in that case we must Index: System.Data.SQLite/SQLiteKeyReader.cs ================================================================== --- System.Data.SQLite/SQLiteKeyReader.cs +++ System.Data.SQLite/SQLiteKeyReader.cs @@ -241,18 +241,21 @@ KeyQuery query = null; List cols = new List(); 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] == (string)indexColumns.Rows[x]["COLUMN_NAME"] && + if ((string)row[SchemaTableColumn.BaseColumnName] == columnName && (string)row[SchemaTableColumn.BaseTableName] == table && (string)row[SchemaTableOptionalColumn.BaseCatalogName] == pair.Key) { indexColumns.Rows.RemoveAt(x); x--; @@ -259,11 +262,11 @@ addKey = false; break; } } if (addKey == true) - cols.Add((string)indexColumns.Rows[x]["COLUMN_NAME"]); + 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 ((string)preferredRow["INDEX_NAME"] != "sqlite_master_PK_" + table) @@ -279,11 +282,11 @@ } // Create a KeyInfo struct for each column of the index for (int x = 0; x < indexColumns.Rows.Count; x++) { - string columnName = (string)indexColumns.Rows[x]["COLUMN_NAME"]; + string columnName = SQLiteConvert.GetStringOrNull(indexColumns.Rows[x]["COLUMN_NAME"]); KeyInfo key = new KeyInfo(); key.rootPage = rootPage; key.cursor = cursor; key.database = database; ADDED Tests/tkt-5251bd0878.eagle Index: Tests/tkt-5251bd0878.eagle ================================================================== --- /dev/null +++ Tests/tkt-5251bd0878.eagle @@ -0,0 +1,78 @@ +############################################################################### +# +# tkt-5251bd0878.eagle -- +# +# Written by Joe Mistachkin. +# Released to the public domain, use at your own risk! +# +############################################################################### + +package require Eagle +package require Eagle.Library +package require Eagle.Test + +runTestPrologue + +############################################################################### + +package require System.Data.SQLite.Test +runSQLiteTestPrologue + +############################################################################### + +runTest {test tkt-5251bd0878-1.1 {indexed expressions schema} -setup { + setupDb [set fileName tkt-5251bd0878-1.1.db] +} -body { + set connection [getDbConnection] + + sql execute $db { + CREATE TABLE t1(x INTEGER PRIMARY KEY, y INTEGER); + INSERT INTO t1 (y) VALUES (-2000); + INSERT INTO t1 (y) VALUES (-1000); + INSERT INTO t1 (y) VALUES (-200); + INSERT INTO t1 (y) VALUES (-100); + INSERT INTO t1 (y) VALUES (-20); + INSERT INTO t1 (y) VALUES (-10); + INSERT INTO t1 (y) VALUES (0); + INSERT INTO t1 (y) VALUES (10); + INSERT INTO t1 (y) VALUES (20); + INSERT INTO t1 (y) VALUES (100); + INSERT INTO t1 (y) VALUES (200); + INSERT INTO t1 (y) VALUES (1000); + INSERT INTO t1 (y) VALUES (2000); + INSERT INTO t1 (y) VALUES (10000); + INSERT INTO t1 (y) VALUES (20000); + CREATE INDEX i1 ON t1(x, abs(y)); + } + + set dataReader [sql execute -execute reader -format datareader \ + -alias $db "SELECT x, y FROM t1;"] + + set dataTable [$dataReader -alias GetSchemaTable] + set result [list] + + foreach row [getRowsFromDataTable $dataTable] { + foreach column $row { + if {[lindex $column 0] in [list ColumnName IsKey]} then { + lappend result $column + } + } + } + + set result +} -cleanup { + unset -nocomplain dataTable dataReader + + cleanupDb $fileName + + freeDbConnection + + unset -nocomplain column row result connection db fileName +} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\ +System.Data.SQLite} -result {{ColumnName x} {IsKey True} {ColumnName y} {IsKey\ +False}}} + +############################################################################### + +runSQLiteTestEpilogue +runTestEpilogue