From 22fd58dccd72b497ea7886899443ef43a4a894d7 Mon Sep 17 00:00:00 2001 From: hiimtmac Date: Tue, 8 Nov 2022 12:50:06 -0600 Subject: [PATCH 1/3] add count distinct --- .../PSQLKit/Expressions/CountExpression.swift | 18 +++++++++++++- Tests/PSQLKitTests/ExpressionTests.swift | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Sources/PSQLKit/Expressions/CountExpression.swift b/Sources/PSQLKit/Expressions/CountExpression.swift index 909fc40..418621e 100644 --- a/Sources/PSQLKit/Expressions/CountExpression.swift +++ b/Sources/PSQLKit/Expressions/CountExpression.swift @@ -6,9 +6,16 @@ import SQLKit public struct CountExpression: AggregateExpression { let content: Content + let isDistinct: Bool + + init(_ content: Content, distinct: Bool) { + self.content = content + self.isDistinct = distinct + } public init(_ content: Content) { self.content = content + self.isDistinct = false } } @@ -16,15 +23,20 @@ extension CountExpression: SelectSQLExpression where Content: SelectSQLExpression { public var selectSqlExpression: SQLExpression { - _Select(content: self.content) + _Select(content: self.content, distinct: self.isDistinct) } private struct _Select: SQLExpression { let content: Content + let distinct: Bool func serialize(to serializer: inout SQLSerializer) { serializer.write("COUNT") serializer.write("(") + if distinct { + serializer.write("DISTINCT") + serializer.writeSpace() + } self.content.selectSqlExpression.serialize(to: &serializer) serializer.write(")") } @@ -58,4 +70,8 @@ extension CountExpression { public func `as`(_ alias: String) -> ExpressionAlias> { ExpressionAlias(expression: self, alias: alias) } + + public func distinct(_ isDistinct: Bool = true) -> Self { + .init(content, distinct: isDistinct) + } } diff --git a/Tests/PSQLKitTests/ExpressionTests.swift b/Tests/PSQLKitTests/ExpressionTests.swift index 7425e0f..98d5d7b 100644 --- a/Tests/PSQLKitTests/ExpressionTests.swift +++ b/Tests/PSQLKitTests/ExpressionTests.swift @@ -62,6 +62,30 @@ final class ExpressionTests: PSQLTestCase { XCTAssertEqual(fluentSerializer.sql, compare) XCTAssertEqual(psqlkitSerializer.sql, compare) } + + func testCountDistinct() { + SELECT { + COUNT(f.$name) + .distinct() + COUNT(f.$age) + .distinct() + .as("age") + } + .serialize(to: &fluentSerializer) + + SELECT { + COUNT(p.$name) + .distinct() + COUNT(p.$age) + .distinct() + .as("age") + } + .serialize(to: &psqlkitSerializer) + + let compare = #"SELECT COUNT(DISTINCT "x"."name"::TEXT), COUNT(DISTINCT "x"."age"::INTEGER) AS "age""# + XCTAssertEqual(fluentSerializer.sql, compare) + XCTAssertEqual(psqlkitSerializer.sql, compare) + } func testSum() { SELECT { From 28fdd283a368e4baa8d32fd432c865889e9e10c5 Mon Sep 17 00:00:00 2001 From: hiimtmac Date: Tue, 8 Nov 2022 13:10:50 -0600 Subject: [PATCH 2/3] better enums --- Sources/PSQLKit/PSQLExpression.swift | 6 ++++++ Sources/PSQLKit/TypeEquatable.swift | 4 ++++ Tests/PSQLKitTests/PSQLTests.swift | 14 ++++++++++++++ Tests/PSQLKitTests/WhereTests.swift | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/Sources/PSQLKit/PSQLExpression.swift b/Sources/PSQLKit/PSQLExpression.swift index 44b87a0..980e14b 100644 --- a/Sources/PSQLKit/PSQLExpression.swift +++ b/Sources/PSQLKit/PSQLExpression.swift @@ -19,3 +19,9 @@ extension PSQLExpression where Self: Encodable { .init(self) } } + +extension PSQLExpression where Self: RawRepresentable, RawValue: PSQLExpression { + public static var postgresColumnType: PostgresColumnType { + RawValue.postgresColumnType + } +} diff --git a/Sources/PSQLKit/TypeEquatable.swift b/Sources/PSQLKit/TypeEquatable.swift index aa8eead..ca76989 100644 --- a/Sources/PSQLKit/TypeEquatable.swift +++ b/Sources/PSQLKit/TypeEquatable.swift @@ -6,3 +6,7 @@ import Foundation public protocol TypeEquatable { associatedtype CompareType } + +extension TypeEquatable where Self: RawRepresentable, RawValue: TypeEquatable { + public typealias CompareType = RawValue +} diff --git a/Tests/PSQLKitTests/PSQLTests.swift b/Tests/PSQLKitTests/PSQLTests.swift index 48ed259..187eb3e 100644 --- a/Tests/PSQLKitTests/PSQLTests.swift +++ b/Tests/PSQLKitTests/PSQLTests.swift @@ -22,6 +22,8 @@ final class FluentModel: Model, Table { var money: Double @Field(key: "birthday") var birthday: Date + @Field(key: "category") + var category: Category @Group(key: "pet") var pet: Pet @@ -44,6 +46,11 @@ final class FluentModel: Model, Table { init() {} } } + + enum Category: String, Codable, Equatable, TypeEquatable, PSQLExpression { + case yes + case no + } } struct PSQLModel: Table { @@ -61,6 +68,8 @@ struct PSQLModel: Table { var money: Double @Column(key: "birthday") var birthday: Date + @Column(key: "category") + var category: Category @NestedColumn(key: "pet") var pet: Pet @@ -83,6 +92,11 @@ struct PSQLModel: Table { init() {} } } + + enum Category: String, Codable, Equatable, TypeEquatable, PSQLExpression { + case yes + case no + } } class PSQLTestCase: XCTestCase { diff --git a/Tests/PSQLKitTests/WhereTests.swift b/Tests/PSQLKitTests/WhereTests.swift index 275d88c..4fcc928 100644 --- a/Tests/PSQLKitTests/WhereTests.swift +++ b/Tests/PSQLKitTests/WhereTests.swift @@ -28,6 +28,24 @@ final class WhereTests: PSQLTestCase { XCTAssertEqual(fluentSerializer.sql, compare) XCTAssertEqual(fluentSerializer.sql, compare) } + + func testEnum() { + WHERE { + FluentModel.$category != FluentModel.$category + FluentModel.$category == FluentModel.Category.yes.rawValue + } + .serialize(to: &fluentSerializer) + + WHERE { + PSQLModel.$category != PSQLModel.$category + PSQLModel.$category == PSQLModel.Category.yes.rawValue + } + .serialize(to: &psqlkitSerializer) + + let compare = #"WHERE ("my_model"."category" != "my_model"."category") AND ("my_model"."category" = 'yes')"# + XCTAssertEqual(fluentSerializer.sql, compare) + XCTAssertEqual(fluentSerializer.sql, compare) + } func testMultiple() { WHERE { From 302be8f16a8681d442f9aadb971822997695ad55 Mon Sep 17 00:00:00 2001 From: hiimtmac Date: Tue, 8 Nov 2022 13:11:15 -0600 Subject: [PATCH 3/3] format --- Sources/PSQLKit/Expressions/CountExpression.swift | 8 ++++---- Tests/PSQLKitTests/ExpressionTests.swift | 2 +- Tests/PSQLKitTests/PSQLTests.swift | 4 ++-- Tests/PSQLKitTests/WhereTests.swift | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/PSQLKit/Expressions/CountExpression.swift b/Sources/PSQLKit/Expressions/CountExpression.swift index 418621e..c9ae293 100644 --- a/Sources/PSQLKit/Expressions/CountExpression.swift +++ b/Sources/PSQLKit/Expressions/CountExpression.swift @@ -7,7 +7,7 @@ import SQLKit public struct CountExpression: AggregateExpression { let content: Content let isDistinct: Bool - + init(_ content: Content, distinct: Bool) { self.content = content self.isDistinct = distinct @@ -33,7 +33,7 @@ extension CountExpression: SelectSQLExpression where func serialize(to serializer: inout SQLSerializer) { serializer.write("COUNT") serializer.write("(") - if distinct { + if self.distinct { serializer.write("DISTINCT") serializer.writeSpace() } @@ -70,8 +70,8 @@ extension CountExpression { public func `as`(_ alias: String) -> ExpressionAlias> { ExpressionAlias(expression: self, alias: alias) } - + public func distinct(_ isDistinct: Bool = true) -> Self { - .init(content, distinct: isDistinct) + .init(self.content, distinct: isDistinct) } } diff --git a/Tests/PSQLKitTests/ExpressionTests.swift b/Tests/PSQLKitTests/ExpressionTests.swift index 98d5d7b..12ece34 100644 --- a/Tests/PSQLKitTests/ExpressionTests.swift +++ b/Tests/PSQLKitTests/ExpressionTests.swift @@ -62,7 +62,7 @@ final class ExpressionTests: PSQLTestCase { XCTAssertEqual(fluentSerializer.sql, compare) XCTAssertEqual(psqlkitSerializer.sql, compare) } - + func testCountDistinct() { SELECT { COUNT(f.$name) diff --git a/Tests/PSQLKitTests/PSQLTests.swift b/Tests/PSQLKitTests/PSQLTests.swift index 187eb3e..f47e361 100644 --- a/Tests/PSQLKitTests/PSQLTests.swift +++ b/Tests/PSQLKitTests/PSQLTests.swift @@ -46,7 +46,7 @@ final class FluentModel: Model, Table { init() {} } } - + enum Category: String, Codable, Equatable, TypeEquatable, PSQLExpression { case yes case no @@ -92,7 +92,7 @@ struct PSQLModel: Table { init() {} } } - + enum Category: String, Codable, Equatable, TypeEquatable, PSQLExpression { case yes case no diff --git a/Tests/PSQLKitTests/WhereTests.swift b/Tests/PSQLKitTests/WhereTests.swift index 4fcc928..e473d26 100644 --- a/Tests/PSQLKitTests/WhereTests.swift +++ b/Tests/PSQLKitTests/WhereTests.swift @@ -28,7 +28,7 @@ final class WhereTests: PSQLTestCase { XCTAssertEqual(fluentSerializer.sql, compare) XCTAssertEqual(fluentSerializer.sql, compare) } - + func testEnum() { WHERE { FluentModel.$category != FluentModel.$category