Skip to content

Commit 9116c1f

Browse files
authored
Merge pull request #381 from zapcannon87/developer
feat(query): static functions of or & and
2 parents 6ce77e4 + beb9896 commit 9116c1f

File tree

3 files changed

+148
-77
lines changed

3 files changed

+148
-77
lines changed

LeanCloudTests/IMConversationTestCase.swift

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,15 +1431,7 @@ class IMConversationTestCase: RTMBaseTestCase {
14311431
})) as ()??)
14321432
wait(for: [generalQueryExp2], timeout: timeout)
14331433

1434-
let invalidQuery = LCQuery(className: "invalid")
1435-
for constraint in
1436-
[ LCQuery.Constraint.selected,
1437-
LCQuery.Constraint.included,
1438-
LCQuery.Constraint.matchedQuery(invalidQuery),
1439-
LCQuery.Constraint.notMatchedQuery(invalidQuery),
1440-
LCQuery.Constraint.matchedQueryAndKey(query: invalidQuery, key: ""),
1441-
LCQuery.Constraint.notMatchedQueryAndKey(query: invalidQuery, key: "")]
1442-
{
1434+
for constraint in [LCQuery.Constraint.selected, LCQuery.Constraint.included] {
14431435
do {
14441436
let conversationQuery = clientA.conversationQuery
14451437
try conversationQuery.where("key", constraint)

Sources/Foundation/Query.swift

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,12 @@ public class LCQuery: NSObject, NSCopying, NSCoding {
269269
}
270270
}
271271

272-
func `where`(_ key: String, _ constraint: Constraint) throws {
272+
/// Add a constraint for key.
273+
/// - Parameters:
274+
/// - key: The key will be constrained.
275+
/// - constraint: See `Constraint`.
276+
/// - Throws: `LCError`
277+
public func `where`(_ key: String, _ constraint: Constraint) throws {
273278
var dictionary: [String: Any]?
274279
switch constraint {
275280
/* Key */
@@ -321,17 +326,21 @@ public class LCQuery: NSObject, NSCopying, NSCoding {
321326
]
322327
/* Query */
323328
case let .matchedQuery(query):
329+
try self.validateApplication(query)
324330
dictionary = ["$inQuery": query]
325331
case let .notMatchedQuery(query):
332+
try self.validateApplication(query)
326333
dictionary = ["$notInQuery": query]
327334
case let .matchedQueryAndKey(query, key):
335+
try self.validateApplication(query)
328336
dictionary = [
329337
"$select": [
330338
"query": query,
331339
"key": key
332340
]
333341
]
334342
case let .notMatchedQueryAndKey(query, key):
343+
try self.validateApplication(query)
335344
dictionary = [
336345
"$dontSelect": [
337346
"query": query,
@@ -375,37 +384,79 @@ public class LCQuery: NSObject, NSCopying, NSCoding {
375384
}
376385
}
377386

378-
private func validateApplicationAndClassName(_ query: LCQuery) throws {
379-
guard query.application === self.application else {
387+
private func validateApplication(_ query: LCQuery) throws {
388+
guard self.application === query.application else {
380389
throw LCError(
381390
code: .inconsistency,
382-
reason: "`application` !== `query.application`, they should be the same instance.")
391+
reason: "`self.application` !== `query.application`, they should be the same instance.")
383392
}
384-
guard query.objectClassName == objectClassName else {
393+
}
394+
395+
private func validateClassName(_ query: LCQuery) throws {
396+
guard self.objectClassName == query.objectClassName else {
385397
throw LCError(
386398
code: .inconsistency,
387-
reason: "`objectClassName` != `query.objectClassName`, they should be equal.")
399+
reason: "`self.objectClassName` != `query.objectClassName`, they should be equal.")
388400
}
389401
}
390402

403+
private static func validateApplicationAndClassName(_ queries: [LCQuery]) throws {
404+
guard let first = queries.first else {
405+
return
406+
}
407+
for item in queries {
408+
try first.validateApplication(item)
409+
try first.validateClassName(item)
410+
}
411+
}
412+
413+
private static func combine(
414+
queries: [LCQuery],
415+
operation: String) throws -> LCQuery
416+
{
417+
try self.validateApplicationAndClassName(queries)
418+
guard let first = queries.first else {
419+
throw LCError(
420+
code: .inconsistency,
421+
reason: "`queries` is empty.")
422+
}
423+
let query = LCQuery(
424+
application: first.application,
425+
className: first.objectClassName)
426+
query.constraintDictionary[operation] = queries.map { $0.constraintDictionary }
427+
return query
428+
}
429+
430+
/// Performs a logical AND operation on an array of one or more expressions of query.
431+
/// - Parameter queries: An array of one or more expressions of query.
432+
/// - Throws: `LCError`
433+
/// - Returns: A new `LCQuery`.
434+
public class func and(_ queries: [LCQuery]) throws -> LCQuery {
435+
return try self.combine(queries: queries, operation: "$and")
436+
}
437+
438+
/// Performs a logical AND operation on self and the query.
439+
/// - Parameter query: The query.
440+
/// - Throws: `LCError`
441+
/// - Returns: A new `LCQuery`.
391442
public func and(_ query: LCQuery) throws -> LCQuery {
392-
try validateApplicationAndClassName(query)
393-
394-
let result = LCQuery(application: self.application, className: objectClassName)
395-
396-
result.constraintDictionary["$and"] = [self.constraintDictionary, query.constraintDictionary]
397-
398-
return result
443+
return try LCQuery.and([self, query])
444+
}
445+
446+
/// Performs a logical OR operation on an array of one or more expressions of query.
447+
/// - Parameter queries: An array of one or more expressions of query.
448+
/// - Throws: `LCError`
449+
/// - Returns: A new `LCQuery`.
450+
public class func or(_ queries: [LCQuery]) throws -> LCQuery {
451+
return try self.combine(queries: queries, operation: "$or")
399452
}
400453

454+
/// Performs a logical OR operation on self and the query.
455+
/// - Parameter query: The query.
456+
/// - Throws: `LCError`
457+
/// - Returns: A new `LCQuery`.
401458
public func or(_ query: LCQuery) throws -> LCQuery {
402-
try validateApplicationAndClassName(query)
403-
404-
let result = LCQuery(application: self.application, className: objectClassName)
405-
406-
result.constraintDictionary["$or"] = [self.constraintDictionary, query.constraintDictionary]
407-
408-
return result
459+
return try LCQuery.or([self, query])
409460
}
410461

411462
func lconWhereString() throws -> String? {

Sources/RTM/IMConversationQuery.swift

Lines changed: 76 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -47,67 +47,85 @@ public class IMConversationQuery: LCQuery {
4747

4848
// MARK: Combine
4949

50-
/**
51-
Get logic AND of another query.
52-
Note that it only combine constraints of two queries, the limit and skip option will be discarded.
53-
54-
- parameter query: The another query.
55-
- returns: The logic AND of two queries.
56-
*/
57-
public func and(_ query: IMConversationQuery) throws -> IMConversationQuery? {
58-
return try self.combine(op: "$and", query: query)
50+
private func validateClient(_ query: IMConversationQuery) throws {
51+
guard let selfClient = self.client,
52+
let queryClient = query.client,
53+
selfClient === queryClient else {
54+
throw LCError(
55+
code: .inconsistency,
56+
reason: "`self.client` !== query.client, they should be the same instance.")
57+
}
5958
}
6059

61-
/**
62-
Get logic OR of another query.
63-
Note that it only combine constraints of two queries, the limit and skip option will be discarded.
64-
65-
- parameter query: The another query.
66-
- returns: The logic OR of two queries.
67-
*/
68-
public func or(_ query: IMConversationQuery) throws -> IMConversationQuery? {
69-
return try self.combine(op: "$or", query: query)
60+
private static func validateClient(_ queries: [IMConversationQuery]) throws {
61+
guard let first = queries.first else {
62+
return
63+
}
64+
for item in queries {
65+
try first.validateClient(item)
66+
}
7067
}
7168

72-
private func combine(op: String, query: IMConversationQuery) throws -> IMConversationQuery? {
73-
guard let client = self.client else {
74-
return nil
75-
}
76-
guard client === query.client else {
69+
private static func combine(
70+
queries: [IMConversationQuery],
71+
operation: String) throws -> IMConversationQuery?
72+
{
73+
guard let first = queries.first else {
7774
throw LCError(
7875
code: .inconsistency,
79-
reason: "`client` !== `query.client`, they should be the same instance.")
76+
reason: "`queries` is empty.")
77+
}
78+
guard let client = first.client else {
79+
return nil
8080
}
81-
let result = IMConversationQuery(client: client, eventQueue: self.eventQueue)
82-
result.constraintDictionary[op] = [self.constraintDictionary, query.constraintDictionary]
83-
return result
81+
try self.validateClient(queries)
82+
let query = IMConversationQuery(
83+
client: client,
84+
eventQueue: first.eventQueue)
85+
query.constraintDictionary[operation] = queries.map { $0.constraintDictionary }
86+
return query
87+
}
88+
89+
/// Performs a logical AND operation on an array of one or more expressions of query.
90+
/// - Parameter queries: An array of one or more expressions of query.
91+
/// - Throws: `LCError`
92+
/// - Returns: An optional `IMConversationQuery`
93+
public static func and(_ queries: [IMConversationQuery]) throws -> IMConversationQuery? {
94+
return try self.combine(queries: queries, operation: "$and")
95+
}
96+
97+
/// Performs a logical AND operation on self and the query.
98+
/// - Parameter query: The query.
99+
/// - Throws: `LCError`
100+
/// - Returns: An optional `IMConversationQuery`
101+
public func and(_ query: IMConversationQuery) throws -> IMConversationQuery? {
102+
return try IMConversationQuery.and([self, query])
84103
}
85104

86-
// MARK: Where Condition
105+
/// Performs a logical OR operation on an array of one or more expressions of query.
106+
/// - Parameter queries: An array of one or more expressions of query.
107+
/// - Throws: `LCError`
108+
/// - Returns: An optional `IMConversationQuery`
109+
public static func or(_ queries: [IMConversationQuery]) throws -> IMConversationQuery? {
110+
return try self.combine(queries: queries, operation: "$or")
111+
}
112+
113+
/// Performs a logical OR operation on self and the query.
114+
/// - Parameter query: The query.
115+
/// - Throws: `LCError`
116+
/// - Returns: An optional `IMConversationQuery`
117+
public func or(_ query: IMConversationQuery) throws -> IMConversationQuery? {
118+
return try IMConversationQuery.or([self, query])
119+
}
120+
121+
// MARK: Where
87122

88-
/// Add constraint in query.
89-
///
90-
/// - Parameters:
91-
/// - key: The key.
92-
/// - constraint: The constraint.
93123
public override func `where`(_ key: String, _ constraint: Constraint) throws {
94-
let typeChecker: (LCQuery) throws -> Void = { query in
95-
guard let _ = query as? IMConversationQuery else {
96-
throw LCError(code: .inconsistency, reason: "\(type(of: query)) not support")
97-
}
98-
}
99124
switch constraint {
100125
case .included, .selected:
101-
throw LCError(code: .inconsistency, reason: "\(constraint) not support")
102-
/* Query matching. */
103-
case let .matchedQuery(query):
104-
try typeChecker(query)
105-
case let .notMatchedQuery(query):
106-
try typeChecker(query)
107-
case let .matchedQueryAndKey(query, _):
108-
try typeChecker(query)
109-
case let .notMatchedQueryAndKey(query, _):
110-
try typeChecker(query)
126+
throw LCError(
127+
code: .inconsistency,
128+
reason: "\(constraint) not support.")
111129
default:
112130
break
113131
}
@@ -310,6 +328,16 @@ public class IMConversationQuery: LCQuery {
310328
fatalError("not support")
311329
}
312330

331+
@available(*, unavailable)
332+
public override class func and(_ queries: [LCQuery]) throws -> LCQuery {
333+
fatalError("not support")
334+
}
335+
336+
@available(*, unavailable)
337+
public override class func or(_ queries: [LCQuery]) throws -> LCQuery {
338+
fatalError("not support")
339+
}
340+
313341
@available(*, unavailable)
314342
public override func and(_ query: LCQuery) throws -> LCQuery {
315343
fatalError("not support")

0 commit comments

Comments
 (0)