stephencelis / SQLite.swift

A type-safe, Swift-language layer over SQLite3.
MIT License
9.72k stars 1.57k forks source link

Join between tables that have some columns with the same name #1230

Closed NickTheFreak97 closed 11 months ago

NickTheFreak97 commented 11 months ago

Context:

Consider for example the following tables. An underline column name means that it's part of the primary key for its table, and foreign keys reference the primary key of the table they were named after.

DEV_STUDIO(name, position) GAME(name, devStudio, position) FK(devStudio) REF DEV_STUDIO(name) MAP(name, game, devStudio, position) FK(game, devStudio) REF GAME(name, devStudio)

Now suppose I want to run this query:

-- Load the first 5 maps for every game SELECT * FROM GAME JOIN MAP ON GAME.devStudio = MAP.devStudio WHERE MAP.position >= 0 AND MAP.position <= 5

Initial attempt:

let game = DomainModel.game
let map = DomainModel.map

let firstFiveMapsForEachGameQuery = game.table.join(
    map.table,
    on: game.devStudioColumn == map.devStudioColumn
).filter(
   map.positionColumn >= 0 && map.positionColumn <= 5
)

let results = try dbConnection.prepare(firstFiveMapsForEachGameQuery)

for map in results {
    // TODO: Process query results.
} 

In the context of the above code snippet, game.devStudioColumn = Expression<String>("devStudio") and map.devStudioColumn = Expression<String>("devStudio"), but of course it refers to different columns for different tables. When I run the above code I get the following fatal error:

Sqlite : ambiguous column name

Failed solution attempt:

Predictably, in SQL you would solve this issue via the following syntax: GAME.devStudio, MAP.devStudio, or assigning an alias to it.

In SQLite.Swift, I tried changing game.devStudioColumn to Expression<String>("\(game.tableName).devStudio") and the same for map.devStudioColumn. The generated template for it, though, is "GAME.devStudio" and "MAP.devStudio", all enclosed in double quotes, which causes

Syntax error near ', no such column: GAME.devStudio

So what's the way to go here?