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

Create Decodable objects after LEFT OUTER JOIN #936

Closed
p-nicolaou opened this issue Jun 4, 2019 · 4 comments
Closed

Create Decodable objects after LEFT OUTER JOIN #936

p-nicolaou opened this issue Jun 4, 2019 · 4 comments

Comments

@p-nicolaou
Copy link

I am wondering if there is a way to init my decodable object after I do left outer join two (or more) Tables. The problem I am facing is that when I join two tables, the column names automatically get prefixed with Table's name. Thus, when I do Customer(from: row.decoder()) this fails as my CodingKeys do not include my Table's name upfront. Is there any way to achieve this without renaming them (CodingKeys)?

@nalexander50
Copy link

I'm facing kind of the opposite issue. I want the CodingKeys to be prefixed with their table_name. But, at decode time, the decoder claims that it can't find the right key.

class A {

    let pokemonID: Int

    enum CodingKeys: String, CodingKey {
        case pokemonID = "pokemon.id"
    }

    init(decoder aDecoder: Decoder) throws {
        let values = try! aDecoder.container(keyedBy: CodingKeys.self)
        self.pokemonID = try! values.decode(Int.self, forKey: .pokemonID)
    }
}
func fetch() -> [A] {
    let tablePokemon = Table("pokemon")
    let tableEncounters = Table("encounters")
    let colPokemonID = Expression<Int>("pokemon_id")
    let colID = Expression<Int>("id")
        
    let query =
        tablePokemon.join(tableEncounters,
                          on: tablePokemon[colID] == tableEncounters[colPokemonID])
                    .filter(tablePokemon[colID] == 1)
            
    return try! self.connection.prepare(query).map { row in
        return try! row.decode()
    }
}

Error:

Fatal error: 'try!' expression unexpectedly raised an error: No such column `"pokemon.id"` in columns ["\"encounters\".\"encounter_slot_id\"", "\"encounters\".\"id\"", "\"encounters\".\"location_area_id\"", "\"encounters\".\"max_level\"", "\"encounters\".\"min_level\"", "\"encounters\".\"pokemon_id\"", "\"encounters\".\"version_id\"", "\"pokemon\".\"base_experience\"", "\"pokemon\".\"height\"", "\"pokemon\".\"id\"", "\"pokemon\".\"identifier\"", "\"pokemon\".\"is_default\"", "\"pokemon\".\"order\"", "\"pokemon\".\"species_id\"", "\"pokemon\".\"weight\""]

Aside from the garbled mess of escape quotes, pokemon.id plainly appears in the list of columns in the error. I have no idea why this doesn't work. If I reduce the CodingKey to just id, naturally it fails because id is ambiguous (both pokemon and encounter have id). If I change the CodingKey to pokemon_id, it works because it finds pokemon_id on encounter -- even though I didn't namespace it.

I must have some kind of fundamental misunderstand of how this decoding happens and what values should appear in my CodingKeys. Right now, I'm at an impasse because values like id, identifier, and pokemon_id are used over and over in nearly every table. As it stands right now, I have no idea how to decode those columns after a join.

@groue
Copy link

groue commented Nov 18, 2019

You may want to check https://github.com/groue/GRDB.swift and its associations: https://github.com/groue/GRDB.swift/blob/master/Documentation/AssociationsBasics.md

They make decoding joined tables a breeze

@nathanfallet
Copy link
Collaborator

Please ask on StackOverflow for this kind of questions (we are tracking bugs on GitHub)

@justinmeiners
Copy link

justinmeiners commented Jan 27, 2022

@nathanfallet I think this is potential shortcoming of the library, not a usage clarification. Row allows us to access namespaced columns by unprefixed name, provided there is no ambiguity. However, the SQLiteDecoder appears to define its set of available keys by only the namespaced version. This means Codable cannot find namespaced keys. If you cannot use Codable with any kind of join, it's probably worthless.

This is also described in #225

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

No branches or pull requests

5 participants