Document the new way of initializing database connections. And stop
saying "instantiate" all the time.
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
Most things should work as they have been, with a few notes:
- The `db.transaction` helpers that took variadic auto-closures have
been removed (Swift no longer supports variadic auto-closures).
Update path: use `&&` and `||` for control flow:
db.transaction() &&
stmt1 &&
stmt2 &&
db.commit() || db.rollback()
Or use the block-based helper:
db.transaction { _ in
stmt1.run()
if stmt1.failed { return .Rollback }
stmt2.run()
if stmt2.failed { return .Rollback }
return .Commit
}
Note: You'll need to explicitly call/return COMMIT and ROLLBACK now.
- There appears to be a bug in Swift causing 2 memory-related,
over-releasing crashes in the test suite. Filed: rdar://19782170
Many bugs marked FIXME with links to rdars are now fixable and have been
fixed.
The tests have also been heavily refactored (they were abusing the power
of `@autoclosure`, which has been curtailed with `@noescape`), but
should be generally more readable, if slightly less flexible.
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
SQLite doesn't really support BOOLEAN values (they're just INTEGERs), so
let's remove support for it in the thin layer.
Bool now conforms to Value, which means the type-safe layer can use it
freely and more safely.
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
This adds support for Expression<T?> to denote SQL expessions that may
evaluate to NULL. It's verbose given the number of permutations to
overload most operators, but brings a lot of benefits to the table:
1. Stricter typing. The compiler will let you know if you do something
like try to compare a NOT NULL column to nil.
let age = Expression<Int?>("age")
let id = Expression<Int>("id")
users.filter(age == nil)
users.filter(id == nil) // Won't compile. Meaningless.
Functions like coalesce and ifnull will also require optional
expressions.
2. Automatic NOT NULL support during schema creation.
t.column(age) // age INTEGER
t.column(id) // id INTEGER NOT NULL
3. Perhaps most importantly, the ability to automatically unwrap a row
and return a value directly.
user[age] // Optional(30)
user[id] // 1
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
Behaves like a dictionary, mostly, but provides typed access to a row's
values. Query objects yield them on iteration/access:
let email = Expression<String>("email")
let users = db["users"]
for user in users.select(email) {
if let email = user[email] {
// email is String
}
}
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
E.g.,
users.insert(name <- "Alice", admin <- true)
I know, I know, this goes beyond operator overloading into custom
operator territory, but hear me out! You don't NEED to use the
operator. I think it works particularly well here, but if you protest:
users.insert(set(name, "Alice"), set(admin, true))
In any case, this is an improvement on the existing state of things. A
block-using builder just to set a bunch of values is a cumbersome
affair. We needn't use blocks where we can avoid it.
Suggested by Thomas Denney <http://programmingthomas.com>.
Signed-off-by: Stephen Celis <stephen@stephencelis.com>
Edits throughout. Let's also change "example.com" to a better example.
There's no need for boring domain names in unnetworked code.
Also: an indentation fix for one of the fragment files. Consistency!
Signed-off-by: Stephen Celis <stephen@stephencelis.com>