Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSQLDecodingError improvements #211

Merged
merged 6 commits into from
Feb 17, 2022

Conversation

fabianfett
Copy link
Collaborator

@fabianfett fabianfett commented Feb 13, 2022

Split out to #209.

Motivation

Currently we hand a large PSQLDecodingContext into the PSQLDecodable's decode method. Lets look at it, as it is today:

struct PSQLDecodingContext {
    let jsonDecoder: PSQLJSONDecoder
    
    let columnIndex: Int
    let columnName: String
    
    let file: String
    let line: Int
    
    init(jsonDecoder: PSQLJSONDecoder, columnName: String, columnIndex: Int, file: String, line: Int) {
        self.jsonDecoder = jsonDecoder
        self.columnName = columnName
        self.columnIndex = columnIndex
        
        self.file = file
        self.line = line
    }
}

We use most of the PSQLDecodingContext's properties to create good error messages for users. Let's look at an implementation example:

    static func decode(from buffer: inout ByteBuffer, type: PSQLDataType, format: PSQLFormat, context: PSQLDecodingContext) throws -> Bool {
        guard type == .bool else {
            throw PSQLCastingError.failure(targetType: Self.self, type: type, postgresData: buffer, context: context)
        }
        
        switch format {
        case .binary:
            guard buffer.readableBytes == 1 else {
                throw PSQLCastingError.failure(targetType: Self.self, type: type, postgresData: buffer, context: context)
            }
            
            switch buffer.readInteger(as: UInt8.self) {
            case .some(0):
                return false
            case .some(1):
                return true
            default:
                throw PSQLCastingError.failure(targetType: Self.self, type: type, postgresData: buffer, context: context)
            }
        case .text:
            guard buffer.readableBytes == 1 else {
                throw PSQLCastingError.failure(targetType: Self.self, type: type, postgresData: buffer, context: context)
            }
            
            switch buffer.readInteger(as: UInt8.self) {
            case .some(UInt8(ascii: "f")):
                return false
            case .some(UInt8(ascii: "t")):
                return true
            default:
                throw PSQLCastingError.failure(targetType: Self.self, type: type, postgresData: buffer, context: context)
            }
        }
    }

As we can see the context is only used to create errors. If library adopters want to implement decoding for their own types, they need to forward the context as well, if they want to create good errors.

However we, as the Postgres library authors, don't need to pass the decoding info to the users and expect them to return it to us.

All decoding metadata can be kept in our code. For this reason users should return a PSQLDecodingError.Code from the decode method and we can create a full PSQLDecodingError based on this information. This also reduces code size quite a bit.

Changes

  • Only return PSQLDecodingError.Code from PSQLDecodable decode function.
  • Remove decode methods from PSQLData as those don't work anyway.
  • Change Optional decoding to something actually working.

Result

  • We can remove unused properties from PSQLDecodingContext
  • Easier code for adopters to write
  • Less code to maintain

@fabianfett fabianfett mentioned this pull request Feb 13, 2022
@codecov-commenter
Copy link

codecov-commenter commented Feb 13, 2022

Codecov Report

Merging #211 (99ba2c9) into main (7660f79) will increase coverage by 3.10%.
The diff coverage is 46.46%.

@@            Coverage Diff             @@
##             main     #211      +/-   ##
==========================================
+ Coverage   40.70%   43.81%   +3.10%     
==========================================
  Files         118      118              
  Lines        7706     7700       -6     
==========================================
+ Hits         3137     3374     +237     
+ Misses       4569     4326     -243     
Flag Coverage Δ
unittests 43.81% <46.46%> (+3.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
Sources/PostgresNIO/New/PSQLCodable.swift 77.77% <0.00%> (-22.23%) ⬇️
Sources/PostgresNIO/New/PSQLData.swift 0.00% <ø> (-100.00%) ⬇️
Sources/PostgresNIO/New/Data/Int+PSQLCodable.swift 20.26% <5.26%> (+2.61%) ⬆️
...ces/PostgresNIO/New/Data/Decimal+PSQLCodable.swift 74.19% <33.33%> (+6.45%) ⬆️
Sources/PostgresNIO/New/PSQLError.swift 57.74% <35.71%> (-26.04%) ⬇️
...ources/PostgresNIO/New/Data/Bool+PSQLCodable.swift 95.34% <60.00%> (+4.65%) ⬆️
...es/PostgresNIO/New/Data/Optional+PSQLCodable.swift 63.15% <70.00%> (+16.09%) ⬆️
...urces/PostgresNIO/New/Data/Float+PSQLCodable.swift 76.66% <75.00%> (+3.33%) ⬆️
...ources/PostgresNIO/New/Data/UUID+PSQLCodable.swift 98.30% <75.00%> (ø)
...urces/PostgresNIO/New/Data/Array+PSQLCodable.swift 94.68% <80.00%> (+1.06%) ⬆️
... and 34 more

@fabianfett fabianfett requested a review from 0xTim February 15, 2022 13:20
Copy link
Member

@gwynne gwynne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actual serious changes need making, just want to be sure I'm clear on what's going on in a couple of spots before moving ahead.

@fabianfett fabianfett requested a review from gwynne February 17, 2022 20:25
Copy link
Member

@gwynne gwynne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks g2g! 👍 ❤️

@fabianfett fabianfett merged commit e61d43c into vapor:main Feb 17, 2022
@fabianfett fabianfett deleted the ff-psqldecodingerror branch February 17, 2022 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants