Browse Source

Add note about multithreaded/async programming and generally update docs.

Kestrel 2 years ago
parent
commit
31d39b4bce
4 changed files with 393 additions and 3 deletions
  1. 322 0
      Cargo.lock
  2. 60 1
      README.md
  3. 1 0
      microrm/Cargo.toml
  4. 10 2
      microrm/src/query.rs

+ 322 - 0
Cargo.lock

@@ -2,6 +2,113 @@
 # It is not intended for manual editing.
 # It is not intended for manual editing.
 version = 3
 version = 3
 
 
+[[package]]
+name = "async-channel"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
+
+[[package]]
+name = "async-executor"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "once_cell",
+ "slab",
+]
+
+[[package]]
+name = "async-global-executor"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940"
+dependencies = [
+ "async-channel",
+ "async-executor",
+ "async-io",
+ "async-lock",
+ "blocking",
+ "futures-lite",
+ "num_cpus",
+ "once_cell",
+]
+
+[[package]]
+name = "async-io"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07"
+dependencies = [
+ "concurrent-queue",
+ "futures-lite",
+ "libc",
+ "log",
+ "once_cell",
+ "parking",
+ "polling",
+ "slab",
+ "socket2",
+ "waker-fn",
+ "winapi",
+]
+
+[[package]]
+name = "async-lock"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
+dependencies = [
+ "event-listener",
+]
+
+[[package]]
+name = "async-std"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
+dependencies = [
+ "async-channel",
+ "async-global-executor",
+ "async-io",
+ "async-lock",
+ "crossbeam-utils",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-lite",
+ "gloo-timers",
+ "kv-log-macro",
+ "log",
+ "memchr",
+ "once_cell",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+ "wasm-bindgen-futures",
+]
+
+[[package]]
+name = "async-task"
+version = "4.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
+
+[[package]]
+name = "atomic-waker"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
+
 [[package]]
 [[package]]
 name = "atty"
 name = "atty"
 version = "0.2.14"
 version = "0.2.14"
@@ -40,6 +147,20 @@ dependencies = [
  "generic-array",
  "generic-array",
 ]
 ]
 
 
+[[package]]
+name = "blocking"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc"
+dependencies = [
+ "async-channel",
+ "async-task",
+ "atomic-waker",
+ "fastrand",
+ "futures-lite",
+ "once_cell",
+]
+
 [[package]]
 [[package]]
 name = "bstr"
 name = "bstr"
 version = "0.2.17"
 version = "0.2.17"
@@ -58,6 +179,12 @@ version = "3.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
 checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
 
 
+[[package]]
+name = "cache-padded"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
+
 [[package]]
 [[package]]
 name = "cast"
 name = "cast"
 version = "0.2.7"
 version = "0.2.7"
@@ -90,6 +217,15 @@ dependencies = [
  "unicode-width",
  "unicode-width",
 ]
 ]
 
 
+[[package]]
+name = "concurrent-queue"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+dependencies = [
+ "cache-padded",
+]
+
 [[package]]
 [[package]]
 name = "convert_case"
 name = "convert_case"
 version = "0.5.0"
 version = "0.5.0"
@@ -218,6 +354,16 @@ dependencies = [
  "memchr",
  "memchr",
 ]
 ]
 
 
+[[package]]
+name = "ctor"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
+dependencies = [
+ "quote",
+ "syn",
+]
+
 [[package]]
 [[package]]
 name = "digest"
 name = "digest"
 version = "0.10.3"
 version = "0.10.3"
@@ -234,6 +380,57 @@ version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
 
 
+[[package]]
+name = "event-listener"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
+
+[[package]]
+name = "fastrand"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+
+[[package]]
+name = "futures-io"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+
+[[package]]
+name = "futures-lite"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
 [[package]]
 [[package]]
 name = "generic-array"
 name = "generic-array"
 version = "0.14.5"
 version = "0.14.5"
@@ -255,6 +452,18 @@ dependencies = [
  "wasi",
  "wasi",
 ]
 ]
 
 
+[[package]]
+name = "gloo-timers"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "js-sys",
+ "wasm-bindgen",
+]
+
 [[package]]
 [[package]]
 name = "half"
 name = "half"
 version = "1.8.2"
 version = "1.8.2"
@@ -270,6 +479,15 @@ dependencies = [
  "libc",
  "libc",
 ]
 ]
 
 
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
 [[package]]
 [[package]]
 name = "itertools"
 name = "itertools"
 version = "0.10.3"
 version = "0.10.3"
@@ -300,6 +518,15 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen",
 ]
 ]
 
 
+[[package]]
+name = "kv-log-macro"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
+dependencies = [
+ "log",
+]
+
 [[package]]
 [[package]]
 name = "lazy_static"
 name = "lazy_static"
 version = "1.4.0"
 version = "1.4.0"
@@ -319,6 +546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
 checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
 dependencies = [
 dependencies = [
  "cfg-if",
  "cfg-if",
+ "value-bag",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -340,6 +568,7 @@ dependencies = [
 name = "microrm"
 name = "microrm"
 version = "0.3.1"
 version = "0.3.1"
 dependencies = [
 dependencies = [
+ "async-std",
  "base64",
  "base64",
  "criterion",
  "criterion",
  "lazy_static",
  "lazy_static",
@@ -383,12 +612,36 @@ dependencies = [
  "libc",
  "libc",
 ]
 ]
 
 
+[[package]]
+name = "once_cell"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+
 [[package]]
 [[package]]
 name = "oorandom"
 name = "oorandom"
 version = "11.1.3"
 version = "11.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
 checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
 
 
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
 [[package]]
 [[package]]
 name = "pkg-config"
 name = "pkg-config"
 version = "0.3.25"
 version = "0.3.25"
@@ -423,6 +676,19 @@ dependencies = [
  "plotters-backend",
  "plotters-backend",
 ]
 ]
 
 
+[[package]]
+name = "polling"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "log",
+ "wepoll-ffi",
+ "winapi",
+]
+
 [[package]]
 [[package]]
 name = "ppv-lite86"
 name = "ppv-lite86"
 version = "0.2.16"
 version = "0.2.16"
@@ -619,6 +885,25 @@ dependencies = [
  "digest",
  "digest",
 ]
 ]
 
 
+[[package]]
+name = "slab"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 [[package]]
 name = "sqlite"
 name = "sqlite"
 version = "0.26.0"
 version = "0.26.0"
@@ -703,12 +988,28 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
 checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
 
 
+[[package]]
+name = "value-bag"
+version = "1.0.0-alpha.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
+dependencies = [
+ "ctor",
+ "version_check",
+]
+
 [[package]]
 [[package]]
 name = "version_check"
 name = "version_check"
 version = "0.9.4"
 version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
 [[package]]
 [[package]]
 name = "walkdir"
 name = "walkdir"
 version = "2.3.2"
 version = "2.3.2"
@@ -751,6 +1052,18 @@ dependencies = [
  "wasm-bindgen-shared",
  "wasm-bindgen-shared",
 ]
 ]
 
 
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 [[package]]
 name = "wasm-bindgen-macro"
 name = "wasm-bindgen-macro"
 version = "0.2.80"
 version = "0.2.80"
@@ -790,6 +1103,15 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen",
 ]
 ]
 
 
+[[package]]
+name = "wepoll-ffi"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 [[package]]
 name = "winapi"
 name = "winapi"
 version = "0.3.9"
 version = "0.3.9"

+ 60 - 1
README.md

@@ -11,7 +11,8 @@ supported though are possible. However, since by design microrm does not
 touch database contents for tables not defined in its model, using raw SQL
 touch database contents for tables not defined in its model, using raw SQL
 for any needed dynamic components may be a better choice.
 for any needed dynamic components may be a better choice.
 
 
-Querying supports a small subset of SQL expressed as type composition.
+Querying supports a small subset of SQL expressed as type composition; see
+[`QueryInterface`](query/struct.QueryInterface.html) for more details.
 
 
 A simple example using an SQLite table as an (indexed) key/value store
 A simple example using an SQLite table as an (indexed) key/value store
 might look something like this:
 might look something like this:
@@ -57,3 +58,61 @@ The schema output from the loop is (details subject to change based on internals
 CREATE TABLE IF NOT EXISTS "kv_store" (id integer primary key,"key" text,"value" text);
 CREATE TABLE IF NOT EXISTS "kv_store" (id integer primary key,"key" text,"value" text);
 CREATE UNIQUE INDEX "kv_store_index" ON "kv_store" ("key");
 CREATE UNIQUE INDEX "kv_store_index" ON "kv_store" ("key");
 ```
 ```
+
+If you're using `microrm` in a threaded or async environment, you'll need to
+use a [`DBPool`](struct.DBPool.html). You can then write code like this:
+
+```rust
+# use microrm::prelude::*;
+# use microrm::{Entity,make_index};
+# #[derive(Debug,Entity,serde::Serialize,serde::Deserialize)]
+# pub struct KVStore {
+    # pub key: String,
+    # pub value: String
+# }
+
+async fn insert_a(dbp: &microrm::DBPool<'_>) {
+    let qi = dbp.query_interface();
+    qi.add(&KVStore {
+        key: "a_key".to_string(),
+        value: "a_value".to_string()
+    });
+}
+
+async fn insert_b(dbp: &microrm::DBPool<'_>) {
+    let qi = dbp.query_interface();
+    qi.add(&KVStore {
+        key: "b_key".to_string(),
+        value: "b_value".to_string()
+    });
+}
+
+# async_std::task::block_on(async { main().await });
+// running in your favourite async runtime
+async fn main() {
+    # let schema = microrm::Schema::new().entity::<KVStore>();
+    let db = microrm::DB::new_in_memory(schema).unwrap();
+    let dbp = microrm::DBPool::new(&db);
+
+    let a = insert_a(&dbp);
+    let b = insert_b(&dbp);
+
+    b.await;
+    a.await;
+
+    let qi = dbp.query_interface();
+
+    let qr = qi.get().by(KVStore::Key, "a_key").one().unwrap();
+    assert_eq!(qr.is_some(), true);
+    assert_eq!(qr.as_ref().unwrap().key, "a_key");
+    assert_eq!(qr.as_ref().unwrap().value, "a_value");
+
+    let qr = qi.get().by(KVStore::Key, "b_key").one().unwrap();
+    assert_eq!(qr.is_some(), true);
+    assert_eq!(qr.as_ref().unwrap().key, "b_key");
+    assert_eq!(qr.as_ref().unwrap().value, "b_value");
+}
+```
+
+Note that between acquiring a [`QueryInterface`] reference and dropping it, you
+must not `.await` anything; the compiler will (appropriately) complain.

+ 1 - 0
microrm/Cargo.toml

@@ -24,6 +24,7 @@ log = "0.4.17"
 criterion = "0.3"
 criterion = "0.3"
 rand = "0.8.5"
 rand = "0.8.5"
 stats_alloc = "0.1.10"
 stats_alloc = "0.1.10"
+async-std = "1.11"
 
 
 [[bench]]
 [[bench]]
 name = "simple_in_memory"
 name = "simple_in_memory"

+ 10 - 2
microrm/src/query.rs

@@ -73,7 +73,8 @@ type CacheIndex = u64;
 /// As the query interface provides some level of caching, try to strive for as much sharing as
 /// As the query interface provides some level of caching, try to strive for as much sharing as
 /// possible. Passing around `QueryInterface` references instead of `DB` references is a good way
 /// possible. Passing around `QueryInterface` references instead of `DB` references is a good way
 /// to achieve this. However, `QueryInterface` is explicitly `!Send`, so you may need to use
 /// to achieve this. However, `QueryInterface` is explicitly `!Send`, so you may need to use
-/// something like a `DBPool`.
+/// something like a [`DBPool`](../struct.DBPool.html) to acquire instances locally if you're using
+/// threads or asynchronous programming.
 pub struct QueryInterface<'l> {
 pub struct QueryInterface<'l> {
     db: &'l crate::DB,
     db: &'l crate::DB,
 
 
@@ -84,6 +85,8 @@ pub struct QueryInterface<'l> {
 }
 }
 
 
 impl<'l> QueryInterface<'l> {
 impl<'l> QueryInterface<'l> {
+    /// Creates a QueryInterface. Generally you probably want to be using
+    /// `DBPool::query_interface()`.
     pub fn new(db: &'l crate::DB) -> Self {
     pub fn new(db: &'l crate::DB) -> Self {
         Self {
         Self {
             db,
             db,
@@ -139,6 +142,7 @@ where {
 }
 }
 
 
 impl<'l> QueryInterface<'l> {
 impl<'l> QueryInterface<'l> {
+    /// Add an entity to its table in the database. Alias for `add`.
     pub fn insert<T: Entity + serde::Serialize>(
     pub fn insert<T: Entity + serde::Serialize>(
         &self,
         &self,
         m: &T,
         m: &T,
@@ -146,7 +150,7 @@ impl<'l> QueryInterface<'l> {
         self.add(m)
         self.add(m)
     }
     }
 
 
-    /// Add an entity to its table
+    /// Add an entity to its table in the database.
     pub fn add<T: Entity + serde::Serialize>(
     pub fn add<T: Entity + serde::Serialize>(
         &self,
         &self,
         m: &T,
         m: &T,
@@ -186,6 +190,7 @@ impl<'l> QueryInterface<'l> {
 
 
 // General query interface
 // General query interface
 impl<'l> QueryInterface<'l> {
 impl<'l> QueryInterface<'l> {
+    /// Get an entity from its table, aka perform a `SELECT` query.
     pub fn get<'a, 'b, T: Entity>(&'a self) -> select::Select<'b, 'l, T>
     pub fn get<'a, 'b, T: Entity>(&'a self) -> select::Select<'b, 'l, T>
     where
     where
         'a: 'b,
         'a: 'b,
@@ -193,6 +198,7 @@ impl<'l> QueryInterface<'l> {
         select::Select::new(self)
         select::Select::new(self)
     }
     }
 
 
+    /// Update an entity in its table, aka perform an `UPDATE` query, by selecting columns.
     pub fn update<'a, 'b, T: Entity>(&'a self) -> update::Update<'b, 'l, T>
     pub fn update<'a, 'b, T: Entity>(&'a self) -> update::Update<'b, 'l, T>
     where
     where
         'a: 'b,
         'a: 'b,
@@ -200,6 +206,7 @@ impl<'l> QueryInterface<'l> {
         update::Update::new(self)
         update::Update::new(self)
     }
     }
 
 
+    /// Delete an entity from its table, aka perform a DELETE query.
     pub fn delete<'a, 'b, T: Entity>(&'a self) -> delete::Delete<'b, 'l, T>
     pub fn delete<'a, 'b, T: Entity>(&'a self) -> delete::Delete<'b, 'l, T>
     where
     where
         'a: 'b,
         'a: 'b,
@@ -209,6 +216,7 @@ impl<'l> QueryInterface<'l> {
 }
 }
 
 
 impl<'l> QueryInterface<'l> {
 impl<'l> QueryInterface<'l> {
+    /// Update an entity in its table, aka perform an `UPDATE` query, for all columns.
     pub fn put<T: Entity>(&self, what: &WithID<T>) -> Result<(), Error> {
     pub fn put<T: Entity>(&self, what: &WithID<T>) -> Result<(), Error> {
         self.update().to(what.as_ref()).by(T::id_column(), &what.id()).exec()
         self.update().to(what.as_ref()).by(T::id_column(), &what.id()).exec()
     }
     }