@@ -21,18 +21,35 @@ public class SchemaReader {
2121 let foreignKeys : [ String : [ ColumnDefinition . ForeignKey ] ] =
2222 Dictionary ( grouping: try foreignKeys ( table: table) , by: { $0. column } )
2323
24- return try connection. prepareRowIterator ( " PRAGMA table_info( \( table. quote ( ) ) ) " )
24+ let columnDefinitions = try connection. prepareRowIterator ( " PRAGMA table_info( \( table. quote ( ) ) ) " )
2525 . map { ( row: Row ) -> ColumnDefinition in
2626 ColumnDefinition (
2727 name: row [ TableInfoTable . nameColumn] ,
2828 primaryKey: ( row [ TableInfoTable . primaryKeyColumn] ?? 0 ) > 0 ?
2929 try parsePrimaryKey ( column: row [ TableInfoTable . nameColumn] ) : nil ,
3030 type: ColumnDefinition . Affinity ( row [ TableInfoTable . typeColumn] ) ,
3131 nullable: row [ TableInfoTable . notNullColumn] == 0 ,
32+ unique: false ,
3233 defaultValue: LiteralValue ( row [ TableInfoTable . defaultValueColumn] ) ,
3334 references: foreignKeys [ row [ TableInfoTable . nameColumn] ] ? . first
3435 )
3536 }
37+
38+ let internalIndexes = try indexDefinitions ( table: table) . filter { $0. isInternal }
39+ return columnDefinitions. map { definition in
40+ if let index = internalIndexes. first ( where: { $0. columns. contains ( definition. name) } ) , index. origin == . uniqueConstraint {
41+
42+ ColumnDefinition ( name: definition. name,
43+ primaryKey: definition. primaryKey,
44+ type: definition. type,
45+ nullable: definition. nullable,
46+ unique: true ,
47+ defaultValue: definition. defaultValue,
48+ references: definition. references)
49+ } else {
50+ definition
51+ }
52+ }
3653 }
3754
3855 public func objectDefinitions( name: String ? = nil ,
@@ -66,27 +83,26 @@ public class SchemaReader {
6683 . first
6784 }
6885
69- func columns ( name: String ) throws -> [ String ] {
86+ func indexInfos ( name: String ) throws -> [ IndexInfo ] {
7087 try connection. prepareRowIterator ( " PRAGMA index_info( \( name. quote ( ) ) ) " )
7188 . compactMap { row in
72- row [ IndexInfoTable . nameColumn]
89+ IndexInfo ( name: row [ IndexInfoTable . nameColumn] ,
90+ columnRank: row [ IndexInfoTable . seqnoColumn] ,
91+ columnRankWithinTable: row [ IndexInfoTable . cidColumn] )
92+
7393 }
7494 }
7595
7696 return try connection. prepareRowIterator ( " PRAGMA index_list( \( table. quote ( ) ) ) " )
7797 . compactMap { row -> IndexDefinition ? in
7898 let name = row [ IndexListTable . nameColumn]
79- guard !name. starts ( with: " sqlite_ " ) else {
80- // Indexes SQLite creates implicitly for internal use start with "sqlite_".
81- // See https://www.sqlite.org/fileformat2.html#intschema
82- return nil
83- }
8499 return IndexDefinition (
85100 table: table,
86101 name: name,
87102 unique: row [ IndexListTable . uniqueColumn] == 1 ,
88- columns: try columns ( name: name) ,
89- indexSQL: try indexSQL ( name: name)
103+ columns: try indexInfos ( name: name) . compactMap { $0. name } ,
104+ indexSQL: try indexSQL ( name: name) ,
105+ origin: IndexDefinition . Origin ( rawValue: row [ IndexListTable . originColumn] )
90106 )
91107 }
92108 }
@@ -123,6 +139,15 @@ public class SchemaReader {
123139 objectDefinitions( name: name, type: . table, temp: true )
124140 ) . compactMap ( \. sql) . first
125141 }
142+
143+ struct IndexInfo {
144+ let name : String ?
145+ // The rank of the column within the index. (0 means left-most.)
146+ let columnRank : Int
147+ // The rank of the column within the table being indexed.
148+ // A value of -1 means rowid and a value of -2 means that an expression is being used
149+ let columnRankWithinTable : Int
150+ }
126151}
127152
128153private enum SchemaTable {
@@ -159,11 +184,12 @@ private enum TableInfoTable {
159184
160185private enum IndexInfoTable {
161186 // The rank of the column within the index. (0 means left-most.)
162- static let seqnoColumn = Expression < Int64 > ( " seqno " )
187+ static let seqnoColumn = Expression < Int > ( " seqno " )
163188 // The rank of the column within the table being indexed.
164189 // A value of -1 means rowid and a value of -2 means that an expression is being used.
165- static let cidColumn = Expression < Int64 > ( " cid " )
166- // The name of the column being indexed. This columns is NULL if the column is the rowid or an expression.
190+ static let cidColumn = Expression < Int > ( " cid " )
191+ // The name of the column being indexed.
192+ // This columns is NULL if the column is the rowid or an expression.
167193 static let nameColumn = Expression < String ? > ( " name " )
168194}
169195
0 commit comments