Skip to content

Commit 667f561

Browse files
authored
Merge pull request #73 from novi/fix-parameter-type
Add support for table name, column type QueryParameter
2 parents 38e7e80 + cdddf25 commit 667f561

13 files changed

+78
-38
lines changed

Sources/MySQL/Blob.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ extension Data: QueryParameterType {
6464
buffer += "'"
6565
return buffer
6666
}
67+
public func escapedForID() -> String? {
68+
return nil
69+
}
6770
}
6871

6972
extension Data: QueryParameter {

Sources/MySQL/Connection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public final class Connection {
142142
return mysql_
143143
}
144144

145-
internal var ping: Bool {
145+
internal func ping() -> Bool {
146146
_ = try? connectIfNeeded()
147147
guard let mysql = mysql else {
148148
return false

Sources/MySQL/ConnectionPool.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ final public class ConnectionPool: CustomStringConvertible {
5757

5858
private func getUsableConnection() -> Connection? {
5959
for c in pool {
60-
if c.isInUse == false && c.ping {
60+
if c.isInUse == false && c.ping() {
6161
c.isInUse = true
6262
return c
6363
}

Sources/MySQL/Date.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ extension Date: QueryParameter {
111111
} // TODO: in Linux
112112

113113
// YYYY-MM-DD HH:MM:SS
114-
return QueryParameterWrap( "'\(pad(num: comp.year ?? 0, digits: 4))-\(pad(num: comp.month ?? 0))-\(pad(num: comp.day ?? 0)) \(pad(num: comp.hour ?? 0)):\(pad(num: comp.minute ?? 0)):\(pad(num: comp.second ?? 0))'" )
114+
return EscapedQueryParameter( "'\(pad(num: comp.year ?? 0, digits: 4))-\(pad(num: comp.month ?? 0))-\(pad(num: comp.day ?? 0)) \(pad(num: comp.hour ?? 0)):\(pad(num: comp.minute ?? 0)):\(pad(num: comp.second ?? 0))'" )
115115
}
116116
}
117117

Sources/MySQL/SQLType.swift renamed to Sources/MySQL/EnumParameter.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,19 @@ extension SQLEnumType where RawValue == String {
2222
}
2323
}
2424

25+
2526
extension SQLEnumType where RawValue == String {
2627
public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
2728
return rawValue.queryParameter(option: option)
2829
}
2930
}
3031

32+
public protocol QueryEnumParameter: RawRepresentable, QueryParameter {
33+
34+
}
35+
36+
extension QueryEnumParameter where Self.RawValue: QueryParameter {
37+
public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
38+
return try rawValue.queryParameter(option: option)
39+
}
40+
}

Sources/MySQL/ParameterBuilder.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,22 @@
66
// Copyright © 2015 Yusuke Ito. All rights reserved.
77
//
88

9+
@available(*, deprecated)
910
public func build<A: QueryParameter>(_ p: (A) ) -> [QueryParameter] {
1011
return [
1112
p
1213
]
1314
}
1415

16+
@available(*, deprecated)
1517
public func build<A: QueryParameter, B: QueryParameter>(_ p: (A, B) ) -> [QueryParameter] {
1618
return [
1719
p.0,
1820
p.1
1921
]
2022
}
2123

24+
@available(*, deprecated)
2225
public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter>(_ p: (A, B, C) ) -> [QueryParameter] {
2326
return [
2427
p.0,
@@ -27,6 +30,7 @@ public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter>(_ p:
2730
]
2831
}
2932

33+
@available(*, deprecated)
3034
public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: QueryParameter>(_ p: (A, B, C, D) ) -> [QueryParameter] {
3135
return [
3236
p.0,
@@ -36,6 +40,7 @@ public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: Qu
3640
]
3741
}
3842

43+
@available(*, deprecated)
3944
public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: QueryParameter, E: QueryParameter>(_ p: (A, B, C, D, E) ) -> [QueryParameter] {
4045
return [
4146
p.0,
@@ -46,6 +51,7 @@ public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: Qu
4651
]
4752
}
4853

54+
@available(*, deprecated)
4955
public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: QueryParameter, E: QueryParameter, F: QueryParameter>(_ p: (A, B, C, D, E, F) ) -> [QueryParameter] {
5056
return [
5157
p.0,
@@ -57,6 +63,7 @@ public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: Qu
5763
]
5864
}
5965

66+
@available(*, deprecated)
6067
public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: QueryParameter, E: QueryParameter, F: QueryParameter, G: QueryParameter>(_ p: (A, B, C, D, E, F, G) ) -> [QueryParameter] {
6168
return [
6269
p.0,
@@ -67,4 +74,4 @@ public func build<A: QueryParameter, B: QueryParameter, C: QueryParameter, D: Qu
6774
p.5,
6875
p.6
6976
]
70-
}
77+
}

Sources/MySQL/QueryParameterType.swift

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public struct QueryParameterNull: QueryParameter, ExpressibleByNilLiteral {
4343

4444
}
4545
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
46-
return QueryParameterWrap( "NULL" )
46+
return EscapedQueryParameter( "NULL" )
4747
}
4848
}
4949

@@ -57,10 +57,10 @@ public struct QueryDictionary: QueryParameter {
5757
var keyVals: [String] = []
5858
for (k, v) in dict {
5959
if v == nil || v?.omitOnQueryParameter == false {
60-
keyVals.append("\(SQLString.escapeId(string: k)) = \(try QueryParameterOptional(v).queryParameter(option: option).escaped())")
60+
keyVals.append("\(SQLString.escapeForID(string: k)) = \(try QueryParameterOptional(v).queryParameter(option: option).escaped())")
6161
}
6262
}
63-
return QueryParameterWrap( keyVals.joined(separator: ", ") )
63+
return EscapedQueryParameter( keyVals.joined(separator: ", ") )
6464
}
6565
}
6666

@@ -82,7 +82,7 @@ public struct QueryArray: QueryParameter, QueryArrayType {
8282
self.arr = arr.map { Optional($0) }
8383
}
8484
public func queryParameter(option: QueryParameterOption) throws -> QueryParameterType {
85-
return QueryParameterWrap( try arr.filter({ val in
85+
return EscapedQueryParameter( try arr.filter({ val in
8686
if let valid = val {
8787
return valid.omitOnQueryParameter == false
8888
}
@@ -137,109 +137,117 @@ struct QueryParameterOptional: QueryParameter {
137137
}
138138
}
139139

140-
struct QueryParameterWrap: QueryParameterType {
141-
let val: String
142-
init(_ val: String) {
143-
self.val = val
140+
struct EscapedQueryParameter: QueryParameterType {
141+
private let value: String
142+
private let idParameter: String?
143+
init(_ val: String, idParameter: String? = nil) {
144+
self.value = val
145+
self.idParameter = idParameter
144146
}
145147
func escaped() -> String {
146-
return val
148+
return value
149+
}
150+
func escapedForID() -> String? {
151+
return idParameter
147152
}
148153
}
149154

150155
extension String: QueryParameterType {
151156
public func escaped() -> String {
152157
return SQLString.escape(string: self)
153158
}
159+
public func escapedForID() -> String? {
160+
return SQLString.escapeForID(string: self)
161+
}
154162
}
155163

156164
extension String: QueryParameter {
157165
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
158-
return QueryParameterWrap( SQLString.escape(string: self) )
166+
return self
159167
}
160168
}
161169

162170
extension Int: QueryParameter {
163171
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
164-
return QueryParameterWrap( String(self) )
172+
return EscapedQueryParameter( String(self) )
165173
}
166174
}
167175

168176
extension UInt: QueryParameter {
169177
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
170-
return QueryParameterWrap( String(self) )
178+
return EscapedQueryParameter( String(self) )
171179
}
172180
}
173181

174182
extension Int64: QueryParameter {
175183
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
176-
return QueryParameterWrap( String(self) )
184+
return EscapedQueryParameter( String(self) )
177185
}
178186
}
179187

180188
extension Int32: QueryParameter {
181189
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
182-
return QueryParameterWrap( String(self) )
190+
return EscapedQueryParameter( String(self) )
183191
}
184192
}
185193

186194
extension Int16: QueryParameter {
187195
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
188-
return QueryParameterWrap( String(self) )
196+
return EscapedQueryParameter( String(self) )
189197
}
190198
}
191199

192200
extension Int8: QueryParameter {
193201
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
194-
return QueryParameterWrap( String(self) )
202+
return EscapedQueryParameter( String(self) )
195203
}
196204
}
197205

198206
extension UInt64: QueryParameter {
199207
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
200-
return QueryParameterWrap( String(self) )
208+
return EscapedQueryParameter( String(self) )
201209
}
202210
}
203211

204212
extension UInt32: QueryParameter {
205213
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
206-
return QueryParameterWrap( String(self) )
214+
return EscapedQueryParameter( String(self) )
207215
}
208216
}
209217

210218
extension UInt16: QueryParameter {
211219
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
212-
return QueryParameterWrap( String(self) )
220+
return EscapedQueryParameter( String(self) )
213221
}
214222
}
215223

216224
extension UInt8: QueryParameter {
217225
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
218-
return QueryParameterWrap( String(self) )
226+
return EscapedQueryParameter( String(self) )
219227
}
220228
}
221229

222230
extension Double: QueryParameter {
223231
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
224-
return QueryParameterWrap( String(self) )
232+
return EscapedQueryParameter( String(self) )
225233
}
226234
}
227235

228236
extension Float: QueryParameter {
229237
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
230-
return QueryParameterWrap( String(self) )
238+
return EscapedQueryParameter( String(self) )
231239
}
232240
}
233241

234242
extension Bool: QueryParameter {
235243
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
236-
return QueryParameterWrap( self ? "true" : "false" )
244+
return EscapedQueryParameter( self ? "true" : "false" )
237245
}
238246
}
239247

240248
extension Decimal: QueryParameter {
241249
public func queryParameter(option: QueryParameterOption) -> QueryParameterType {
242-
return QueryParameterWrap( String(describing: self) )
250+
return EscapedQueryParameter( String(describing: self) )
243251
}
244252
}
245253

Sources/MySQL/Result.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ infix operator <| : DecodingPrecedence
1717
infix operator <|? : DecodingPrecedence
1818

1919

20+
@available(*, deprecated)
2021
public protocol QueryRowResultType {
2122
static func decodeRow(r: QueryRowResult) throws -> Self
2223
}

Sources/SQLFormatter/Error.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
public enum QueryFormatError: Error {
1010
case castError(actual: String, expected: String, key: String)
1111
case queryParameterCountMismatch(query: String)
12-
case queryParameterIdTypeError(query: String)
12+
case queryParameterIDTypeError(given: String, query: String)
1313
}

Sources/SQLFormatter/QueryFormatter.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import Foundation
1010

1111
public protocol QueryParameterType {
1212
func escaped() -> String
13+
func escapedForID() -> String? // returns nil, if not supported for query id parameter
1314
}
1415

1516
public struct SQLString {
1617

17-
public static func escapeId(string str: String) -> String {
18+
public static func escapeForID(string str: String) -> String {
1819
var step1 = ""
1920
for c in str {
2021
switch c {
@@ -96,10 +97,10 @@ public struct QueryFormatter {
9697
if placeHolderCount >= args.count {
9798
throw QueryFormatError.queryParameterCountMismatch(query: query)
9899
}
99-
guard let val = args[placeHolderCount] as? String else {
100-
throw QueryFormatError.queryParameterIdTypeError(query: query)
100+
guard let escapedVal = args[placeHolderCount].escapedForID() else {
101+
throw QueryFormatError.queryParameterIDTypeError(given: "\(args[placeHolderCount])", query: query)
101102
}
102-
formatted.replaceSubrange(r, with: SQLString.escapeId(string: val))
103+
formatted.replaceSubrange(r, with: escapedVal)
103104
scanRange = r.upperBound..<formatted.endIndex
104105
case "?":
105106
if placeHolderCount >= args.count {

Tests/MySQLTests/ConnectionTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ final class ConnectionTests: XCTestCase, MySQLTestType {
3232

3333
func testConnect() throws {
3434
let conn = try pool.getConnection()
35-
XCTAssertTrue(conn.ping)
35+
XCTAssertTrue(conn.ping())
3636
}
3737

3838
func testConnect2() throws {
3939
let conn = try pool.getConnection()
4040
_ = try conn.query("SELECT 1;" as String)
41-
XCTAssertTrue(conn.ping)
41+
XCTAssertTrue(conn.ping())
4242
}
4343

4444
struct Option: ConnectionOption {

Tests/MySQLTests/QueryFormatterTests.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,24 @@ extension QueryFormatterTests {
2323

2424
final class QueryFormatterTests: XCTestCase {
2525

26+
fileprivate enum TableName: String, QueryEnumParameter {
27+
case user = "user"
28+
}
29+
2630
func testBasicFormatting() throws {
2731

28-
let params: (String, String, Int, String, Int?) = (
32+
let params: (String, TableName, String, Int, String, Int?) = (
2933
"i.d",
34+
TableName.user,
3035
"id",
3136
1,
3237
"user's",
3338
nil
3439
)
3540
let args = build(params)
3641

37-
let formatted = try QueryFormatter.format(query: "SELECT name,??,id FROM users WHERE ?? = ? OR name = ? OR age is ?;", args: Connection.buildArgs(args, option: queryOption) )
38-
XCTAssertEqual(formatted, "SELECT name,`i`.`d`,id FROM users WHERE `id` = 1 OR name = 'user\\'s' OR age is NULL;")
42+
let formatted = try QueryFormatter.format(query: "SELECT name,??,id FROM ?? WHERE ?? = ? OR name = ? OR age is ?;", args: Connection.buildArgs(args, option: queryOption) )
43+
XCTAssertEqual(formatted, "SELECT name,`i`.`d`,id FROM `user` WHERE `id` = 1 OR name = 'user\\'s' OR age is NULL;")
3944
}
4045

4146
func testPlaceholder() throws {

Tests/MySQLTests/SQLTypeTests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ final class SQLTypeTests: XCTestCase {
3434
case second = "second' 2"
3535
}
3636

37+
enum SomeEnumParameter: String, QueryEnumParameter {
38+
case first = "first 1"
39+
case second = "second' 2"
40+
}
41+
3742
enum SomeEnumCodable: String, Codable, QueryParameter {
3843
case first = "first 1"
3944
case second = "second' 2"

0 commit comments

Comments
 (0)