<commit_before>import Foundation

extension FetchableRecord where Self: Decodable {
    public init(row: Row) {
        // Intended force-try. FetchableRecord is designed for records that
        // reliably decode from rows.
        self = try! RowDecoder().decode(from: row)
    }
}

// For testability. Not intended to become public as long as FetchableRecord has
// a non-throwing row initializer, since this would open an undesired door.
class RowDecoder {
    init() { }
    
    func decode<T: FetchableRecord & Decodable>(_ type: T.Type = T.self, from row: Row) throws -> T {
        let decoder = _RowDecoder<T>(row: row, codingPath: [], keyDecodingStrategy: T.databaseColumnDecodingStrategy)
        return try T(from: decoder)
    }
}

// MARK: - _RowDecoder

/// The decoder that decodes a record from a database row
private struct _RowDecoder<R: FetchableRecord>: Decoder {
    var row: Row
    var codingPath: [CodingKey]
    var keyDecodingStrategy: DatabaseColumnDecodingStrategy
    var userInfo: [CodingUserInfoKey: Any] { R.databaseDecodingUserInfo }
    
    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
        KeyedDecodingContainer(KeyedContainer<Key>(decoder: self))
    }
    
    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
        guard let codingKey = codingPath.last else {
            fatalError("unkeyed decoding from database row is not supported")
        }
        let keys = row.prefetchedRows.keys
        let debugDescription: String
        if keys.isEmpty {
            debugDescription = "No available prefetched rows"
        } else {
            debugDescription = "Available keys for prefetched rows: \(keys.sorted())"
        }
        throw DecodingError.keyNotFound(
            codingKey,
            DecodingError.Context(
                codingPath: Array(codingPath.dropLast()),
                debugDescription: debugDescription))
    }
    
    func singleValueContainer() throws -> SingleValueDecodingContainer {
        guard let key = codingPath.last else {
            // Decoding an array of scalars from rows: pick the first column
            return ColumnDecoder<R>(row: row, columnIndex: 0, codingPath: codingPath)
        }
        guard let index = row.index(forColumn: key.stringValue) else {
            // Don't use DecodingError.keyNotFound:
            // We need to specifically recognize missing columns in order to
            // provide correct feedback.
            throw RowDecodingError.columnNotFound(key.stringValue, context: RowDecodingContext(row: row))
        }
        // TODO: test
        // See DatabaseValueConversionErrorTests.testDecodableFetchableRecord2
        return ColumnDecoder<R>(row: row, columnIndex: index, codingPath: codingPath)
    }
    
    class KeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
        let decoder: _RowDecoder
        var codingPath: [CodingKey] { decoder.codingPath }
        var decodedRootKey: CodingKey?
        
        init(decoder: _RowDecoder) {
            self.decoder = decoder
        }
        
        lazy var allKeys: [Key] = {
            let row = decoder.row
            return Set(row.columnNames)
                .union(row.scopesTree.names)
                .union(row.prefetchedRows.keys)
                .compactMap(Key.init(stringValue:))
        }()
        
        func contains(_ key: Key) -> Bool {
            let row = decoder.row
            return row.hasColumn(key.stringValue)
                || (row.scopesTree[key.stringValue] != nil)
                || (row.prefetchedRows[key.stringValue] != nil)
        }
        
        func decodeNil(forKey key: Key) throws -> Bool {
            // Nil is only possible for columns and scopes (optional
            // associations), not for prefetched rows.
            let row = decoder.row
            return row[key.stringValue] == nil && (row.scopesTree[key.stringValue] == nil)
        }
        
        // swiftlint:disable comma
        // swiftlint:disable line_length
        func decode(_ type: Bool.Type,   forKey key: Key) throws -> Bool   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int.Type,    forKey key: Key) throws -> Int    { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int8.Type,   forKey key: Key) throws -> Int8   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int16.Type,  forKey key: Key) throws -> Int16  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int32.Type,  forKey key: Key) throws -> Int32  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int64.Type,  forKey key: Key) throws -> Int64  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt.Type,   forKey key: Key) throws -> UInt   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt8.Type,  forKey key: Key) throws -> UInt8  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Float.Type,  forKey key: Key) throws -> Float  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Double.Type, forKey key: Key) throws -> Double { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: String.Type, forKey key: Key) throws -> String { try decoder.row.decode(forKey: column(forKey: key)) }
        // swiftlint:enable line_length
        // swiftlint:enable comma
        
        private func column(forKey key: Key) -> String {
            decoder.keyDecodingStrategy.column(forKey: key)
        }
        
        func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Decodable {
            let row = decoder.row
            let keyName = key.stringValue
            
            // Column?
            if let index = row.index(forColumn: keyName) {
                // Prefer DatabaseValueConvertible decoding over Decodable.
                // This allows decoding Date from String, or DatabaseValue from NULL.
                if type == Date.self {
                    return try R.databaseDateDecodingStrategy.decodeIfPresent(
                        fromRow: row,
                        atUncheckedIndex: index) as! T?
                } else if let type = T.self as? (DatabaseValueConvertible & StatementColumnConvertible).Type {
                    return try type.fastDecodeIfPresent(fromRow: row, atUncheckedIndex: index) as! T?
                } else if let type = T.self as? DatabaseValueConvertible.Type {
                    return try type.decodeIfPresent(fromRow: row, atUncheckedIndex: index) as! T?
                } else if row.impl.hasNull(atUncheckedIndex: index) {
                    return nil
                } else {
                    return try decode(type, fromRow: row, columnAtIndex: index, key: key)
                }
            }
            
            // Scope? (beware left joins: check if scoped row contains non-null values)
            if let scopedRow = row.scopesTree[keyName], scopedRow.containsNonNullValue {
                return try decode(type, fromRow: scopedRow, codingPath: codingPath + [key])
            }
            
            // Key is not a column, and not a scope.
            return nil
        }
        
        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable {
            let row = decoder.row
            let keyName = column(forKey: key)
            
            // Column?
            if let index = row.index(forColumn: keyName) {
                // Prefer DatabaseValueConvertible decoding over Decodable.
                // This allows decoding Date from String, or DatabaseValue from NULL.
                if type == Date.self {
                    return try R.databaseDateDecodingStrategy.decode(fromRow: row, atUncheckedIndex: index) as! T
                } else if let type = T.self as? (DatabaseValueConvertible & StatementColumnConvertible).Type {
                    return try type.fastDecode(fromRow: row, atUncheckedIndex: index) as! T
                } else if let type = T.self as? DatabaseValueConvertible.Type {
                    return try type.decode(fromRow: row, atUncheckedIndex: index) as! T
                } else {
                    return try decode(type, fromRow: row, columnAtIndex: index, key: key)
                }
            }
            
            // Scope?
            if let scopedRow = row.scopesTree[keyName] {
                return try decode(type, fromRow: scopedRow, codingPath: codingPath + [key])
            }
            
            // Prefetched Rows?
            if let prefetchedRows = row.prefetchedRows[keyName] {
                let decoder = PrefetchedRowsDecoder<R>(rows: prefetchedRows, codingPath: codingPath)
                return try T(from: decoder)
            }
            
            // Key is not a column, and not a scope.
            //
            // Should be throw an error? Well... The use case is the following:
            //
            //      // SELECT book.*, author.* FROM book
            //      // JOIN author ON author.id = book.authorId
            //      let request = Book.including(required: Book.author)
            //
            // Rows loaded from this request don't have any "book" key:
            //
            //      let row = try Row.fetchOne(db, request)!
            //      print(row.debugDescription)
            //      // ▿ [id:1 title:"Moby-Dick" authorId:2]
            //      //   unadapted: [id:1 title:"Moby-Dick" authorId:2 id:2 name:"Melville"]
            //      //   author: [id:2 name:"Melville"]
            //
            // And yet we have to decode the "book" key when we decode the
            // BookInfo type below:
            //
            //      struct BookInfo {
            //          var book: Book // <- decodes from the "book" key
            //          var author: Author
            //      }
            //      let infos = try BookInfos.fetchAll(db, request)
            //<commit_msg>Column decoding strategy only applies to columns<commit_after>import Foundation

extension FetchableRecord where Self: Decodable {
    public init(row: Row) {
        // Intended force-try. FetchableRecord is designed for records that
        // reliably decode from rows.
        self = try! RowDecoder().decode(from: row)
    }
}

// For testability. Not intended to become public as long as FetchableRecord has
// a non-throwing row initializer, since this would open an undesired door.
class RowDecoder {
    init() { }
    
    func decode<T: FetchableRecord & Decodable>(_ type: T.Type = T.self, from row: Row) throws -> T {
        let decoder = _RowDecoder<T>(row: row, codingPath: [], keyDecodingStrategy: T.databaseColumnDecodingStrategy)
        return try T(from: decoder)
    }
}

// MARK: - _RowDecoder

/// The decoder that decodes a record from a database row
private struct _RowDecoder<R: FetchableRecord>: Decoder {
    var row: Row
    var codingPath: [CodingKey]
    var keyDecodingStrategy: DatabaseColumnDecodingStrategy
    var userInfo: [CodingUserInfoKey: Any] { R.databaseDecodingUserInfo }
    
    func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
        KeyedDecodingContainer(KeyedContainer<Key>(decoder: self))
    }
    
    func unkeyedContainer() throws -> UnkeyedDecodingContainer {
        guard let codingKey = codingPath.last else {
            fatalError("unkeyed decoding from database row is not supported")
        }
        let keys = row.prefetchedRows.keys
        let debugDescription: String
        if keys.isEmpty {
            debugDescription = "No available prefetched rows"
        } else {
            debugDescription = "Available keys for prefetched rows: \(keys.sorted())"
        }
        throw DecodingError.keyNotFound(
            codingKey,
            DecodingError.Context(
                codingPath: Array(codingPath.dropLast()),
                debugDescription: debugDescription))
    }
    
    func singleValueContainer() throws -> SingleValueDecodingContainer {
        guard let key = codingPath.last else {
            // Decoding an array of scalars from rows: pick the first column
            return ColumnDecoder<R>(row: row, columnIndex: 0, codingPath: codingPath)
        }
        guard let index = row.index(forColumn: key.stringValue) else {
            // Don't use DecodingError.keyNotFound:
            // We need to specifically recognize missing columns in order to
            // provide correct feedback.
            throw RowDecodingError.columnNotFound(key.stringValue, context: RowDecodingContext(row: row))
        }
        // TODO: test
        // See DatabaseValueConversionErrorTests.testDecodableFetchableRecord2
        return ColumnDecoder<R>(row: row, columnIndex: index, codingPath: codingPath)
    }
    
    class KeyedContainer<Key: CodingKey>: KeyedDecodingContainerProtocol {
        let decoder: _RowDecoder
        var codingPath: [CodingKey] { decoder.codingPath }
        var decodedRootKey: CodingKey?
        
        init(decoder: _RowDecoder) {
            self.decoder = decoder
        }
        
        lazy var allKeys: [Key] = {
            let row = decoder.row
            return Set(row.columnNames)
                .union(row.scopesTree.names)
                .union(row.prefetchedRows.keys)
                .compactMap(Key.init(stringValue:))
        }()
        
        func contains(_ key: Key) -> Bool {
            let row = decoder.row
            return row.hasColumn(key.stringValue)
                || (row.scopesTree[key.stringValue] != nil)
                || (row.prefetchedRows[key.stringValue] != nil)
        }
        
        func decodeNil(forKey key: Key) throws -> Bool {
            // Nil is only possible for columns and scopes (optional
            // associations), not for prefetched rows.
            let row = decoder.row
            return row[key.stringValue] == nil && (row.scopesTree[key.stringValue] == nil)
        }
        
        // swiftlint:disable comma
        // swiftlint:disable line_length
        func decode(_ type: Bool.Type,   forKey key: Key) throws -> Bool   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int.Type,    forKey key: Key) throws -> Int    { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int8.Type,   forKey key: Key) throws -> Int8   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int16.Type,  forKey key: Key) throws -> Int16  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int32.Type,  forKey key: Key) throws -> Int32  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Int64.Type,  forKey key: Key) throws -> Int64  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt.Type,   forKey key: Key) throws -> UInt   { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt8.Type,  forKey key: Key) throws -> UInt8  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Float.Type,  forKey key: Key) throws -> Float  { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: Double.Type, forKey key: Key) throws -> Double { try decoder.row.decode(forKey: column(forKey: key)) }
        func decode(_ type: String.Type, forKey key: Key) throws -> String { try decoder.row.decode(forKey: column(forKey: key)) }
        // swiftlint:enable line_length
        // swiftlint:enable comma
        
        private func column(forKey key: Key) -> String {
            decoder.keyDecodingStrategy.column(forKey: key)
        }
        
        func decodeIfPresent<T>(_ type: T.Type, forKey key: Key) throws -> T? where T: Decodable {
            let row = decoder.row
            let keyName = key.stringValue
            
            // Column?
            if let index = row.index(forColumn: keyName) {
                // Prefer DatabaseValueConvertible decoding over Decodable.
                // This allows decoding Date from String, or DatabaseValue from NULL.
                if type == Date.self {
                    return try R.databaseDateDecodingStrategy.decodeIfPresent(
                        fromRow: row,
                        atUncheckedIndex: index) as! T?
                } else if let type = T.self as? (DatabaseValueConvertible & StatementColumnConvertible).Type {
                    return try type.fastDecodeIfPresent(fromRow: row, atUncheckedIndex: index) as! T?
                } else if let type = T.self as? DatabaseValueConvertible.Type {
                    return try type.decodeIfPresent(fromRow: row, atUncheckedIndex: index) as! T?
                } else if row.impl.hasNull(atUncheckedIndex: index) {
                    return nil
                } else {
                    return try decode(type, fromRow: row, columnAtIndex: index, key: key)
                }
            }
            
            // Scope? (beware left joins: check if scoped row contains non-null values)
            if let scopedRow = row.scopesTree[keyName], scopedRow.containsNonNullValue {
                return try decode(type, fromRow: scopedRow, codingPath: codingPath + [key])
            }
            
            // Key is not a column, and not a scope.
            return nil
        }
        
        func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable {
            let row = decoder.row
            
            // Column?
            if let index = row.index(forColumn: column(forKey: key)) {
                // Prefer DatabaseValueConvertible decoding over Decodable.
                // This allows decoding Date from String, or DatabaseValue from NULL.
                if type == Date.self {
                    return try R.databaseDateDecodingStrategy.decode(fromRow: row, atUncheckedIndex: index) as! T
                } else if let type = T.self as? (DatabaseValueConvertible & StatementColumnConvertible).Type {
                    return try type.fastDecode(fromRow: row, atUncheckedIndex: index) as! T
                } else if let type = T.self as? DatabaseValueConvertible.Type {
                    return try type.decode(fromRow: row, atUncheckedIndex: index) as! T
                } else {
                    return try decode(type, fromRow: row, columnAtIndex: index, key: key)
                }
            }
            
            // Scope?
            if let scopedRow = row.scopesTree[key.stringValue] {
                return try decode(type, fromRow: scopedRow, codingPath: codingPath + [key])
            }
            
            // Prefetched Rows?
            if let prefetchedRows = row.prefetchedRows[key.stringValue] {
                let decoder = PrefetchedRowsDecoder<R>(rows: prefetchedRows, codingPath: codingPath)
                return try T(from: decoder)
            }
            
            // Key is not a column, and not a scope.
            //
            // Should be throw an error? Well... The use case is the following:
            //
            //      // SELECT book.*, author.* FROM book
            //      // JOIN author ON author.id = book.authorId
            //      let request = Book.including(required: Book.author)
            //
            // Rows loaded from this request don't have any "book" key:
            //
            //      let row = try Row.fetchOne(db, request)!
            //      print(row.debugDescription)
            //      // ▿ [id:1 title:"Moby-Dick" authorId:2]
            //      //   unadapted: [id:1 title:"Moby-Dick" authorId:2 id:2 name:"Melville"]
            //      //   author: [id:2 name:"Melville"]
            //
            // And yet we have to decode the "book" key when we decode the
            // BookInfo type below:
            //
            //      struct BookInfo {
            //          var book: Book // <- decodes from the "book" key
            //          var author: Author
            //      }
            //      let infos = try BookInfos.fetchAll(db, request)
            //
{'fraction_non_alphanumeric': 0.09592541763286168, 'fraction_numerical': 0.0034073162652027826, 'mean_word_length': 1.919994472847865, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2547256', 'n_tokens_mistral': 5883, 'n_tokens_neox': 5649, 'n_words': 1697}