I'm not sure how to phrase this, which may be why I couldn't find any information, but I have a many-to-many relationship where one of the entities has multiple properties of many of the other.
For instance, take the Artist and Song relationship. One artist can have many songs, and one song can have many artists. BUT, a song can have (many) main artists, (many) featured artists and (many) album artists. So these all come from the same table, but I'm not sure how to model this.
In code, I am using GRDB in Swift, so I follow the docs with:
import GRDB
struct Artist: TableRecord {
let id: Int
let name: String
...
static let artistSong = hasMany(ArtistSong.self)
static let songs = hasMany(Song.self, through: artistSong, using: ArtistSong.song)
}
struct ArtistSong: TableRecord {
static let artist = belongsTo(Artist.self)
static let song = belongsTo(Song.self)
}
struct Song: TableRecord {
let id: Int
let name: String
...
static let artistSong = hasMany(ArtistSong.self)
static let artists = hasMany(Artist.self, through: artistSong, using: ArtistSong.artist)
}
I imagine this would be fine if there were simply only "artists" on a song. But I have 3 different types of artists for a song (main, featured, album artist) but they all come from the same Artist table.
What would be the best way to tackle this?

For Many to Many relationship you need additional tables to define the relationship. Like with addition to Song and Artist tables you need additional table to define main, featured, album artist relationships.
These are join table which contains common fields from two or more other tables. In this way, it creates a many-to-many relationship between data.
You can go ahead and have only one extra table with a column defining relationship between song and artist. But this will create redundancy and several anomalies. For which you need Normalization. And need to have additional tables.
Note: Minimum of three tables are required in the Many to Many relationships. If we try to merge it will create redundant data.