Skip to content

Commit f06d7fe

Browse files
committed
Add “in” filter
1 parent 604ab81 commit f06d7fe

3 files changed

Lines changed: 55 additions & 7 deletions

File tree

Sources/DataTransferObjects/Query/CustomQuery+CompileDown.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ public extension CustomQuery {
162162
return filter
163163
case .null:
164164
return filter
165+
case .in:
166+
return filter
165167
case .and(let filterExpression):
166168
return Filter.and(.init(fields: filterExpression.fields.map { compileRelativeFilterInterval(filter: $0) }))
167169
case .or(let filterExpression):

Sources/DataTransferObjects/Query/Filter.swift

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,22 +193,34 @@ extension FilterEquals.MatchValue: Codable {
193193
var container = encoder.singleValueContainer()
194194

195195
switch self {
196-
case .string(let value):
196+
case let .string(value):
197197
try container.encode(value)
198-
case .int(let value):
198+
case let .int(value):
199199
try container.encode(value)
200-
case .double(let value):
200+
case let .double(value):
201201
try container.encode(value)
202-
case .arrayString(let value):
202+
case let .arrayString(value):
203203
try container.encode(value)
204-
case .arrayInt(let value):
204+
case let .arrayInt(value):
205205
try container.encode(value)
206-
case .arrayDouble(let value):
206+
case let .arrayDouble(value):
207207
try container.encode(value)
208208
}
209209
}
210210
}
211211

212+
/// The in filter can match input rows against a set of values, where a match occurs if the value is contained in the set.
213+
public struct FilterIn: Codable, Hashable, Equatable, Sendable {
214+
public init(dimension: String, values: [String]) {
215+
self.dimension = dimension
216+
self.values = values
217+
}
218+
219+
public let dimension: String
220+
public let values: [String]
221+
// extractionFn not supported atm
222+
}
223+
212224
/// The null filter matches rows where a column value is null.
213225
public struct FilterNull: Codable, Hashable, Equatable, Sendable {
214226
public init(column: String) {
@@ -223,7 +235,7 @@ public struct FilterNull: Codable, Hashable, Equatable, Sendable {
223235
public indirect enum Filter: Codable, Hashable, Equatable, Sendable {
224236
/// The selector filter will match a specific dimension with a specific value.
225237
/// Selector filters can be used as the base filters for more complex Boolean
226-
/// expressions of filters.
238+
/// expressions of filters (deprecated -- use equals instead)
227239
case selector(FilterSelector)
228240

229241
/// The column comparison filter is similar to the selector filter, but instead
@@ -252,6 +264,10 @@ public indirect enum Filter: Codable, Hashable, Equatable, Sendable {
252264
/// The null filter matches rows where a column value is null.
253265
case null(FilterNull)
254266

267+
/// The in filter can match input rows against a set of values, where a match occurs
268+
/// if the value is contained in the set.
269+
case `in`(FilterIn)
270+
255271
// logical expression filters
256272
case and(FilterExpression)
257273
case or(FilterExpression)
@@ -280,6 +296,8 @@ public indirect enum Filter: Codable, Hashable, Equatable, Sendable {
280296
self = try .equals(FilterEquals(from: decoder))
281297
case "null":
282298
self = try .null(FilterNull(from: decoder))
299+
case "in":
300+
self = try .in(FilterIn(from: decoder))
283301
case "and":
284302
self = try .and(FilterExpression(from: decoder))
285303
case "or":
@@ -321,6 +339,9 @@ public indirect enum Filter: Codable, Hashable, Equatable, Sendable {
321339
case let .null(null):
322340
try container.encode("null", forKey: .type)
323341
try null.encode(to: encoder)
342+
case let .in(inFilter):
343+
try container.encode("in", forKey: .type)
344+
try inFilter.self.encode(to: encoder)
324345
case let .and(and):
325346
try container.encode("and", forKey: .type)
326347
try and.encode(to: encoder)

Tests/QueryTests/FilterEqualsNullTests.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,29 @@ class FilterEqualsNullTests: XCTestCase {
205205
XCTAssertEqual(filterNull, decodedFilter)
206206
XCTAssertEqual(filterJSON, String(data: encodedFilter, encoding: .utf8))
207207
}
208+
209+
func testFilterIn() throws {
210+
let filterJSON = """
211+
{
212+
"dimension": "outlaw",
213+
"type": "in",
214+
"values": ["Good", "Bad", "Ugly"]
215+
}
216+
"""
217+
.filter { !$0.isWhitespace }
218+
219+
let filterNull = Filter.in(
220+
FilterIn(dimension: "outlaw", values: ["Good", "Bad", "Ugly"])
221+
)
222+
223+
let decodedFilter = try JSONDecoder.telemetryDecoder.decode(
224+
Filter.self,
225+
from: filterJSON.data(using: .utf8)!
226+
)
227+
228+
let encodedFilter = try JSONEncoder.telemetryEncoder.encode(filterNull)
229+
230+
XCTAssertEqual(filterNull, decodedFilter)
231+
XCTAssertEqual(filterJSON, String(data: encodedFilter, encoding: .utf8))
232+
}
208233
}

0 commit comments

Comments
 (0)