Skip to content

Commit f646213

Browse files
Merge pull request #1 from fred-sch/main
ClickHouseVapor fail safely if row count is inconsistent
2 parents 3a38ada + ab8916f commit f646213

File tree

4 files changed

+42
-11
lines changed

4 files changed

+42
-11
lines changed

Sources/ClickHouseVapor/ClickHouseColumnConvertible.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension ClickHouseColumnConvertibleTyped {
4040

4141
public func setClickHouseArray(_ data: [ClickHouseDataType]) throws {
4242
guard let array = data as? [Value] else {
43-
throw ClickHouseVaporError.missmatchingDataType(columnName: key)
43+
throw ClickHouseVaporError.mismatchingDataType(columnName: key)
4444
}
4545
self.wrappedValue = array
4646
}

Sources/ClickHouseVapor/ClickHouseModel.swift

+11-6
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,22 @@ extension ClickHouseModel {
6464
}
6565
}
6666

67-
public func insert(on connection: ClickHouseConnectionProtocol, engine: ClickHouseEngine? = nil) -> EventLoopFuture<Void> {
67+
public func insert(on connection: ClickHouseConnectionProtocol, engine: ClickHouseEngine? = nil) throws -> EventLoopFuture<Void> {
6868
let fields = properties
6969
let engine = engine ?? Self.engine
70-
let data = fields.compactMap {
71-
return $0.count == 0 ? nil : ClickHouseColumn($0.key, $0.getClickHouseArray())
72-
}
73-
guard data.count > 0 else {
74-
// no values -> nothing to do
70+
71+
guard let rowCount = fields.first?.count else {
72+
// no columns -> nothing to do
7573
return connection.eventLoop.makeSucceededFuture(())
7674
}
7775

76+
let data = try fields.compactMap { field -> ClickHouseColumn? in
77+
// check that all columns have the same amount of rows
78+
guard field.count == rowCount else {
79+
throw ClickHouseVaporError.mismatchingRowCount(count: field.count, expected: rowCount)
80+
}
81+
return rowCount == 0 ? nil : ClickHouseColumn(field.key, field.getClickHouseArray())
82+
}
7883
return connection.insert(into: engine.tableWithDatabase, data: data)
7984
}
8085

Sources/ClickHouseVapor/ClickHouseVaporError.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
//
77

88
public enum ClickHouseVaporError: Error {
9-
case missmatchingDataType(columnName: String)
9+
case mismatchingDataType(columnName: String)
10+
case mismatchingRowCount(count: Int, expected: Int)
1011
}

Tests/ClickHouseVaporTests/ClickHouseVaporTests.swift

+28-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ public class TestModel : ClickHouseModel {
4848

4949

5050
final class ClickHouseVaporTests: XCTestCase {
51+
52+
static var allTests = [
53+
("testPing", testPing),
54+
("testModel", testModel),
55+
("testModelMissesColumns", testModelMissesColumns)
56+
]
57+
5158
func testPing() {
5259
let app = Application(.testing)
5360
defer { app.shutdown() }
@@ -103,8 +110,26 @@ final class ClickHouseVaporTests: XCTestCase {
103110
XCTAssertEqual(model3.id, model2.id)
104111
XCTAssertEqual(model3.timestamp, model2.timestamp)
105112
}
113+
114+
/// model should fail if insert with empty columns is tried
115+
public func testModelMissesColumns() {
116+
let app = Application(.testing)
117+
defer { app.shutdown() }
118+
try! app.configureClickHouseDatabases()
119+
app.logger.logLevel = .trace
120+
121+
let model = TestModel()
122+
123+
// drop table to ensure unit test
124+
try! TestModel.deleteTable(on: app.clickHouse).wait()
125+
126+
127+
model.id = [ "x010", "ax51", "cd22" ]
128+
model.fixed = [ "", "123456", "12345678901234" ]
129+
model.temperature = [ 11.1, 10.4, 8.9 ]
130+
131+
try! TestModel.createTable(on: app.clickHouse).wait()
132+
XCTAssertThrowsError(try model.insert(on: app.clickHouse).wait(), "\(ClickHouseVaporError.mismatchingRowCount(count: 0, expected: 3))")
133+
}
106134

107-
static var allTests = [
108-
("testPing", testPing),
109-
]
110135
}

0 commit comments

Comments
 (0)