Skip to content

Instantly share code, notes, and snippets.

@Danappelxx
Created July 2, 2016 06:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Danappelxx/1f5b117b1e4730a23a6b517cdb635a31 to your computer and use it in GitHub Desktop.
Save Danappelxx/1f5b117b1e4730a23a6b517cdb635a31 to your computer and use it in GitHub Desktop.
An exercise to execute basic SQL queries (skipped parsing)
indirect enum Query {
case equal(field: String, value: String)
case notEqual(field: String, value: String)
case not(query: Query)
case or(first: Query, second: Query)
case and(first: Query, second: Query)
}
func &&(lhs: Query, rhs: Query) -> Query {
return .and(first: lhs, second: rhs)
}
func ||(lhs: Query, rhs: Query) -> Query {
return .or(first: lhs, second: rhs)
}
prefix func !(query: Query) -> Query {
return .not(query: query)
}
func ==(lhs: String, rhs: String) -> Query {
return .equal(field: lhs, value: rhs)
}
func !=(lhs: String, rhs: String) -> Query {
return .notEqual(field: lhs, value: rhs)
}
extension Query {
func satisfied(by row: [String:String]) -> Bool {
switch self {
case let .equal(field: field, value: value):
return !row.filter { $0 == (field, value) }.isEmpty
case let .notEqual(field: field, value: value):
return !Query.equal(field: field, value: value).satisfied(by: row)
case let .not(query: query):
return !query.satisfied(by: row)
case let .or(first: first, second: second):
return first.satisfied(by: row) || second.satisfied(by: row)
case let .and(first: first, second: second):
return first.satisfied(by: row) && second.satisfied(by: row)
}
}
}
func execute(_ query: Query) -> [String:String]? {
let database: [[String:String]] = [
[
"birthyear": "2000",
"name": "dan"
],
[
"birthyear": "1972",
"name": "vladimir"
]
]
for row in database where query.satisfied(by: row) {
return row
}
return nil
}
let query: Query = "name" == "igor" || "birthyear" == "2000" && ("name" == "dan" || "name" == "vladimir")
print(query) // -> .or(.equal("name", "igor"), .and(.equal("birthyear", "2000"), .or(.equal("name", "dan"), .equal("name", "vladimir"))))
let matching = execute(query)
print(matching) // -> ["birthyear": "1972", "name": "vladimir"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment