HealthImport/HealthImport/Model/Tables/SamplesTable.swift
2024-02-02 13:06:27 +01:00

89 lines
3.6 KiB
Swift

import Foundation
import SQLite
struct SamplesTable {
private let database: Connection
private let quantitySamples: QuantitySamplesTable
private let objects: ObjectsTable
private let dataProvenances: DataProvenancesTable
private let unitStrings: UnitStringsTable
init(database: Connection) {
self.database = database
self.quantitySamples = .init(database: database)
self.objects = .init(database: database)
self.dataProvenances = .init(database: database)
self.unitStrings = .init(database: database)
}
func create() throws {
try database.execute("CREATE TABLE samples (data_id INTEGER PRIMARY KEY, start_date REAL, end_date REAL, data_type INTEGER)")
}
private let table = Table("samples")
private let dataId = Expression<Int>("data_id")
// NOTE: Technically optional
private let startDate = Expression<Double>("start_date")
// NOTE: Technically optional
private let endDate = Expression<Double>("end_date")
private let dataType = Expression<Int>("data_type")
func samples(from start: Date, to end: Date) throws -> [Sample] {
let start = start.timeIntervalSinceReferenceDate
let end = end.timeIntervalSinceReferenceDate
// Samples: data_id, start_date, end_date, data_type
// JOIN quantity_samples on samples.data_id == quantity_samples.data_id
// quantity_samples: quantity, original_quantity, original_unit
// JOIN objects on samples.data_id == objects.data_id
// objects: data_id, uuid, provenance, type, creation_date
// JOIN data_provenances on objects.provenance == data_provenances.ROWID
// SELECT tz_name FROM data_provenances
let selection = table
.select(table[*],
quantitySamples.table[*],
dataProvenances.table[dataProvenances.tzName],
unitStrings.table[unitStrings.unitString])
.filter(startDate >= start && endDate <= end)
.join(.leftOuter, quantitySamples.table, on: table[dataId] == quantitySamples.table[quantitySamples.dataId])
.join(.leftOuter, objects.table, on: table[dataId] == objects.table[objects.dataId])
.join(.leftOuter, dataProvenances.table, on: objects.table[objects.provenance] == dataProvenances.table[dataProvenances.rowId])
.join(.leftOuter, unitStrings.table, on: quantitySamples.table[quantitySamples.originalUnit] == unitStrings.table[unitStrings.rowId])
return try database.prepare(selection).map { row in
let startDate = Date(timeIntervalSinceReferenceDate: row[startDate])
let endDate = Date(timeIntervalSinceReferenceDate: row[endDate])
let dataType = Sample.DataType(rawValue: row[dataType])
let quantity = row[quantitySamples.quantity]
let original = row[quantitySamples.originalQuantity]
let unit = row[unitStrings.unitString]
let timeZone = row[dataProvenances.tzName].nonEmpty
return .init(
startDate: startDate,
endDate: endDate,
dataType: dataType,
quantity: quantity,
originalQuantity: original,
originalUnit: unit,
timeZoneName: timeZone)
}
}
func sampleCount(from start: Date, to end: Date) throws -> Int {
let start = start.timeIntervalSinceReferenceDate
let end = end.timeIntervalSinceReferenceDate
return try database.scalar(table.filter(startDate >= start && endDate <= end).count)
}
}