Skip to content

Commit

Permalink
Add and use LaxSchemaOptionSet
Browse files Browse the repository at this point in the history
- The backup & batch programs still have a lax/strict switch. However all the tables now use the option set to set how strict they are.
- They default to .strict since the programs did.
- Next step will be to add control for each table to the programs.
- This reverts #532.
  • Loading branch information
bolsinga committed Dec 26, 2024
1 parent b035874 commit 985e01b
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 28 deletions.
4 changes: 2 additions & 2 deletions Sources/iTunes/Array+DB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import Foundation

extension Array where Element == Track {
func database(
storage: DatabaseStorage, loggingToken: String?, schemaConstrainsts: SchemaConstraints
storage: DatabaseStorage, loggingToken: String?, laxSchemaOptions: LaxSchemaOptions
) async throws -> Data {
let dbEncoder = try TracksDBEncoder(
storage: storage, rowEncoder: self.rowEncoder(loggingToken), loggingToken: loggingToken)
do {
try await dbEncoder.encode(schemaConstrainsts: schemaConstrainsts)
try await dbEncoder.encode(laxSchemaOptions: laxSchemaOptions)
let data = try await dbEncoder.data()
await dbEncoder.close()
return data
Expand Down
4 changes: 2 additions & 2 deletions Sources/iTunes/Array+TracksSqlData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import Foundation

extension Array where Element == Track {
func sqlData(loggingToken: String?, schemaConstraints: SchemaConstraints) throws -> Data {
func sqlData(loggingToken: String?, laxSchemaOptions: LaxSchemaOptions) throws -> Data {
let encoder = TracksSQLSourceEncoder()
return try encoder.encode(
self, loggingToken: loggingToken, schemaConstraints: schemaConstraints)
self, loggingToken: loggingToken, laxSchemaOptions: laxSchemaOptions)
}
}
2 changes: 1 addition & 1 deletion Sources/iTunes/BackupCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public struct BackupCommand: AsyncParsableCommand {

try await destination.context(outputFile: outputFile).emit(
tracks, branch: "main", tagPrefix: tagPrefix, version: Self.configuration.version,
schemaConstraints: schemaConstraints)
laxSchemaOptions: schemaConstraints.laxSchemaOptionSet)
}

public init() {} // This is public and empty to help the compiler.
Expand Down
4 changes: 2 additions & 2 deletions Sources/iTunes/Batch/Batch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum Batch: CaseIterable {
extension Batch {
func build(
_ configuration: GitTagData.Configuration, outputDirectory: URL,
schemaConstraints: SchemaConstraints
laxSchemaOptions: LaxSchemaOptions
) async throws {
var patchedTracksData = try await GitTagData(configuration: configuration)
.transformTaggedTracks {
Expand All @@ -29,7 +29,7 @@ extension Batch {
}()

return try await destination.data(
for: $1, loggingToken: "batch-\($0)", schemaConstraints: schemaConstraints)
for: $1, loggingToken: "batch-\($0)", laxSchemaOptions: laxSchemaOptions)
}

let pathExtension = {
Expand Down
3 changes: 2 additions & 1 deletion Sources/iTunes/Batch/BatchCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public struct BatchCommand: AsyncParsableCommand {
let configuration = GitTagData.Configuration(
directory: gitDirectory, tagPrefix: tagPrefix, fileName: Self.fileName)
try await batch.build(
configuration, outputDirectory: outputDirectory, schemaConstraints: schemaConstraints)
configuration, outputDirectory: outputDirectory,
laxSchemaOptions: schemaConstraints.laxSchemaOptionSet)
}

public init() {} // This is public and empty to help the compiler.
Expand Down
6 changes: 3 additions & 3 deletions Sources/iTunes/Destination+Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
import Foundation

extension Destination {
func data(for tracks: [Track], loggingToken: String?, schemaConstraints: SchemaConstraints)
func data(for tracks: [Track], loggingToken: String?, laxSchemaOptions: LaxSchemaOptions)
async throws -> Data
{
switch self {
case .json, .jsonGit:
try tracks.jsonData()
case .sqlCode:
try tracks.sqlData(loggingToken: loggingToken, schemaConstraints: schemaConstraints)
try tracks.sqlData(loggingToken: loggingToken, laxSchemaOptions: laxSchemaOptions)
case .db:
try await tracks.database(
storage: .memory, loggingToken: loggingToken, schemaConstrainsts: schemaConstraints)
storage: .memory, loggingToken: loggingToken, laxSchemaOptions: laxSchemaOptions)
}
}
}
4 changes: 2 additions & 2 deletions Sources/iTunes/Destination+Tracks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extension Destination {

func emit(
_ tracks: [Track], branch: String, tagPrefix: String, version: String,
schemaConstraints: SchemaConstraints
laxSchemaOptions: LaxSchemaOptions
) async throws {
enum DataExportError: Error {
case noTracks
Expand All @@ -52,7 +52,7 @@ extension Destination {
let tracks = tracks.sorted()

let data = try await self.data(
for: tracks, loggingToken: nil, schemaConstraints: schemaConstraints)
for: tracks, loggingToken: nil, laxSchemaOptions: laxSchemaOptions)

if let outputFile = self.url {
try await self.fileWriter(
Expand Down
25 changes: 25 additions & 0 deletions Sources/iTunes/LaxSchemaOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// LaxSchemaOptions.swift
// itunes_json
//
// Created by Greg Bolsinga on 12/25/24.
//

import Foundation

struct LaxSchemaOptions: OptionSet {
let rawValue: UInt

static let artist = LaxSchemaOptions(rawValue: 1 << 0)
static let album = LaxSchemaOptions(rawValue: 1 << 1)
static let song = LaxSchemaOptions(rawValue: 1 << 2)
static let plays = LaxSchemaOptions(rawValue: 1 << 3)

static let strictSchema = LaxSchemaOptions()
static let laxSchema: LaxSchemaOptions = [Self.artist, Self.album, Self.song, Self.plays]

var artistConstraints: SchemaConstraints { self.contains(.artist) ? .lax : .strict }
var albumConstraints: SchemaConstraints { self.contains(.album) ? .lax : .strict }
var songConstraints: SchemaConstraints { self.contains(.song) ? .lax : .strict }
var playsConstraints: SchemaConstraints { self.contains(.plays) ? .lax : .strict }
}
17 changes: 17 additions & 0 deletions Sources/iTunes/SchemaConstraints+LaxSchemaOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// SchemaConstraints+LaxSchemaOptions.swift
// itunes_json
//
// Created by Greg Bolsinga on 12/25/24.
//

extension SchemaConstraints {
var laxSchemaOptionSet: LaxSchemaOptions {
switch self {
case .strict:
.strictSchema
case .lax:
.laxSchema
}
}
}
12 changes: 7 additions & 5 deletions Sources/iTunes/TracksDBEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ struct TracksDBEncoder {
rowEncoder.playTableBuilder(songLookup), schemaConstraints: schemaConstrainsts)
}

func encode(schemaConstrainsts: SchemaConstraints) async throws {
func encode(laxSchemaOptions: LaxSchemaOptions) async throws {
try await db.execute("PRAGMA foreign_keys = ON;")
let artistLookup = try await emitArtists(schemaConstrainsts: .strict)
let albumLookup = try await emitAlbums(schemaConstrainsts: schemaConstrainsts)
let artistLookup = try await emitArtists(schemaConstrainsts: laxSchemaOptions.artistConstraints)
let albumLookup = try await emitAlbums(schemaConstrainsts: laxSchemaOptions.albumConstraints)
let songLookup = try await emitSongs(
artistLookup: artistLookup, albumLookup: albumLookup, schemaConstrainsts: schemaConstrainsts)
try await emitPlays(songLookup: songLookup, schemaConstrainsts: schemaConstrainsts)
artistLookup: artistLookup, albumLookup: albumLookup,
schemaConstrainsts: laxSchemaOptions.songConstraints)
try await emitPlays(
songLookup: songLookup, schemaConstrainsts: laxSchemaOptions.playsConstraints)
try await db.execute(rowEncoder.views)
}

Expand Down
24 changes: 14 additions & 10 deletions Sources/iTunes/TracksSQLSourceEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,42 @@ struct TracksSQLSourceEncoder {
self.rowEncoder = rowEncoder
}

private var tableBuilders: [any TableBuilder] {
private func tableBuilders(laxSchemaOptions: LaxSchemaOptions) -> [(
any TableBuilder, SchemaConstraints
)] {
[
rowEncoder.artistTableBuilder, rowEncoder.albumTableBuilder, rowEncoder.songTableBuilder(),
rowEncoder.playTableBuilder(),
(rowEncoder.artistTableBuilder, laxSchemaOptions.artistConstraints),
(rowEncoder.albumTableBuilder, laxSchemaOptions.albumConstraints),
(rowEncoder.songTableBuilder(), laxSchemaOptions.songConstraints),
(rowEncoder.playTableBuilder(), laxSchemaOptions.playsConstraints),
]
}

fileprivate func sqlStatements(schemaConstraints: SchemaConstraints) -> String {
fileprivate func sqlStatements(laxSchemaOptions: LaxSchemaOptions) -> String {
(["PRAGMA foreign_keys = ON;"]
+ tableBuilders.flatMap {
var statements = [$0.schema(constraints: schemaConstraints)]
+ tableBuilders(laxSchemaOptions: laxSchemaOptions).flatMap {
var statements = [$0.schema(constraints: $1)]
statements.append(contentsOf: $0.statements.map { "\($0)" }.sorted())
return statements
} + [rowEncoder.views].compactMap { $0 }).joined(separator: "\n")
}
}

private func encode(
_ tracks: [Track], loggingToken: String?, schemaConstraints: SchemaConstraints
_ tracks: [Track], loggingToken: String?, laxSchemaOptions: LaxSchemaOptions
) -> String {
let encoder = Encoder(rowEncoder: tracks.rowEncoder(loggingToken))
return encoder.sqlStatements(schemaConstraints: schemaConstraints)
return encoder.sqlStatements(laxSchemaOptions: laxSchemaOptions)
}

func encode(_ tracks: [Track], loggingToken: String?, schemaConstraints: SchemaConstraints) throws
func encode(_ tracks: [Track], loggingToken: String?, laxSchemaOptions: LaxSchemaOptions) throws
-> Data
{
enum TracksSQLSourceEncoderError: Error {
case cannotMakeData
}
guard
let data = encode(tracks, loggingToken: loggingToken, schemaConstraints: schemaConstraints)
let data = encode(tracks, loggingToken: loggingToken, laxSchemaOptions: laxSchemaOptions)
.data(using: .utf8)
else {
throw TracksSQLSourceEncoderError.cannotMakeData
Expand Down

0 comments on commit 985e01b

Please sign in to comment.