Compare commits

..

369 commits

Author SHA1 Message Date
201ec39dd2 updates (#323)
Reviewed-on: #323
Co-authored-by: Greg Burd <greg@burd.me>
Co-committed-by: Greg Burd <greg@burd.me>
2023-12-07 20:03:13 +00:00
216f078d44 Merge pull request 'Update peg requirement from ~0.7 to ~0.8' (#311) from dependabot/cargo/peg-approx-0.8 into master
Reviewed-on: #311
2023-11-25 16:00:29 +00:00
8ab11d3503 Merge branch 'master' into dependabot/cargo/peg-approx-0.8 2023-11-25 16:00:09 +00:00
92eab3692f Merge pull request 'Update indexmap requirement from ~1.7 to ~1.9' (#316) from dependabot/cargo/indexmap-approx-1.9 into master
Reviewed-on: #316
2023-11-25 15:59:55 +00:00
02ebaf5bae Merge branch 'master' into dependabot/cargo/indexmap-approx-1.9 2023-11-25 15:59:43 +00:00
517b781da1 Merge pull request 'Update rusqlite requirement from ~0.26 to ~0.29' (#320) from dependabot/cargo/rusqlite-approx-0.29 into master
Reviewed-on: #320
2023-11-25 15:59:34 +00:00
6b269a660d Merge branch 'master' into dependabot/cargo/rusqlite-approx-0.29 2023-11-25 15:59:20 +00:00
92f400a553 Merge pull request 'Update tempfile requirement from ~3.2 to ~3.5' (#321) from dependabot/cargo/tempfile-approx-3.5 into master
Reviewed-on: #321
2023-11-25 15:58:29 +00:00
ff527ad220 Merge branch 'master' into dependabot/cargo/tempfile-approx-3.5 2023-11-25 15:57:56 +00:00
73240913cc Merge pull request 'Update pretty requirement from ~0.10 to ~0.12' (#322) from dependabot/cargo/pretty-approx-0.12 into master
Reviewed-on: #322
2023-11-25 15:57:44 +00:00
dependabot[bot]
c10575e04d
Update pretty requirement from ~0.10 to ~0.12
Updates the requirements on [pretty](https://github.com/Marwes/pretty.rs) to permit the latest version.
- [Release notes](https://github.com/Marwes/pretty.rs/releases)
- [Changelog](https://github.com/Marwes/pretty.rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Marwes/pretty.rs/compare/v0.10.0...v0.12.0)

---
updated-dependencies:
- dependency-name: pretty
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-31 10:02:08 +00:00
dependabot[bot]
5fdb9a4970
Update tempfile requirement from ~3.2 to ~3.5
Updates the requirements on [tempfile](https://github.com/Stebalien/tempfile) to permit the latest version.
- [Release notes](https://github.com/Stebalien/tempfile/releases)
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS)
- [Commits](https://github.com/Stebalien/tempfile/commits)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-29 10:02:12 +00:00
dependabot[bot]
8f226ca050
Update rusqlite requirement from ~0.26 to ~0.29
Updates the requirements on [rusqlite](https://github.com/rusqlite/rusqlite) to permit the latest version.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/compare/rusqlite-0.26.1...v0.29.0)

---
updated-dependencies:
- dependency-name: rusqlite
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 10:11:21 +00:00
dependabot[bot]
aa6b634e64
Update indexmap requirement from ~1.7 to ~1.9
Updates the requirements on [indexmap](https://github.com/bluss/indexmap) to permit the latest version.
- [Release notes](https://github.com/bluss/indexmap/releases)
- [Changelog](https://github.com/bluss/indexmap/blob/master/RELEASES.md)
- [Commits](https://github.com/bluss/indexmap/compare/1.7.0...1.9.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-17 09:37:21 +00:00
986b439fb9 ignore warnings from clippy 2022-05-04 17:09:30 -04:00
dependabot[bot]
0d55e6acba
Update peg requirement from ~0.7 to ~0.8
Updates the requirements on [peg](https://github.com/kevinmehall/rust-peg) to permit the latest version.
- [Release notes](https://github.com/kevinmehall/rust-peg/releases)
- [Commits](https://github.com/kevinmehall/rust-peg/compare/0.7.0...0.8.0)

---
updated-dependencies:
- dependency-name: peg
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-04 18:47:06 +00:00
d39f8aad4e
Merge pull request #310 from qpdb/dependabot/cargo/uuid-approx-1.0
Update uuid requirement from ~0.8 to ~1.0
2022-05-04 14:45:35 -04:00
7cfff34602 Name changed, prefix 'to_' was removed.
Signed-off-by: Greg Burd <greg@burd.me>
2022-05-04 14:41:21 -04:00
dependabot[bot]
8175b98a7c
Update uuid requirement from ~0.8 to ~1.0
Updates the requirements on [uuid](https://github.com/uuid-rs/uuid) to permit the latest version.
- [Release notes](https://github.com/uuid-rs/uuid/releases)
- [Commits](https://github.com/uuid-rs/uuid/compare/0.8.0...1.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-03 17:30:32 +00:00
Mark Watts
b19a994c68 resolve compile errors from rusqlite update 2021-11-10 22:17:19 -05:00
Mark Watts
9a4ba44060
Merge pull request #29 from mwatts/dependabot/cargo/rusqlite-approx-0.26
Update rusqlite requirement from ~0.25 to ~0.26
2021-11-09 22:43:40 -05:00
Mark Watts
124bf54385
Merge pull request #26 from mwatts/dependabot/cargo/ordered-float-approx-2.8
Update ordered-float requirement from ~2.7 to ~2.8
2021-11-09 22:43:08 -05:00
Mark Watts
3df00eb63a
Merge pull request #27 from mwatts/dependabot/cargo/dirs-approx-4.0
Update dirs requirement from ~3.0 to ~4.0
2021-11-09 22:42:51 -05:00
Mark Watts
8041c704dc
Merge pull request #28 from mwatts/dependabot/bundler/docs/nokogiri-1.12.5
Bump nokogiri from 1.11.7 to 1.12.5 in /docs
2021-11-09 22:42:26 -05:00
dependabot[bot]
4aa70567b8
Update rusqlite requirement from ~0.25 to ~0.26
Updates the requirements on [rusqlite](https://github.com/rusqlite/rusqlite) to permit the latest version.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/compare/v0.25.0...v0.26.0)

---
updated-dependencies:
- dependency-name: rusqlite
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-04 21:22:11 +00:00
dependabot[bot]
c9a46327bc
Bump nokogiri from 1.11.7 to 1.12.5 in /docs
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.7 to 1.12.5.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.7...v1.12.5)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-28 05:59:06 +00:00
dependabot[bot]
d22bf451a4
Update dirs requirement from ~3.0 to ~4.0
Updates the requirements on [dirs](https://github.com/soc/dirs-rs) to permit the latest version.
- [Release notes](https://github.com/soc/dirs-rs/releases)
- [Commits](https://github.com/soc/dirs-rs/commits)

---
updated-dependencies:
- dependency-name: dirs
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-16 21:21:31 +00:00
dependabot[bot]
e73effb7d2
Update ordered-float requirement from ~2.7 to ~2.8
Updates the requirements on [ordered-float](https://github.com/reem/rust-ordered-float) to permit the latest version.
- [Release notes](https://github.com/reem/rust-ordered-float/releases)
- [Commits](https://github.com/reem/rust-ordered-float/compare/v2.7.0...v2.8.0)

---
updated-dependencies:
- dependency-name: ordered-float
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-02 21:14:10 +00:00
Mark Watts
eae76e6f43 cargo fmt 2021-08-23 21:31:50 -04:00
Mark Watts
bd818ba1f1
Merge pull request #24 from mwatts/feature/blobs
add blob/bytes as a type
2021-08-23 21:19:24 -04:00
Mark Watts
73feb622cd implement bytes (aka blobs) as native type 2021-08-23 17:25:10 -04:00
Mark Watts
d3821432bc fix problem parsing entities
issue with how bytes are not a collection -> bytes not correctly viewed as atoms
2021-08-23 17:23:09 -04:00
Mark Watts
179c123061 fix panic macro use 2021-08-23 17:21:51 -04:00
Mark Watts
1500d4348c add blobs via #bytes to edn 2021-08-22 17:41:50 -04:00
Mark Watts
479fbc4572
Merge pull request #22 from mwatts/dependabot/cargo/time-0.3.1
Update time requirement from 0.2.15 to 0.3.1
2021-08-22 17:17:11 -04:00
dependabot[bot]
97628a251f
Update time requirement from 0.2.15 to 0.3.1
Updates the requirements on [time](https://github.com/time-rs/time) to permit the latest version.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.2.15...v0.3.1)

---
updated-dependencies:
- dependency-name: time
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-22 21:12:22 +00:00
Mark Watts
903ac24589
Merge pull request #18 from mwatts/dependabot/cargo/ordered-float-approx-2.7
Update ordered-float requirement from ~2.5 to ~2.7
2021-08-22 17:11:01 -04:00
Mark Watts
1f6620bf87
Merge pull request #16 from mwatts/dependabot/cargo/petgraph-approx-0.6
Update petgraph requirement from ~0.5 to ~0.6
2021-08-22 17:10:17 -04:00
Mark Watts
e64e2cf2f2
Merge pull request #23 from mwatts/feature/blobs
remove warnings about Itertools::intersperse
2021-08-22 17:09:42 -04:00
Mark Watts
08694dc45a remove warnings about Itertools::intersperse 2021-08-22 16:53:29 -04:00
Mark Watts
64bb6284d0
Merge pull request #20 from mwatts/dependabot/cargo/env_logger-approx-0.9
Update env_logger requirement from ~0.8 to ~0.9
2021-07-17 17:05:56 -04:00
Mark Watts
5f376a8664
Merge pull request #19 from mwatts/dependabot/bundler/docs/addressable-2.8.0
Bump addressable from 2.7.0 to 2.8.0 in /docs
2021-07-17 16:49:04 -04:00
dependabot[bot]
ad3d7157a5
Update env_logger requirement from ~0.8 to ~0.9
Updates the requirements on [env_logger](https://github.com/env-logger-rs/env_logger) to permit the latest version.
- [Release notes](https://github.com/env-logger-rs/env_logger/releases)
- [Changelog](https://github.com/env-logger-rs/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/env-logger-rs/env_logger/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-14 21:21:11 +00:00
dependabot[bot]
46ddac347e
Bump addressable from 2.7.0 to 2.8.0 in /docs
Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.7.0 to 2.8.0.
- [Release notes](https://github.com/sporkmonger/addressable/releases)
- [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.7.0...addressable-2.8.0)

---
updated-dependencies:
- dependency-name: addressable
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-13 18:24:45 +00:00
dependabot[bot]
fba46fb1f2
Update ordered-float requirement from ~2.5 to ~2.7
Updates the requirements on [ordered-float](https://github.com/reem/rust-ordered-float) to permit the latest version.
- [Release notes](https://github.com/reem/rust-ordered-float/releases)
- [Commits](https://github.com/reem/rust-ordered-float/compare/v2.5.0...v2.7.0)

---
updated-dependencies:
- dependency-name: ordered-float
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-12 21:20:06 +00:00
dependabot[bot]
071a916981
Update petgraph requirement from ~0.5 to ~0.6
Updates the requirements on [petgraph](https://github.com/petgraph/petgraph) to permit the latest version.
- [Release notes](https://github.com/petgraph/petgraph/releases)
- [Changelog](https://github.com/petgraph/petgraph/blob/master/RELEASES.rst)
- [Commits](https://github.com/petgraph/petgraph/compare/0.5.0...0.6.0)

---
updated-dependencies:
- dependency-name: petgraph
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-05 21:18:06 +00:00
Mark Watts
d4736a83e4 warnings cleanup 2021-07-02 20:39:02 -04:00
Mark Watts
15df38fc8f update rusqlite - all tests pass - some warnings 2021-07-02 20:29:41 -04:00
Mark Watts
614ce63e2b
Merge pull request #13 from mwatts/dependabot/cargo/itertools-approx-0.10
Update itertools requirement from ~0.9 to ~0.10
2021-07-02 19:44:34 -04:00
Mark Watts
5a7caf7488 more package updates; all tests pass 2021-07-02 18:09:07 -04:00
Mark Watts
a02570fd5e
Merge pull request #14 from mwatts/dependabot/cargo/peg-approx-0.7
Update peg requirement from ~0.6 to ~0.7
2021-07-02 17:52:18 -04:00
Mark Watts
4ec3c3cddc
Merge pull request #15 from mwatts/dependabot/cargo/tokio-approx-1.8
Update tokio requirement from ~0.2 to ~1.8
2021-07-02 17:51:58 -04:00
dependabot[bot]
8e8e7b9739
Update itertools requirement from ~0.9 to ~0.10
Updates the requirements on [itertools](https://github.com/rust-itertools/itertools) to permit the latest version.
- [Release notes](https://github.com/rust-itertools/itertools/releases)
- [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-itertools/itertools/compare/v0.9.0...v0.10.1)

---
updated-dependencies:
- dependency-name: itertools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:50:01 +00:00
Mark Watts
abcdad5976
Merge pull request #11 from mwatts/dependabot/cargo/hyper-tls-approx-0.5
Update hyper-tls requirement from ~0.4 to ~0.5
2021-07-02 17:49:02 -04:00
dependabot[bot]
9d4f328af1
Update tokio requirement from ~0.2 to ~1.8
Updates the requirements on [tokio](https://github.com/tokio-rs/tokio) to permit the latest version.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-0.2.0...tokio-1.8.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:49:02 +00:00
dependabot[bot]
f918dcd915
Update peg requirement from ~0.6 to ~0.7
Updates the requirements on [peg](https://github.com/kevinmehall/rust-peg) to permit the latest version.
- [Release notes](https://github.com/kevinmehall/rust-peg/releases)
- [Commits](https://github.com/kevinmehall/rust-peg/compare/0.6.0...0.7.0)

---
updated-dependencies:
- dependency-name: peg
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:48:51 +00:00
Mark Watts
7185d5ee13
Merge pull request #12 from mwatts/dependabot/cargo/indexmap-approx-1.7
Update indexmap requirement from ~1.5 to ~1.7
2021-07-02 17:48:48 -04:00
Mark Watts
c8c7dda27a
Merge pull request #8 from mwatts/dependabot/cargo/num-approx-0.4
Update num requirement from ~0.3 to ~0.4
2021-07-02 17:47:48 -04:00
Mark Watts
2f299fde6c update gitignore to ignore doc related files 2021-07-02 17:44:41 -04:00
Mark Watts
3a62dbc122 add packages to workspace 2021-07-02 17:44:13 -04:00
Mark Watts
0d79eeed8f update Gemfile.lock 2021-07-02 17:40:14 -04:00
dependabot[bot]
ca9d8c0096
Update hyper-tls requirement from ~0.4 to ~0.5
Updates the requirements on [hyper-tls](https://github.com/hyperium/hyper-tls) to permit the latest version.
- [Release notes](https://github.com/hyperium/hyper-tls/releases)
- [Commits](https://github.com/hyperium/hyper-tls/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: hyper-tls
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:30:48 +00:00
dependabot[bot]
ffaba698e0
Update indexmap requirement from ~1.5 to ~1.7
Updates the requirements on [indexmap](https://github.com/bluss/indexmap) to permit the latest version.
- [Release notes](https://github.com/bluss/indexmap/releases)
- [Commits](https://github.com/bluss/indexmap/compare/1.5.0...1.7.0)

---
updated-dependencies:
- dependency-name: indexmap
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:30:48 +00:00
Mark Watts
8446a1bc4a
Merge pull request #7 from mwatts/dependabot/cargo/hyper-approx-0.14
Update hyper requirement from ~0.13 to ~0.14
2021-07-02 17:29:13 -04:00
dependabot[bot]
722f7fb782
Update num requirement from ~0.3 to ~0.4
Updates the requirements on [num](https://github.com/rust-num/num) to permit the latest version.
- [Release notes](https://github.com/rust-num/num/releases)
- [Changelog](https://github.com/rust-num/num/blob/master/RELEASES.md)
- [Commits](https://github.com/rust-num/num/compare/num-0.3.0...num-0.4.0)

---
updated-dependencies:
- dependency-name: num
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:29:09 +00:00
Mark Watts
75b5a66a91
Merge pull request #10 from mwatts/dependabot/cargo/env_logger-0.8
Update env_logger requirement from 0.7 to 0.8
2021-07-02 17:27:57 -04:00
Mark Watts
ac532be358
Merge pull request #9 from mwatts/dependabot/cargo/ordered-float-approx-2.5
Update ordered-float requirement from ~2.0 to ~2.5
2021-07-02 17:26:35 -04:00
dependabot[bot]
44036160d0
Update env_logger requirement from 0.7 to 0.8
Updates the requirements on [env_logger](https://github.com/env-logger-rs/env_logger) to permit the latest version.
- [Release notes](https://github.com/env-logger-rs/env_logger/releases)
- [Changelog](https://github.com/env-logger-rs/env_logger/blob/main/CHANGELOG.md)
- [Commits](https://github.com/env-logger-rs/env_logger/commits/v0.8.4)

---
updated-dependencies:
- dependency-name: env_logger
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:21:18 +00:00
dependabot[bot]
c8c1363b14
Update ordered-float requirement from ~2.0 to ~2.5
Updates the requirements on [ordered-float](https://github.com/reem/rust-ordered-float) to permit the latest version.
- [Release notes](https://github.com/reem/rust-ordered-float/releases)
- [Commits](https://github.com/reem/rust-ordered-float/compare/v2.0.0...v2.5.1)

---
updated-dependencies:
- dependency-name: ordered-float
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:21:07 +00:00
dependabot[bot]
32ce6d2129
Update hyper requirement from ~0.13 to ~0.14
Updates the requirements on [hyper](https://github.com/hyperium/hyper) to permit the latest version.
- [Release notes](https://github.com/hyperium/hyper/releases)
- [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/hyperium/hyper/compare/v0.13.0...v0.14.9)

---
updated-dependencies:
- dependency-name: hyper
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 21:20:42 +00:00
Mark Watts
380945a655 update Gemfile.lock 2021-07-02 17:18:18 -04:00
Mark Watts
af9bb1fcfe add packages to workspace 2021-07-02 17:11:28 -04:00
Mark Watts
c295d82872
Merge pull request #5 from mwatts/dependabot/cargo/combine-approx-4.6
Update combine requirement from ~4.3 to ~4.6
2021-07-02 10:11:50 -04:00
Mark Watts
c2e39eeb5c
Merge pull request #4 from mwatts/dependabot/cargo/rustc_version-approx-0.4
Update rustc_version requirement from ~0.3 to ~0.4
2021-07-02 10:11:26 -04:00
Mark Watts
985fd0bbdf
Merge pull request #3 from mwatts/dependabot/cargo/tempfile-approx-3.2
Update tempfile requirement from ~3.1 to ~3.2
2021-07-02 10:10:59 -04:00
dependabot[bot]
c02c06ce2b
Update combine requirement from ~4.3 to ~4.6
Updates the requirements on [combine](https://github.com/Marwes/combine) to permit the latest version.
- [Release notes](https://github.com/Marwes/combine/releases)
- [Changelog](https://github.com/Marwes/combine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Marwes/combine/compare/v4.3.0...v4.6.0)

---
updated-dependencies:
- dependency-name: combine
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 14:06:31 +00:00
dependabot[bot]
b138c7e257
Update rustc_version requirement from ~0.3 to ~0.4
Updates the requirements on [rustc_version](https://github.com/Kimundi/rustc-version-rs) to permit the latest version.
- [Release notes](https://github.com/Kimundi/rustc-version-rs/releases)
- [Commits](https://github.com/Kimundi/rustc-version-rs/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: rustc_version
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 14:06:12 +00:00
dependabot[bot]
88df3c4d8d
Update tempfile requirement from ~3.1 to ~3.2
Updates the requirements on [tempfile](https://github.com/Stebalien/tempfile) to permit the latest version.
- [Release notes](https://github.com/Stebalien/tempfile/releases)
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.1.0...v3.2.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 14:06:01 +00:00
Mark Watts
feb9665299
Create dependabot.yml 2021-07-02 10:04:44 -04:00
Mark Watts
19cb2870da
fix invalid cron in audit 2021-07-02 08:55:38 -04:00
Mark Watts
5c2a7261a1
Merge pull request #2 from mwatts/dependabot/bundler/docs/nokogiri-1.11.7
Bump nokogiri from 1.8.3 to 1.11.7 in /docs
2021-07-02 08:50:52 -04:00
Mark Watts
0f015b2f10
Merge pull request #1 from mwatts/dependabot/bundler/docs/rubyzip-2.3.0
Bump rubyzip from 1.2.1 to 2.3.0 in /docs
2021-07-02 08:40:26 -04:00
dependabot[bot]
da89cfc797
Bump nokogiri from 1.8.3 to 1.11.7 in /docs
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.8.3 to 1.11.7.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.8.3...v1.11.7)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 12:37:59 +00:00
dependabot[bot]
9a6ae48d8e
Bump rubyzip from 1.2.1 to 2.3.0 in /docs
Bumps [rubyzip](https://github.com/rubyzip/rubyzip) from 1.2.1 to 2.3.0.
- [Release notes](https://github.com/rubyzip/rubyzip/releases)
- [Changelog](https://github.com/rubyzip/rubyzip/blob/master/Changelog.md)
- [Commits](https://github.com/rubyzip/rubyzip/compare/v1.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: rubyzip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-02 12:37:57 +00:00
Mark Watts
d97e882a4a
remove windows temporarily 2020-11-17 21:15:42 -05:00
5a65cd38c9 Start integrating GitHub Actions for CI. 2020-10-29 16:02:30 -04:00
5e700133f5 Use new call for single character push. 2020-10-29 16:02:02 -04:00
4a63ca98df Add a few more versions. 2020-10-29 16:01:01 -04:00
2e28e87af8 A few minor fixes. 2020-10-29 15:59:31 -04:00
5998ef73fb Take 3, a potential fix for CI/CD issues. 2020-10-29 14:05:10 -04:00
9bcd0955ba
Merge pull request #298 from qpdb/dependabot/cargo/combine-approx-4.3
Update combine requirement from ~4.2 to ~4.3
2020-10-29 14:04:31 -04:00
39219af1ff
Merge pull request #300 from qpdb/dependabot/cargo/rustc_version-approx-0.3
Update rustc_version requirement from ~0.2 to ~0.3
2020-10-29 14:03:53 -04:00
6d88abfb44
Merge pull request #299 from qpdb/dependabot/cargo/env_logger-approx-0.8
Update env_logger requirement from ~0.7 to ~0.8
2020-10-29 14:03:05 -04:00
dependabot-preview[bot]
31ec02afd3
Update rustc_version requirement from ~0.2 to ~0.3
Updates the requirements on [rustc_version](https://github.com/Kimundi/rustc-version-rs) to permit the latest version.
- [Release notes](https://github.com/Kimundi/rustc-version-rs/releases)
- [Commits](https://github.com/Kimundi/rustc-version-rs/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-29 10:29:13 +00:00
dependabot-preview[bot]
1622978acf
Update env_logger requirement from ~0.7 to ~0.8
Updates the requirements on [env_logger](https://github.com/env-logger-rs/env_logger) to permit the latest version.
- [Release notes](https://github.com/env-logger-rs/env_logger/releases)
- [Changelog](https://github.com/env-logger-rs/env_logger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/env-logger-rs/env_logger/compare/v0.7.0...v0.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-19 10:28:38 +00:00
dependabot-preview[bot]
26cd399e3a
Update combine requirement from ~4.2 to ~4.3
Updates the requirements on [combine](https://github.com/Marwes/combine) to permit the latest version.
- [Release notes](https://github.com/Marwes/combine/releases)
- [Changelog](https://github.com/Marwes/combine/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Marwes/combine/compare/v4.2.0...v4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-27 10:35:57 +00:00
949386a43f Hopefully fix CI/CD issue with clippy install. 2020-08-26 10:05:32 -04:00
5b0cb80b32 Fix CI/CD issue with clippy install. 2020-08-26 08:46:31 -04:00
8039183097 Update to newer tokio. 2020-08-24 21:49:16 -04:00
9c472eff41
Merge pull request #297 from qpdb/dependabot/cargo/rusqlite-approx-0.24
Update rusqlite requirement from ~0.23 to ~0.24
2020-08-24 16:46:25 -04:00
324929a02a Update all uses of rusqlite to 0.24 2020-08-24 16:41:17 -04:00
dependabot-preview[bot]
526c9c3928
Update rusqlite requirement from ~0.23 to ~0.24
Updates the requirements on [rusqlite](https://github.com/rusqlite/rusqlite) to permit the latest version.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/compare/0.23.0...0.23.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-24 10:29:49 +00:00
4b1583473e Fix more issues identified by clippy (aka: lint). 2020-08-07 09:15:36 -04:00
125306e108 Update dependencies. Lint. 2020-08-05 23:03:58 -04:00
0e63167aab Update TravisCI. 2020-05-25 11:18:42 -04:00
5899bf8624 Minor version adjustments and fixes. 2020-05-25 10:51:22 -04:00
bf1ac14d32 Update dependency versions. Fix minor warnings. 2020-05-12 10:21:51 -04:00
b428579865 Update dependencies, Rust version 1.44.0-nightly and fix warnings. 2020-04-23 12:23:12 -04:00
9eb6bc6220 Add an example, more notes. 2020-02-27 12:09:11 -05:00
41f1ff2393 Box the SelectQuery in ProjectedSelect. 2020-02-27 11:18:13 -05:00
5979fa5844 Starting points for makefile and some general notes. 2020-02-27 09:27:07 -05:00
dfb5866174 lint 2020-02-21 10:27:39 -05:00
58e06742fd lint 2020-02-21 09:53:40 -05:00
a8223d11c9 Box the ConjoiningClauses in the enum ComputedTable to lower the size of that struct. 2020-02-20 12:16:21 -05:00
b41bcf40f3 Cleanup. 2020-02-10 10:46:48 -05:00
18a0c15320
Merge pull request #3 from qpdb/gburd/learning-by-linting
lint
2020-01-31 13:59:38 -05:00
6b7343a893 Tweak CI/Travis config. 2020-01-31 13:25:00 -05:00
Greg Burd
4f81c4e15b Attempting to cleanup with clippy, rustfmt, etc.
Integrate https://github.com/mozilla/mentat/pull/806
2020-01-31 10:55:45 -05:00
8aec4048b9
Merge pull request #2 from qpdb/gburd/update-peg-dep
rust-peg parser updates
2020-01-23 11:19:25 -05:00
Greg Burd
ef1c196516 Update pretty_print dependency and fix issues. 2020-01-23 11:16:14 -05:00
Greg Burd
fcb3a9182f Fix module issue found when testing all-features. 2020-01-23 11:16:14 -05:00
Greg Burd
9421a5c3bb Fixes some mistakes when updating the grammar. 2020-01-23 11:16:14 -05:00
Greg Burd
60c65033b2 Specify dependency versions without patch component unless necessary. 2020-01-23 11:15:49 -05:00
Greg Burd
fa3091d078 Update indexmap dependency. 2020-01-16 13:30:29 -05:00
286155a18a
Merge pull request #1 from qpdb/gburd/2018edition-fmt-fix-deps
Breathe life back into this project.
2020-01-16 11:27:20 -05:00
Greg Burd
d6b3d1818a Booleans should be stored as their int value, not string value. 2020-01-16 10:58:26 -05:00
Greg Burd
b2f92b8461 Update to 2018 edition of Rust (1.42). Fix and format code. Update dependencies. Fix tests. 2020-01-16 10:58:21 -05:00
Conrad Dean
c2122a210c fix compiler warnings 2019-07-23 10:38:59 -04:00
Conrad Dean
bcb56b0561 stop the docs folder from taking over every search result 2019-07-23 09:01:22 -04:00
Conrad Dean
be02b86bbe fix tolstoy tests when running "cargo test -p mentat_tolstoy" 2019-07-23 08:51:57 -04:00
Conrad Dean
e6a2af3553 fix compile errors in tests 2019-07-22 22:48:38 -04:00
Conrad Dean
2b97a90b64 not sure if this Value is needed. it started to conflict a different return type a few days ago 2019-07-22 22:31:44 -04:00
Conrad Dean
ae9f969e59 re structure result type nesting combined with correct .into call
this was a bit of a trip!  we will see if I actually did this correctly
later...
2019-07-22 22:30:08 -04:00
Conrad Dean
4d92e3eef9 the params macro fixes everything 2019-07-22 22:29:35 -04:00
Conrad Dean
3547cfcd16 fix weird params mis-matches with the params macro 2019-07-22 22:20:14 -04:00
Conrad Dean
4e9d6b3f58 help compiler with an annotation on the outside of an expression instead of halfway through the middle of an expression 2019-07-22 09:10:49 -04:00
Conrad Dean
76ae972e2e fix for rusqlite Result api 2019-07-22 08:58:19 -04:00
Conrad Dean
f4002f34f4 fix empty param type inference with macro and update for rusqlite Result api 2019-07-22 08:54:51 -04:00
Conrad Dean
5596873e8f fiddle with changes in borrow types since rusqlite changed their api 2019-07-22 08:47:23 -04:00
Conrad Dean
cdfd1f6b30 Fix raw get() api to using the Result-based api
rusqlite must have just returned the data itself rather than relying on
the Result type to communicate failures to callers.  Fixing that here,
albeit in a fragile way.
2019-07-22 08:36:32 -04:00
Conrad Dean
ff48f6369a fix breaking change on rusqlite changing RowIndex's signature
RowIndex must have just been an alias over i32, but now it's a trait
implemented on str and usize, so we need to change mentat's internal
type alias for it to a usize.
2019-07-22 08:33:34 -04:00
Conrad Dean
95780c0ab5 type signature on rusqlite::Row changed, only need one lifetime annotation 2019-07-22 07:41:53 -04:00
Conrad Dean
e3bd1cb77e iterator error was because it must return a rusqlite::Result. use rusqlite macro for empty params 2019-07-22 07:40:59 -04:00
Conrad Dean
a25f476734 remove wrapper types that seem unnecessary, and wrap the result of a fn with a Result as the compiler told me 2019-07-20 13:22:46 -04:00
Conrad Dean
17112dbc4d fix bug where param types cannot be inferred (because its an empty set of params) 2019-07-19 11:25:00 -04:00
Conrad Dean
b6b316953e seems to resolve some compiler errors 2019-07-17 11:46:47 -04:00
Conrad Dean
3d965fdf6e try fixing build by upgrading rusqlite to 0.19 2019-07-17 10:59:38 -04:00
Grisha Kruglov
e55376e98b
Updates the Sync section of the README 2018-09-10 12:52:41 -07:00
Grisha Kruglov
b22b29679b
Basic sync support (#563) r=nalexander
* Pre: remove remnants of 'open_empty'

* Pre: Cleanup 'datoms' table after a timeline move

Since timeline move operations use a transactor, they generate a
"phantom" 'tx' and a 'txInstant' assertion. It is "phantom" in a sense
that it was never present in the 'transactions' table, and is entirely
synthetic as far as our database is concerned.
It's an implementational artifact, and we were not cleaning it up.

It becomes a problem when we start inserting transactions after a move.
Once the transactor clashes with the phantom 'tx', it will retract the
phantom 'txInstant' value, leaving the transactions log in an incorrect state.

This patch adds a test for this scenario and elects the easy way out: simply
remove the offending 'txInstant' datom.

* Part 1: Sync without support for side-effects

A "side-effect" is defined here as a mutation of a remote state as part
of the sync.

If, during a sync we determine that a remote state needs to be changed, bail out.

This generally supports different variations of "baton-passing" syncing, where clients
will succeed syncing if each change is non-conflicting.

* Part 2: Support basic "side-effects" syncing

This patch introduces a concept of a follow-up sync. If a sync generated
a "merge transaction" (a regular transaction that contains assertions
necessary for local and remote transaction logs to converge), then
this transaction needs to be uploaded in a follow-up sync.

Generated SyncReport indicates if a follow-up sync is required.

Follow-up sync itself is just a regular sync. If remote state did not change,
it will result in a simple RemoteFastForward. Otherwise, we'll continue
merging and requesting a follow-up.

Schema alterations are explicitly not supported.

As local transactions are rebased on top of remote, following changes happen:
- entids are changed into tempids, letting transactor upsert :db/unique values
- entids for retractions are changed into lookup-refs if we're confident they'll succeed
-- otherwise, retractions are dropped on the floor

* Post: use a macro for more readable tests

* Tolstoy README
2018-09-07 19:18:20 -07:00
Nick Alexander
64821079c2
Update README.md to mark Mentat as unmaintained.
See https://mail.mozilla.org/pipermail/firefox-dev/2018-September/006780.html.
2018-09-07 14:37:50 -07:00
Grisha Kruglov
bcec011ca5 Make sure double retractions are not inserted. Fixes #818. (#819) r=nalexander 2018-09-07 13:12:28 -07:00
sc13-bioinf
fba9568d44 Allow plus symbol "+" in symbol names. (#821) r=nalexander 2018-09-05 09:28:32 -07:00
Emily Toop
e3113783ae Fix merge error on iOS automation patch 2018-08-22 16:44:45 +01:00
Emily Toop
cd99774e2c Adding iOS Build and Test to CI (#804)
* Add iOS SDK build and test to rust 1.25.0 version of travis CI build

* Address review comments

* Move iOS testing and document generation into post test jobs
2018-08-22 08:43:17 -07:00
Grisha Kruglov
66cc4e14ad Post: use dirs crate, avoiding compile warning about home_dir 2018-08-20 18:23:46 -07:00
Grisha Kruglov
22b17a6779 Split "mentat transaction" logic away from the main crate
Sync needs to operate over a "mentat transaction", not just a "db transaction".
This shuffle allows internal mentat crates to consume InProgress, which models
the concept of a "mentat transaction".
2018-08-20 18:23:46 -07:00
Grisha Kruglov
6160dd59f7 Pre: use 'db/syncable' feature; derive serialization for PartitionMap 2018-08-20 18:23:46 -07:00
Grisha Kruglov
b8b2aef181 Pre: Split a Db error for clarity
error_chain stack limitations no longer apply, so let's have better errors!
2018-08-20 18:23:46 -07:00
Grisha Kruglov
5bc6d76bb3 Pre: expose read_partition_map from the db crate 2018-08-20 18:23:46 -07:00
Nick Alexander
8c2245ff0b Pre: Add top-level NotYetImplemented error. 2018-08-20 18:23:46 -07:00
Nick Alexander
0b84a0802d Pre: Remove open_empty.
This was a work-around for Tolstoy, which couldn't gracefully handle
syncing a store with a bootstrap transaction.  Tolstoy now handles
that single transaction, so this is no longer necessary.
2018-08-20 18:23:46 -07:00
Grisha Kruglov
8ddbd18f5f
Add travis-ci build status badge to README. 2018-08-20 17:56:49 -07:00
Grisha Kruglov
9e8292e68b Allow 'sqlcipher' feature for all uses of rusqlite
This also patches our CI test script to only run "--feature sqlcipher"
tests on sub-crates which expose this feature (i.e. themselves rely on rusqlite).
2018-08-20 16:55:34 -07:00
Emily Toop
fe1a034822 Fix broken iOS tests 2018-08-20 14:40:39 -07:00
Emily Toop
d61e070e08 Get iOS tests building again. 2018-08-20 14:40:39 -07:00
Grisha Kruglov
db4350aab7 Bump version to 0.11.1 2018-08-09 13:16:05 -07:00
Grisha Kruglov
5976869b0a Post: Make tests pass on Rust 1.25.0
For some reason, the converted doc test fails on Rust 1.25.0, while
working with other Rust versions. For simplicity, just convert it into
a regular test.
2018-08-09 13:16:05 -07:00
Grisha Kruglov
bf8c2c1516 Post: Remove bunch of dependencies from query-pull 2018-08-09 13:16:05 -07:00
Grisha Kruglov
dbb4aab071 Post: Remove mentat_sql dependency from query-projector 2018-08-09 13:16:05 -07:00
Grisha Kruglov
1e488d720b Post: Use a single implementation of bail macro 2018-08-09 13:16:05 -07:00
Grisha Kruglov
e9398dd50d Part 1: Move public errors into public-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
c00e14f5ff Pre: Remove :: dependency from src/errors.rs 2018-08-09 13:16:05 -07:00
Grisha Kruglov
c8e6a511f4 Pre: Move tolstoy/errors into tolstoy-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
9381af4289 Pre: Move core/Attribute* to core-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
68d0e17824 Pre: Move sql/errors into sql_traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
05ef149545 Pre: Fold query-translator into query-projector 2018-08-09 13:16:05 -07:00
Grisha Kruglov
6312e89aba Pre: Move query-projectors/errors and aggregates into query-projector-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
ccdd17551a Pre: Move query-algebrizer/error.rs into query-algebrizer-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
9fd198f96a Pre: Move ValueTypeSet into core-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
2ae8594d20 Pre: Do not re-export EdnParseError from core 2018-08-09 13:16:05 -07:00
Grisha Kruglov
07beb68c7a Pre: Remove query/ crate 2018-08-09 13:16:05 -07:00
Grisha Kruglov
11aaa193f5 Pre: Move query-pull/errors into query-pull-traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
cebb85a7fe Pre: Move db/errors.rs into db_traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
d0214fad7d Pre: Move core/types.rs into core_traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
a57ba5d79f Pre: Move Entid and KnownEntid into core_traits 2018-08-09 13:16:05 -07:00
Grisha Kruglov
f8478835a2 Use crates.io version of the enum-set
rnewman upstreamed his changes in https://github.com/contain-rs/enum-set/pull/20
2018-08-03 15:41:19 -07:00
Nick Alexander
79113498e7 [automation] Split into generic and Mentat-specific Docker images. 2018-08-03 12:53:22 -07:00
Nick Alexander
b5d0e12a24 [automation] Re-add project-specific Mentat Docker image. 2018-08-03 12:53:01 -07:00
Nick Alexander
814ab19ecb [automation] Move project-agnostic Dockerfile into subdirectory.
Docker is directory oriented so we have to play along.
2018-08-03 12:53:01 -07:00
Nick Alexander
0cb8227750 [automation] Be project agnostic; use armv7-linux-androideabi; install Android standalone toolchains.
This is ready for Android Rust-y components: it no longer references Mentat.

The standalone toolchains are installed into
$ANDROID_NDK_TOOLCHAIN_DIR/arch-$ANDROID_NDK_API_VERSION.
2018-08-03 12:53:01 -07:00
Nick Alexander
f747e2e550 [sdks/android] Pre: Disable testCaching for frequent intermittent failures. 2018-08-03 12:53:01 -07:00
Nick Alexander
5b4f50ce1b Fix vcsTag, yet again. 2018-07-31 14:42:08 -07:00
Nick Alexander
3cd61a0c93 Fix vcsTag, again. 2018-07-31 14:05:55 -07:00
Nick Alexander
65e9822ad6 Bump to version 0.11.0. 2018-07-31 09:59:18 -07:00
Nick Alexander
4325d6c0c3 [sdks/android] Move main Mentat Android SDK tests from androidTest to test.
This leverages JNA to test the Android SDK on the host machine using
Robolectric, which is significantly faster and easier to debug than
the equivalent on-device instrumentation tests.

We'll still want instrumentation smoke tests, but they won't need to
cover the entire range of the Android SDK.
2018-07-31 09:54:29 -07:00
Nick Alexander
e06bfd1b7d [sdks/android] Workaround Android Studio JUnit test runner runtime classpath issue. 2018-07-27 10:43:53 -07:00
Nick Alexander
a7d2057bc6 [sdks/android] Post: Address most Android Studio complaints.
The only ones I cared about were unchecked access, but while I'm here,
might as well do most of them.
2018-07-27 10:43:53 -07:00
Nick Alexander
2978ad91c0 [sdks/android] Part 3: Finish conversion to Robolectric. 2018-07-27 10:43:53 -07:00
Nick Alexander
190e05e360 [sdks/android] Part 2: Replace Expectation/wait/notify with CountDownLatch.
Locally, I witnessed very slow tests.  Profiling with Visual VM
revealed a lot of time spent in `wait`.

Digging in, we were trying to be clever, with a `wait(1000)/notify`
mechanism.  However, there were never multiple threads in play, so the
waiter wasn't waiting when `notify` was invoked.  That means we always
timed out.  I think this never worked and using bare `wait()` would
have revealed that.

Anyway, `CountDownLatch` maintains the one bit of state (was I
notified) and generalizes smoothly to when we have threads.
2018-07-27 10:43:53 -07:00
Nick Alexander
d23f2b373a [sdks/android] Include vcsTag when uploading to bintray. 2018-07-27 10:43:52 -07:00
Nick Alexander
6856462f1b [sdks/android] Part 1: Move androidTest to test. 2018-07-27 10:43:52 -07:00
Grisha Kruglov
536d40ad84 Part 4: Add support for moving transactions off of main timeline 2018-07-26 17:14:05 -07:00
Grisha Kruglov
4ec780c87a Part 3: Use a view to derive parts table
Being able to derive partition map from partition definitions and current
state of the world (transactions), segmented by timelines, is useful
because it lets us not worry about keeping materialized partition maps
up-to-date - since there's no need for materialized partition maps at that point.

This comes in very handy when we start moving chunks of transactions off of our mainline.
Alternative to this work would look like materializing partition maps per timeline,
growing support for incremental "backwards update" of the materialized maps, etc.

Our core partitions are defined in 'known_parts' table during bootstrap,
and what used to be 'parts' table is a generated view that operates over
transactions to figure out partition index.

'parts' is defined for the main timeline. Querying parts for other timelines
or for particular timeline+tx combinations will look similar.
2018-07-26 17:14:05 -07:00
Grisha Kruglov
3ca5255cde Part 2: Add basic support for timelines to the transactor
This records transactions onto a default timeline (0).
2018-07-26 17:14:05 -07:00
Grisha Kruglov
0974108a52 Part 1: Allow specifying transactor's commit behaviour
Normally we want to both materialize our changes (into 'datoms')
as well as commit source transactions into 'transactions' table.

However, when moving transactions from timeline to timeline
we don't want to persist artifacts (rewind assertions), just their
materializations.

This patch expands the 'db' interface to allow for this split,
and changes transactor's functions to take a crate-private 'action'
which defines desired behaviour.
2018-07-26 17:14:05 -07:00
Grisha Kruglov
5a29efa336 Part 0: Allow retractions of installed attributes
This is necessary for the timelines work ahead. When schema is being
moved off of a main timeline, we need to be able to retract it cleanly.

Retractions are only processed if the whole defining attribute set
is being retracted at once (:db/ident, :db/valueType, :db/cardinality).
2018-07-26 17:14:05 -07:00
Grisha Kruglov
9a47d8905f Pre: 'Into' implementation chaining TermWithoutTempIds -> TermWithTempIds -> TermWithTempIdsAndLookupRefs 2018-07-26 17:14:05 -07:00
Nick Alexander
e6066769ca Pre: Differentiate bad attribute retractions from unrecognized retractions. 2018-07-26 17:14:05 -07:00
Nick Alexander
fba378ee39 [sdks/android] Build Mentat Android SDK in TaskCluster; publish org.mozilla.mentat to nalexander's personal Bintray repo.
I haven't had this reviewed thoroughly, but it mostly works.
2018-07-26 13:12:20 -07:00
Nick Alexander
faef4e9ee8 Bump to version 0.10.0. 2018-07-26 13:09:18 -07:00
Nick Alexander
a8cc9cb70d [sdks/android] Don't strip Mentat library.
Help folks debugging by including symbols in our native libraries.
Yes, this makes the resulting AAR very large.  The Android ecosystem
seems to be in flux around who is in charge of stripping native
binaries, but for now let's provide symbols and see how consumers
react.
2018-07-26 13:06:03 -07:00
Nick Alexander
76d7df5548 [sdks/android] Package JNA using upstream dependency. 2018-07-26 13:05:31 -07:00
Nick Alexander
7e31ca15bc [sdks] Make store_open{_encrypted} return useful errors.
Because this was formerly a constructor, the pattern needed to change
to a factory function, but that's better than what we had.
2018-07-26 13:01:53 -07:00
Nick Alexander
67a14ca756 [sdks/android] Build Mentat Android SDK in TaskCluster; publish org.mozilla.mentat to nalexander's personal Bintray repo.
The automation parts were cribbed directly from
50add3e176.

The automation permissions were added in
https://bugzilla.mozilla.org/show_bug.cgi?id=1477311.

This uses a very rudimentary Gradle plugin, `rust-android-gradle`,
with custom fixes and extensions.  It works pretty well for what it
is!  See https://github.com/ncalexan/rust-android-gradle.
2018-07-25 20:50:44 -07:00
Nick Alexander
0955c784b7 [sdks/android] Pre: Trim unused Android bits.
We don't use UI libraries, don't require UI resources, and don't
require any permissions.
2018-07-25 20:38:56 -07:00
Nick Alexander
9e6505a930 [sdks/android] Pre: Fix unused warnings. 2018-07-25 20:38:48 -07:00
Victor Porof
89d8ac50a8
Run serde_support tests for the EDN module on CI (#792)
Signed-off-by: Victor Porof <victor.porof@gmail.com>
2018-07-19 19:03:19 +02:00
Victor Porof
2540404b00
Generate rust documentation on CI and publish to gh-pages automatically (#793)
Signed-off-by: Victor Porof <victor.porof@gmail.com>
2018-07-19 18:32:54 +02:00
Nick Alexander
22dad5d6ca [build] Include Gradle wrapper JAR in repository.
Presumably this was an error: `.gitignore` ignores all JAR files, but
this one really needs to be in version control.
2018-07-17 15:30:10 -07:00
Grisha Kruglov
69c9f512a0 Move entid allocation logic into Partition r=nalexander 2018-07-17 06:20:37 -07:00
Grisha Kruglov
6290cc9db2 Enforce partition integrity when setting its index r=nalexander
Timelines work starts to perform modifications on the partitions
that go beyond simple allocations. This change pre-emptively protects
partition integrity by asserting that index modifications are legal.
2018-07-17 06:20:37 -07:00
Nick Alexander
38a92229d7 Pre: Replace PartitionMapping trait with newtype. r=grisha
Generally, I think that Mentat is using too many small traits rather
than wrapping types into newtypes.  Wrapping into newtypes is cheap in
Rust, and it makes it easier to reason about the code.
2018-07-17 06:20:37 -07:00
Grisha Kruglov
675a865896
Extract and improve test macros (#787) r=nalexander
* Part 1: Extract low-level test framework into mentat_db::debug for re-use.

* Part 2: Improve assert_matches!.

This corrects an incorrect pattern: a conversion method taking &self
but returning an owned value should be named like `to_FOO(&self) -> FOO`.  (A
reference-to-reference conversion should be named like `as_FOO(&self)
-> &FOO`.  A consuming conversion should be named like `into_FOO(self)
-> FOO`.)

In addition, this pushes the conversion via `to_edn` into the
`assert_matches!` macro, which lets consumers get a real data
structure (say, `Datoms`) and use it directly before or after
`assert_matches!`.  (Currently, consumers get back `edn::Value`
instances, which aren't nearly as pleasant to use as real data
structures.)

Co-authored-by: Grisha Kruglov <gkruglov@mozilla.com>

* Part 3: Use mentat_db::debug framework in Tolstoy crate.

The advantage of this approach is that compiling Tolstoy (or anything
that's not db, really) can be quite a bit faster than compiling db.
2018-07-16 13:58:34 -07:00
Nick Alexander
e9cddd63e4 [tx] Don't treat :db/doc as defining a schema attribute. (#784) r=grisha 2018-07-16 12:20:34 -07:00
Nick Alexander
9291b2a0b0 [tx] Don't treat :db/doc as defining a schema attribute. (#784) 2018-07-13 14:29:29 -07:00
Grisha Kruglov
bff24c60b7
Add a top-level "syncable" feature. (#782) r=ncalexan
* Add a top-level "syncable" feature.

Tested with:

cargo test --all
cargo test --all --no-default-features
cargo build --manifest-path tools/cli/Cargo.toml --no-default-features
cargo run --manifest-path tools/cli/Cargo.toml --no-default-features debugcli

Co-authored-by: Nick Alexander <nalexander@mozilla.com>

* Add 'syncable' feature to 'db' crate to conditionally derive serialization for Partition*

This is leading up to syncing with partition support.
2018-07-11 16:26:06 -07:00
Nick Alexander
61e6b85e6a Make Partition include end of range and allow_excision flag. r=grisha,nalexander 2018-07-06 16:12:28 -07:00
Nick Alexander
82610f17f8 Part 2: Make partition include an allow_excision flag.
This is leading up to the implementation of
https://github.com/mozilla/mentat/issues/21.
2018-07-06 16:11:42 -07:00
Grisha Kruglov
c0ddc2ca70 Part 1: Make Partition include explicit end range bound.
It's helpful to have the full range when syncing.
2018-07-06 15:23:06 -07:00
Nick Alexander
7d2fe8c625 Remove low-hanging dependency fruit. (#773) r=nalexander 2018-07-06 14:58:06 -07:00
Thom Chiovoloni
0549bbd604 Remove needless num dependency from mentat_core. 2018-07-06 14:56:42 -07:00
Thom Chiovoloni
dcc0770ca4 Remove needless num dependency from mentat_db and optimize remove_every.
This implementation of `remove_every` is O(n) and not O(n^2) like it was before.
2018-07-06 14:56:33 -07:00
Thom Chiovoloni
ad2b646700 Remove regex dependency from query_sql. Fixes #771. 2018-07-06 14:56:11 -07:00
Nick Alexander
f65512158b Make kw!(foo.bar/bar.baz) work. 2018-07-06 14:19:50 -07:00
Nick Alexander
07c5d733d6 Bump to version 0.8.0.
We've made many breaking changes, especially to error handling, so
it's time to bump versions.
2018-07-05 16:48:27 -07:00
Nick Alexander
46f7db36c9 Small improvements accumulated while building the logins API on top of Mentat. (#779) r=grisha
These build on #778, and implement a variety of small fixes (related
parts are labelled as such), and one non-trivial part -- matching
tuple results with the `BindingTuple` trait. In practice, this is very
helpful, and greatly streamlined the logins API.
2018-07-05 16:46:02 -07:00
Nick Alexander
2cb7d441dc Part 2: Make it easier to match tuple results.
Right now, we write code like
```rust
match q_once(q, inputs)?.into_tuple()? {
    Some(vs) => match (vs.len(), vs.get(0), vs.get(1)) {
        (2, &Some(Binding::Scalar(TypedValue::Long(a))), &Some(Binding::Scalar(TypedValue::Instant(ref b)))) => Some((a, b.clone())),
        _ => panic!(),
    },
    None => None,
}
```
to length-check tuples coming out of the database.  It can also lead
to a lot of cloning because references are the easiest thing to hand.

This commit allows to write code like
```rust
match q_once(q, inputs)?.into_tuple()? {
    Some((Binding::Scalar(TypedValue::Long(a)), Binding::Scalar(TypedValue::Instant(b)))) => Some((a, b)),
    Some(_) => panic!(),
    None => None,
}
```
which is generally much easier to reason about.
2018-07-05 16:45:42 -07:00
Nick Alexander
e362ca6213 Part 1: Allow to clone useful query structures. 2018-07-05 16:45:42 -07:00
Nick Alexander
2ab481f83e Part 2: Expose time related things at top-level.
Perhaps we actually want to subdivide the top-level namespace so that
there is a `mentat::time` module, but I'd prefer to make part of the
process of fixing the public API as we get ready to christen version
1.0.
2018-07-05 16:45:42 -07:00
Nick Alexander
1c0602fa00 Part 1: Add {From,To}Millis.
I think this is just oversight.  Generally, we should anticipate what
our consumers need to do to interact with Mentat, and producing milli-
and micro-second timestamps is part of that need.
2018-07-05 16:45:42 -07:00
Nick Alexander
3744982cd9 Add last_tx_id. 2018-07-05 16:45:42 -07:00
Nick Alexander
b9f3681728 Part 2: Allow to Deref StructuredMap to the underlying IndexMap.
Again, this is a fundamental Rust pattern for newtypes.  It's awfully
hard to actually use `StructuredMap` without it!
2018-07-05 16:45:42 -07:00
Nick Alexander
d49f702512 Part 1: Expand Binding::val() into Binding::{into_*,as_*}.
This is simply for completeness: we should provide fundamental
conversion patterns even when they are mostly unused in our code base.
2018-07-05 16:45:42 -07:00
Nick Alexander
99deb87b9f Build Entity instances, not Term* instances. Fixes #674. (#778) r=grisha 2018-07-05 16:42:02 -07:00
Nick Alexander
eb1df31ac4 Part 7: Improve TermBuilder interface; expose lookup refs and tx functions.
These are functions on `TermBuilder` itself to prevent mixing mutable
and immutable references in the most natural style.  That is,
```
builder.add(e, a, builder.lookup_ref(...))
```
fails because `add` borrows `builder` mutably and `lookup_ref` borrows
`builder` immutably.  There's nothing here that requires a specific
builder (since we're not interning lookup refs on the builder, like we
are tempids) so we don't need an instance.
2018-07-05 16:33:51 -07:00
Nick Alexander
06056a8468 Part 6: Lift TxReport to core crate.
The `core` create didn't exist when the `db` was started, but this
type is clearly part of the public interface of Mentat.
2018-07-05 16:33:51 -07:00
Nick Alexander
1cb1847aa6 Part 5: Make existing TermBuilder actually build Entity instances.
There are a few tricky details to call out here.  The first is the
`TransactableValueMarker` trait.  This is strictly a marker (like
`Sized`, for example) to give some control over what types can be used
as value types in `Entity` instances.  This expression is needed due
to the network of `Into` and `From` relations between the parts of
valid `Entity` instances.  This allows to drop the `IntoThing`
work-around trait and use the established patterns.  (Observe that
`KnownEntid` makes this a little harder, due to the cross-crate
consistency restrictions.)

The second is that we can get rid `{add,retract}_kw`, since the
network of relations expresses the coercions directly.

The third is that this commit doesn't change the name `TermBuilder`,
even though it is now building `Entity` instances.  This is because
there's _already_ an `EntityBuilder` which fixes the `EntityPlace`.
It's not clear whether the existing entity building interface should
be removed or whether both should be renamed.  That can be follow-up.
2018-07-05 16:33:51 -07:00
Nick Alexander
76507623ac Part 4: Prepare EDN Entity type for interning tempids during parsing.
This is all part of moving the entity builder away from building term
instances and toward building entity instances.  One of the nice
things that the existing term interface does is allow consumers to use
lightweight reference counted tempid handles; I don't want to lose
that, so we'll build it into the entity data structures directly.
2018-07-05 11:17:20 -07:00
Nick Alexander
106d6fae11 Part 3: Implement Deref and DerefMut for InternSet.
This pattern is generally how newtype wrappers (like `struct
Foo(Bar)`) are implemented in Rust.
2018-07-05 11:16:55 -07:00
Nick Alexander
02a163a10f Part 2: Use ValueRc in InternSet.
We haven't observed performance issues using `Arc` instead of `Rc`,
and we want to be able to include things that are interned (including,
soon, `TempId` instances) in errors coming out of the
transactor.  (And `Rc` isn't `Sync`, so it can't be included in errors
directly.)
2018-07-05 11:16:53 -07:00
Nick Alexander
87f850a44e Part 1: Move intern_set into edn crate.
It's not great to keep lifting functionality higher and higher up the
crate hierarchy, but we really do want to intern while we parse.
Eventually, I expect that we will split the `edn` crate into `types`
and `parsing`, and the `types` crate can depend on a more efficient
interning dependency.
2018-07-05 11:16:48 -07:00
Nick Alexander
d82c7f8ef2 Cull unused mentat_parser_utils crate.
With the transition toward parsing with `rust-peg` and away from
`combine`, we're not using some of the many helpers we built to
support our unusual `combine` usage.  They can just go!
2018-06-30 16:21:50 -07:00
Nick Alexander
8725bad18c Pre: Fix error printing rusqlite::Error. 2018-06-30 14:58:23 -07:00
Emily Toop
da599c3a78 Fix broken documentation links. (#775) (#767) r=nalexander
* Fix broken API doc links

Create symlink for latest to point to v0.7.
Group APIs by top version number rather than individual

* Update swift and android version numbers to match Mentats

* Update documentation

* Update top level .gitignore to ignore docs site & metatdata

* Add README to help with building documentation site

* Address review comments @ncalexan
2018-06-29 10:28:44 -07:00
Grisha Kruglov
8af5288a60 Use TolstoyError for tolstoy's Results; wrap tolstoy's dependency errors r=nalexander
This is inline with the rest of mentat, and helps with upcoming tolstoy work.
2018-06-29 00:47:19 -04:00
Nick Alexander
5fe4f12d32 Use concrete Mentat error types rather than failure::Error. (#769) r=grisha
In the language of
868273409c/book/src/error-errorkind.md
Mentat is a mid-level API, not an application, and therefore we should
prefer our own error types.  Writing an initial consumer of Mentat (a
Rust logins API targeting Mozilla Lockbox), I have found this to be
true: my consumer wants to consume concrete Mentat error types.

This doesn't go "all the way" and convert all sub-crates to the
Error/ErrorKind, but it does go part of the way.
2018-06-27 15:30:55 -07:00
Nick Alexander
ae427849d5 Expose sub-crate *Error types at top-level.
We're not exposing a uniform API with `mentat::Result` yet, meaning
that early consumers (e.g., the logins work for Mozilla Lockbox) need
to wrap errors from all over the Mentat crate hierarchy.
2018-06-27 15:05:43 -07:00
Nick Alexander
d31ec28aa8 Patch it all together: use MentatError at top-level.
I elected to keep Tolstoy using `failure::Error`, because Tolstoy
looks rather more like a high-level application (and will continue to
do so for a while) than a production-ready mid- or low-level API.
2018-06-27 15:05:43 -07:00
Nick Alexander
ac1b0b15fe Convert query-translator/ to query-projector's ProjectorError. 2018-06-27 15:05:43 -07:00
Nick Alexander
b2249f189d Convert query-projector/ to ProjectorError. 2018-06-27 15:05:43 -07:00
Nick Alexander
af005a7669 Convert query-algebrizer/ to AlgebrizerError. 2018-06-27 15:05:43 -07:00
Nick Alexander
d6569a6a22 Convert query-pull/ to PullError. 2018-06-27 15:05:43 -07:00
Nick Alexander
0e4991fa26 Make db/ use DbErrorKind. 2018-06-27 15:05:43 -07:00
Thom
72a9b302f9
Rename or delete things so that there is only one type named Entid (#768)
* Delete the (apparently unused) EntId

* Rename edn's Entid to EntidOrIdent to avoid confusion with the Entid that's actually an i64

* Fix travis beta bustage (This is actually unrelated to entids, but is a trivial fix nonetheless)
2018-06-26 16:34:18 -07:00
Thom
f335253d4c
Fix known leaks and memory safety issues in both swift and android SDKs (#745) 2018-06-25 12:10:11 -07:00
Emily Toop
605c3d938c
Remove duplicated header (#764) 2018-06-25 12:11:58 +01:00
Emily Toop
7232e6ef33
Setting baseurl (#763) 2018-06-25 12:01:16 +01:00
Emily Toop
b323448630
Attempting to get minima theme building on github (#762) 2018-06-25 11:56:59 +01:00
Emily Toop
08b83abe21 Set theme jekyll-theme-tactile 2018-06-25 11:21:42 +01:00
Emily Toop
c5180656cc
Mentat documentation website using Jekyll (#754)
Steps to building docs locally:

    1. Install Jekyll
    2. cd docs
    3. bundle exec jekyll serve --incremental
    4. open local docs site at http://127.0.0.1:4000/


* basic Jekyll site

* Add docs to documentation site

* Update javadoc to allow for error free builds

* Remove docs for rust dependencies

* Better display examples, about and contributing documentation for Mentat

* Version docs
2018-06-25 11:20:36 +01:00
Nick Alexander
7f76d53612 Load and save CLI history. (#758, #760) r=grisha 2018-06-22 15:39:46 -07:00
Nick Alexander
4ea9c78c50 [cli] Part 3: {load,save}_history as appropriate.
It's possible that we should be saving more aggressively -- perhaps
after each entered command -- but we can add that later.
2018-06-22 15:39:29 -07:00
Nick Alexander
c41d728d1d [cli] Part 2: Don't use exit() to terminate the CLI.
It's not possible to do meaningful clean-up (such as saving history)
if we use exit() to quit.  Instead, each handled command returns a
boolean requesting exit.  I elected not to allow ".exit" when
processing commands from the command line; it might be useful to
handle accept that.  In general, though, REPLs that accept "-c
'commands'" on the command line exit after processing those commands,
so I'd rather think more deeply about that model than build in ".exit"
with our existing system.
2018-06-22 15:36:09 -07:00
Nick Alexander
c19337c8bf [cli] Part 1: Bump linefeed; use linefeed::Interface; add "--no-tty" argument.
I don't really understand why we were using `linefeed::Reader`
directly, but reading is not the full set of linefeed features we want
to access.  I think the `linefeed::Interface` should be owned by the
`Repl`, not the `InputReader`, but it's a little awkward to share
access with that configuration, so I'm not going to lift the ownership
until I have a reason to.

I think the "--no-tty" argument might be useful for running inside
Emacs.  Along the way, I made read_stdin() strip the trailing newline,
which agrees with InputReader::read_line().
2018-06-22 15:36:09 -07:00
Nick Alexander
8e2d795778
[cli] Handle line comments in EDN input. (#759) (#761) r=grisha
What was happening is that ["[;", "]"] would get glued to "[; ]",
which of course can never complete.

It would be good to add tests of this, but the existing multi-line
`InputReader` makes that challenging and I don't want to invest the
time to improve it: I expect it to be overhauled as part of a
transition away from parsing with `combine` and toward parsing with
`rust-peg`.
2018-06-22 14:34:16 -07:00
Nick Alexander
60a57ea493 Use failure instead of error_chain. (#586) r=nalexander 2018-06-20 14:56:08 -07:00
Nick Alexander
3760f84da8 Post: Fix comment referring to error-chain. 2018-06-20 14:42:39 -07:00
Grisha Kruglov
4e46adeba1 Convert tolstoy/ to failure. 2018-06-20 14:42:36 -07:00
Grisha Kruglov
31de5be64f Convert db/ to failure. 2018-06-20 14:42:34 -07:00
Grisha Kruglov
0adfa6aae6 Convert tools/cli to failure. 2018-06-20 14:42:30 -07:00
Grisha Kruglov
800f404a23 Convert ffi/ to failure.
This is neat, because currently at the FFI boundary we're primarily concerned
with verbalizing our errors. It doesn't matter what 'error' that's wrapped by
Result is then, as long as it can be displayed.

Once we're past the prototyping stage, it might be a good idea to formalize this.
2018-06-20 14:42:21 -07:00
Grisha Kruglov
4e01929334 Convert src/ to failure. 2018-06-20 14:42:18 -07:00
Grisha Kruglov
836fdb3a35 Convert query_translator/ to failure. 2018-06-20 14:42:14 -07:00
Grisha Kruglov
c075434f84 Convert query_projector/ to failure. 2018-06-20 14:42:10 -07:00
Grisha Kruglov
061967f268 Convert query-pull/ to failure. 2018-06-20 14:42:05 -07:00
Grisha Kruglov
326fe881a0 Convert query-algebrizer/ to failure. 2018-06-20 14:41:59 -07:00
Grisha Kruglov
ce3ce1ccbf Convert sql/ and query-sql/ to failure.
sql/query-sql
2018-06-20 14:41:52 -07:00
Mario Wenzel
fb7d2357de Don't try to match "key" when not using sqlcipher. (#752, #753) r=nalexander
This causes a runtime error, since `opt_str("key")` isn't recognized.
2018-06-20 13:26:36 -07:00
Emily Toop
aae50f40ac Set theme jekyll-theme-tactile 2018-06-20 15:59:50 +01:00
Emily Toop
4282b2d332 Set theme jekyll-theme-cayman 2018-06-20 15:53:34 +01:00
Nick Alexander
91fa34e462
[website] Create placeholder index.html. 2018-06-19 11:39:08 -07:00
Thom
88c6a4b05c
Fix typo nit accidentally missed in #743 (#744) 2018-06-14 13:30:03 -07:00
Thom
87fb505c56
Make travis test sqlcipher by running the tests on macos. Fixes #738 (#743) 2018-06-14 13:23:17 -07:00
Thom
54d592df29
Merge pull request #742 from thomcc/fix-bustage 2018-06-14 07:58:09 -07:00
Thom Chiovoloni
99a73ccb03 Avoid using 1.26.0-only features when using sqlcipher, and move the sqlcipher Store support to the correct file 2018-06-13 22:48:28 -07:00
Emily Toop
8e918949fb Separate Store from Conn.
This is a Pre: part extracted from #660.
2018-06-13 15:29:11 -07:00
Nick Alexander
f041dfe509 Bustage fix: Build against Rust 1.25. 2018-06-13 15:28:44 -07:00
Nick Alexander
8cc0e5a64e Make Travis test against multiple Rust versions, including Rust 1.25. 2018-06-13 15:28:44 -07:00
Thom
6a1a265894
Add support for using sqlcipher (#737). Fixes #118 2018-06-13 08:49:40 -07:00
Emily Toop
c0d4568970 Support consumption by Carthage; bump iOS minimum version to 11. r=nalexander
Principally, this adds producing libmentat_ffi.a for consumption by Carthage.

To achieve this, we disable bitcode and bump the miniumum iOS version
to 11.  In addition, we make things open and public so that consumers
can, well, consume.
2018-06-08 13:53:36 -07:00
Nick Alexander
3d5ae797b2 Parse queries with rust-peg. r=rnewman,grisha (#728) 2018-06-04 15:46:13 -07:00
Nick Alexander
cfed968514 Review comments. 2018-06-04 15:21:27 -07:00
Nick Alexander
e68cc4016c Part 7: Remove tx entirely.
This was left over from #681.
2018-06-04 15:04:39 -07:00
Nick Alexander
d4166cc67c Part 6: Remove query-parser entirely. 2018-06-04 15:04:39 -07:00
Nick Alexander
47441f56dc Part 5: Push FindQuery into query-algebrizer; structure errors.
This is a big deck-chair re-arrangement.  This puts FindQuery into
query-algebrizer and puts the validation from ParsedFindQuery ->
FindQuery their as well.

Some tests were re-homed for this.

In addition, the little-used maplit crate dependency was replaced with
inline expressions.
2018-06-04 15:04:39 -07:00
Nick Alexander
09f1d633b5 Part 4: Parse queries with rust-peg.
There's an unfortunate conflation here between implementing the query
parser in `rust-peg` and moving some validation that now happens at
parse time to happen later.  The result is that we introduce
`ParsedFindQuery` as a less-processed `FindQuery`, and that we only
use string errors (which is all `rust-peg` supports) instead of the
structured errors in query-parser's errors module.  The next commit
will address this, on the road to removing the `query-parser` module
entirely.
2018-06-04 15:04:39 -07:00
Nick Alexander
a8073056f2 Part 3: Move query into edn.
It's unfortunate to squash two crates together like this, but it's the
best option.
2018-06-04 15:04:37 -07:00
Nick Alexander
a4a8892309 Part 3a: Move file to preserve blame. 2018-06-04 14:56:56 -07:00
Nick Alexander
1d8d94f887 Part 2: Turn (type-function ?var) into (type ?var type-keyword).
This is more general (the parser doesn't encode the set of known
types), and avoids a dependency on `ValueType`.
2018-06-04 14:52:51 -07:00
Nick Alexander
ad9a1394a3 Part 1: Push ValueRc and friends into edn crate.
This is a pre-requisite for moving the existing `combine`-based parser
to use `rust-peg` -- part of the push to use `rust-peg` for all parsing
started in https://github.com/mozilla/mentat/pull/681.  We need the
types for the parsed structure "very early", and the `edn` crate is
the earliest such crate.

This is an unfortunate destruction of boundaries between parts of the
system, but it's the best way we have to achieve this right now.
2018-06-04 14:52:51 -07:00
Nick Alexander
f1fc9f1846 Part 0: Extract query-parser errors. 2018-06-04 14:52:51 -07:00
Nick Alexander
3cc8b4fd24 Pre: Prefer [(pred ...)] to [[pred ...]] syntax.
This is a style choice.  We supported both, perhaps for Datomic
compliance, but it's not the standard we use in our code base.  In
addition, it doesn't read like lisp (which is what EDN is copying),
since [] is not function application in most lisps.

It's also a convenience: I don't want to parse brackets that have to
agree with `rust-peg`.  It's not hard but it's also not worth doing.
2018-06-04 14:52:51 -07:00
Nick Alexander
47a0f40cce Pre: Fix warnings. 2018-06-04 14:52:51 -07:00
Nick Alexander
729fe59578 [edn] Pre: Rename keyword to namespaced_keyword.
The `Keyword` type evolved to become more general: we now use the one
type for both :regular and :name/spaced keywords.  This changes
reflects the new generality.
2018-06-04 14:52:51 -07:00
Nick Alexander
d8d18a1731
[query] Handle SQL NULL for aggregates over 0 rows. (#684) (#688) r=rnewman
This uses a `SELECT *` from an inner subselect to filter potentially `NULL` aggregates.

The alternative is to handle `NULL` values throughout the projector, which is simple but loses a valuable invariant: Mentat SQL queries produce values that are not `NULL`.
2018-06-01 14:17:31 -07:00
Grisha Kruglov
2a025916fe
Android SDK basic sample project and symlinked SDK Mentat binaries (#729) r=nalexander
* Add an IntelliJ section to gitignore
* Add Android SDK sample project which exercises mentat SDK
* Symlink libmentat_ffi.so in Android SDK to the generated --release files
* README files for Android SDK and mentat_ffi
2018-06-01 12:44:31 -07:00
Grisha Kruglov
93b7d25446
Android build script which supports target specification (#727) r=self 2018-05-31 12:25:24 -07:00
Grisha Kruglov
250e35b726
Gradle support for publishing to bintray (#720) r=ncalexan
* Rename SDK package name from com.mozilla.mentat to org.mozilla.mentat
* Gradle configuration for publishing to a bintray repository
2018-05-30 13:38:45 -07:00
Grisha Kruglov
b0421c61b4
Min SDK 16, bump dependency versions, update gradle & wrapper, fix linter error (#717) r= fluffyemily
Bump versions, update gradle wrapper, fix linter error (log tag too long)
2018-05-29 10:16:32 -07:00
Richard Newman
01db9232b4
Include namespace-separating solidus in NamespaceableName; improve type handling around ground (#713) r=nalexander
* Include the namespace-separating solidus in NamespaceableName.
* Use type annotations when deciding how to process ambiguous ground input.
* Include simple patterns in the type extraction phase of pattern application. (#705)
* Review comment.
* Add a test.
2018-05-29 16:45:53 +02:00
Chris Foster
e4447927c7 Update README.md
Grammar -- the subjunctive is appropriate here.
2018-05-24 10:00:01 -07:00
Emily Toop
6121da3592 Address review comments @nalexander 2018-05-15 15:39:15 +01:00
Emily Toop
2c0f755632 Address review comments @nalexander 2018-05-15 15:39:15 +01:00
Emily Toop
35467c1b24 Wrap caching FFI functions in Android Java library.
`CacheDirection` enum is used only on the Android side to provide a usable interface. FFI calls are more explicit.

Tests ensure that a cached query is faster than the uncached one.
2018-05-15 15:39:15 +01:00
Emily Toop
8add073001 Wrap caching FFI functions in Swift library.
`CacheDirection` enum is used only on the Swift side to provide a usable interface. FFI calls are more explicit.

Tests ensure that a cached query is faster than the uncached one.
2018-05-15 15:39:15 +01:00
Emily Toop
b4b558e196 Expose cache over the FFI.
This exposes an FFI function for each direction of caching, `Forward`, `Reverse` and `Both`. This is to make is as clear as possible to consumers which direction they are caching their attributes in. The original implementation exposed the `CacheDirection` enum over FFI and it made mistakes very easy to make. This is more explicit and therefore less prone to error.
2018-05-15 15:39:15 +01:00
Emily Toop
e0cd9b6b20 Implement InProgress transactions and InProgress and Entity builders on Android.
Rename some of the functions in TypedValue, TupleResult and QueryBuilder to make them more Javay and less Swifty
2018-05-15 15:39:15 +01:00
Emily Toop
38c1a93712 Implement InProgress transactions and InProgress and Entity builders on iOS 2018-05-15 15:39:15 +01:00
Emily Toop
ed5427253b Expose InProgress, InProgressBuilder and EntityBuilder over the FFI.
There are two ways to create each builder, directly from a `Store` or from an `InProgress`. Creating from `Store` will perform two actions, creating a new `InProgress` and then returning a builder from that `InProgress`. In the case of `store_entity_builder_with_entid` and `store_entity_builder_from_tempid`, the function goes a step further and calls `describe` or `describe_tempid` from the created `InProgressBuilder` and returning the `EntityBuilder` that results. These two functions are replicated on `InProgress`. This has been done to reduce the overhead of objects being passed over the FFI boundary.

The decision to do this enables us to go from something like

```
in_progress  = store_begin_transaction(store);
builder = in_progress_builder(in_progress);
entity_builder = in_progress_builder_describe(builder, entid);
```
to
```
entity_builder = store_entity_builder_from_entid(store);
```

There is an `add_*` and `retract_*` function specified for each `TypedValue` type for both `InProgressBuilder` and `EntityBuilder`.

To enable `transact` on `EntityBuilder` and `InProgressBuilder`, a new `repr(C)` struct has been created that contains a pointer to an `InProgress` and a pointer to a `Result<TxReport>` to allow passing the tuple result returned from `transact` on those types over the FFI.

Commit is possible from both builders and `InProgress`.
2018-05-15 15:39:15 +01:00
Richard Newman
b2e98f44f6
Generalize Entity by value type. (#701) (#691) r=rnewman
* Part 3: Parameterize Entity by value type.

This isn't quite right, because after parsing, we shouldn't care
about` `edn::ValueAndSpan`, we should care only about edn::Value.
However, I think we can drop `ValueAndSpan` entirely if we just use
`rust-peg` (and its simpler error messages) rather than a mix of
`rust-peg` and `combine`.

In any case, this paves the way to transacting `Entity<TypedValue>`,
which is a nice step towards building general entities.

* Part 1: Add AttributePlace.

* Part 2: Name other places EntityPlace and ValuePlace.

Now we're consistent and closer to self-documenting.  Both matter more
as we expose `Entity` as the thing to build for programmatic usage.

* Part 4: Allow Ident and TempId in ValuePlace.

The parser will never produce these, since determining whether an
integer/keyword or string is an ident or a tempid, respectively, in
the value place requires the schema.

But a builder that produces `Entity` instances directly will want to
produce these.
2018-05-15 00:43:07 -07:00
Nick Alexander
46c2a0801f Add type checking and constraint checking to the transactor. (#663, #532, #679)
This should address #663, by re-inserting type checking in the
transactor stack after the entry point used by the term builder.

Before this commit, we were using an SQLite UNIQUE index to assert
that no `[e a]` pair, with `a` a cardinality one attribute, was
asserted more than once.  However, that's not in line with Datomic,
which treats transaction inputs as a set and allows a single datom
like `[e a v]` to appear multiple times.  It's both awkward and not
particularly efficient to look for _distinct_ repetitions in SQL, so
we accept some runtime cost in order to check for repetitions in the
transactor.  This will allow us to address #532, which is really about
whether we treat inputs as sets.  A side benefit is that we can
provide more helpful error messages when the transactor does detect
that the input truly violates the cardinality constraints of the
schema.

This commit builds a trie while error checking and collecting final
terms, which should be fairly efficient.  It also allows a simpler
expression of input-provided :db/txInstant datoms, which in turn
uncovered a small issue with the transaction watcher, where-by the
watcher would not see non-input-provided :db/txInstant datoms.

This transition to Datomic-like input-as-set semantics allows us to
address #532.  Previously, two tempids that upserted to the same entid
would produce duplicate datoms, and that would have been rejected by
the transactor -- correctly, since we did not allow duplicate datoms
under the input-as-list semantics.  With input-as-set semantics,
duplicate datoms are allowed; and that means that we must allow
tempids to be equivalent, i.e., to resolve to the same tempid.

To achieve this, we:
- index the set of tempids
- identify tempid indices that share an upsert
- map tempids to a dense set of contiguous integer labels

We use the well-known union-find algorithm, as implemented by
petgraph, to efficiently manage the set of equivalent tempids.

Along the way, I've fixed and added tests for two small errors in the
transactor.  First, don't drop datoms resolved by upsert (#679).
Second, ensure that complex upserts are allocated.

I don't know quite what happened here.  The Clojure implementation
correctly kept complex upserts that hadn't resolved as complex
upserts (see
9a9dfb502a/src/common/datomish/transact.cljc (L436))
and then allocated complex upserts if they didn't resolve (see
9a9dfb502a/src/common/datomish/transact.cljc (L509)).

Based on the code comments, I think the Rust implementation must have
incorrectly tried to optimize by handling all complex upserts in at
most a single generation of evolution, and that's just not correct.
We're effectively implementing a topological sort, using very specific
domain knowledge, and its not true that a node in a topological sort
can be considered only once!
2018-05-14 15:22:45 -07:00
Nick Alexander
e5e37178af Pre: Remove ancient Clojure code comments. 2018-05-14 15:22:45 -07:00
Richard Newman
3cba87c74b Allow pull aliases to be non-namespaced. (#694) r=nalexander 2018-05-14 10:45:48 -07:00
Emily Toop
013629dec6
iOS and Android (Java) sdk framework (#643)
Documents the FFI layer for Mentat, and provides transaction functionality via an EDN string. Creates two native libraries for iOS (Swift) and Android (Java) and fully tests the FFI for both platforms.

Closes #619 #614 #611
2018-05-14 16:20:36 +01:00
Richard Newman
60cb5d2432
Pull improvements (#682) r=nalexander
* Parse and handle aliased pull attributes.
* Allow :db/id to be mentioned as a pull attribute.
* Clean up comment.
* Remove unused function.
2018-05-13 14:15:36 -07:00
Nick Alexander
4fde4fe0a6 Bustage fixes: compile on stable; avoid unused variable warning. 2018-05-11 10:22:57 -07:00
Richard Newman
3dc68bcd38 Combine NamespacedKeyword and Keyword. (#689) r=nalexander
* Make properties on NamespacedKeyword/NamespacedSymbol private

* Use only a single String for NamespacedKeyword/NamespacedSymbol

* Review comments.

* Remove unsafe code in namespaced_name.

Benchmarking shows approximately zero change.

* Allow the types of ns and name to differ when constructing a NamespacedName.

* Make symbol namespaces optional.

* Normalize names of keyword/symbol constructors.

This will make the subsequent refactor much less painful.

* Use expect not unwrap.

* Merge Keyword and NamespacedKeyword.
2018-05-11 09:52:17 -07:00
Nick Alexander
c8f74fa41b [edn] Round-trip instants. (#686) (#687) r=rnewman
First, the parser had a small grouping bug where-by it wouldn't parse
Z as timezone correctly.  Second, we weren't printing instants in the format
that we parse.
2018-05-11 02:11:04 -07:00
Thom
37a6f7be28 Use Cell instead of AtomicUsize in RcCounter. (#646) r=rnewman 2018-05-11 02:03:09 -07:00
Nick Alexander
9a4bd0de4f Use rust-peg for tx parsing. r=rnewman 2018-05-10 10:32:27 -07:00
Nick Alexander
7a8c9d90c2 Post: Remove tx-parser crate entirely. 2018-05-10 10:24:05 -07:00
Nick Alexander
cbffe5e545 Use rust-peg for tx parsing.
There are few reasons to do this:

- it's difficult to add symbol interning to combine-based parsers like
  tx-parser -- literally every type changes to reflect the interner,
  and that means every convenience macro we've built needs to chagne.
  It's trivial to add interning to rust-peg-based parsers.

- combine has rolled forward to 3.2, and I spent a similar amount of
  time investigating how to upgrade tx-parser (to take advantage of
  the new parser! macros in combine that I think are necessary for
  adapting to changing types) as I did just converting to rust-peg.

- it's easy to improve the error messages in rust-peg, where-as I have
  tried twice to improve the nested error messages in combine and am
  stumped.

- it's roughly 4x faster to parse strings directly as opposed to
  edn::ValueAndSpan, and it'll be even better when we intern directly.
2018-05-10 10:24:05 -07:00
Nick Alexander
e437944d94 Pre: Don't use tx-parser for destructuring map notation.
This was always a choice, but we've outgrown it: now we want to accept
value types that don't come from EDN and/or tx-parser.
2018-05-10 10:19:54 -07:00
Nick Alexander
4c4af46315 Add TransactableValue abstracting value places that can be transacted.
This is a stepping stone to transacting entities that are not based on
`edn::ValueAndSpan`.  We need to turn some value places (general) into
entity places (restricted), and those restrictions are captured in
tx-parser right now.  But for `TypedValue` value places, those
restrictions are encoded in the type itself.  This lays the track to
accept other value types in value places, which is good for
programmatic builder interfaces.
2018-05-10 10:19:54 -07:00
Emily Toop
e1e7cbaa44
Closes #634 - Fix variables in predicates (#635) r=rnewman
We were forgetting to check for bound variables when resolving types other than ref types during inequality handling. This patch adds in the binding checks and `bails` if the bound variable is of the wrong type. #634
2018-05-09 16:24:12 +01:00
Richard Newman
e21156a754
Implement simple pull expressions (#638) r=nalexander
* Refactor AttributeCache populator code for use from pull.

* Pre: add to_value_rc to Cloned.

* Pre: add From<StructuredMap> for Binding.

* Pre: clarify Store::open_empty.

* Pre: StructuredMap cleanup.

* Pre: clean up a doc test.

* Split projector crate. Pass schema to projector.

* CLI support for printing bindings.

* Add and use ConjoiningClauses::derive_types_from_find_spec.

* Define pull types.

* Implement pull on top of the attribute cache layer.

* Add pull support to the projector.

* Parse pull expressions.

* Add simple pull support to connection objects.

* Tests for pull.

* Compile with Rust 1.25.

The only choice involved in this commit is that of replacing the
anonymous lifetime '_ with a named lifetime for the cache; since we're
accepting a Known, which includes the cache in question, I think it's
clear that we expect the function to apply to any given cache
lifetime.

* Review comments.

* Bail on unnamed attribute.

* Make assert_parse_failure_contains safe to use.

* Rework query parser to report better errors for pull.

* Test for mixed wildcard and simple attribute.
2018-05-04 12:56:00 -07:00
Nick Alexander
90465ae74a Flip ValueRc to Arc in order to allow TypedValue in errors. (#677) (#678) r=rnewman
@mmacedoeu did a good deal of work to show that Arc instead of Rc
wasn't too difficult in #656, and @rnewman pushed the refactoring
across the line in #659. However, we didn't flip the switch at that
time. For #673, we'd like to include TypedValue instances in errors,
and with error-chain (and failure) error types need to be 'Sync +
'Send, so we need Arc.

This builds on #659 and should also finish #656.
2018-05-03 16:46:49 -07:00
Nick Alexander
1b66818ac9 Post: Fix CLI bustage. 2018-05-01 16:10:06 -07:00
Nick Alexander
9513012aa5 [tx] Fail transactions where complex upserts resolve to multiple entids. (#670) r=rnewman 2018-05-01 15:35:44 -07:00
Nick Alexander
2b82ffb2e5 [tx] Fail transactions where complex upserts resolve to multiple entids. (#670)
This innocuous looking change (upserts_ev -> upserts_e -> resolved in
all situations, rather than upserts_ev -> resolved in some situations)
is a significant change in semantics and assumptions in the
transactor.  Witness the large comment being removed about the same
tempid resolving in different generations!

To support this change, we provide more holistic errors for
conflicting upserts, which entails collecting some (relatively
expensive) diagnostic data.

I left in some debug logging, simply since it shouldn't hurt in
general, and will likely be useful for the next bug we see in the
transactor.
2018-05-01 15:34:44 -07:00
Nick Alexander
7960b4ccd2 Pre: Get ready to use log in mentat_db.
We don't yet have a logging system for production use, but I'd like to
start experimenting with log, which seems to be (close to) a Rust
standard.  We're already using it in mentat_cli.
2018-05-01 13:46:03 -07:00
Nick Alexander
d4a635f4e7 (tx) Replace :db/tx with (current-tx) transaction function and broaden support. (#664) r=rnewman 2018-04-26 19:33:16 -07:00
Nick Alexander
32ed56685e (tx) Replace :db/tx with (transaction-tx) transaction function and broaden support. (#664)
:db/tx (and Datomic's version, :datomic/tx) suffer from the same
ambiguities that [a v] lookup references do -- determining the type of
the result is context sensitive.  (In this case, is :db/tx a reference
to the current transaction ID, or is it a valid keyword?)  This commit
addresses the ambiguity by introducing a notion of a transaction
functions, and provides a little scaffolding for adding more (should
the need arise).  I left the scaffolding in place rather than handling
just (transaction-tx) because I started trying to
implement (transaction-instant) as well, which is more difficult --
see the comments.

It's worth noting that this approach generalizes more or less directly
to ?input variables, since those can be eagerly bound like the
implemented transaction function (transaction-tx).
2018-04-26 19:32:14 -07:00
Richard Newman
f979044ba1
Refactor value type boxing. (#659) r=nalexander
* Pre: eliminate some occurrences of Rc, largely through the magic of Into.
* Pre: introduce FromRc to convert between refcounted types.
* Introduce ValueRc as an abstraction over Rc/Arc choice.
* Move Cloned to core.
* Move CString-creation methods to TypedValue.
* Finish transition.
2018-04-25 14:23:27 -07:00
Richard Newman
a2e13f624c
Add 'Binding', a structured value type to return from queries. (#657) r=nalexander
Bump to 0.7: breaking change.
2018-04-24 15:08:38 -07:00
Richard Newman
1818e0b98e Split mentat_core TypedValue code into separate files for clarity. 2018-04-24 15:05:04 -07:00
Richard Newman
a74a2deffc
Introduce RelResult rather than Vec<Vec<TypedValue>>. (#639) r=nalexander
* Pre: clean up core/src/lib.rs.
* Pre: use indexmap 1.0 in db and query-projector.
* Change rel results to be a RelResult instance, not a Vec<Vec<TypedValue>>.

This avoids memory fragmentation and improves locality by using a single
heap-allocated vector for all bindings, rather than a separate
heap-allocated vector for each row.

We hide this abstraction behind the `RelResult` type, which tracks the
stride length (width) of each row.

* Don't allocate temporary vectors when projecting RelResults.
2018-04-24 15:04:00 -07:00
Nick Alexander
0c31fc7875 (query) Implement tx-log API: (tx-ids ...) and (tx-data ...) functions. r=rnewman 2018-04-19 09:59:05 -07:00
Nick Alexander
c8da4be38f (query) Implement tx-log API: (tx-ids ...) and (tx-data ...) functions.
`tx-ids` allows to enumerate transaction IDs efficiently.

`tx-data` allows to extract transaction log data efficiently.

We might eventually allow to filter by impacted attribute sets as well.
2018-04-19 09:58:41 -07:00
Nick Alexander
e532614908 (query) Pre: Model columns that don't have type tags closer to Column. 2018-04-19 09:58:41 -07:00
Nick Alexander
36eca0bfb0 (chore) Pre: Use the same features of uuid throughout the project. 2018-04-19 09:58:41 -07:00
Richard Newman
1f1818448a
Begin adding worked examples. (#629) r=nalexander 2018-04-17 10:39:36 -07:00
Richard Newman
8ca657ec03 Simplify vocabulary migration test.
We don't need to explicitly retract if the transactor will do it
for us -- which it will if an attribute is cardinality-one.
2018-04-12 11:53:19 -07:00
Richard Newman
1509d16c3e
Fix (the ?foo) (#633) r=nalexander
Don't group by ?var when processing (the ?var).

This PR also finishes error generation in the projector.
2018-04-10 11:58:58 -07:00
Richard Newman
909b2a8be5 Refactoring: split up the projector crate. No other code changes. 2018-04-09 10:26:09 -07:00
Richard Newman
39f1d61175 Bump version to 0.6.2. 2018-04-09 09:47:49 -07:00
Richard Newman
3f8464e8ed Implement vocabulary-driven schema upgrades. (#595) r=emily 2018-04-09 09:47:49 -07:00
Richard Newman
a5cda7c3e9 Allow passing a TermBuilder to be transacted by InProgress; add TermBuilder::is_empty. r=emily 2018-04-09 09:47:49 -07:00
Richard Newman
27dde378e0 Allow retraction of some schema attributes. (#379) r=nalexander 2018-04-09 09:47:49 -07:00
2329 changed files with 314626 additions and 19879 deletions

3
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,3 @@
liberapay: svartalf
patreon: svartalf
custom: ["https://svartalf.info/donate/", "https://www.buymeacoffee.com/svartalf"]

11
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "cargo" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

20
.github/workflows/audit.yml vendored Normal file
View file

@ -0,0 +1,20 @@
name: Security audit
on:
schedule:
- cron: '0 0 1 * *'
push:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
pull_request:
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/audit-check@issue-104
with:
token: ${{ secrets.GITHUB_TOKEN }}

13
.github/workflows/clippy-ng.yml vendored Normal file
View file

@ -0,0 +1,13 @@
on: [push, pull_request]
name: Clippy (new version test, don't use it!)
jobs:
clippy_check_ng:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: clippy
override: true
- uses: actions-rs/clippy@master

16
.github/workflows/clippy_check.yml vendored Normal file
View file

@ -0,0 +1,16 @@
on: [push, pull_request]
name: Clippy check
jobs:
clippy_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
components: clippy
override: true
- uses: actions-rs/clippy-check@v1
with:
args: --all-targets --all-features -- -D warnings
token: ${{ secrets.GITHUB_TOKEN }}

28
.github/workflows/cross_compile.yml vendored Normal file
View file

@ -0,0 +1,28 @@
# We could use `@actions-rs/cargo` Action ability to automatically install `cross` tool
# in order to compile our application for some unusual targets.
on: [push, pull_request]
name: Cross-compile
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
target:
- armv7-unknown-linux-gnueabihf
- powerpc64-unknown-linux-gnu
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: ${{ matrix.target }}
override: true
- uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --release --target=${{ matrix.target }}

66
.github/workflows/grcov.yml vendored Normal file
View file

@ -0,0 +1,66 @@
on: [push, pull_request]
name: Code coverage with grcov
jobs:
grcov:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- macOS-latest
# - windows-latest
steps:
- uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
profile: minimal
- name: Execute tests
uses: actions-rs/cargo@v1
with:
command: test
args: --all
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests"
# Note that `actions-rs/grcov` Action can install `grcov` too,
# but can't use faster installation methods yet.
# As a temporary experiment `actions-rs/install` Action plugged in here.
# Consider **NOT** to copy that into your workflow,
# but use `actions-rs/grcov` only
- name: Pre-installing grcov
uses: actions-rs/install@v0.1
with:
crate: grcov
use-tool-cache: true
- name: Gather coverage data
id: coverage
uses: actions-rs/grcov@v0.1
with:
coveralls-token: ${{ secrets.COVERALLS_TOKEN }}
- name: Coveralls upload
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel: true
path-to-lcov: ${{ steps.coverage.outputs.report }}
grcov_finalize:
runs-on: ubuntu-latest
needs: grcov
steps:
- name: Coveralls finalization
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true

110
.github/workflows/msrv.yml vendored Normal file
View file

@ -0,0 +1,110 @@
# Based on https://github.com/actions-rs/meta/blob/master/recipes/msrv.md
on: [push, pull_request]
name: MSRV
jobs:
check:
name: Check
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.31.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- name: Run cargo check
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: check
test:
name: Test Suite
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.31.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- name: Run cargo test
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: test
fmt:
name: Rustfmt
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.31.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- name: Install rustfmt
run: rustup component add rustfmt
- name: Run cargo fmt
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: fmt
args: --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.31.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
- name: Install clippy
run: rustup component add clippy
- name: Run cargo clippy
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: clippy
args: -- -D warnings

78
.github/workflows/nightly_lints.yml vendored Normal file
View file

@ -0,0 +1,78 @@
on: [push, pull_request]
name: Nightly lints
jobs:
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install nightly toolchain with clippy available
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: clippy
- name: Run cargo clippy
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: clippy
args: -- -D warnings
rustfmt:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install nightly toolchain with rustfmt available
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt
- name: Run cargo fmt
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: fmt
args: --all -- --check
combo:
name: Clippy + rustfmt
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install nightly toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt, clippy
- name: Run cargo fmt
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: fmt
args: --all -- --check
- name: Run cargo clippy
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: clippy
args: -- -D warnings

79
.github/workflows/quickstart.yml vendored Normal file
View file

@ -0,0 +1,79 @@
# Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md
#
# While our "example" application has the platform-specific code,
# for simplicity we are compiling and testing everything on the Ubuntu environment only.
# For multi-OS testing see the `cross.yml` workflow.
on: [push, pull_request]
name: Quickstart
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Run cargo check
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: check
test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Run cargo test
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: test
lints:
name: Lints
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- name: Run cargo fmt
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: fmt
args: --all -- --check
- name: Run cargo clippy
uses: actions-rs/cargo@v1
continue-on-error: true # WARNING: only for this example, remove it!
with:
command: clippy
args: -- -D warnings

23
.gitignore vendored
View file

@ -3,7 +3,7 @@
*.jar *.jar
*jar *jar
*~ *~
*.rs.bk **/*.rs.bk
.s* .s*
.*.sw* .*.sw*
*.rs.bak *.rs.bak
@ -15,6 +15,8 @@
.lein-plugins/ .lein-plugins/
.lein-repl-history .lein-repl-history
.nrepl-port .nrepl-port
.bundle/
docs/vendor/
/.lein-* /.lein-*
/.nrepl-port /.nrepl-port
Cargo.lock Cargo.lock
@ -22,7 +24,7 @@ Cargo.lock
/classes/ /classes/
/node_modules/ /node_modules/
/out/ /out/
target/ /target
pom.xml pom.xml
pom.xml.asc pom.xml.asc
/.cljs_node_repl/ /.cljs_node_repl/
@ -54,8 +56,10 @@ pom.xml.asc
/fixtures/*.db-shm /fixtures/*.db-shm
/fixtures/*.db-wal /fixtures/*.db-wal
/query-parser/out/ /query-parser/out/
## Build generated ## Build generated
build/ /sdks/swift/Mentat/build/
/sdks/android/**/build
DerivedData DerivedData
build.xcarchive build.xcarchive
@ -78,4 +82,15 @@ build.xcarchive
## Obj-C/Swift specific ## Obj-C/Swift specific
*.hmap *.hmap
*.ipa *.ipa
/sdks/swift/Mentat/External-Dependencies
# Android & IntelliJ
**/*.iml
**/.idea
/sdks/android/**/local.properties
# Documentation
docs/_site
docs/.sass-cache
docs/.jekyll-metadata

1
.ignore Normal file
View file

@ -0,0 +1 @@
docs/

80
.taskcluster.yml Normal file
View file

@ -0,0 +1,80 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
version: 0
allowPullRequests: public
tasks:
####################################################################################################
# Task: Pull requests
####################################################################################################
- provisionerId: '{{ taskcluster.docker.provisionerId }}'
workerType: '{{ taskcluster.docker.workerType }}'
extra:
github:
env: true
events:
- pull_request.opened
- pull_request.edited
- pull_request.synchronize
- pull_request.reopened
- push
scopes:
- "queue:create-task:aws-provisioner-v1/github-worker"
- "queue:scheduler-id:taskcluster-github"
payload:
maxRunTime: 3600
deadline: "{{ '2 hours' | $fromNow }}"
image: 'mozillamobile/android-components:1.4'
command:
- /bin/bash
- '--login'
- '-cx'
- >-
export TERM=dumb
&& git fetch {{ event.head.repo.url }} {{ event.head.repo.branch }}
&& git config advice.detachedHead false
&& git checkout {{event.head.sha}}
&& python automation/taskcluster/decision_task_pull_request.py
features:
taskclusterProxy: true
metadata:
name: Mentat Android SDK - Pull Request
description: Building and testing the Mentat Android SDK - triggered by a pull request.
owner: '{{ event.head.user.email }}'
source: '{{ event.head.repo.url }}'
####################################################################################################
# Task: Release
####################################################################################################
- provisionerId: '{{ taskcluster.docker.provisionerId }}'
workerType: '{{ taskcluster.docker.workerType }}'
extra:
github:
events:
- release
scopes:
- "secrets:get:project/mentat/publish"
payload:
maxRunTime: 3600
deadline: "{{ '2 hours' | $fromNow }}"
image: 'mozillamobile/mentat:1.2'
command:
- /bin/bash
- '--login'
- '-cx'
- >-
export TERM=dumb
&& git fetch origin --tags
&& git config advice.detachedHead false
&& git checkout {{ event.version }}
&& python automation/taskcluster/release/fetch-bintray-api-key.py
&& cd sdks/android/Mentat
&& ./gradlew --no-daemon clean library:assembleRelease
&& VCS_TAG=`git show-ref {{ event.version }}` ./gradlew bintrayUpload --debug -PvcsTag="$VCS_TAG"
features:
taskclusterProxy: true
metadata:
name: Mentat Android SDK - Release ({{ event.version }})
description: Building and publishing release versions.
owner: '{{ event.head.user.email }}'
source: '{{ event.head.repo.url }}'

View file

@ -1,3 +1,78 @@
language: rust language: rust
env:
- CARGO_INCREMENTAL=0
# https://bheisler.github.io/post/efficient-use-of-travis-ci-cache-for-rust/
before_cache:
# Delete loose files in the debug directory
- find ./target/debug -maxdepth 1 -type f -delete
# Delete the test and benchmark executables. Finding these all might take some
# experimentation.
- rm -rf ./target/debug/deps/criterion*
- rm -rf ./target/debug/deps/bench*
# Delete the associated metadata files for those executables
- rm -rf ./target/debug/.fingerprint/criterion*
- rm -rf ./target/debug/.fingerprint/bench*
# Note that all of the above need to be repeated for `release/` instead of
# `debug/` if your build script builds artifacts in release mode.
# This is just more metadata
- rm -f ./target/.rustc_info.json
# Also delete the saved benchmark data from the test benchmarks. If you
# have Criterion.rs benchmarks, you'll probably want to do this as well, or set
# the CRITERION_HOME environment variable to move that data out of the
# `target/` directory.
- rm -rf ./target/criterion
# Also delete cargo's registry index. This is updated on every build, but it's
# way cheaper to re-download than the whole cache is.
- rm -rf "$TRAVIS_HOME/.cargo/registry/index/"
- rm -rf "$TRAVIS_HOME/.cargo/registry/src"
cache:
directories:
- ./target
- $TRAVIS_HOME/.cache/sccache
- $TRAVIS_HOME/.cargo/
- $TRAVIS_HOME/.rustup/
before_script:
- cargo install --force cargo-audit
- cargo generate-lockfile
- rustup component add clippy-preview
script: script:
- cargo audit
# We use OSX so that we can get a reasonably up to date version of SQLCipher.
# (The version in Travis's default Ubuntu Trusty is much too old).
os: osx
before_install:
- brew install sqlcipher
rust:
- 1.43.0
- 1.44.0
- 1.45.0
- 1.46.0
- 1.47.0
- stable
- beta
- nightly
matrix:
allow_failures:
- rust: nightly
fast_finish: true
jobs:
include:
- stage: "Test iOS"
rust: 1.47.0
script: ./scripts/test-ios.sh
- stage: "Docs"
rust: 1.47.0
script: ./scripts/cargo-doc.sh
script:
- cargo build --verbose --all
- cargo clippy --all-targets --all-features -- -D warnings -A clippy::comparison-chain -A clippy::many-single-char-names # Check tests and non-default crate features.
- cargo test --verbose --all - cargo test --verbose --all
- cargo test --features edn/serde_support --verbose --all
# We can't pick individual features out with `cargo test --all` (At the time of this writing, this
# works but does the wrong thing because of a bug in cargo, but its fix will be to disallow doing
# this all-together, see https://github.com/rust-lang/cargo/issues/5364 for more information). To
# work around this, we run tests individually for sub-crates that rely on `rusqlite`.
- |
for crate in "" "db" "db-traits" "ffi" "public-traits" "query-projector" "query-projector-traits" "query-pull" "sql" "tolstoy" "tolstoy-traits" "transaction" "tools/cli"; do
cargo test --manifest-path ./$crate/Cargo.toml --verbose --no-default-features --features sqlcipher
done

39
CHANGELOG.md Normal file
View file

@ -0,0 +1,39 @@
# 0.11.1 (2018-08-09)
* sdks/android compiled against:
* Kotlin standard library 1.2.41
* **API changes**: Changed wording of MentatError::ConflictingAttributeDefinitions, MentatError::ExistingVocabularyTooNew, MentatError::UnexpectedCoreSchema.
* [Commits](https://github.com/mozilla/mentat/compare/v0.11.0...v0.11.1)
# 0.11 (2018-07-31)
* sdks/android compiled against:
* Kotlin standard library 1.2.41
* **sdks/android**: `Mentat()` constructor replaced with `open` factory method.
* [Commits](https://github.com/mozilla/mentat/compare/v0.10.0...v0.11.0)
# 0.10 (2018-07-26)
* sdks/android compiled against:
* Kotlin standard library 1.2.41
* **API changes**:
* `store_open{_encrypted}` now accepts an error parameter; corresponding constructors changed to be factory functions.
* [Commits](https://github.com/mozilla/mentat/compare/v0.9.0...v0.10.0)
# 0.9 (2018-07-25)
* sdks/android compiled against:
* Kotlin standard library 1.2.41
* **API changes**:
* Mentat partitions now enforce their integrity, denying entids that aren't already known.
* **sdks/android**: First version published to nalexander's personal bintray repository.
* Various bugfixes and refactorings (see commits below for details)
* [Commits](https://github.com/mozilla/mentat/compare/v0.8.1...v0.9.0)

View file

@ -1,4 +1,5 @@
[package] [package]
edition = "2021"
authors = [ authors = [
"Richard Newman <rnewman@twinql.com>", "Richard Newman <rnewman@twinql.com>",
"Nicholas Alexander <nalexander@mozilla.com>", "Nicholas Alexander <nalexander@mozilla.com>",
@ -10,38 +11,56 @@ authors = [
"Kit Cambridge <kit@yakshaving.ninja>", "Kit Cambridge <kit@yakshaving.ninja>",
"Edouard Oger <eoger@fastmail.com>", "Edouard Oger <eoger@fastmail.com>",
"Thom Chiovoloni <tchiovoloni@mozilla.com>", "Thom Chiovoloni <tchiovoloni@mozilla.com>",
"Gregory Burd <greg@burd.me>",
] ]
name = "mentat" name = "mentat"
version = "0.6.1" version = "0.14.0"
build = "build/version.rs" build = "build/version.rs"
[features] [features]
default = ["bundled_sqlite3"] default = ["bundled_sqlite3", "syncable"]
bundled_sqlite3 = ["rusqlite/bundled"] bundled_sqlite3 = ["rusqlite/bundled"]
sqlcipher = ["rusqlite/sqlcipher", "mentat_db/sqlcipher"]
syncable = ["mentat_tolstoy", "tolstoy_traits", "mentat_db/syncable"]
[workspace] [workspace]
members = ["tools/cli", "ffi"] members = [
"tools/cli",
"ffi", "core", "core-traits","db", "db-traits", "edn", "public-traits", "query-algebrizer",
"query-algebrizer-traits", "query-projector", "query-projector-traits","query-pull",
"query-sql", "sql", "sql-traits", "tolstoy-traits", "tolstoy", "transaction"
]
[build-dependencies] [build-dependencies]
rustc_version = "0.2" rustc_version = "~0.4"
[dev-dependencies]
assert_approx_eq = "~1.1"
#[dev-dependencies.cargo-husky]
#version = "1"
#default-features = false # Disable features which are enabled by default
#features = ["run-for-all", "precommit-hook", "run-cargo-fmt", "run-cargo-test", "run-cargo-check", "run-cargo-clippy"]
#cargo audit
#cargo outdated
[dependencies] [dependencies]
chrono = "0.4" chrono = "~0.4"
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" } failure = "~0.1"
lazy_static = "0.2" lazy_static = "~1.4"
time = "0.1" time = "0.3.1"
uuid = "0.5" log = "~0.4"
uuid = { version = "~1", features = ["v4", "serde"] }
[dependencies.rusqlite] [dependencies.rusqlite]
version = "0.13" version = "~0.29"
# System sqlite might be very old. features = ["limits", "bundled"]
features = ["limits"]
[dependencies.edn] [dependencies.edn]
path = "edn" path = "edn"
[dependencies.mentat_parser_utils] [dependencies.core_traits]
path = "parser-utils" path = "core-traits"
[dependencies.mentat_core] [dependencies.mentat_core]
path = "core" path = "core"
@ -52,32 +71,46 @@ path = "sql"
[dependencies.mentat_db] [dependencies.mentat_db]
path = "db" path = "db"
[dependencies.mentat_query] [dependencies.db_traits]
path = "query" path = "db-traits"
[dependencies.mentat_query_algebrizer] [dependencies.mentat_query_algebrizer]
path = "query-algebrizer" path = "query-algebrizer"
[dependencies.mentat_query_parser] [dependencies.query_algebrizer_traits]
path = "query-parser" path = "query-algebrizer-traits"
[dependencies.mentat_query_projector] [dependencies.mentat_query_projector]
path = "query-projector" path = "query-projector"
[dependencies.query_projector_traits]
path = "query-projector-traits"
[dependencies.mentat_query_pull]
path = "query-pull"
[dependencies.query_pull_traits]
path = "query-pull-traits"
[dependencies.mentat_query_sql] [dependencies.mentat_query_sql]
path = "query-sql" path = "query-sql"
[dependencies.mentat_query_translator] [dependencies.sql_traits]
path = "query-translator" path = "sql-traits"
[dependencies.mentat_tx] [dependencies.public_traits]
path = "tx" path = "public-traits"
[dependencies.mentat_tx_parser] [dependencies.mentat_transaction]
path = "tx-parser" path = "transaction"
[dependencies.mentat_tolstoy] [dependencies.mentat_tolstoy]
path = "tolstoy" path = "tolstoy"
optional = true
[dependencies.tolstoy_traits]
path = "tolstoy-traits"
optional = true
[profile.release] [profile.release]
opt-level = 3 opt-level = 3

11
Makefile Normal file
View file

@ -0,0 +1,11 @@
.PHONY: outdated fix
outdated:
for p in $(dirname $(ls Cargo.toml */Cargo.toml */*/Cargo.toml)); do echo $p; (cd $p; cargo outdated -R); done
fix:
$(for p in $(dirname $(ls Cargo.toml */Cargo.toml */*/Cargo.toml)); do echo $p; (cd $p; cargo fix --allow-dirty --broken-code --edition-idioms); done)
upgrades:
cargo upgrades

29
NOTES Normal file
View file

@ -0,0 +1,29 @@
* sqlite -> monetdb-lite-c + fts5 + bayesdb
* fts5 + regex + tre/fuzzy + codesearch/trigram filters, streaming bloom filters https://arxiv.org/abs/2001.03147
* datalog to "goblin relational engine" (gtk)
* branching distributed wal (chain replication) and CRDTs
* alf:fn query language
* datatypes via bit syntax+some code?
* pure lang?
* https://github.com/dahjelle/pouch-datalog
* https://github.com/edn-query-language/eql
* https://github.com/borkdude/jet
* https://github.com/walmartlabs/dyn-edn
* https://github.com/go-edn/edn
* https://github.com/smothers/cause
* https://github.com/oscaro/eq
* https://github.com/clojure-emacs/parseedn
* https://github.com/exoscale/seql
* https://github.com/axboe/liburing
* (EAVtf) - entity attribute value type flags
* distributed, replicated WAL
* https://github.com/mirage/irmin
* What if facts had "confidence" [0-1)?
* entity attribute value type flags
* https://github.com/probcomp/BayesDB
* https://github.com/probcomp/bayeslite
* http://probcomp.csail.mit.edu/software/bayesdb/

View file

@ -1,18 +1,19 @@
# Project Mentat # Project Mentat
[![Build Status](https://travis-ci.org/qpdb/mentat.svg?branch=master)](https://travis-ci.org/qpdb/mentat)
Project Mentat is a persistent, embedded knowledge base. It draws heavily on [DataScript](https://github.com/tonsky/datascript) and [Datomic](http://datomic.com). Project Mentat is a persistent, embedded knowledge base. It draws heavily on [DataScript](https://github.com/tonsky/datascript) and [Datomic](http://datomic.com).
Mentat is implemented in Rust. This project was started by Mozilla, but [is no longer being developed or actively maintained by them](https://mail.mozilla.org/pipermail/firefox-dev/2018-September/006780.html). [Their repository](https://github.com/mozilla/mentat) was marked read-only, [this fork](https://github.com/qpdb/mentat) is an attempt to revive and continue that interesting work. We owe the team at Mozilla more than words can express for inspiring us all and for this project in particular.
The first version of Project Mentat, named Datomish, [was written in ClojureScript](https://github.com/mozilla/mentat/tree/clojure), targeting both Node (on top of `promise_sqlite`) and Firefox (on top of `Sqlite.jsm`). It also worked in pure Clojure on the JVM on top of `jdbc-sqlite`. The name was changed to avoid confusion with [Datomic](http://datomic.com). *Thank you*.
The Rust implementation gives us a smaller compiled output, better performance, more type safety, better tooling, and easier deployment into Firefox and mobile platforms. [Documentation](https://docs.rs/mentat)
--- ---
## Motivation ## Motivation
Mentat is intended to be a flexible relational (not key-value, not document-oriented) store that makes it easy to describe, grow, and reuse your domain schema. Mentat is a flexible relational (not key-value, not document-oriented) store that makes it easy to describe, grow, and reuse your domain schema.
By abstracting away the storage schema, and by exposing change listeners outside the database (not via triggers), we hope to make domain schemas stable, and allow both the data store itself and embedding applications to use better architectures, meeting performance goals in a way that allows future evolution. By abstracting away the storage schema, and by exposing change listeners outside the database (not via triggers), we hope to make domain schemas stable, and allow both the data store itself and embedding applications to use better architectures, meeting performance goals in a way that allows future evolution.
@ -70,11 +71,13 @@ We've observed that data storage is a particular area of difficulty for software
## Comparison to DataScript ## Comparison to DataScript
DataScript asks the question: "What if creating a database would be as cheap as creating a Hashmap?" DataScript asks the question: "What if creating a database were as cheap as creating a Hashmap?"
Mentat is not interested in that. Instead, it's strongly interested in persistence and performance, with very little interest in immutable databases/databases as values or throwaway use. Mentat is not interested in that. Instead, it's focused on persistence and performance, with very little interest in immutable databases/databases as values or throwaway use.
One might say that Mentat's question is: "What if an SQLite database could store arbitrary relations, for arbitrary consumers, without them having to coordinate an up-front storage-level schema?" One might say that Mentat's question is: "What if a database could store arbitrary relations, for arbitrary consumers, without them having to coordinate an up-front storage-level schema?"
Consider this a practical approach to facts, to knowledge its storage and access, much like SQLite is a practical RDBMS.
(Note that [domain-level schemas are very valuable](http://martinfowler.com/articles/schemaless/).) (Note that [domain-level schemas are very valuable](http://martinfowler.com/articles/schemaless/).)
@ -84,7 +87,7 @@ Some thought has been given to how databases as values — long-term references
Just like DataScript, Mentat speaks Datalog for querying and takes additions and retractions as input to a transaction. Just like DataScript, Mentat speaks Datalog for querying and takes additions and retractions as input to a transaction.
Unlike DataScript, Mentat exposes free-text indexing, thanks to SQLite. Unlike DataScript, Mentat exposes free-text indexing, thanks to SQLite/FTS.
## Comparison to Datomic ## Comparison to Datomic
@ -93,8 +96,6 @@ Datomic is a server-side, enterprise-grade data storage system. Datomic has a be
Many of these design decisions are inapplicable to deployed desktop software; indeed, the use of multiple JVM processes makes Datomic's use in a small desktop app, or a mobile device, prohibitive. Many of these design decisions are inapplicable to deployed desktop software; indeed, the use of multiple JVM processes makes Datomic's use in a small desktop app, or a mobile device, prohibitive.
Mentat was designed for embedding, initially in an experimental Electron app ([Tofino](https://github.com/mozilla/tofino)). It is less concerned with exposing consistent database states outside transaction boundaries, because that's less important here, and dropping some of these requirements allows us to leverage SQLite itself.
## Comparison to SQLite ## Comparison to SQLite
@ -109,7 +110,7 @@ Mentat aims to offer many of the advantages of SQLite — single-file use, embed
Please note that this project is released with a Contributor Code of Conduct. Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms. By participating in this project you agree to abide by its terms.
See [CONTRIBUTING.md](/CONTRIBUTING.md) for further notes. See [CONTRIBUTING.md](CONTRIBUTING.md) for further notes.
This project is very new, so we'll probably revise these guidelines. Please This project is very new, so we'll probably revise these guidelines. Please
comment on an issue before putting significant effort in if you'd like to comment on an issue before putting significant effort in if you'd like to
@ -133,12 +134,12 @@ To run tests use:
# Run tests for everything. # Run tests for everything.
cargo test --all cargo test --all
# Run tests for just the query-parser folder (specify the crate, not the folder), # Run tests for just the query-algebrizer folder (specify the crate, not the folder),
# printing debug output. # printing debug output.
cargo test -p mentat_query_parser -- --nocapture cargo test -p mentat_query_algebrizer -- --nocapture
```` ````
For most `cargo` commands you can pass the `-p` argument to run the command just on that package. So, `cargo build -p mentat_query_parser` will build just the "query-parser" folder. For most `cargo` commands you can pass the `-p` argument to run the command just on that package. So, `cargo build -p mentat_query_algebrizer` will build just the "query-algebrizer" folder.
## What are all of these crates? ## What are all of these crates?
@ -157,20 +158,18 @@ So what are they?
Our EDN parser. It uses `rust-peg` to parse [EDN](https://github.com/edn-format/edn), which is Clojure/Datomic's richer alternative to JSON. `edn`'s dependencies are all either for representing rich values (`chrono`, `uuid`, `ordered-float`) or for parsing (`serde`, `peg`). Our EDN parser. It uses `rust-peg` to parse [EDN](https://github.com/edn-format/edn), which is Clojure/Datomic's richer alternative to JSON. `edn`'s dependencies are all either for representing rich values (`chrono`, `uuid`, `ordered-float`) or for parsing (`serde`, `peg`).
In addition, this crate turns a stream of EDN values into a representation suitable to be transacted.
#### `mentat_core` #### `mentat_core`
This is the lowest-level Mentat crate. It collects together the following things: This is the lowest-level Mentat crate. It collects together the following things:
- Fundamental domain-specific data structures like `ValueType` and `TypedValue`. - Fundamental domain-specific data structures like `ValueType` and `TypedValue`.
- Fundamental SQL-related linkages like `SQLValueType`. These encode the mapping between Mentat's types and values and their representation in our SQLite format. - Fundamental SQL-related linkages like `SQLValueType`. These encode the mapping between Mentat's types and values and their representation in our SQLite format.
- Conversion to and from EDN types (_e.g._, `edn::NamespacedKeyword` to `TypedValue::Keyword`). - Conversion to and from EDN types (_e.g._, `edn::Keyword` to `TypedValue::Keyword`).
- Common utilities (some in the `util` module, and others that should be moved there or broken out) like `Either`, `InternSet`, and `RcCounter`. - Common utilities (some in the `util` module, and others that should be moved there or broken out) like `Either`, `InternSet`, and `RcCounter`.
- Reusable lazy namespaced keywords (_e.g._, `DB_TYPE_DOUBLE`) that are used by `mentat_db` and EDN serialization of core structs. - Reusable lazy namespaced keywords (_e.g._, `DB_TYPE_DOUBLE`) that are used by `mentat_db` and EDN serialization of core structs.
#### `mentat_parser_utils`
This is a utility library for writing `combine` parsers over streams of `edn::Value`/`edn::ValueAndSpan`.
### Types ### Types
#### `mentat_query` #### `mentat_query`
@ -181,22 +180,8 @@ This crate defines the structs and enums that are the output of the query parser
Similarly, this crate defines an abstract representation of a SQL query as understood by Mentat. This bridges between Mentat's types (_e.g._, `TypedValue`) and SQL concepts (`ColumnOrExpression`, `GroupBy`). It's produced by the algebrizer and consumed by the translator. Similarly, this crate defines an abstract representation of a SQL query as understood by Mentat. This bridges between Mentat's types (_e.g._, `TypedValue`) and SQL concepts (`ColumnOrExpression`, `GroupBy`). It's produced by the algebrizer and consumed by the translator.
#### `mentat_tx`
Mentat has two main inputs: reads (queries) and writes (transacts). Just as `mentat_query` defines the types produced by the query parser, `mentat_tx` defines the types produced by the tx parser.
### Transact processing
#### `mentat_tx_parser`
This is a `combine` parser that turns a stream of EDN values into a representation suitable to be transacted.
### Query processing ### Query processing
#### `mentat_query_parser`
This is a `combine` parser that uses `mentat_parser_utils` and `mentat_query` to turn a stream of EDN values into a more usable representation of a query.
#### `mentat_query_algebrizer` #### `mentat_query_algebrizer`
This is the biggest piece of the query engine. It takes a parsed query, which at this point is _independent of a database_, and combines it with the current state of the schema and data. This involves translating keywords into attributes, abstract values into concrete values with a known type, and producing an `AlgebraicQuery`, which is a representation of how a query's Datalog semantics can be satisfied as SQL table joins and constraints over Mentat's SQL schema. An algebrized query is tightly coupled with both the disk schema and the vocabulary present in the store when the work is done. This is the biggest piece of the query engine. It takes a parsed query, which at this point is _independent of a database_, and combines it with the current state of the schema and data. This involves translating keywords into attributes, abstract values into concrete values with a known type, and producing an `AlgebraicQuery`, which is a representation of how a query's Datalog semantics can be satisfied as SQL table joins and constraints over Mentat's SQL schema. An algebrized query is tightly coupled with both the disk schema and the vocabulary present in the store when the work is done.
@ -223,7 +208,7 @@ The top-level main crate of Mentat assembles these component crates into somethi
### Syncing ### Syncing
Sync code lives, for [referential reasons](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying), in a crate named `tolstoy`. This code is a work in progress. Sync code lives, for [referential reasons](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying), in a crate named `tolstoy`. This code is a work in progress; current state is a proof-of-concept implementation which largely relies on the internal transactor to make progress in most cases and comes with a basic support for timelines. See [Tolstoy's documentation](https://github.com/mozilla/mentat/tree/master/tolstoy/README.md) for details.
### The command-line interface ### The command-line interface

View file

@ -0,0 +1,36 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
FROM mozillamobile/rust-component:buildtools-27.0.3-ndk-r17b-ndk-version-26-rust-stable-rust-beta
MAINTAINER Nick Alexander "nalexander@mozilla.com"
#----------------------------------------------------------------------------------------------------------------------
#-- Project -----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
ENV PROJECT_REPOSITORY "https://github.com/mozilla/mentat.git"
RUN git clone $PROJECT_REPOSITORY
WORKDIR /build/mentat
# Temporary.
RUN git fetch origin master && git checkout origin/generic-automation-images && git show-ref HEAD
# Populate dependencies.
RUN ./sdks/android/Mentat/gradlew --no-daemon -p sdks/android/Mentat tasks
# Build Rust.
RUN ./sdks/android/Mentat/gradlew --no-daemon -p sdks/android/Mentat cargoBuild
# Actually build. In the future, we might also lint (to cache additional dependencies).
RUN ./sdks/android/Mentat/gradlew --no-daemon -p sdks/android/Mentat assemble test
#----------------------------------------------------------------------------------------------------------------------
# -- Cleanup ----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
# Drop built Rust artifacts.
RUN cargo clean

View file

@ -0,0 +1,81 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
FROM mozillamobile/android-components:1.4
MAINTAINER Nick Alexander "nalexander@mozilla.com"
#----------------------------------------------------------------------------------------------------------------------
#-- Configuration -----------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
ENV ANDROID_NDK_VERSION "r17b"
#----------------------------------------------------------------------------------------------------------------------
#-- System ------------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
RUN apt-get update -qq
#----------------------------------------------------------------------------------------------------------------------
#-- Android NDK (Android SDK comes from base `android-components` image) ----------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
RUN mkdir -p /build
WORKDIR /build
ENV ANDROID_NDK_HOME /build/android-ndk
RUN curl -L https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip > ndk.zip \
&& unzip ndk.zip -d /build \
&& rm ndk.zip \
&& mv /build/android-ndk-${ANDROID_NDK_VERSION} ${ANDROID_NDK_HOME}
ENV ANDROID_NDK_TOOLCHAIN_DIR /build/android-ndk-toolchain
ENV ANDROID_NDK_API_VERSION 26
RUN set -eux; \
python "$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py" --arch="arm" --api="$ANDROID_NDK_API_VERSION" --install-dir="$ANDROID_NDK_TOOLCHAIN_DIR/arm-$ANDROID_NDK_API_VERSION" --force; \
python "$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py" --arch="arm64" --api="$ANDROID_NDK_API_VERSION" --install-dir="$ANDROID_NDK_TOOLCHAIN_DIR/arm64-$ANDROID_NDK_API_VERSION" --force; \
python "$ANDROID_NDK_HOME/build/tools/make_standalone_toolchain.py" --arch="x86" --api="$ANDROID_NDK_API_VERSION" --install-dir="$ANDROID_NDK_TOOLCHAIN_DIR/x86-$ANDROID_NDK_API_VERSION" --force
#----------------------------------------------------------------------------------------------------------------------
#-- Rust (cribbed from https://github.com/rust-lang-nursery/docker-rust/blob/ced83778ec6fea7f63091a484946f95eac0ee611/1.27.1/stretch/Dockerfile)
#-- Rust is after the Android NDK since Rust rolls forward more frequently. Both stable and beta for advanced consumers.
#----------------------------------------------------------------------------------------------------------------------
ENV RUSTUP_HOME=/usr/local/rustup \
CARGO_HOME=/usr/local/cargo \
PATH=/usr/local/cargo/bin:$PATH \
RUST_VERSION=1.27.1
RUN set -eux; \
rustArch='x86_64-unknown-linux-gnu'; rustupSha256='4d382e77fd6760282912d2d9beec5e260ec919efd3cb9bdb64fe1207e84b9d91'; \
url="https://static.rust-lang.org/rustup/archive/1.12.0/${rustArch}/rustup-init"; \
wget "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
./rustup-init -y --no-modify-path --default-toolchain $RUST_VERSION; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version; \
rustup target add i686-linux-android; \
rustup target add armv7-linux-androideabi; \
rustup target add aarch64-linux-android
RUN set -eux; \
rustup install beta; \
rustup target add --toolchain beta i686-linux-android; \
rustup target add --toolchain beta armv7-linux-androideabi; \
rustup target add --toolchain beta aarch64-linux-android
#----------------------------------------------------------------------------------------------------------------------
# -- Cleanup ----------------------------------------------------------------------------------------------------------
#----------------------------------------------------------------------------------------------------------------------
WORKDIR /build
RUN apt-get clean

View file

@ -0,0 +1,122 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import datetime
import json
import os
import taskcluster
import re
import subprocess
import sys
"""
Decision task for pull requests
"""
TASK_ID = os.environ.get('TASK_ID')
REPO_URL = os.environ.get('GITHUB_HEAD_REPO_URL')
BRANCH = os.environ.get('GITHUB_HEAD_BRANCH')
COMMIT = os.environ.get('GITHUB_HEAD_SHA')
def fetch_module_names():
process = subprocess.Popen(["./gradlew", "--no-daemon", "printModules"], stdout=subprocess.PIPE,
cwd=os.path.join(os.getcwd(), "sdks", "android", "Mentat"))
(output, err) = process.communicate()
exit_code = process.wait()
if exit_code is not 0:
print "Gradle command returned error:", exit_code
return re.findall('module: (.*)', output, re.M)
def schedule_task(queue, taskId, task):
print "TASK", taskId
print json.dumps(task, indent=4, separators=(',', ': '))
result = queue.createTask(taskId, task)
print "RESULT", taskId
print json.dumps(result, indent=4, separators=(',', ': '))
def create_task(name, description, command):
created = datetime.datetime.now()
expires = taskcluster.fromNow('1 year')
deadline = taskcluster.fromNow('1 day')
return {
"workerType": 'github-worker',
"taskGroupId": TASK_ID,
"expires": taskcluster.stringDate(expires),
"retries": 5,
"created": taskcluster.stringDate(created),
"tags": {},
"priority": "lowest",
"schedulerId": "taskcluster-github",
"deadline": taskcluster.stringDate(deadline),
"dependencies": [ TASK_ID ],
"routes": [],
"scopes": [],
"requires": "all-completed",
"payload": {
"features": {},
"maxRunTime": 7200,
"image": "mozillamobile/mentat:1.2",
"command": [
"/bin/bash",
"--login",
"-cx",
"export TERM=dumb && git fetch %s %s && git config advice.detachedHead false && git checkout %s && cd sdks/android/Mentat && ./gradlew --no-daemon clean %s" % (REPO_URL, BRANCH, COMMIT, command)
],
"artifacts": {},
"deadline": taskcluster.stringDate(deadline)
},
"provisionerId": "aws-provisioner-v1",
"metadata": {
"name": name,
"description": description,
"owner": "nalexander@mozilla.com",
"source": "https://github.com/mozilla/mentat"
}
}
def create_module_task(module):
return create_task(
name='Mentat Android SDK - Module ' + module,
description='Building and testing module ' + module,
command=" ".join(map(lambda x: module + ":" + x, ['assemble', 'test', 'lint'])))
# def create_detekt_task():
# return create_task(
# name='Android Components - detekt',
# description='Running detekt over all modules',
# command='detektCheck')
# def create_ktlint_task():
# return create_task(
# name='Android Components - ktlint',
# description='Running ktlint over all modules',
# command='ktlint')
if __name__ == "__main__":
queue = taskcluster.Queue({ 'baseUrl': 'http://taskcluster/queue/v1' })
modules = fetch_module_names()
if len(modules) == 0:
print "Could not get module names from gradle"
sys.exit(2)
for module in modules:
task = create_module_task(module)
task_id = taskcluster.slugId()
schedule_task(queue, task_id, task)
# schedule_task(queue, taskcluster.slugId(), create_detekt_task())
# schedule_task(queue, taskcluster.slugId(), create_ktlint_task())

View file

@ -0,0 +1,28 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os
import taskcluster
SECRET_NAME = 'project/mentat/publish'
TASKCLUSTER_BASE_URL = 'http://taskcluster/secrets/v1'
def fetch_publish_secrets(secret_name):
"""Fetch and return secrets from taskcluster's secret service"""
secrets = taskcluster.Secrets({'baseUrl': TASKCLUSTER_BASE_URL})
return secrets.get(secret_name)
def main():
"""Fetch the bintray user and api key from taskcluster's secret service
and save it to local.properties in the project root directory.
"""
data = fetch_publish_secrets(SECRET_NAME)
properties_file_path = os.path.join(os.path.dirname(__file__), '../../../sdks/android/Mentat/local.properties')
with open(properties_file_path, 'w') as properties_file:
properties_file.write("bintray.user=%s\n" % data['secret']['bintray_user'])
properties_file.write("bintray.apikey=%s\n" % data['secret']['bintray_apikey'])
if __name__ == "__main__":
main()

View file

@ -8,24 +8,25 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
extern crate rustc_version; use rustc_version::{version, Version};
use std::io::{self, Write}; use std::io::{self, Write};
use std::process::exit; use std::process::exit;
use rustc_version::{
Version,
version,
};
/// MIN_VERSION should be changed when there's a new minimum version of rustc required /// MIN_VERSION should be changed when there's a new minimum version of rustc required
/// to build the project. /// to build the project.
static MIN_VERSION: &'static str = "1.24.0"; static MIN_VERSION: &str = "1.69.0";
fn main() { fn main() {
let ver = version().unwrap(); let ver = version().unwrap();
let min = Version::parse(MIN_VERSION).unwrap(); let min = Version::parse(MIN_VERSION).unwrap();
if ver < min { if ver < min {
writeln!(&mut io::stderr(), "Mentat requires rustc {} or higher.", MIN_VERSION).unwrap(); writeln!(
&mut io::stderr(),
"Mentat requires rustc {} or higher, you were using version {}.",
MIN_VERSION,
ver
)
.unwrap();
exit(1); exit(1);
} }
} }

23
core-traits/Cargo.toml Normal file
View file

@ -0,0 +1,23 @@
[package]
name = "core_traits"
version = "0.0.2"
workspace = ".."
[lib]
name = "core_traits"
path = "lib.rs"
[dependencies]
chrono = { version = "~0.4", features = ["serde"] }
enum-set = "~0.0.8"
lazy_static = "~1.4"
indexmap = "~1.9"
ordered-float = { version = "~2.8", features = ["serde"] }
uuid = { version = "~1", features = ["v4", "serde"] }
serde = { version = "~1.0", features = ["rc"] }
serde_derive = "~1.0"
bytes = { version = "1.0.1", features = ["serde"] }
[dependencies.edn]
path = "../edn"
features = ["serde_support"]

1109
core-traits/lib.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,181 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use enum_set::EnumSet;
use crate::ValueType;
trait EnumSetExtensions<T: ::enum_set::CLike + Clone> {
/// Return a set containing both `x` and `y`.
fn of_both(x: T, y: T) -> EnumSet<T>;
/// Return a clone of `self` with `y` added.
fn with(&self, y: T) -> EnumSet<T>;
}
impl<T: ::enum_set::CLike + Clone> EnumSetExtensions<T> for EnumSet<T> {
/// Return a set containing both `x` and `y`.
fn of_both(x: T, y: T) -> Self {
let mut o = EnumSet::new();
o.insert(x);
o.insert(y);
o
}
/// Return a clone of `self` with `y` added.
fn with(&self, y: T) -> EnumSet<T> {
let mut o = self.clone();
o.insert(y);
o
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ValueTypeSet(pub EnumSet<ValueType>);
impl Default for ValueTypeSet {
fn default() -> ValueTypeSet {
ValueTypeSet::any()
}
}
impl ValueTypeSet {
pub fn any() -> ValueTypeSet {
ValueTypeSet(ValueType::all_enums())
}
pub fn none() -> ValueTypeSet {
ValueTypeSet(EnumSet::new())
}
/// Return a set containing only `t`.
pub fn of_one(t: ValueType) -> ValueTypeSet {
let mut s = EnumSet::new();
s.insert(t);
ValueTypeSet(s)
}
/// Return a set containing `Double` and `Long`.
pub fn of_numeric_types() -> ValueTypeSet {
ValueTypeSet(EnumSet::of_both(ValueType::Double, ValueType::Long))
}
/// Return a set containing `Double`, `Long`, and `Instant`.
pub fn of_numeric_and_instant_types() -> ValueTypeSet {
let mut s = EnumSet::new();
s.insert(ValueType::Double);
s.insert(ValueType::Long);
s.insert(ValueType::Instant);
ValueTypeSet(s)
}
/// Return a set containing `Ref` and `Keyword`.
pub fn of_keywords() -> ValueTypeSet {
ValueTypeSet(EnumSet::of_both(ValueType::Ref, ValueType::Keyword))
}
/// Return a set containing `Ref` and `Long`.
pub fn of_longs() -> ValueTypeSet {
ValueTypeSet(EnumSet::of_both(ValueType::Ref, ValueType::Long))
}
}
impl ValueTypeSet {
pub fn insert(&mut self, vt: ValueType) -> bool {
self.0.insert(vt)
}
pub fn len(self) -> usize {
self.0.len()
}
/// Returns a set containing all the types in this set and `other`.
pub fn union(self, other: ValueTypeSet) -> ValueTypeSet {
ValueTypeSet(self.0.union(other.0))
}
pub fn intersection(self, other: ValueTypeSet) -> ValueTypeSet {
ValueTypeSet(self.0.intersection(other.0))
}
/// Returns the set difference between `self` and `other`, which is the
/// set of items in `self` that are not in `other`.
pub fn difference(self, other: ValueTypeSet) -> ValueTypeSet {
ValueTypeSet(self.0 - other.0)
}
/// Return an arbitrary type that's part of this set.
/// For a set containing a single type, this will be that type.
pub fn exemplar(self) -> Option<ValueType> {
self.0.iter().next()
}
pub fn is_subset(self, other: ValueTypeSet) -> bool {
self.0.is_subset(&other.0)
}
/// Returns true if `self` and `other` contain no items in common.
pub fn is_disjoint(self, other: ValueTypeSet) -> bool {
self.0.is_disjoint(&other.0)
}
pub fn contains(self, vt: ValueType) -> bool {
self.0.contains(&vt)
}
pub fn is_empty(self) -> bool {
self.0.is_empty()
}
pub fn is_unit(self) -> bool {
self.0.len() == 1
}
pub fn iter(self) -> ::enum_set::Iter<ValueType> {
self.0.iter()
}
}
impl From<ValueType> for ValueTypeSet {
fn from(t: ValueType) -> Self {
ValueTypeSet::of_one(t)
}
}
impl ValueTypeSet {
pub fn is_only_numeric(self) -> bool {
self.is_subset(ValueTypeSet::of_numeric_types())
}
}
impl IntoIterator for ValueTypeSet {
type Item = ValueType;
type IntoIter = ::enum_set::Iter<ValueType>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl ::std::iter::FromIterator<ValueType> for ValueTypeSet {
fn from_iter<I: IntoIterator<Item = ValueType>>(iterator: I) -> Self {
let mut ret = Self::none();
ret.0.extend(iterator);
ret
}
}
impl ::std::iter::Extend<ValueType> for ValueTypeSet {
fn extend<I: IntoIterator<Item = ValueType>>(&mut self, iter: I) {
for element in iter {
self.0.insert(element);
}
}
}

View file

@ -10,28 +10,27 @@
#![allow(dead_code)] #![allow(dead_code)]
use edn::symbols;
/// Literal `Value` instances in the the "db" namespace. /// Literal `Value` instances in the the "db" namespace.
/// ///
/// Used through-out the transactor to match core DB constructs. /// Used through-out the transactor to match core DB constructs.
use edn::types::Value; use edn::types::Value;
use edn::symbols;
/// Declare a lazy static `ident` of type `Value::NamespacedKeyword` with the given `namespace` and /// Declare a lazy static `ident` of type `Value::Keyword` with the given `namespace` and
/// `name`. /// `name`.
/// ///
/// It may look surprising that we declare a new `lazy_static!` block rather than including /// It may look surprising to declare a new `lazy_static!` block rather than including
/// invocations inside an existing `lazy_static!` block. The latter cannot be done, since macros /// invocations inside an existing `lazy_static!` block. The latter cannot be done, since macros
/// are expanded outside-in. Looking at the `lazy_static!` source suggests that there is no harm in /// will be expanded outside-in. Looking at the `lazy_static!` source suggests that there is no
/// repeating that macro, since internally a multi-`static` block is expanded into many /// harm in repeating that macro, since internally a multi-`static` block will be expanded into
/// single-`static` blocks. /// many single-`static` blocks.
/// ///
/// TODO: take just ":db.part/db" and define DB_PART_DB using "db.part" and "db". /// TODO: take just ":db.part/db" and define DB_PART_DB using "db.part" and "db".
macro_rules! lazy_static_namespaced_keyword_value ( macro_rules! lazy_static_namespaced_keyword_value (
($tag:ident, $namespace:expr, $name:expr) => ( ($tag:ident, $namespace:expr, $name:expr) => (
lazy_static! { lazy_static! {
pub static ref $tag: Value = { pub static ref $tag: Value = {
Value::NamespacedKeyword(symbols::NamespacedKeyword::new($namespace, $name)) Value::Keyword(symbols::Keyword::namespaced($namespace, $name))
}; };
} }
) )
@ -59,6 +58,7 @@ lazy_static_namespaced_keyword_value!(DB_TYPE_REF, "db.type", "ref");
lazy_static_namespaced_keyword_value!(DB_TYPE_STRING, "db.type", "string"); lazy_static_namespaced_keyword_value!(DB_TYPE_STRING, "db.type", "string");
lazy_static_namespaced_keyword_value!(DB_TYPE_URI, "db.type", "uri"); lazy_static_namespaced_keyword_value!(DB_TYPE_URI, "db.type", "uri");
lazy_static_namespaced_keyword_value!(DB_TYPE_UUID, "db.type", "uuid"); lazy_static_namespaced_keyword_value!(DB_TYPE_UUID, "db.type", "uuid");
lazy_static_namespaced_keyword_value!(DB_TYPE_BYTES, "db.type", "bytes");
lazy_static_namespaced_keyword_value!(DB_UNIQUE, "db", "unique"); lazy_static_namespaced_keyword_value!(DB_UNIQUE, "db", "unique");
lazy_static_namespaced_keyword_value!(DB_UNIQUE_IDENTITY, "db.unique", "identity"); lazy_static_namespaced_keyword_value!(DB_UNIQUE_IDENTITY, "db.unique", "identity");
lazy_static_namespaced_keyword_value!(DB_UNIQUE_VALUE, "db.unique", "value"); lazy_static_namespaced_keyword_value!(DB_UNIQUE_VALUE, "db.unique", "value");

View file

@ -1,17 +1,18 @@
[package] [package]
name = "mentat_core" name = "mentat_core"
version = "0.0.1" version = "0.0.2"
workspace = ".." workspace = ".."
[dependencies] [dependencies]
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "~0.4", features = ["serde"] }
enum-set = { git = "https://github.com/rnewman/enum-set" } enum-set = "~0.0"
lazy_static = "0.2" failure = "~0.1"
num = "0.1" indexmap = "~1.9"
ordered-float = { version = "0.5", features = ["serde"] } ordered-float = { version = "~2.8", features = ["serde"] }
uuid = "0.5" uuid = { version = "~1", features = ["v4", "serde"] }
serde = { version = "1.0", features = ["rc"] }
serde_derive = "1.0" [dependencies.core_traits]
path = "../core-traits"
[dependencies.edn] [dependencies.edn]
path = "../edn" path = "../edn"

View file

@ -9,32 +9,41 @@
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
/// Cache traits. /// Cache traits.
use std::collections::BTreeSet;
use std::collections::{ use core_traits::{Entid, TypedValue};
BTreeSet,
};
use ::{ use crate::Schema;
Entid,
Schema,
TypedValue,
};
pub trait CachedAttributes { pub trait CachedAttributes {
fn is_attribute_cached_reverse(&self, entid: Entid) -> bool; fn is_attribute_cached_reverse(&self, entid: Entid) -> bool;
fn is_attribute_cached_forward(&self, entid: Entid) -> bool; fn is_attribute_cached_forward(&self, entid: Entid) -> bool;
fn has_cached_attributes(&self) -> bool; fn has_cached_attributes(&self) -> bool;
fn get_values_for_entid(&self, schema: &Schema, attribute: Entid, entid: Entid) -> Option<&Vec<TypedValue>>; fn get_values_for_entid(
fn get_value_for_entid(&self, schema: &Schema, attribute: Entid, entid: Entid) -> Option<&TypedValue>; &self,
schema: &Schema,
attribute: Entid,
entid: Entid,
) -> Option<&Vec<TypedValue>>;
fn get_value_for_entid(
&self,
schema: &Schema,
attribute: Entid,
entid: Entid,
) -> Option<&TypedValue>;
/// Reverse lookup. /// Reverse lookup.
fn get_entid_for_value(&self, attribute: Entid, value: &TypedValue) -> Option<Entid>; fn get_entid_for_value(&self, attribute: Entid, value: &TypedValue) -> Option<Entid>;
fn get_entids_for_value(&self, attribute: Entid, value: &TypedValue) -> Option<&BTreeSet<Entid>>; fn get_entids_for_value(
&self,
attribute: Entid,
value: &TypedValue,
) -> Option<&BTreeSet<Entid>>;
} }
pub trait UpdateableCache { pub trait UpdateableCache<E> {
type Error; fn update<I>(&mut self, schema: &Schema, retractions: I, assertions: I) -> Result<(), E>
fn update<I>(&mut self, schema: &Schema, retractions: I, assertions: I) -> Result<(), Self::Error> where
where I: Iterator<Item=(Entid, Entid, TypedValue)>; I: Iterator<Item = (Entid, Entid, TypedValue)>;
} }

View file

@ -8,26 +8,26 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::{ #[derive(Clone, Default)]
AtomicUsize,
Ordering,
};
#[derive(Clone)]
pub struct RcCounter { pub struct RcCounter {
c: Rc<AtomicUsize>, c: Rc<Cell<usize>>,
} }
/// A simple shared counter. /// A simple shared counter.
impl RcCounter { impl RcCounter {
pub fn with_initial(value: usize) -> Self { pub fn with_initial(value: usize) -> Self {
RcCounter { c: Rc::new(AtomicUsize::new(value)) } RcCounter {
c: Rc::new(Cell::new(value)),
}
} }
pub fn new() -> Self { pub fn new() -> Self {
RcCounter { c: Rc::new(AtomicUsize::new(0)) } RcCounter {
c: Rc::new(Cell::new(0)),
}
} }
/// Return the next value in the sequence. /// Return the next value in the sequence.
@ -43,7 +43,8 @@ impl RcCounter {
/// assert_eq!(c.next(), 6); /// assert_eq!(c.next(), 6);
/// ``` /// ```
pub fn next(&self) -> usize { pub fn next(&self) -> usize {
self.c.fetch_add(1, Ordering::SeqCst) let current = self.c.get();
self.c.replace(current + 1)
} }
} }

File diff suppressed because it is too large Load diff

140
core/src/sql_types.rs Normal file
View file

@ -0,0 +1,140 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::collections::BTreeSet;
use core_traits::{ValueType, ValueTypeSet};
use crate::types::ValueTypeTag;
/// Type safe representation of the possible return values from SQLite's `typeof`
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub enum SQLTypeAffinity {
Null, // "null"
Integer, // "integer"
Real, // "real"
Text, // "text"
Blob, // "blob"
}
// Put this here rather than in `db` simply because it's widely needed.
pub trait SQLValueType {
fn value_type_tag(&self) -> ValueTypeTag;
fn accommodates_integer(&self, int: i64) -> bool;
/// Return a pair of the ValueTypeTag for this value type, and the SQLTypeAffinity required
/// to distinguish it from any other types that share the same tag.
///
/// Background: The tag alone is not enough to determine the type of a value, since multiple
/// ValueTypes may share the same tag (for example, ValueType::Long and ValueType::Double).
/// However, each ValueType can be determined by checking both the tag and the type's affinity.
fn sql_representation(&self) -> (ValueTypeTag, Option<SQLTypeAffinity>);
}
impl SQLValueType for ValueType {
fn sql_representation(&self) -> (ValueTypeTag, Option<SQLTypeAffinity>) {
match *self {
ValueType::Ref => (0, None),
ValueType::Boolean => (1, None),
ValueType::Instant => (4, None),
// SQLite distinguishes integral from decimal types, allowing long and double to share a tag.
ValueType::Long => (5, Some(SQLTypeAffinity::Integer)),
ValueType::Double => (5, Some(SQLTypeAffinity::Real)),
ValueType::String => (10, None),
ValueType::Uuid => (11, None),
ValueType::Keyword => (13, None),
ValueType::Bytes => (15, Some(SQLTypeAffinity::Blob)),
}
}
#[inline]
fn value_type_tag(&self) -> ValueTypeTag {
self.sql_representation().0
}
/// Returns true if the provided integer is in the SQLite value space of this type. For
/// example, `1` is how we encode `true`.
fn accommodates_integer(&self, int: i64) -> bool {
use crate::ValueType::*;
match *self {
Instant => false, // Always use #inst.
Long | Double => true,
Ref => int >= 0,
Boolean => (int == 0) || (int == 1),
ValueType::String => false,
Keyword => false,
Uuid => false,
Bytes => false,
}
}
}
/// We have an enum of types, `ValueType`. It can be collected into a set, `ValueTypeSet`. Each type
/// is associated with a type tag, which is how a type is represented in, e.g., SQL storage. Types
/// can share type tags, because backing SQL storage is able to differentiate between some types
/// (e.g., longs and doubles), and so distinct tags aren't necessary. That association is defined by
/// `SQLValueType`. That trait similarly extends to `ValueTypeSet`, which maps a collection of types
/// into a collection of tags.
pub trait SQLValueTypeSet {
fn value_type_tags(&self) -> BTreeSet<ValueTypeTag>;
fn has_unique_type_tag(&self) -> bool;
fn unique_type_tag(&self) -> Option<ValueTypeTag>;
}
impl SQLValueTypeSet for ValueTypeSet {
// This is inefficient, but it'll do for now.
fn value_type_tags(&self) -> BTreeSet<ValueTypeTag> {
let mut out = BTreeSet::new();
for t in self.0.iter() {
out.insert(t.value_type_tag());
}
out
}
fn unique_type_tag(&self) -> Option<ValueTypeTag> {
if self.is_unit() || self.has_unique_type_tag() {
self.exemplar().map(|t| t.value_type_tag())
} else {
None
}
}
fn has_unique_type_tag(&self) -> bool {
if self.is_unit() {
return true;
}
let mut acc = BTreeSet::new();
for t in self.0.iter() {
if acc.insert(t.value_type_tag()) && acc.len() > 1 {
// We inserted a second or subsequent value.
return false;
}
}
!acc.is_empty()
}
}
#[cfg(test)]
mod tests {
use crate::sql_types::SQLValueType;
use core_traits::ValueType;
#[test]
fn test_accommodates_integer() {
assert!(!ValueType::Instant.accommodates_integer(1493399581314));
assert!(!ValueType::Instant.accommodates_integer(1493399581314000));
assert!(ValueType::Boolean.accommodates_integer(1));
assert!(!ValueType::Boolean.accommodates_integer(-1));
assert!(!ValueType::Boolean.accommodates_integer(10));
assert!(!ValueType::String.accommodates_integer(10));
}
}

34
core/src/tx_report.rs Normal file
View file

@ -0,0 +1,34 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(dead_code)]
use std::collections::BTreeMap;
use core_traits::Entid;
use crate::{DateTime, Utc};
/// A transaction report summarizes an applied transaction.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub struct TxReport {
/// The transaction ID of the transaction.
pub tx_id: Entid,
/// The timestamp when the transaction began to be committed.
pub tx_instant: DateTime<Utc>,
/// A map from string literal tempid to resolved or allocated entid.
///
/// Every string literal tempid presented to the transactor either resolves via upsert to an
/// existing entid, or is allocated a new entid. (It is possible for multiple distinct string
/// literal tempids to all unify to a single freshly allocated entid.)
pub tempids: BTreeMap<String, Entid>,
}

View file

@ -1,4 +1,4 @@
// Copyright 2016 Mozilla // Copyright 2018 Mozilla
// //
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the // this file except in compliance with the License. You may obtain a copy of the
@ -8,4 +8,4 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
pub mod entities; pub type ValueTypeTag = i32;

View file

@ -67,7 +67,8 @@ pub enum Either<L, R> {
// Cribbed from https://github.com/bluss/either/blob/f793721f3fdeb694f009e731b23a2858286bc0d6/src/lib.rs#L219-L259. // Cribbed from https://github.com/bluss/either/blob/f793721f3fdeb694f009e731b23a2858286bc0d6/src/lib.rs#L219-L259.
impl<L, R> Either<L, R> { impl<L, R> Either<L, R> {
pub fn map_left<F, M>(self, f: F) -> Either<M, R> pub fn map_left<F, M>(self, f: F) -> Either<M, R>
where F: FnOnce(L) -> M where
F: FnOnce(L) -> M,
{ {
use self::Either::*; use self::Either::*;
match self { match self {
@ -77,7 +78,8 @@ impl<L, R> Either<L, R> {
} }
pub fn map_right<F, S>(self, f: F) -> Either<L, S> pub fn map_right<F, S>(self, f: F) -> Either<L, S>
where F: FnOnce(R) -> S where
F: FnOnce(R) -> S,
{ {
use self::Either::*; use self::Either::*;
match self { match self {

25
db-traits/Cargo.toml Normal file
View file

@ -0,0 +1,25 @@
[package]
name = "db_traits"
version = "0.0.2"
workspace = ".."
[lib]
name = "db_traits"
path = "lib.rs"
[features]
sqlcipher = ["rusqlite/sqlcipher"]
[dependencies]
failure = "~0.1"
failure_derive = "~0.1"
[dependencies.edn]
path = "../edn"
[dependencies.core_traits]
path = "../core-traits"
[dependencies.rusqlite]
version = "~0.29"
features = ["limits", "bundled"]

300
db-traits/errors.rs Normal file
View file

@ -0,0 +1,300 @@
// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(dead_code)]
use failure::{Backtrace, Context, Fail};
use std::collections::{BTreeMap, BTreeSet};
use rusqlite;
use edn::entities::TempId;
use core_traits::{Entid, KnownEntid, TypedValue, ValueType};
pub type Result<T> = ::std::result::Result<T, DbError>;
// TODO Error/ErrorKind pair
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CardinalityConflict {
/// A cardinality one attribute has multiple assertions `[e a v1], [e a v2], ...`.
CardinalityOneAddConflict {
e: Entid,
a: Entid,
vs: BTreeSet<TypedValue>,
},
/// A datom has been both asserted and retracted, like `[:db/add e a v]` and `[:db/retract e a v]`.
AddRetractConflict {
e: Entid,
a: Entid,
vs: BTreeSet<TypedValue>,
},
}
// TODO Error/ErrorKind pair
#[derive(Clone, Debug, Eq, PartialEq, Fail)]
pub enum SchemaConstraintViolation {
/// A transaction tried to assert datoms where one tempid upserts to two (or more) distinct
/// entids.
ConflictingUpserts {
/// A map from tempid to the entids it would upsert to.
///
/// In the future, we might even be able to attribute the upserts to particular (reduced)
/// datoms, i.e., to particular `[e a v]` triples that caused the constraint violation.
/// Attributing constraint violations to input data is more difficult to the multiple
/// rewriting passes the input undergoes.
conflicting_upserts: BTreeMap<TempId, BTreeSet<KnownEntid>>,
},
/// A transaction tried to assert a datom or datoms with the wrong value `v` type(s).
TypeDisagreements {
/// The key (`[e a v]`) has an invalid value `v`: it is not of the expected value type.
conflicting_datoms: BTreeMap<(Entid, Entid, TypedValue), ValueType>,
},
/// A transaction tried to assert datoms that don't observe the schema's cardinality constraints.
CardinalityConflicts { conflicts: Vec<CardinalityConflict> },
}
impl ::std::fmt::Display for SchemaConstraintViolation {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
use self::SchemaConstraintViolation::*;
match self {
ConflictingUpserts {
ref conflicting_upserts,
} => {
writeln!(f, "conflicting upserts:")?;
for (tempid, entids) in conflicting_upserts {
writeln!(f, " tempid {:?} upserts to {:?}", tempid, entids)?;
}
Ok(())
}
TypeDisagreements {
ref conflicting_datoms,
} => {
writeln!(f, "type disagreements:")?;
for (ref datom, expected_type) in conflicting_datoms {
writeln!(
f,
" expected value of type {} but got datom [{} {} {:?}]",
expected_type, datom.0, datom.1, datom.2
)?;
}
Ok(())
}
CardinalityConflicts { ref conflicts } => {
writeln!(f, "cardinality conflicts:")?;
for conflict in conflicts {
writeln!(f, " {:?}", conflict)?;
}
Ok(())
}
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
pub enum InputError {
/// Map notation included a bad `:db/id` value.
BadDbId,
/// A value place cannot be interpreted as an entity place (for example, in nested map
/// notation).
BadEntityPlace,
}
impl ::std::fmt::Display for InputError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
use self::InputError::*;
match self {
BadDbId => {
writeln!(f, ":db/id in map notation must either not be present or be an entid, an ident, or a tempid")
}
BadEntityPlace => {
writeln!(f, "cannot convert value place into entity place")
}
}
}
}
#[derive(Debug)]
pub struct DbError {
inner: Context<DbErrorKind>,
}
impl ::std::fmt::Display for DbError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::std::fmt::Display::fmt(&self.inner, f)
}
}
impl Fail for DbError {
fn cause(&self) -> Option<&dyn Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl DbError {
pub fn kind(&self) -> DbErrorKind {
self.inner.get_context().clone()
}
}
impl From<DbErrorKind> for DbError {
fn from(kind: DbErrorKind) -> Self {
DbError {
inner: Context::new(kind),
}
}
}
impl From<Context<DbErrorKind>> for DbError {
fn from(inner: Context<DbErrorKind>) -> Self {
DbError { inner }
}
}
impl From<rusqlite::Error> for DbError {
fn from(error: rusqlite::Error) -> Self {
DbError {
inner: Context::new(DbErrorKind::RusqliteError(error.to_string())),
}
}
}
#[derive(Clone, PartialEq, Debug, Fail)]
pub enum DbErrorKind {
/// We're just not done yet. Recognized a feature that is not yet implemented.
#[fail(display = "not yet implemented: {}", _0)]
NotYetImplemented(String),
/// We've been given a value that isn't the correct Mentat type.
#[fail(
display = "value '{}' is not the expected Mentat value type {:?}",
_0, _1
)]
BadValuePair(String, ValueType),
/// We've got corrupt data in the SQL store: a value and value_type_tag don't line up.
/// TODO _1.data_type()
#[fail(display = "bad SQL (value_type_tag, value) pair: ({:?}, {:?})", _0, _1)]
BadSQLValuePair(rusqlite::types::Value, i32),
/// The SQLite store user_version isn't recognized. This could be an old version of Mentat
/// trying to open a newer version SQLite store; or it could be a corrupt file; or ...
/// #[fail(display = "bad SQL store user_version: {}", _0)]
/// BadSQLiteStoreVersion(i32),
/// A bootstrap definition couldn't be parsed or installed. This is a programmer error, not
/// a runtime error.
#[fail(display = "bad bootstrap definition: {}", _0)]
BadBootstrapDefinition(String),
/// A schema assertion couldn't be parsed.
#[fail(display = "bad schema assertion: {}", _0)]
BadSchemaAssertion(String),
/// An ident->entid mapping failed.
#[fail(display = "no entid found for ident: {}", _0)]
UnrecognizedIdent(String),
/// An entid->ident mapping failed.
#[fail(display = "no ident found for entid: {}", _0)]
UnrecognizedEntid(Entid),
/// Tried to transact an entid that isn't allocated.
#[fail(display = "entid not allocated: {}", _0)]
UnallocatedEntid(Entid),
#[fail(display = "unknown attribute for entid: {}", _0)]
UnknownAttribute(Entid),
#[fail(display = "cannot reverse-cache non-unique attribute: {}", _0)]
CannotCacheNonUniqueAttributeInReverse(Entid),
#[fail(display = "schema alteration failed: {}", _0)]
SchemaAlterationFailed(String),
/// A transaction tried to violate a constraint of the schema of the Mentat store.
#[fail(display = "schema constraint violation: {}", _0)]
SchemaConstraintViolation(SchemaConstraintViolation),
/// The transaction was malformed in some way (that was not recognized at parse time; for
/// example, in a way that is schema-dependent).
#[fail(display = "transaction input error: {}", _0)]
InputError(InputError),
#[fail(
display = "Cannot transact a fulltext assertion with a typed value that is not :db/valueType :db.type/string"
)]
WrongTypeValueForFtsAssertion,
// SQL errors.
#[fail(display = "could not update a cache")]
CacheUpdateFailed,
#[fail(display = "Could not set_user_version")]
CouldNotSetVersionPragma,
#[fail(display = "Could not get_user_version")]
CouldNotGetVersionPragma,
#[fail(display = "Could not search!")]
CouldNotSearch,
#[fail(display = "Could not insert transaction: failed to add datoms not already present")]
TxInsertFailedToAddMissingDatoms,
#[fail(display = "Could not insert transaction: failed to retract datoms already present")]
TxInsertFailedToRetractDatoms,
#[fail(display = "Could not update datoms: failed to retract datoms already present")]
DatomsUpdateFailedToRetract,
#[fail(display = "Could not update datoms: failed to add datoms not already present")]
DatomsUpdateFailedToAdd,
#[fail(display = "Failed to create temporary tables")]
FailedToCreateTempTables,
#[fail(display = "Could not insert non-fts one statements into temporary search table!")]
NonFtsInsertionIntoTempSearchTableFailed,
#[fail(display = "Could not insert fts values into fts table!")]
FtsInsertionFailed,
#[fail(display = "Could not insert FTS statements into temporary search table!")]
FtsInsertionIntoTempSearchTableFailed,
#[fail(display = "Could not drop FTS search ids!")]
FtsFailedToDropSearchIds,
#[fail(display = "Could not update partition map")]
FailedToUpdatePartitionMap,
#[fail(display = "Can't operate over mixed timelines")]
TimelinesMixed,
#[fail(display = "Can't move transactions to a non-empty timeline")]
TimelinesMoveToNonEmpty,
#[fail(display = "Supplied an invalid transaction range")]
TimelinesInvalidRange,
// It would be better to capture the underlying `rusqlite::Error`, but that type doesn't
// implement many useful traits, including `Clone`, `Eq`, and `PartialEq`.
#[fail(display = "SQL error: {}", _0)]
RusqliteError(String),
}

18
db-traits/lib.rs Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
extern crate failure;
extern crate failure_derive;
extern crate rusqlite;
extern crate core_traits;
extern crate edn;
pub mod errors;

View file

@ -1,20 +1,29 @@
[package] [package]
name = "mentat_db" name = "mentat_db"
version = "0.0.1" version = "0.0.2"
workspace = ".." workspace = ".."
[features]
default = []
sqlcipher = ["rusqlite/sqlcipher"]
syncable = ["serde", "serde_json", "serde_derive"]
[dependencies] [dependencies]
error-chain = { git = "https://github.com/rnewman/error-chain", branch = "rnewman/sync" } failure = "~0.1"
indexmap = "0.4" indexmap = "~1.9"
itertools = "0.7" itertools = "~0.10"
lazy_static = "0.2" lazy_static = "~1.4"
num = "0.1" log = "~0.4"
ordered-float = "0.5" ordered-float = "~2.8"
time = "0.1" time = "~0.3"
petgraph = "~0.6"
serde = { version = "~1.0", optional = true }
serde_json = { version = "~1.0", optional = true }
serde_derive = { version = "~1.0", optional = true }
[dependencies.rusqlite] [dependencies.rusqlite]
version = "0.13" version = "~0.29"
features = ["limits"] features = ["limits", "bundled"]
[dependencies.edn] [dependencies.edn]
path = "../edn" path = "../edn"
@ -22,12 +31,19 @@ path = "../edn"
[dependencies.mentat_core] [dependencies.mentat_core]
path = "../core" path = "../core"
[dependencies.mentat_tx] [dependencies.core_traits]
path = "../tx" path = "../core-traits"
[dependencies.mentat_tx_parser] [dependencies.db_traits]
path = "../tx-parser" path = "../db-traits"
# Should be dev-dependencies. [dependencies.mentat_sql]
path = "../sql"
# TODO: This should be in dev-dependencies.
[dependencies.tabwriter] [dependencies.tabwriter]
version = "1.0.3" version = "~1.2"
[dev-dependencies]
env_logger = "0.9"
#tabwriter = { version = "1.2.1" }

View file

@ -24,7 +24,10 @@ pub struct AddRetractAlterSet<K, V> {
pub altered: BTreeMap<K, (V, V)>, pub altered: BTreeMap<K, (V, V)>,
} }
impl<K, V> Default for AddRetractAlterSet<K, V> where K: Ord { impl<K, V> Default for AddRetractAlterSet<K, V>
where
K: Ord,
{
fn default() -> AddRetractAlterSet<K, V> { fn default() -> AddRetractAlterSet<K, V> {
AddRetractAlterSet { AddRetractAlterSet {
asserted: BTreeMap::default(), asserted: BTreeMap::default(),
@ -34,7 +37,10 @@ impl<K, V> Default for AddRetractAlterSet<K, V> where K: Ord {
} }
} }
impl<K, V> AddRetractAlterSet<K, V> where K: Ord { impl<K, V> AddRetractAlterSet<K, V>
where
K: Ord,
{
pub fn witness(&mut self, key: K, value: V, added: bool) { pub fn witness(&mut self, key: K, value: V, added: bool) {
if added { if added {
if let Some(retracted_value) = self.retracted.remove(&key) { if let Some(retracted_value) = self.retracted.remove(&key) {
@ -42,12 +48,10 @@ impl<K, V> AddRetractAlterSet<K, V> where K: Ord {
} else { } else {
self.asserted.insert(key, value); self.asserted.insert(key, value);
} }
} else if let Some(asserted_value) = self.asserted.remove(&key) {
self.altered.insert(key, (value, asserted_value));
} else { } else {
if let Some(asserted_value) = self.asserted.remove(&key) { self.retracted.insert(key, value);
self.altered.insert(key, (value, asserted_value));
} else {
self.retracted.insert(key, value);
}
} }
} }
} }

View file

@ -10,27 +10,24 @@
#![allow(dead_code)] #![allow(dead_code)]
use crate::db::TypedSQLValue;
use crate::entids;
use db_traits::errors::{DbErrorKind, Result};
use edn; use edn;
use errors::{ErrorKind, Result}; use edn::entities::Entity;
use edn::types::Value;
use edn::symbols; use edn::symbols;
use entids; use edn::types::Value;
use db::TypedSQLValue;
use mentat_tx::entities::Entity; use core_traits::{values, TypedValue};
use mentat_tx_parser;
use mentat_core::{ use crate::schema::SchemaBuilding;
IdentMap, use crate::types::{Partition, PartitionMap};
Schema, use mentat_core::{IdentMap, Schema};
TypedValue,
values,
};
use schema::SchemaBuilding;
use types::{Partition, PartitionMap};
/// The first transaction ID applied to the knowledge base. /// The first transaction ID applied to the knowledge base.
/// ///
/// This is the start of the :db.part/tx partition. /// This is the start of the :db.part/tx partition.
pub const TX0: i64 = 0x10000000; pub const TX0: i64 = 0x1000_0000;
/// This is the start of the :db.part/user partition. /// This is the start of the :db.part/user partition.
pub const USER0: i64 = 0x10000; pub const USER0: i64 = 0x10000;
@ -39,77 +36,119 @@ pub const USER0: i64 = 0x10000;
pub const CORE_SCHEMA_VERSION: u32 = 1; pub const CORE_SCHEMA_VERSION: u32 = 1;
lazy_static! { lazy_static! {
static ref V1_IDENTS: [(symbols::NamespacedKeyword, i64); 40] = { static ref V1_IDENTS: [(symbols::Keyword, i64); 40] = {
[(ns_keyword!("db", "ident"), entids::DB_IDENT), [
(ns_keyword!("db.part", "db"), entids::DB_PART_DB), (ns_keyword!("db", "ident"), entids::DB_IDENT),
(ns_keyword!("db", "txInstant"), entids::DB_TX_INSTANT), (ns_keyword!("db.part", "db"), entids::DB_PART_DB),
(ns_keyword!("db.install", "partition"), entids::DB_INSTALL_PARTITION), (ns_keyword!("db", "txInstant"), entids::DB_TX_INSTANT),
(ns_keyword!("db.install", "valueType"), entids::DB_INSTALL_VALUE_TYPE), (
(ns_keyword!("db.install", "attribute"), entids::DB_INSTALL_ATTRIBUTE), ns_keyword!("db.install", "partition"),
(ns_keyword!("db", "valueType"), entids::DB_VALUE_TYPE), entids::DB_INSTALL_PARTITION,
(ns_keyword!("db", "cardinality"), entids::DB_CARDINALITY), ),
(ns_keyword!("db", "unique"), entids::DB_UNIQUE), (
(ns_keyword!("db", "isComponent"), entids::DB_IS_COMPONENT), ns_keyword!("db.install", "valueType"),
(ns_keyword!("db", "index"), entids::DB_INDEX), entids::DB_INSTALL_VALUE_TYPE,
(ns_keyword!("db", "fulltext"), entids::DB_FULLTEXT), ),
(ns_keyword!("db", "noHistory"), entids::DB_NO_HISTORY), (
(ns_keyword!("db", "add"), entids::DB_ADD), ns_keyword!("db.install", "attribute"),
(ns_keyword!("db", "retract"), entids::DB_RETRACT), entids::DB_INSTALL_ATTRIBUTE,
(ns_keyword!("db.part", "user"), entids::DB_PART_USER), ),
(ns_keyword!("db.part", "tx"), entids::DB_PART_TX), (ns_keyword!("db", "valueType"), entids::DB_VALUE_TYPE),
(ns_keyword!("db", "excise"), entids::DB_EXCISE), (ns_keyword!("db", "cardinality"), entids::DB_CARDINALITY),
(ns_keyword!("db.excise", "attrs"), entids::DB_EXCISE_ATTRS), (ns_keyword!("db", "unique"), entids::DB_UNIQUE),
(ns_keyword!("db.excise", "beforeT"), entids::DB_EXCISE_BEFORE_T), (ns_keyword!("db", "isComponent"), entids::DB_IS_COMPONENT),
(ns_keyword!("db.excise", "before"), entids::DB_EXCISE_BEFORE), (ns_keyword!("db", "index"), entids::DB_INDEX),
(ns_keyword!("db.alter", "attribute"), entids::DB_ALTER_ATTRIBUTE), (ns_keyword!("db", "fulltext"), entids::DB_FULLTEXT),
(ns_keyword!("db.type", "ref"), entids::DB_TYPE_REF), (ns_keyword!("db", "noHistory"), entids::DB_NO_HISTORY),
(ns_keyword!("db.type", "keyword"), entids::DB_TYPE_KEYWORD), (ns_keyword!("db", "add"), entids::DB_ADD),
(ns_keyword!("db.type", "long"), entids::DB_TYPE_LONG), (ns_keyword!("db", "retract"), entids::DB_RETRACT),
(ns_keyword!("db.type", "double"), entids::DB_TYPE_DOUBLE), (ns_keyword!("db.part", "user"), entids::DB_PART_USER),
(ns_keyword!("db.type", "string"), entids::DB_TYPE_STRING), (ns_keyword!("db.part", "tx"), entids::DB_PART_TX),
(ns_keyword!("db.type", "uuid"), entids::DB_TYPE_UUID), (ns_keyword!("db", "excise"), entids::DB_EXCISE),
(ns_keyword!("db.type", "uri"), entids::DB_TYPE_URI), (ns_keyword!("db.excise", "attrs"), entids::DB_EXCISE_ATTRS),
(ns_keyword!("db.type", "boolean"), entids::DB_TYPE_BOOLEAN), (
(ns_keyword!("db.type", "instant"), entids::DB_TYPE_INSTANT), ns_keyword!("db.excise", "beforeT"),
(ns_keyword!("db.type", "bytes"), entids::DB_TYPE_BYTES), entids::DB_EXCISE_BEFORE_T,
(ns_keyword!("db.cardinality", "one"), entids::DB_CARDINALITY_ONE), ),
(ns_keyword!("db.cardinality", "many"), entids::DB_CARDINALITY_MANY), (ns_keyword!("db.excise", "before"), entids::DB_EXCISE_BEFORE),
(ns_keyword!("db.unique", "value"), entids::DB_UNIQUE_VALUE), (
(ns_keyword!("db.unique", "identity"), entids::DB_UNIQUE_IDENTITY), ns_keyword!("db.alter", "attribute"),
(ns_keyword!("db", "doc"), entids::DB_DOC), entids::DB_ALTER_ATTRIBUTE,
(ns_keyword!("db.schema", "version"), entids::DB_SCHEMA_VERSION), ),
(ns_keyword!("db.schema", "attribute"), entids::DB_SCHEMA_ATTRIBUTE), (ns_keyword!("db.type", "ref"), entids::DB_TYPE_REF),
(ns_keyword!("db.schema", "core"), entids::DB_SCHEMA_CORE), (ns_keyword!("db.type", "keyword"), entids::DB_TYPE_KEYWORD),
(ns_keyword!("db.type", "long"), entids::DB_TYPE_LONG),
(ns_keyword!("db.type", "double"), entids::DB_TYPE_DOUBLE),
(ns_keyword!("db.type", "string"), entids::DB_TYPE_STRING),
(ns_keyword!("db.type", "uuid"), entids::DB_TYPE_UUID),
(ns_keyword!("db.type", "uri"), entids::DB_TYPE_URI),
(ns_keyword!("db.type", "boolean"), entids::DB_TYPE_BOOLEAN),
(ns_keyword!("db.type", "instant"), entids::DB_TYPE_INSTANT),
(ns_keyword!("db.type", "bytes"), entids::DB_TYPE_BYTES),
(
ns_keyword!("db.cardinality", "one"),
entids::DB_CARDINALITY_ONE,
),
(
ns_keyword!("db.cardinality", "many"),
entids::DB_CARDINALITY_MANY,
),
(ns_keyword!("db.unique", "value"), entids::DB_UNIQUE_VALUE),
(
ns_keyword!("db.unique", "identity"),
entids::DB_UNIQUE_IDENTITY,
),
(ns_keyword!("db", "doc"), entids::DB_DOC),
(
ns_keyword!("db.schema", "version"),
entids::DB_SCHEMA_VERSION,
),
(
ns_keyword!("db.schema", "attribute"),
entids::DB_SCHEMA_ATTRIBUTE,
),
(ns_keyword!("db.schema", "core"), entids::DB_SCHEMA_CORE),
] ]
}; };
pub static ref V1_PARTS: [(symbols::Keyword, i64, i64, i64, bool); 3] = {
static ref V1_PARTS: [(symbols::NamespacedKeyword, i64, i64); 3] = { [
[(ns_keyword!("db.part", "db"), 0, (1 + V1_IDENTS.len()) as i64), (
(ns_keyword!("db.part", "user"), USER0, USER0), ns_keyword!("db.part", "db"),
(ns_keyword!("db.part", "tx"), TX0, TX0), 0,
USER0 - 1,
(1 + V1_IDENTS.len()) as i64,
false,
),
(ns_keyword!("db.part", "user"), USER0, TX0 - 1, USER0, true),
(
ns_keyword!("db.part", "tx"),
TX0,
i64::max_value(),
TX0,
false,
),
] ]
}; };
static ref V1_CORE_SCHEMA: [symbols::Keyword; 16] = {
static ref V1_CORE_SCHEMA: [(symbols::NamespacedKeyword); 16] = { [
[(ns_keyword!("db", "ident")), (ns_keyword!("db", "ident")),
(ns_keyword!("db.install", "partition")), (ns_keyword!("db.install", "partition")),
(ns_keyword!("db.install", "valueType")), (ns_keyword!("db.install", "valueType")),
(ns_keyword!("db.install", "attribute")), (ns_keyword!("db.install", "attribute")),
(ns_keyword!("db", "txInstant")), (ns_keyword!("db", "txInstant")),
(ns_keyword!("db", "valueType")), (ns_keyword!("db", "valueType")),
(ns_keyword!("db", "cardinality")), (ns_keyword!("db", "cardinality")),
(ns_keyword!("db", "doc")), (ns_keyword!("db", "doc")),
(ns_keyword!("db", "unique")), (ns_keyword!("db", "unique")),
(ns_keyword!("db", "isComponent")), (ns_keyword!("db", "isComponent")),
(ns_keyword!("db", "index")), (ns_keyword!("db", "index")),
(ns_keyword!("db", "fulltext")), (ns_keyword!("db", "fulltext")),
(ns_keyword!("db", "noHistory")), (ns_keyword!("db", "noHistory")),
(ns_keyword!("db.alter", "attribute")), (ns_keyword!("db.alter", "attribute")),
(ns_keyword!("db.schema", "version")), (ns_keyword!("db.schema", "version")),
(ns_keyword!("db.schema", "attribute")), (ns_keyword!("db.schema", "attribute")),
] ]
}; };
static ref V1_SYMBOLIC_SCHEMA: Value = { static ref V1_SYMBOLIC_SCHEMA: Value = {
let s = r#" let s = r#"
{:db/ident {:db/valueType :db.type/keyword {:db/ident {:db/valueType :db.type/keyword
@ -157,65 +196,85 @@ lazy_static! {
:db/cardinality :db.cardinality/many}}"#; :db/cardinality :db.cardinality/many}}"#;
edn::parse::value(s) edn::parse::value(s)
.map(|v| v.without_spans()) .map(|v| v.without_spans())
.map_err(|_| ErrorKind::BadBootstrapDefinition("Unable to parse V1_SYMBOLIC_SCHEMA".into())) .map_err(|_| {
DbErrorKind::BadBootstrapDefinition("Unable to parse V1_SYMBOLIC_SCHEMA".into())
})
.unwrap() .unwrap()
}; };
} }
/// Convert (ident, entid) pairs into [:db/add IDENT :db/ident IDENT] `Value` instances. /// Convert (ident, entid) pairs into [:db/add IDENT :db/ident IDENT] `Value` instances.
fn idents_to_assertions(idents: &[(symbols::NamespacedKeyword, i64)]) -> Vec<Value> { fn idents_to_assertions(idents: &[(symbols::Keyword, i64)]) -> Vec<Value> {
idents idents
.into_iter() .iter()
.map(|&(ref ident, _)| { .map(|&(ref ident, _)| {
let value = Value::NamespacedKeyword(ident.clone()); let value = Value::Keyword(ident.clone());
Value::Vector(vec![values::DB_ADD.clone(), value.clone(), values::DB_IDENT.clone(), value.clone()]) Value::Vector(vec![
values::DB_ADD.clone(),
value.clone(),
values::DB_IDENT.clone(),
value,
])
}) })
.collect() .collect()
} }
/// Convert an ident list into [:db/add :db.schema/core :db.schema/attribute IDENT] `Value` instances. /// Convert an ident list into [:db/add :db.schema/core :db.schema/attribute IDENT] `Value` instances.
fn schema_attrs_to_assertions(version: u32, idents: &[symbols::NamespacedKeyword]) -> Vec<Value> { fn schema_attrs_to_assertions(version: u32, idents: &[symbols::Keyword]) -> Vec<Value> {
let schema_core = Value::NamespacedKeyword(ns_keyword!("db.schema", "core")); let schema_core = Value::Keyword(ns_keyword!("db.schema", "core"));
let schema_attr = Value::NamespacedKeyword(ns_keyword!("db.schema", "attribute")); let schema_attr = Value::Keyword(ns_keyword!("db.schema", "attribute"));
let schema_version = Value::NamespacedKeyword(ns_keyword!("db.schema", "version")); let schema_version = Value::Keyword(ns_keyword!("db.schema", "version"));
idents idents
.into_iter() .iter()
.map(|ident| { .map(|ident| {
let value = Value::NamespacedKeyword(ident.clone()); let value = Value::Keyword(ident.clone());
Value::Vector(vec![values::DB_ADD.clone(), Value::Vector(vec![
schema_core.clone(), values::DB_ADD.clone(),
schema_attr.clone(), schema_core.clone(),
value]) schema_attr.clone(),
value,
])
}) })
.chain(::std::iter::once(Value::Vector(vec![values::DB_ADD.clone(), .chain(::std::iter::once(Value::Vector(vec![
schema_core.clone(), values::DB_ADD.clone(),
schema_version, schema_core.clone(),
Value::Integer(version as i64)]))) schema_version,
Value::Integer(version as i64),
])))
.collect() .collect()
} }
/// Convert {:ident {:key :value ...} ...} to /// Convert {:ident {:key :value ...} ...} to
/// vec![(symbols::NamespacedKeyword(:ident), symbols::NamespacedKeyword(:key), TypedValue(:value)), ...]. /// vec![(symbols::Keyword(:ident), symbols::Keyword(:key), TypedValue(:value)), ...].
/// ///
/// Such triples are closer to what the transactor will produce when processing attribute /// Such triples are closer to what the transactor will produce when processing attribute
/// assertions. /// assertions.
fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) -> Result<Vec<(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>> { fn symbolic_schema_to_triples(
ident_map: &IdentMap,
symbolic_schema: &Value,
) -> Result<Vec<(symbols::Keyword, symbols::Keyword, TypedValue)>> {
// Failure here is a coding error, not a runtime error. // Failure here is a coding error, not a runtime error.
let mut triples: Vec<(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)> = vec![]; let mut triples: Vec<(symbols::Keyword, symbols::Keyword, TypedValue)> = vec![];
// TODO: Consider `flat_map` and `map` rather than loop. // TODO: Consider `flat_map` and `map` rather than loop.
match *symbolic_schema { match *symbolic_schema {
Value::Map(ref m) => { Value::Map(ref m) => {
for (ident, mp) in m { for (ident, mp) in m {
let ident = match ident { let ident = match ident {
&Value::NamespacedKeyword(ref ident) => ident, Value::Keyword(ref ident) => ident,
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for ident but got '{:?}'", ident))) _ => bail!(DbErrorKind::BadBootstrapDefinition(format!(
"Expected namespaced keyword for ident but got '{:?}'",
ident
))),
}; };
match *mp { match *mp {
Value::Map(ref mpp) => { Value::Map(ref mpp) => {
for (attr, value) in mpp { for (attr, value) in mpp {
let attr = match attr { let attr = match attr {
&Value::NamespacedKeyword(ref attr) => attr, Value::Keyword(ref attr) => attr,
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected namespaced keyword for attr but got '{:?}'", attr))) _ => bail!(DbErrorKind::BadBootstrapDefinition(format!(
"Expected namespaced keyword for attr but got '{:?}'",
attr
))),
}; };
// We have symbolic idents but the transactor handles entids. Ad-hoc // We have symbolic idents but the transactor handles entids. Ad-hoc
@ -227,23 +286,27 @@ fn symbolic_schema_to_triples(ident_map: &IdentMap, symbolic_schema: &Value) ->
// bootstrap symbolic schema, or by representing the initial bootstrap // bootstrap symbolic schema, or by representing the initial bootstrap
// schema directly as Rust data. // schema directly as Rust data.
let typed_value = match TypedValue::from_edn_value(value) { let typed_value = match TypedValue::from_edn_value(value) {
Some(TypedValue::Keyword(ref k)) => { Some(TypedValue::Keyword(ref k)) => ident_map
ident_map.get(k) .get(k)
.map(|entid| TypedValue::Ref(*entid)) .map(|entid| TypedValue::Ref(*entid))
.ok_or(ErrorKind::UnrecognizedIdent(k.to_string()))? .ok_or_else(|| DbErrorKind::UnrecognizedIdent(k.to_string()))?,
},
Some(v) => v, Some(v) => v,
_ => bail!(ErrorKind::BadBootstrapDefinition(format!("Expected Mentat typed value for value but got '{:?}'", value))) _ => bail!(DbErrorKind::BadBootstrapDefinition(format!(
"Expected Mentat typed value for value but got '{:?}'",
value
))),
}; };
triples.push((ident.clone(), attr.clone(), typed_value)); triples.push((ident.clone(), attr.clone(), typed_value));
} }
}, }
_ => bail!(ErrorKind::BadBootstrapDefinition("Expected {:db/ident {:db/attr value ...} ...}".into())) _ => bail!(DbErrorKind::BadBootstrapDefinition(
"Expected {:db/ident {:db/attr value ...} ...}".into()
)),
} }
} }
}, }
_ => bail!(ErrorKind::BadBootstrapDefinition("Expected {...}".into())) _ => bail!(DbErrorKind::BadBootstrapDefinition("Expected {...}".into())),
} }
Ok(triples) Ok(triples)
} }
@ -258,48 +321,62 @@ fn symbolic_schema_to_assertions(symbolic_schema: &Value) -> Result<Vec<Value>>
match *mp { match *mp {
Value::Map(ref mpp) => { Value::Map(ref mpp) => {
for (attr, value) in mpp { for (attr, value) in mpp {
assertions.push(Value::Vector(vec![values::DB_ADD.clone(), assertions.push(Value::Vector(vec![
ident.clone(), values::DB_ADD.clone(),
attr.clone(), ident.clone(),
value.clone()])); attr.clone(),
value.clone(),
]));
} }
}, }
_ => bail!(ErrorKind::BadBootstrapDefinition("Expected {:db/ident {:db/attr value ...} ...}".into())) _ => bail!(DbErrorKind::BadBootstrapDefinition(
"Expected {:db/ident {:db/attr value ...} ...}".into()
)),
} }
} }
}, }
_ => bail!(ErrorKind::BadBootstrapDefinition("Expected {...}".into())) _ => bail!(DbErrorKind::BadBootstrapDefinition("Expected {...}".into())),
} }
Ok(assertions) Ok(assertions)
} }
pub(crate) fn bootstrap_partition_map() -> PartitionMap { pub(crate) fn bootstrap_partition_map() -> PartitionMap {
V1_PARTS.iter() V1_PARTS
.map(|&(ref part, start, index)| (part.to_string(), Partition::new(start, index))) .iter()
.collect() .map(|&(ref part, start, end, index, allow_excision)| {
(
part.to_string(),
Partition::new(start, end, index, allow_excision),
)
})
.collect()
} }
pub(crate) fn bootstrap_ident_map() -> IdentMap { pub(crate) fn bootstrap_ident_map() -> IdentMap {
V1_IDENTS.iter() V1_IDENTS
.map(|&(ref ident, entid)| (ident.clone(), entid)) .iter()
.collect() .map(|&(ref ident, entid)| (ident.clone(), entid))
.collect()
} }
pub(crate) fn bootstrap_schema() -> Schema { pub(crate) fn bootstrap_schema() -> Schema {
let ident_map = bootstrap_ident_map(); let ident_map = bootstrap_ident_map();
let bootstrap_triples = symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).unwrap(); let bootstrap_triples =
symbolic_schema_to_triples(&ident_map, &V1_SYMBOLIC_SCHEMA).expect("symbolic schema");
Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap() Schema::from_ident_map_and_triples(ident_map, bootstrap_triples).unwrap()
} }
pub(crate) fn bootstrap_entities() -> Vec<Entity> { pub(crate) fn bootstrap_entities() -> Vec<Entity<edn::ValueAndSpan>> {
let bootstrap_assertions: Value = Value::Vector([ let bootstrap_assertions: Value = Value::Vector(
symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).unwrap(), [
idents_to_assertions(&V1_IDENTS[..]), symbolic_schema_to_assertions(&V1_SYMBOLIC_SCHEMA).expect("symbolic schema"),
schema_attrs_to_assertions(CORE_SCHEMA_VERSION, V1_CORE_SCHEMA.as_ref()), idents_to_assertions(&V1_IDENTS[..]),
].concat()); schema_attrs_to_assertions(CORE_SCHEMA_VERSION, V1_CORE_SCHEMA.as_ref()),
]
.concat(),
);
// Failure here is a coding error (since the inputs are fixed), not a runtime error. // Failure here is a coding error (since the inputs are fixed), not a runtime error.
// TODO: represent these bootstrap data errors rather than just panicing. // TODO: represent these bootstrap entity data errors rather than just panicing.
let bootstrap_entities: Vec<Entity> = mentat_tx_parser::Tx::parse(&bootstrap_assertions.with_spans()).unwrap(); edn::parse::entities(&bootstrap_assertions.to_string()).expect("bootstrap assertions")
return bootstrap_entities;
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,44 +9,90 @@
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#![allow(dead_code)] #![allow(dead_code)]
#![allow(unused_macros)]
/// Low-level functions for testing. /// Low-level functions for testing.
// Macro to parse a `Borrow<str>` to an `edn::Value` and assert the given `edn::Value` `matches`
// against it.
//
// This is a macro only to give nice line numbers when tests fail.
#[macro_export]
macro_rules! assert_matches {
( $input: expr, $expected: expr ) => {{
// Failure to parse the expected pattern is a coding error, so we unwrap.
let pattern_value = edn::parse::value($expected.borrow())
.expect(format!("to be able to parse expected {}", $expected).as_str())
.without_spans();
let input_value = $input.to_edn();
assert!(
input_value.matches(&pattern_value),
"Expected value:\n{}\nto match pattern:\n{}\n",
input_value.to_pretty(120).unwrap(),
pattern_value.to_pretty(120).unwrap()
);
}};
}
// Transact $input against the given $conn, expecting success or a `Result<TxReport, String>`.
//
// This unwraps safely and makes asserting errors pleasant.
#[macro_export]
macro_rules! assert_transact {
( $conn: expr, $input: expr, $expected: expr ) => {{
trace!("assert_transact: {}", $input);
let result = $conn.transact($input).map_err(|e| e.to_string());
assert_eq!(result, $expected.map_err(|e| e.to_string()));
}};
( $conn: expr, $input: expr ) => {{
trace!("assert_transact: {}", $input);
let result = $conn.transact($input);
assert!(
result.is_ok(),
"Expected Ok(_), got `{}`",
result.unwrap_err()
);
result.unwrap()
}};
}
use std::borrow::Borrow; use std::borrow::Borrow;
use std::io::{Write}; use std::collections::BTreeMap;
use std::rc::Rc; use std::io::Write;
use itertools::Itertools; use itertools::Itertools;
use rusqlite; use rusqlite;
use rusqlite::types::{ToSql}; use rusqlite::types::ToSql;
use rusqlite::TransactionBehavior;
use tabwriter::TabWriter; use tabwriter::TabWriter;
use bootstrap; use crate::bootstrap;
use db::TypedSQLValue; use crate::db::*;
use crate::db::{read_attribute_map, read_ident_map};
use crate::entids;
use db_traits::errors::Result;
use edn; use edn;
use entids;
use errors::Result; use core_traits::{Entid, TypedValue, ValueType};
use mentat_core::{
HasSchema, use crate::internal_types::TermWithTempIds;
SQLValueType, use crate::schema::SchemaBuilding;
TypedValue, use crate::tx::{transact, transact_terms};
ValueType, use crate::types::*;
}; use crate::watcher::NullWatcher;
use mentat_tx::entities::{Entid}; use edn::entities::{EntidOrIdent, TempId};
use schema::{ use edn::InternSet;
SchemaBuilding, use mentat_core::{HasSchema, SQLValueType, TxReport};
};
use types::Schema;
/// Represents a *datom* (assertion) in the store. /// Represents a *datom* (assertion) in the store.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub(crate) struct Datom { pub struct Datom {
// TODO: generalize this. // TODO: generalize this.
e: Entid, pub e: EntidOrIdent,
a: Entid, pub a: EntidOrIdent,
v: edn::Value, pub v: edn::Value,
tx: i64, pub tx: i64,
added: Option<bool>, pub added: Option<bool>,
} }
/// Represents a set of datoms (assertions) in the store. /// Represents a set of datoms (assertions) in the store.
@ -54,7 +100,7 @@ pub(crate) struct Datom {
/// To make comparision easier, we deterministically order. The ordering is the ascending tuple /// To make comparision easier, we deterministically order. The ordering is the ascending tuple
/// ordering determined by `(e, a, (value_type_tag, v), tx)`, where `value_type_tag` is an internal /// ordering determined by `(e, a, (value_type_tag, v), tx)`, where `value_type_tag` is an internal
/// value that is not exposed but is deterministic. /// value that is not exposed but is deterministic.
pub(crate) struct Datoms(pub Vec<Datom>); pub struct Datoms(pub Vec<Datom>);
/// Represents an ordered sequence of transactions in the store. /// Represents an ordered sequence of transactions in the store.
/// ///
@ -62,17 +108,17 @@ pub(crate) struct Datoms(pub Vec<Datom>);
/// ordering determined by `(e, a, (value_type_tag, v), tx, added)`, where `value_type_tag` is an /// ordering determined by `(e, a, (value_type_tag, v), tx, added)`, where `value_type_tag` is an
/// internal value that is not exposed but is deterministic, and `added` is ordered such that /// internal value that is not exposed but is deterministic, and `added` is ordered such that
/// retracted assertions appear before added assertions. /// retracted assertions appear before added assertions.
pub(crate) struct Transactions(pub Vec<Datoms>); pub struct Transactions(pub Vec<Datoms>);
/// Represents the fulltext values in the store. /// Represents the fulltext values in the store.
pub(crate) struct FulltextValues(pub Vec<(i64, String)>); pub struct FulltextValues(pub Vec<(i64, String)>);
impl Datom { impl Datom {
pub(crate) fn into_edn(&self) -> edn::Value { pub fn to_edn(&self) -> edn::Value {
let f = |entid: &Entid| -> edn::Value { let f = |entid: &EntidOrIdent| -> edn::Value {
match *entid { match *entid {
Entid::Entid(ref y) => edn::Value::Integer(y.clone()), EntidOrIdent::Entid(ref y) => edn::Value::Integer(*y),
Entid::Ident(ref y) => edn::Value::NamespacedKeyword(y.clone()), EntidOrIdent::Ident(ref y) => edn::Value::Keyword(y.clone()),
} }
}; };
@ -87,32 +133,43 @@ impl Datom {
} }
impl Datoms { impl Datoms {
pub(crate) fn into_edn(&self) -> edn::Value { pub fn to_edn(&self) -> edn::Value {
edn::Value::Vector((&self.0).into_iter().map(|x| x.into_edn()).collect()) edn::Value::Vector((&self.0).iter().map(|x| x.to_edn()).collect())
} }
} }
impl Transactions { impl Transactions {
pub(crate) fn into_edn(&self) -> edn::Value { pub fn to_edn(&self) -> edn::Value {
edn::Value::Vector((&self.0).into_iter().map(|x| x.into_edn()).collect()) edn::Value::Vector((&self.0).iter().map(|x| x.to_edn()).collect())
} }
} }
impl FulltextValues { impl FulltextValues {
pub(crate) fn into_edn(&self) -> edn::Value { pub fn to_edn(&self) -> edn::Value {
edn::Value::Vector((&self.0).into_iter().map(|&(x, ref y)| edn::Value::Vector(vec![edn::Value::Integer(x), edn::Value::Text(y.clone())])).collect()) edn::Value::Vector(
(&self.0)
.iter()
.map(|&(x, ref y)| {
edn::Value::Vector(vec![edn::Value::Integer(x), edn::Value::Text(y.clone())])
})
.collect(),
)
} }
} }
/// Turn TypedValue::Ref into TypedValue::Keyword when it is possible. /// Turn TypedValue::Ref into TypedValue::Keyword when it is possible.
trait ToIdent { trait ToIdent {
fn map_ident(self, schema: &Schema) -> Self; fn map_ident(self, schema: &Schema) -> Self;
} }
impl ToIdent for TypedValue { impl ToIdent for TypedValue {
fn map_ident(self, schema: &Schema) -> Self { fn map_ident(self, schema: &Schema) -> Self {
if let TypedValue::Ref(e) = self { if let TypedValue::Ref(e) = self {
schema.get_ident(e).cloned().map(|i| TypedValue::Keyword(Rc::new(i))).unwrap_or(TypedValue::Ref(e)) schema
.get_ident(e)
.cloned()
.map(|i| i.into())
.unwrap_or(TypedValue::Ref(e))
} else { } else {
self self
} }
@ -120,13 +177,22 @@ impl ToIdent for TypedValue {
} }
/// Convert a numeric entid to an ident `Entid` if possible, otherwise a numeric `Entid`. /// Convert a numeric entid to an ident `Entid` if possible, otherwise a numeric `Entid`.
fn to_entid(schema: &Schema, entid: i64) -> Entid { pub fn to_entid(schema: &Schema, entid: i64) -> EntidOrIdent {
schema.get_ident(entid).map_or(Entid::Entid(entid), |ident| Entid::Ident(ident.clone())) schema
.get_ident(entid)
.map_or(EntidOrIdent::Entid(entid), |ident| {
EntidOrIdent::Ident(ident.clone())
})
} }
// /// Convert a symbolic ident to an ident `Entid` if possible, otherwise a numeric `Entid`.
// pub fn to_ident(schema: &Schema, entid: i64) -> Entid {
// schema.get_ident(entid).map_or(Entid::Entid(entid), |ident| Entid::Ident(ident.clone()))
// }
/// Return the set of datoms in the store, ordered by (e, a, v, tx), but not including any datoms of /// Return the set of datoms in the store, ordered by (e, a, v, tx), but not including any datoms of
/// the form [... :db/txInstant ...]. /// the form [... :db/txInstant ...].
pub(crate) fn datoms<S: Borrow<Schema>>(conn: &rusqlite::Connection, schema: &S) -> Result<Datoms> { pub fn datoms<S: Borrow<Schema>>(conn: &rusqlite::Connection, schema: &S) -> Result<Datoms> {
datoms_after(conn, schema, bootstrap::TX0 - 1) datoms_after(conn, schema, bootstrap::TX0 - 1)
} }
@ -134,38 +200,49 @@ pub(crate) fn datoms<S: Borrow<Schema>>(conn: &rusqlite::Connection, schema: &S)
/// ordered by (e, a, v, tx). /// ordered by (e, a, v, tx).
/// ///
/// The datom set returned does not include any datoms of the form [... :db/txInstant ...]. /// The datom set returned does not include any datoms of the form [... :db/txInstant ...].
pub(crate) fn datoms_after<S: Borrow<Schema>>(conn: &rusqlite::Connection, schema: &S, tx: i64) -> Result<Datoms> { pub fn datoms_after<S: Borrow<Schema>>(
conn: &rusqlite::Connection,
schema: &S,
tx: i64,
) -> Result<Datoms> {
let borrowed_schema = schema.borrow(); let borrowed_schema = schema.borrow();
let mut stmt: rusqlite::Statement = conn.prepare("SELECT e, a, v, value_type_tag, tx FROM datoms WHERE tx > ? ORDER BY e ASC, a ASC, value_type_tag ASC, v ASC, tx ASC")?; let mut stmt: rusqlite::Statement = conn.prepare("SELECT e, a, v, value_type_tag, tx FROM datoms WHERE tx > ? ORDER BY e ASC, a ASC, value_type_tag ASC, v ASC, tx ASC")?;
let r: Result<Vec<_>> = stmt.query_and_then(&[&tx], |row| { let r: Result<Vec<_>> = stmt
let e: i64 = row.get_checked(0)?; .query_and_then(&[&tx], |row| {
let a: i64 = row.get_checked(1)?; let e: i64 = row.get(0)?;
let a: i64 = row.get(1)?;
if a == entids::DB_TX_INSTANT { if a == entids::DB_TX_INSTANT {
return Ok(None); return Ok(None);
} }
let v: rusqlite::types::Value = row.get_checked(2)?; let v: rusqlite::types::Value = row.get(2)?;
let value_type_tag: i32 = row.get_checked(3)?; let value_type_tag: i32 = row.get(3)?;
let attribute = borrowed_schema.require_attribute_for_entid(a)?; let attribute = borrowed_schema.require_attribute_for_entid(a)?;
let value_type_tag = if !attribute.fulltext { value_type_tag } else { ValueType::Long.value_type_tag() }; let value_type_tag = if !attribute.fulltext {
value_type_tag
} else {
ValueType::Long.value_type_tag()
};
let typed_value = TypedValue::from_sql_value_pair(v, value_type_tag)?.map_ident(borrowed_schema); let typed_value =
let (value, _) = typed_value.to_edn_value_pair(); TypedValue::from_sql_value_pair(v, value_type_tag)?.map_ident(borrowed_schema);
let (value, _) = typed_value.to_edn_value_pair();
let tx: i64 = row.get_checked(4)?; let tx: i64 = row.get(4)?;
Ok(Some(Datom { Ok(Some(Datom {
e: Entid::Entid(e), e: EntidOrIdent::Entid(e),
a: to_entid(borrowed_schema, a), a: to_entid(borrowed_schema, a),
v: value, v: value,
tx: tx, tx,
added: None, added: None,
})) }))
})?.collect(); })?
.collect();
Ok(Datoms(r?.into_iter().filter_map(|x| x).collect())) Ok(Datoms(r?.into_iter().filter_map(|x| x).collect()))
} }
@ -173,51 +250,70 @@ pub(crate) fn datoms_after<S: Borrow<Schema>>(conn: &rusqlite::Connection, schem
/// Return the sequence of transactions in the store with transaction ID strictly greater than the /// Return the sequence of transactions in the store with transaction ID strictly greater than the
/// given `tx`, ordered by (tx, e, a, v). /// given `tx`, ordered by (tx, e, a, v).
/// ///
/// Each transaction returned includes the [:db/tx :db/txInstant ...] datom. /// Each transaction returned includes the [(transaction-tx) :db/txInstant ...] datom.
pub(crate) fn transactions_after<S: Borrow<Schema>>(conn: &rusqlite::Connection, schema: &S, tx: i64) -> Result<Transactions> { pub fn transactions_after<S: Borrow<Schema>>(
conn: &rusqlite::Connection,
schema: &S,
tx: i64,
) -> Result<Transactions> {
let borrowed_schema = schema.borrow(); let borrowed_schema = schema.borrow();
let mut stmt: rusqlite::Statement = conn.prepare("SELECT e, a, v, value_type_tag, tx, added FROM transactions WHERE tx > ? ORDER BY tx ASC, e ASC, a ASC, value_type_tag ASC, v ASC, added ASC")?; let mut stmt: rusqlite::Statement = conn.prepare("SELECT e, a, v, value_type_tag, tx, added FROM transactions WHERE tx > ? ORDER BY tx ASC, e ASC, a ASC, value_type_tag ASC, v ASC, added ASC")?;
let r: Result<Vec<_>> = stmt.query_and_then(&[&tx], |row| { let r: Result<Vec<_>> = stmt
let e: i64 = row.get_checked(0)?; .query_and_then(&[&tx], |row| {
let a: i64 = row.get_checked(1)?; let e: i64 = row.get(0)?;
let a: i64 = row.get(1)?;
let v: rusqlite::types::Value = row.get_checked(2)?; let v: rusqlite::types::Value = row.get(2)?;
let value_type_tag: i32 = row.get_checked(3)?; let value_type_tag: i32 = row.get(3)?;
let attribute = borrowed_schema.require_attribute_for_entid(a)?; let attribute = borrowed_schema.require_attribute_for_entid(a)?;
let value_type_tag = if !attribute.fulltext { value_type_tag } else { ValueType::Long.value_type_tag() }; let value_type_tag = if !attribute.fulltext {
value_type_tag
} else {
ValueType::Long.value_type_tag()
};
let typed_value = TypedValue::from_sql_value_pair(v, value_type_tag)?.map_ident(borrowed_schema); let typed_value =
let (value, _) = typed_value.to_edn_value_pair(); TypedValue::from_sql_value_pair(v, value_type_tag)?.map_ident(borrowed_schema);
let (value, _) = typed_value.to_edn_value_pair();
let tx: i64 = row.get_checked(4)?; let tx: i64 = row.get(4)?;
let added: bool = row.get_checked(5)?; let added: bool = row.get(5)?;
Ok(Datom { Ok(Datom {
e: Entid::Entid(e), e: EntidOrIdent::Entid(e),
a: to_entid(borrowed_schema, a), a: to_entid(borrowed_schema, a),
v: value, v: value,
tx: tx, tx,
added: Some(added), added: Some(added),
}) })
})?.collect(); })?
.collect();
// Group by tx. // Group by tx.
let r: Vec<Datoms> = r?.into_iter().group_by(|x| x.tx).into_iter().map(|(_key, group)| Datoms(group.collect())).collect(); let r: Vec<Datoms> = r?
.into_iter()
.group_by(|x| x.tx)
.into_iter()
.map(|(_key, group)| Datoms(group.collect()))
.collect();
Ok(Transactions(r)) Ok(Transactions(r))
} }
/// Return the set of fulltext values in the store, ordered by rowid. /// Return the set of fulltext values in the store, ordered by rowid.
pub(crate) fn fulltext_values(conn: &rusqlite::Connection) -> Result<FulltextValues> { pub fn fulltext_values(conn: &rusqlite::Connection) -> Result<FulltextValues> {
let mut stmt: rusqlite::Statement = conn.prepare("SELECT rowid, text FROM fulltext_values ORDER BY rowid")?; let mut stmt: rusqlite::Statement =
conn.prepare("SELECT rowid, text FROM fulltext_values ORDER BY rowid")?;
let r: Result<Vec<_>> = stmt.query_and_then(&[], |row| { let r: Result<Vec<_>> = stmt
let rowid: i64 = row.get_checked(0)?; .query_and_then([], |row| {
let text: String = row.get_checked(1)?; let rowid: i64 = row.get(0)?;
Ok((rowid, text)) let text: String = row.get(1)?;
})?.collect(); Ok((rowid, text))
})?
.collect();
r.map(FulltextValues) r.map(FulltextValues)
} }
@ -227,27 +323,222 @@ pub(crate) fn fulltext_values(conn: &rusqlite::Connection) -> Result<FulltextVal
/// ///
/// The query is printed followed by a newline, then the returned columns followed by a newline, and /// The query is printed followed by a newline, then the returned columns followed by a newline, and
/// then the data rows and columns. All columns are aligned. /// then the data rows and columns. All columns are aligned.
pub(crate) fn dump_sql_query(conn: &rusqlite::Connection, sql: &str, params: &[&ToSql]) -> Result<String> { pub fn dump_sql_query(
conn: &rusqlite::Connection,
sql: &str,
params: &[&dyn ToSql],
) -> Result<String> {
let mut stmt: rusqlite::Statement = conn.prepare(sql)?; let mut stmt: rusqlite::Statement = conn.prepare(sql)?;
let mut tw = TabWriter::new(Vec::new()).padding(2); let mut tw = TabWriter::new(Vec::new()).padding(2);
write!(&mut tw, "{}\n", sql).unwrap(); writeln!(&mut tw, "{}", sql).unwrap();
for column_name in stmt.column_names() { for column_name in stmt.column_names() {
write!(&mut tw, "{}\t", column_name).unwrap(); write!(&mut tw, "{}\t", column_name).unwrap();
} }
write!(&mut tw, "\n").unwrap(); writeln!(&mut tw).unwrap();
let r: Result<Vec<_>> = stmt.query_and_then(params, |row| { let r: Result<Vec<_>> = stmt
for i in 0..row.column_count() { .query_and_then(params, |row| {
let value: rusqlite::types::Value = row.get_checked(i)?; for i in 0..row.as_ref().column_count() {
write!(&mut tw, "{:?}\t", value).unwrap(); let value: rusqlite::types::Value = row.get(i)?;
} write!(&mut tw, "{:?}\t", value).unwrap();
write!(&mut tw, "\n").unwrap(); }
Ok(()) writeln!(&mut tw).unwrap();
})?.collect(); Ok(())
})?
.collect();
r?; r?;
let dump = String::from_utf8(tw.into_inner().unwrap()).unwrap(); let dump = String::from_utf8(tw.into_inner().unwrap()).unwrap();
Ok(dump) Ok(dump)
} }
// A connection that doesn't try to be clever about possibly sharing its `Schema`. Compare to
// `mentat::Conn`.
pub struct TestConn {
pub sqlite: rusqlite::Connection,
pub partition_map: PartitionMap,
pub schema: Schema,
}
impl TestConn {
fn assert_materialized_views(&self) {
let materialized_ident_map = read_ident_map(&self.sqlite).expect("ident map");
let materialized_attribute_map = read_attribute_map(&self.sqlite).expect("schema map");
let materialized_schema = Schema::from_ident_map_and_attribute_map(
materialized_ident_map,
materialized_attribute_map,
)
.expect("schema");
assert_eq!(materialized_schema, self.schema);
}
pub fn transact<I>(&mut self, transaction: I) -> Result<TxReport>
where
I: Borrow<str>,
{
// Failure to parse the transaction is a coding error, so we unwrap.
let entities = edn::parse::entities(transaction.borrow()).unwrap_or_else(|_| {
panic!("to be able to parse {} into entities", transaction.borrow())
});
let details = {
// The block scopes the borrow of self.sqlite.
// We're about to write, so go straight ahead and get an IMMEDIATE transaction.
let tx = self
.sqlite
.transaction_with_behavior(TransactionBehavior::Immediate)?;
// Applying the transaction can fail, so we don't unwrap.
let details = transact(
&tx,
self.partition_map.clone(),
&self.schema,
&self.schema,
NullWatcher(),
entities,
)?;
tx.commit()?;
details
};
let (report, next_partition_map, next_schema, _watcher) = details;
self.partition_map = next_partition_map;
if let Some(next_schema) = next_schema {
self.schema = next_schema;
}
// Verify that we've updated the materialized views during transacting.
self.assert_materialized_views();
Ok(report)
}
pub fn transact_simple_terms<I>(
&mut self,
terms: I,
tempid_set: InternSet<TempId>,
) -> Result<TxReport>
where
I: IntoIterator<Item = TermWithTempIds>,
{
let details = {
// The block scopes the borrow of self.sqlite.
// We're about to write, so go straight ahead and get an IMMEDIATE transaction.
let tx = self
.sqlite
.transaction_with_behavior(TransactionBehavior::Immediate)?;
// Applying the transaction can fail, so we don't unwrap.
let details = transact_terms(
&tx,
self.partition_map.clone(),
&self.schema,
&self.schema,
NullWatcher(),
terms,
tempid_set,
)?;
tx.commit()?;
details
};
let (report, next_partition_map, next_schema, _watcher) = details;
self.partition_map = next_partition_map;
if let Some(next_schema) = next_schema {
self.schema = next_schema;
}
// Verify that we've updated the materialized views during transacting.
self.assert_materialized_views();
Ok(report)
}
pub fn last_tx_id(&self) -> Entid {
self.partition_map
.get(&":db.part/tx".to_string())
.unwrap()
.next_entid()
- 1
}
pub fn last_transaction(&self) -> Datoms {
transactions_after(&self.sqlite, &self.schema, self.last_tx_id() - 1)
.expect("last_transaction")
.0
.pop()
.unwrap()
}
pub fn transactions(&self) -> Transactions {
transactions_after(&self.sqlite, &self.schema, bootstrap::TX0).expect("transactions")
}
pub fn datoms(&self) -> Datoms {
datoms_after(&self.sqlite, &self.schema, bootstrap::TX0).expect("datoms")
}
pub fn fulltext_values(&self) -> FulltextValues {
fulltext_values(&self.sqlite).expect("fulltext_values")
}
pub fn with_sqlite(mut conn: rusqlite::Connection) -> TestConn {
let db = ensure_current_version(&mut conn).unwrap();
// Does not include :db/txInstant.
let datoms = datoms_after(&conn, &db.schema, 0).unwrap();
assert_eq!(datoms.0.len(), 94);
// Includes :db/txInstant.
let transactions = transactions_after(&conn, &db.schema, 0).unwrap();
assert_eq!(transactions.0.len(), 1);
assert_eq!(transactions.0[0].0.len(), 95);
let mut parts = db.partition_map;
// Add a fake partition to allow tests to do things like
// [:db/add 111 :foo/bar 222]
{
let fake_partition = Partition::new(100, 2000, 1000, true);
parts.insert(":db.part/fake".into(), fake_partition);
}
let test_conn = TestConn {
sqlite: conn,
partition_map: parts,
schema: db.schema,
};
// Verify that we've created the materialized views during bootstrapping.
test_conn.assert_materialized_views();
test_conn
}
pub fn sanitized_partition_map(&mut self) {
self.partition_map.remove(":db.part/fake");
}
}
impl Default for TestConn {
fn default() -> TestConn {
TestConn::with_sqlite(new_connection("").expect("Couldn't open in-memory db"))
}
}
pub struct TempIds(edn::Value);
impl TempIds {
pub fn to_edn(&self) -> edn::Value {
self.0.clone()
}
}
pub fn tempids(report: &TxReport) -> TempIds {
let mut map: BTreeMap<edn::Value, edn::Value> = BTreeMap::default();
for (tempid, &entid) in report.tempids.iter() {
map.insert(edn::Value::Text(tempid.clone()), edn::Value::Integer(entid));
}
TempIds(edn::Value::Map(map))
}

View file

@ -13,8 +13,7 @@
/// Literal `Entid` values in the the "db" namespace. /// Literal `Entid` values in the the "db" namespace.
/// ///
/// Used through-out the transactor to match core DB constructs. /// Used through-out the transactor to match core DB constructs.
use core_traits::Entid;
use types::{Entid};
// Added in SQL schema v1. // Added in SQL schema v1.
pub const DB_IDENT: Entid = 1; pub const DB_IDENT: Entid = 1;
@ -61,23 +60,35 @@ pub const DB_SCHEMA_CORE: Entid = 40;
/// Return `false` if the given attribute will not change the metadata: recognized idents, schema, /// Return `false` if the given attribute will not change the metadata: recognized idents, schema,
/// partitions in the partition map. /// partitions in the partition map.
pub fn might_update_metadata(attribute: Entid) -> bool { pub fn might_update_metadata(attribute: Entid) -> bool {
if attribute > DB_DOC { if attribute >= DB_DOC {
return false return false;
} }
match attribute { matches!(
attribute,
// Idents. // Idents.
DB_IDENT | DB_IDENT |
// Schema. // Schema.
DB_CARDINALITY | DB_CARDINALITY |
DB_DOC |
DB_FULLTEXT | DB_FULLTEXT |
DB_INDEX | DB_INDEX |
DB_IS_COMPONENT | DB_IS_COMPONENT |
DB_UNIQUE | DB_UNIQUE |
DB_VALUE_TYPE => DB_VALUE_TYPE
true, )
_ => false, }
}
/// Return 'false' if the given attribute might be used to describe a schema attribute.
pub fn is_a_schema_attribute(attribute: Entid) -> bool {
matches!(
attribute,
DB_IDENT
| DB_CARDINALITY
| DB_FULLTEXT
| DB_INDEX
| DB_IS_COMPONENT
| DB_UNIQUE
| DB_VALUE_TYPE
)
} }
lazy_static! { lazy_static! {
@ -89,9 +100,8 @@ lazy_static! {
/// Attributes that are "schema related". These might change the "schema" materialized view. /// Attributes that are "schema related". These might change the "schema" materialized view.
pub static ref SCHEMA_SQL_LIST: String = { pub static ref SCHEMA_SQL_LIST: String = {
format!("({}, {}, {}, {}, {}, {}, {})", format!("({}, {}, {}, {}, {}, {})",
DB_CARDINALITY, DB_CARDINALITY,
DB_DOC,
DB_FULLTEXT, DB_FULLTEXT,
DB_INDEX, DB_INDEX,
DB_IS_COMPONENT, DB_IS_COMPONENT,
@ -101,9 +111,8 @@ lazy_static! {
/// Attributes that are "metadata" related. These might change one of the materialized views. /// Attributes that are "metadata" related. These might change one of the materialized views.
pub static ref METADATA_SQL_LIST: String = { pub static ref METADATA_SQL_LIST: String = {
format!("({}, {}, {}, {}, {}, {}, {}, {})", format!("({}, {}, {}, {}, {}, {}, {})",
DB_CARDINALITY, DB_CARDINALITY,
DB_DOC,
DB_FULLTEXT, DB_FULLTEXT,
DB_IDENT, DB_IDENT,
DB_INDEX, DB_INDEX,

View file

@ -1,101 +0,0 @@
// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(dead_code)]
use edn;
use rusqlite;
use mentat_tx_parser;
use types::{Entid, ValueType};
error_chain! {
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links {
Rusqlite(rusqlite::Error);
}
links {
TxParseError(mentat_tx_parser::Error, mentat_tx_parser::ErrorKind);
}
errors {
/// We're just not done yet. Message that the feature is recognized but not yet
/// implemented.
NotYetImplemented(t: String) {
description("not yet implemented")
display("not yet implemented: {}", t)
}
/// We've been given an EDN value that isn't the correct Mentat type.
BadEDNValuePair(value: edn::types::Value, value_type: ValueType) {
description("EDN value is not the expected Mentat value type")
display("EDN value '{}' is not the expected Mentat value type {:?}", value, value_type)
}
/// We've got corrupt data in the SQL store: a value and value_type_tag don't line up.
BadSQLValuePair(value: rusqlite::types::Value, value_type_tag: i32) {
description("bad SQL (value_type_tag, value) pair")
display("bad SQL (value_type_tag, value) pair: ({}, {:?})", value_type_tag, value.data_type())
}
// /// The SQLite store user_version isn't recognized. This could be an old version of Mentat
// /// trying to open a newer version SQLite store; or it could be a corrupt file; or ...
// BadSQLiteStoreVersion(version: i32) {
// description("bad SQL store user_version")
// display("bad SQL store user_version: {}", version)
// }
/// A bootstrap definition couldn't be parsed or installed. This is a programmer error, not
/// a runtime error.
BadBootstrapDefinition(t: String) {
description("bad bootstrap definition")
display("bad bootstrap definition: {}", t)
}
/// A schema assertion couldn't be parsed.
BadSchemaAssertion(t: String) {
description("bad schema assertion")
display("bad schema assertion: {}", t)
}
/// An ident->entid mapping failed.
UnrecognizedIdent(ident: String) {
description("no entid found for ident")
display("no entid found for ident: {}", ident)
}
/// An entid->ident mapping failed.
/// We also use this error if you try to transact an entid that we didn't allocate,
/// in part because we blow the stack in error_chain if we define a new enum!
UnrecognizedEntid(entid: Entid) {
description("unrecognized or no ident found for entid")
display("unrecognized or no ident found for entid: {}", entid)
}
ConflictingDatoms {
description("conflicting datoms in tx")
display("conflicting datoms in tx")
}
UnknownAttribute(attr: Entid) {
description("unknown attribute")
display("unknown attribute for entid: {}", attr)
}
CannotCacheNonUniqueAttributeInReverse(attr: Entid) {
description("cannot reverse-cache non-unique attribute")
display("cannot reverse-cache non-unique attribute: {}", attr)
}
}
}

View file

@ -12,25 +12,113 @@
//! Types used only within the transactor. These should not be exposed outside of this crate. //! Types used only within the transactor. These should not be exposed outside of this crate.
use std::collections::HashMap; use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::rc::Rc;
use mentat_core::KnownEntid; use core_traits::{Attribute, Entid, KnownEntid, TypedValue, ValueType};
use mentat_core::util::Either; use mentat_core::util::Either;
use errors; use edn;
use errors::ErrorKind; use edn::entities;
use types::{ use edn::entities::{EntityPlace, OpType, TempId, TxFunction};
AVMap, use edn::{SpannedValue, ValueAndSpan, ValueRc};
AVPair,
Entid, use crate::schema::SchemaTypeChecking;
TypedValue, use crate::types::{AVMap, AVPair, Schema, TransactableValue};
}; use db_traits::errors;
use mentat_tx::entities::{ use db_traits::errors::{DbErrorKind, Result};
OpType,
TempId, impl TransactableValue for ValueAndSpan {
}; fn into_typed_value(self, schema: &Schema, value_type: ValueType) -> Result<TypedValue> {
schema.to_typed_value(&self, value_type)
}
fn into_entity_place(self) -> Result<EntityPlace<Self>> {
use self::SpannedValue::*;
match self.inner {
Integer(v) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Entid(v))),
Keyword(v) => {
if v.is_namespaced() {
Ok(EntityPlace::Entid(entities::EntidOrIdent::Ident(v)))
} else {
// We only allow namespaced idents.
bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace))
}
}
Text(v) => Ok(EntityPlace::TempId(TempId::External(v).into())),
List(ls) => {
let mut it = ls.iter();
match (it.next().map(|x| &x.inner), it.next(), it.next(), it.next()) {
// Like "(transaction-id)".
(Some(&PlainSymbol(ref op)), None, None, None) => {
Ok(EntityPlace::TxFunction(TxFunction { op: op.clone() }))
}
// Like "(lookup-ref)".
(Some(&PlainSymbol(edn::PlainSymbol(ref s))), Some(a), Some(v), None)
if s == "lookup-ref" =>
{
match a.clone().into_entity_place()? {
EntityPlace::Entid(a) => {
Ok(EntityPlace::LookupRef(entities::LookupRef {
a: entities::AttributePlace::Entid(a),
v: v.clone(),
}))
}
EntityPlace::TempId(_)
| EntityPlace::TxFunction(_)
| EntityPlace::LookupRef(_) => {
bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace))
}
}
}
_ => bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace)),
}
}
Nil | Boolean(_) | Instant(_) | BigInteger(_) | Float(_) | Uuid(_) | PlainSymbol(_)
| NamespacedSymbol(_) | Vector(_) | Set(_) | Map(_) | Bytes(_) => {
bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace))
}
}
}
fn as_tempid(&self) -> Option<TempId> {
self.inner.as_text().cloned().map(TempId::External)
}
}
impl TransactableValue for TypedValue {
fn into_typed_value(self, _schema: &Schema, value_type: ValueType) -> Result<TypedValue> {
if self.value_type() != value_type {
bail!(DbErrorKind::BadValuePair(format!("{:?}", self), value_type));
}
Ok(self)
}
fn into_entity_place(self) -> Result<EntityPlace<Self>> {
match self {
TypedValue::Ref(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Entid(x))),
TypedValue::Keyword(x) => Ok(EntityPlace::Entid(entities::EntidOrIdent::Ident(
(*x).clone(),
))),
TypedValue::String(x) => Ok(EntityPlace::TempId(TempId::External((*x).clone()).into())),
TypedValue::Boolean(_)
| TypedValue::Long(_)
| TypedValue::Double(_)
| TypedValue::Instant(_)
| TypedValue::Uuid(_)
| TypedValue::Bytes(_) => {
bail!(DbErrorKind::InputError(errors::InputError::BadEntityPlace))
}
}
}
fn as_tempid(&self) -> Option<TempId> {
match self {
TypedValue::String(ref s) => Some(TempId::External((**s).clone())),
_ => None,
}
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub enum Term<E, V> { pub enum Term<E, V> {
@ -42,21 +130,22 @@ use self::Either::*;
pub type KnownEntidOr<T> = Either<KnownEntid, T>; pub type KnownEntidOr<T> = Either<KnownEntid, T>;
pub type TypedValueOr<T> = Either<TypedValue, T>; pub type TypedValueOr<T> = Either<TypedValue, T>;
pub type TempIdHandle = Rc<TempId>; pub type TempIdHandle = ValueRc<TempId>;
pub type TempIdMap = HashMap<TempIdHandle, KnownEntid>; pub type TempIdMap = HashMap<TempIdHandle, KnownEntid>;
pub type LookupRef = Rc<AVPair>; pub type LookupRef = ValueRc<AVPair>;
/// Internal representation of an entid on its way to resolution. We either have the simple case (a /// Internal representation of an entid on its way to resolution. We either have the simple case (a
/// numeric entid), a lookup-ref that still needs to be resolved (an atomized [a v] pair), or a temp /// numeric entid), a lookup-ref that still needs to be resolved (an atomized [a v] pair), or a temp
/// ID that needs to be upserted or allocated (an atomized tempid). /// ID that needs to be upserted or allocated (an atomized tempid).
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub enum LookupRefOrTempId { pub enum LookupRefOrTempId {
LookupRef(LookupRef), LookupRef(LookupRef),
TempId(TempIdHandle) TempId(TempIdHandle),
} }
pub type TermWithTempIdsAndLookupRefs = Term<KnownEntidOr<LookupRefOrTempId>, TypedValueOr<LookupRefOrTempId>>; pub type TermWithTempIdsAndLookupRefs =
Term<KnownEntidOr<LookupRefOrTempId>, TypedValueOr<LookupRefOrTempId>>;
pub type TermWithTempIds = Term<KnownEntidOr<TempIdHandle>, TypedValueOr<TempIdHandle>>; pub type TermWithTempIds = Term<KnownEntidOr<TempIdHandle>, TypedValueOr<TempIdHandle>>;
pub type TermWithoutTempIds = Term<KnownEntid, TypedValue>; pub type TermWithoutTempIds = Term<KnownEntid, TypedValue>;
pub type Population = Vec<TermWithTempIds>; pub type Population = Vec<TermWithTempIds>;
@ -73,6 +162,14 @@ impl TermWithTempIds {
} }
} }
impl TermWithoutTempIds {
pub(crate) fn rewrap<A, B>(self) -> Term<KnownEntidOr<A>, TypedValueOr<B>> {
match self {
Term::AddOrRetract(op, n, a, v) => Term::AddOrRetract(op, Left(n), a, Left(v)),
}
}
}
/// Given a `KnownEntidOr` or a `TypedValueOr`, replace any internal `LookupRef` with the entid from /// Given a `KnownEntidOr` or a `TypedValueOr`, replace any internal `LookupRef` with the entid from
/// the given map. Fail if any `LookupRef` cannot be replaced. /// the given map. Fail if any `LookupRef` cannot be replaced.
/// ///
@ -82,17 +179,43 @@ impl TermWithTempIds {
/// The reason for this awkward expression is that we're parameterizing over the _type constructor_ /// The reason for this awkward expression is that we're parameterizing over the _type constructor_
/// (`EntidOr` or `TypedValueOr`), which is not trivial to express in Rust. This only works because /// (`EntidOr` or `TypedValueOr`), which is not trivial to express in Rust. This only works because
/// they're both the same `Result<...>` type with different parameterizations. /// they're both the same `Result<...>` type with different parameterizations.
pub fn replace_lookup_ref<T, U>(lookup_map: &AVMap, desired_or: Either<T, LookupRefOrTempId>, lift: U) -> errors::Result<Either<T, TempIdHandle>> where U: FnOnce(Entid) -> T { pub fn replace_lookup_ref<T, U>(
lookup_map: &AVMap,
desired_or: Either<T, LookupRefOrTempId>,
lift: U,
) -> errors::Result<Either<T, TempIdHandle>>
where
U: FnOnce(Entid) -> T,
{
match desired_or { match desired_or {
Left(desired) => Ok(Left(desired)), // N.b., must unwrap here -- the ::Left types are different! Left(desired) => Ok(Left(desired)), // N.b., must unwrap here -- the ::Left types are different!
Right(other) => { Right(other) => {
match other { match other {
LookupRefOrTempId::TempId(t) => Ok(Right(t)), LookupRefOrTempId::TempId(t) => Ok(Right(t)),
LookupRefOrTempId::LookupRef(av) => lookup_map.get(&*av) LookupRefOrTempId::LookupRef(av) => lookup_map
.map(|x| lift(*x)).map(Left) .get(&*av)
.map(|x| lift(*x))
.map(Left)
// XXX TODO: fix this error kind! // XXX TODO: fix this error kind!
.ok_or_else(|| ErrorKind::UnrecognizedIdent(format!("couldn't lookup [a v]: {:?}", (*av).clone())).into()), .ok_or_else(|| {
DbErrorKind::UnrecognizedIdent(format!(
"couldn't lookup [a v]: {:?}",
(*av).clone()
))
.into()
}),
} }
} }
} }
} }
#[derive(Clone, Debug, Default)]
pub(crate) struct AddAndRetract {
pub(crate) add: BTreeSet<TypedValue>,
pub(crate) retract: BTreeSet<TypedValue>,
}
// A trie-like structure mapping a -> e -> v that prefix compresses and makes uniqueness constraint
// checking more efficient. BTree* for deterministic errors.
pub(crate) type AEVTrie<'schema> =
BTreeMap<(Entid, &'schema Attribute), BTreeMap<Entid, AddAndRetract>>;

View file

@ -8,108 +8,94 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
// Oh, error_chain. extern crate failure;
#![recursion_limit="128"]
#[macro_use]
extern crate error_chain;
extern crate indexmap; extern crate indexmap;
extern crate itertools; extern crate itertools;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate num; #[cfg(feature = "syncable")]
#[macro_use]
extern crate serde_derive;
extern crate petgraph;
extern crate rusqlite; extern crate rusqlite;
extern crate tabwriter; extern crate tabwriter;
extern crate time; extern crate time;
#[macro_use] #[macro_use]
extern crate edn; extern crate edn;
#[macro_use]
extern crate mentat_core; extern crate mentat_core;
extern crate mentat_tx; extern crate db_traits;
extern crate mentat_tx_parser; #[macro_use]
extern crate core_traits;
extern crate mentat_sql;
use std::iter::repeat; use std::iter::repeat;
use itertools::Itertools; use itertools::Itertools;
pub use errors::{Error, ErrorKind, ResultExt, Result}; use db_traits::errors::{DbErrorKind, Result};
#[macro_use]
pub mod debug;
mod add_retract_alter_set; mod add_retract_alter_set;
mod bootstrap;
pub mod cache; pub mod cache;
pub mod db; pub mod db;
mod bootstrap;
pub mod debug;
pub mod entids; pub mod entids;
pub mod errors; pub mod internal_types; // pub because we need them for building entities programmatically.
pub mod internal_types; // pub because we need them for building entities programmatically.
mod metadata; mod metadata;
mod schema; mod schema;
pub mod tx_observer; pub mod timelines;
mod watcher;
mod tx; mod tx;
mod tx_checking;
pub mod tx_observer;
pub mod types; pub mod types;
mod upsert_resolution; mod upsert_resolution;
mod watcher;
// Export these for reference from tests. cfg(test) should work, but doesn't. // Export these for reference from sync code and tests.
// #[cfg(test)] pub use crate::bootstrap::{TX0, USER0, V1_PARTS};
pub use bootstrap::{
TX0,
USER0,
};
pub use schema::{ pub static TIMELINE_MAIN: i64 = 0;
AttributeBuilder,
AttributeValidation, pub use crate::schema::{AttributeBuilder, AttributeValidation};
};
pub use bootstrap::{ pub use crate::bootstrap::CORE_SCHEMA_VERSION;
CORE_SCHEMA_VERSION,
};
use edn::symbols; use edn::symbols;
pub use entids::{ pub use crate::entids::DB_SCHEMA_CORE;
DB_SCHEMA_CORE,
};
pub use db::{ pub use crate::db::{new_connection, TypedSQLValue};
TypedSQLValue,
new_connection,
};
pub use watcher::{ #[cfg(feature = "sqlcipher")]
TransactWatcher, pub use db::{change_encryption_key, new_connection_with_key};
};
pub use tx::{ pub use crate::watcher::TransactWatcher;
transact,
transact_terms,
};
pub use tx_observer::{ pub use crate::tx::{transact, transact_terms};
InProgressObserverTransactWatcher,
TxObservationService,
TxObserver,
};
pub use types::{ pub use crate::tx_observer::{InProgressObserverTransactWatcher, TxObservationService, TxObserver};
AttributeSet,
DB,
PartitionMap,
TxReport,
};
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::NamespacedKeyword> { pub use crate::types::{AttributeSet, Partition, PartitionMap, TransactableValue, DB};
pub fn to_namespaced_keyword(s: &str) -> Result<symbols::Keyword> {
let splits = [':', '/']; let splits = [':', '/'];
let mut i = s.split(&splits[..]); let mut i = s.split(&splits[..]);
let nsk = match (i.next(), i.next(), i.next(), i.next()) { let nsk = match (i.next(), i.next(), i.next(), i.next()) {
(Some(""), Some(namespace), Some(name), None) => Some(symbols::NamespacedKeyword::new(namespace, name)), (Some(""), Some(namespace), Some(name), None) => {
Some(symbols::Keyword::namespaced(namespace, name))
}
_ => None, _ => None,
}; };
// TODO Use custom ErrorKind https://github.com/brson/error-chain/issues/117 nsk.ok_or_else(|| DbErrorKind::NotYetImplemented(format!("InvalidKeyword: {}", s)).into())
nsk.ok_or(ErrorKind::NotYetImplemented(format!("InvalidNamespacedKeyword: {}", s)).into())
} }
/// Prepare an SQL `VALUES` block, like (?, ?, ?), (?, ?, ?). /// Prepare an SQL `VALUES` block, like (?, ?, ?), (?, ?, ?).

View file

@ -24,34 +24,23 @@
//! //!
//! This module recognizes, validates, applies, and reports on these mutations. //! This module recognizes, validates, applies, and reports on these mutations.
use std::collections::{BTreeMap, BTreeSet}; use failure::ResultExt;
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, BTreeSet};
use itertools::Itertools; // For join(). use crate::add_retract_alter_set::AddRetractAlterSet;
use crate::entids;
use add_retract_alter_set::{ use db_traits::errors::{DbErrorKind, Result};
AddRetractAlterSet,
};
use edn::symbols; use edn::symbols;
use entids;
use errors::{
ErrorKind,
Result,
ResultExt,
};
use mentat_core::{
attribute,
Entid,
Schema,
AttributeMap,
TypedValue,
ValueType,
};
use schema::{ use core_traits::{attribute, Entid, TypedValue, ValueType};
AttributeBuilder,
AttributeValidation, use mentat_core::{AttributeMap, Schema};
};
use crate::schema::{AttributeBuilder, AttributeValidation};
use crate::types::EAV;
/// An alteration to an attribute. /// An alteration to an attribute.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
@ -74,7 +63,7 @@ pub enum AttributeAlteration {
/// An alteration to an ident. /// An alteration to an ident.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub enum IdentAlteration { pub enum IdentAlteration {
Ident(symbols::NamespacedKeyword), Ident(symbols::Keyword),
} }
/// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`. /// Summarizes changes to metadata such as a a `Schema` and (in the future) a `PartitionMap`.
@ -93,35 +82,162 @@ pub struct MetadataReport {
impl MetadataReport { impl MetadataReport {
pub fn attributes_did_change(&self) -> bool { pub fn attributes_did_change(&self) -> bool {
!(self.attributes_installed.is_empty() && !(self.attributes_installed.is_empty() && self.attributes_altered.is_empty())
self.attributes_altered.is_empty())
} }
} }
/// Update an 'AttributeMap' in place given two sets of ident and attribute retractions, which
/// together contain enough information to reason about a "schema retraction".
///
/// Schema may only be retracted if all of its necessary attributes are being retracted:
/// - :db/ident, :db/valueType, :db/cardinality.
///
/// Note that this is currently incomplete/flawed:
/// - we're allowing optional attributes to not be retracted and dangle afterwards
///
/// Returns a set of attribute retractions which do not involve schema-defining attributes.
fn update_attribute_map_from_schema_retractions(
attribute_map: &mut AttributeMap,
retractions: Vec<EAV>,
ident_retractions: &BTreeMap<Entid, symbols::Keyword>,
) -> Result<Vec<EAV>> {
// Process retractions of schema attributes first. It's allowed to retract a schema attribute
// if all of the schema-defining schema attributes are being retracted.
// A defining set of attributes is :db/ident, :db/valueType, :db/cardinality.
let mut filtered_retractions = vec![];
let mut suspect_retractions = vec![];
// Filter out sets of schema altering retractions.
let mut eas = BTreeMap::new();
for (e, a, v) in retractions.into_iter() {
if entids::is_a_schema_attribute(a) {
eas.entry(e).or_insert_with(Vec::new).push(a);
suspect_retractions.push((e, a, v));
} else {
filtered_retractions.push((e, a, v));
}
}
// TODO (see https://github.com/mozilla/mentat/issues/796).
// Retraction of idents is allowed, but if an ident names a schema attribute, then we should enforce
// retraction of all of the associated schema attributes.
// Unfortunately, our current in-memory schema representation (namely, how we define an Attribute) is not currently
// rich enough: it lacks distinction between presence and absence, and instead assumes default values.
// Currently, in order to do this enforcement correctly, we'd need to inspect 'datoms'.
// Here is an incorrect way to enforce this. It's incorrect because it prevents us from retracting non-"schema naming" idents.
// for retracted_e in ident_retractions.keys() {
// if !eas.contains_key(retracted_e) {
// bail!(DbErrorKind::BadSchemaAssertion(format!("Retracting :db/ident of a schema without retracting its defining attributes is not permitted.")));
// }
// }
for (e, a, v) in suspect_retractions.into_iter() {
let attributes = eas.get(&e).unwrap();
// Found a set of retractions which negate a schema.
if attributes.contains(&entids::DB_CARDINALITY)
&& attributes.contains(&entids::DB_VALUE_TYPE)
{
// Ensure that corresponding :db/ident is also being retracted at the same time.
if ident_retractions.contains_key(&e) {
// Remove attributes corresponding to retracted attribute.
attribute_map.remove(&e);
} else {
bail!(DbErrorKind::BadSchemaAssertion("Retracting defining attributes of a schema without retracting its :db/ident is not permitted.".to_string()));
}
} else {
filtered_retractions.push((e, a, v));
}
}
Ok(filtered_retractions)
}
/// Update a `AttributeMap` in place from the given `[e a typed_value]` triples. /// Update a `AttributeMap` in place from the given `[e a typed_value]` triples.
/// ///
/// This is suitable for producing a `AttributeMap` from the `schema` materialized view, which does not /// This is suitable for producing a `AttributeMap` from the `schema` materialized view, which does not
/// contain install and alter markers. /// contain install and alter markers.
/// ///
/// Returns a report summarizing the mutations that were applied. /// Returns a report summarizing the mutations that were applied.
pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeMap, assertions: U) -> Result<MetadataReport> pub fn update_attribute_map_from_entid_triples(
where U: IntoIterator<Item=(Entid, Entid, TypedValue)> { attribute_map: &mut AttributeMap,
assertions: Vec<EAV>,
retractions: Vec<EAV>,
) -> Result<MetadataReport> {
fn attribute_builder_to_modify(
attribute_id: Entid,
existing: &AttributeMap,
) -> AttributeBuilder {
existing
.get(&attribute_id)
.map(AttributeBuilder::modify_attribute)
.unwrap_or_else(AttributeBuilder::default)
}
// Group mutations by impacted entid. // Group mutations by impacted entid.
let mut builders: BTreeMap<Entid, AttributeBuilder> = BTreeMap::new(); let mut builders: BTreeMap<Entid, AttributeBuilder> = BTreeMap::new();
for (entid, attr, ref value) in assertions.into_iter() { // For retractions, we start with an attribute builder that's pre-populated with the existing
let builder = builders.entry(entid).or_insert(AttributeBuilder::default()); // attribute values. That allows us to check existing values and unset them.
for (entid, attr, ref value) in retractions {
// TODO: improve error messages throughout. let builder = builders
.entry(entid)
.or_insert_with(|| attribute_builder_to_modify(entid, attribute_map));
match attr { match attr {
entids::DB_DOC => { // You can only retract :db/unique, :db/isComponent; all others must be altered instead
match *value { // of retracted, or are not allowed to change.
TypedValue::String(_) => {}, entids::DB_IS_COMPONENT => {
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/doc \"string value\"] but got [... :db/doc {:?}] for entid {} and attribute {}", value, entid, attr))) match value {
&TypedValue::Boolean(v) if builder.component == Some(v) => {
builder.component(false);
},
v => {
bail!(DbErrorKind::BadSchemaAssertion(format!("Attempted to retract :db/isComponent with the wrong value {:?}.", v)));
},
} }
}, },
entids::DB_UNIQUE => {
match *value {
TypedValue::Ref(u) => {
match u {
entids::DB_UNIQUE_VALUE if builder.unique == Some(Some(attribute::Unique::Value)) => {
builder.non_unique();
},
entids::DB_UNIQUE_IDENTITY if builder.unique == Some(Some(attribute::Unique::Identity)) => {
builder.non_unique();
},
v => {
bail!(DbErrorKind::BadSchemaAssertion(format!("Attempted to retract :db/unique with the wrong value {}.", v)));
},
}
},
_ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [:db/retract _ :db/unique :db.unique/_] but got [:db/retract {} :db/unique {:?}]", entid, value)))
}
},
entids::DB_VALUE_TYPE |
entids::DB_CARDINALITY |
entids::DB_INDEX |
entids::DB_FULLTEXT |
entids::DB_NO_HISTORY => {
bail!(DbErrorKind::BadSchemaAssertion(format!("Retracting attribute {} for entity {} not permitted.", attr, entid)));
},
_ => {
bail!(DbErrorKind::BadSchemaAssertion(format!("Do not recognize attribute {} for entid {}", attr, entid)))
}
}
}
for (entid, attr, ref value) in assertions.into_iter() {
// For assertions, we can start with an empty attribute builder.
let builder = builders.entry(entid).or_insert_with(Default::default);
// TODO: improve error messages throughout.
match attr {
entids::DB_VALUE_TYPE => { entids::DB_VALUE_TYPE => {
match *value { match *value {
TypedValue::Ref(entids::DB_TYPE_BOOLEAN) => { builder.value_type(ValueType::Boolean); }, TypedValue::Ref(entids::DB_TYPE_BOOLEAN) => { builder.value_type(ValueType::Boolean); },
@ -132,7 +248,8 @@ pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeM
TypedValue::Ref(entids::DB_TYPE_REF) => { builder.value_type(ValueType::Ref); }, TypedValue::Ref(entids::DB_TYPE_REF) => { builder.value_type(ValueType::Ref); },
TypedValue::Ref(entids::DB_TYPE_STRING) => { builder.value_type(ValueType::String); }, TypedValue::Ref(entids::DB_TYPE_STRING) => { builder.value_type(ValueType::String); },
TypedValue::Ref(entids::DB_TYPE_UUID) => { builder.value_type(ValueType::Uuid); }, TypedValue::Ref(entids::DB_TYPE_UUID) => { builder.value_type(ValueType::Uuid); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/valueType :db.type/*] but got [... :db/valueType {:?}] for entid {} and attribute {}", value, entid, attr))) TypedValue::Ref(entids::DB_TYPE_BYTES) => { builder.value_type(ValueType::Bytes); },
_ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/valueType :db.type/*] but got [... :db/valueType {:?}] for entid {} and attribute {}", value, entid, attr)))
} }
}, },
@ -140,56 +257,51 @@ pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeM
match *value { match *value {
TypedValue::Ref(entids::DB_CARDINALITY_MANY) => { builder.multival(true); }, TypedValue::Ref(entids::DB_CARDINALITY_MANY) => { builder.multival(true); },
TypedValue::Ref(entids::DB_CARDINALITY_ONE) => { builder.multival(false); }, TypedValue::Ref(entids::DB_CARDINALITY_ONE) => { builder.multival(false); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/cardinality :db.cardinality/many|:db.cardinality/one] but got [... :db/cardinality {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/cardinality :db.cardinality/many|:db.cardinality/one] but got [... :db/cardinality {:?}]", value)))
} }
}, },
entids::DB_UNIQUE => { entids::DB_UNIQUE => {
match *value { match *value {
// TODO: accept nil in some form.
// TypedValue::Nil => {
// builder.unique_value(false);
// builder.unique_identity(false);
// },
TypedValue::Ref(entids::DB_UNIQUE_VALUE) => { builder.unique(attribute::Unique::Value); }, TypedValue::Ref(entids::DB_UNIQUE_VALUE) => { builder.unique(attribute::Unique::Value); },
TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => { builder.unique(attribute::Unique::Identity); }, TypedValue::Ref(entids::DB_UNIQUE_IDENTITY) => { builder.unique(attribute::Unique::Identity); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/unique :db.unique/value|:db.unique/identity] but got [... :db/unique {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/unique :db.unique/value|:db.unique/identity] but got [... :db/unique {:?}]", value)))
} }
}, },
entids::DB_INDEX => { entids::DB_INDEX => {
match *value { match *value {
TypedValue::Boolean(x) => { builder.index(x); }, TypedValue::Boolean(x) => { builder.index(x); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/index true|false] but got [... :db/index {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/index true|false] but got [... :db/index {:?}]", value)))
} }
}, },
entids::DB_FULLTEXT => { entids::DB_FULLTEXT => {
match *value { match *value {
TypedValue::Boolean(x) => { builder.fulltext(x); }, TypedValue::Boolean(x) => { builder.fulltext(x); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/fulltext true|false] but got [... :db/fulltext {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/fulltext true|false] but got [... :db/fulltext {:?}]", value)))
} }
}, },
entids::DB_IS_COMPONENT => { entids::DB_IS_COMPONENT => {
match *value { match *value {
TypedValue::Boolean(x) => { builder.component(x); }, TypedValue::Boolean(x) => { builder.component(x); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/isComponent true|false] but got [... :db/isComponent {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/isComponent true|false] but got [... :db/isComponent {:?}]", value)))
} }
}, },
entids::DB_NO_HISTORY => { entids::DB_NO_HISTORY => {
match *value { match *value {
TypedValue::Boolean(x) => { builder.no_history(x); }, TypedValue::Boolean(x) => { builder.no_history(x); },
_ => bail!(ErrorKind::BadSchemaAssertion(format!("Expected [... :db/noHistory true|false] but got [... :db/noHistory {:?}]", value))) _ => bail!(DbErrorKind::BadSchemaAssertion(format!("Expected [... :db/noHistory true|false] but got [... :db/noHistory {:?}]", value)))
} }
}, },
_ => { _ => {
bail!(ErrorKind::BadSchemaAssertion(format!("Do not recognize attribute {} for entid {}", attr, entid))) bail!(DbErrorKind::BadSchemaAssertion(format!("Do not recognize attribute {} for entid {}", attr, entid)))
} }
} }
}; }
let mut attributes_installed: BTreeSet<Entid> = BTreeSet::default(); let mut attributes_installed: BTreeSet<Entid> = BTreeSet::default();
let mut attributes_altered: BTreeMap<Entid, Vec<AttributeAlteration>> = BTreeMap::default(); let mut attributes_altered: BTreeMap<Entid, Vec<AttributeAlteration>> = BTreeMap::default();
@ -198,28 +310,36 @@ pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeM
match attribute_map.entry(entid) { match attribute_map.entry(entid) {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
// Validate once… // Validate once…
builder.validate_install_attribute() builder
.chain_err(|| ErrorKind::BadSchemaAssertion(format!("Schema alteration for new attribute with entid {} is not valid", entid)))?; .validate_install_attribute()
.context(DbErrorKind::BadSchemaAssertion(format!(
"Schema alteration for new attribute with entid {} is not valid",
entid
)))?;
// … and twice, now we have the Attribute. // … and twice, now we have the Attribute.
let a = builder.build(); let a = builder.build();
a.validate(|| entid.to_string())?; a.validate(|| entid.to_string())?;
entry.insert(builder.build()); entry.insert(a);
attributes_installed.insert(entid); attributes_installed.insert(entid);
}, }
Entry::Occupied(mut entry) => { Entry::Occupied(mut entry) => {
builder.validate_alter_attribute() builder
.chain_err(|| ErrorKind::BadSchemaAssertion(format!("Schema alteration for existing attribute with entid {} is not valid", entid)))?; .validate_alter_attribute()
.context(DbErrorKind::BadSchemaAssertion(format!(
"Schema alteration for existing attribute with entid {} is not valid",
entid
)))?;
let mutations = builder.mutate(entry.get_mut()); let mutations = builder.mutate(entry.get_mut());
attributes_altered.insert(entid, mutations); attributes_altered.insert(entid, mutations);
}, }
} }
} }
Ok(MetadataReport { Ok(MetadataReport {
attributes_installed: attributes_installed, attributes_installed,
attributes_altered: attributes_altered, attributes_altered,
idents_altered: BTreeMap::default(), idents_altered: BTreeMap::default(),
}) })
} }
@ -232,22 +352,27 @@ pub fn update_attribute_map_from_entid_triples<U>(attribute_map: &mut AttributeM
/// This is suitable for mutating a `Schema` from an applied transaction. /// This is suitable for mutating a `Schema` from an applied transaction.
/// ///
/// Returns a report summarizing the mutations that were applied. /// Returns a report summarizing the mutations that were applied.
pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U) -> Result<MetadataReport> pub fn update_schema_from_entid_quadruples<U>(
where U: IntoIterator<Item=(Entid, Entid, TypedValue, bool)> { schema: &mut Schema,
assertions: U,
) -> Result<MetadataReport>
where
U: IntoIterator<Item = (Entid, Entid, TypedValue, bool)>,
{
// Group attribute assertions into asserted, retracted, and updated. We assume all our // Group attribute assertions into asserted, retracted, and updated. We assume all our
// attribute assertions are :db/cardinality :db.cardinality/one (so they'll only be added or // attribute assertions are :db/cardinality :db.cardinality/one (so they'll only be added or
// retracted at most once), which means all attribute alterations are simple changes from an old // retracted at most once), which means all attribute alterations are simple changes from an old
// value to a new value. // value to a new value.
let mut attribute_set: AddRetractAlterSet<(Entid, Entid), TypedValue> = AddRetractAlterSet::default(); let mut attribute_set: AddRetractAlterSet<(Entid, Entid), TypedValue> =
let mut ident_set: AddRetractAlterSet<Entid, symbols::NamespacedKeyword> = AddRetractAlterSet::default(); AddRetractAlterSet::default();
let mut ident_set: AddRetractAlterSet<Entid, symbols::Keyword> = AddRetractAlterSet::default();
for (e, a, typed_value, added) in assertions.into_iter() { for (e, a, typed_value, added) in assertions.into_iter() {
// Here we handle :db/ident assertions. // Here we handle :db/ident assertions.
if a == entids::DB_IDENT { if a == entids::DB_IDENT {
if let TypedValue::Keyword(ref keyword) = typed_value { if let TypedValue::Keyword(ref keyword) = typed_value {
ident_set.witness(e, keyword.as_ref().clone(), added); ident_set.witness(e, keyword.as_ref().clone(), added);
continue continue;
} else { } else {
// Something is terribly wrong: the schema ensures we have a keyword. // Something is terribly wrong: the schema ensures we have a keyword.
unreachable!(); unreachable!();
@ -257,17 +382,34 @@ pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U
attribute_set.witness((e, a), typed_value, added); attribute_set.witness((e, a), typed_value, added);
} }
// Datomic does not allow to retract attributes or idents. For now, Mentat follows suit.
if !attribute_set.retracted.is_empty() {
bail!(ErrorKind::NotYetImplemented(format!("Retracting metadata attribute assertions not yet implemented: retracted [e a] pairs [{}]",
attribute_set.retracted.keys().map(|&(e, a)| format!("[{} {}]", e, a)).join(", "))));
}
// Collect triples. // Collect triples.
let asserted_triples = attribute_set.asserted.into_iter().map(|((e, a), typed_value)| (e, a, typed_value)); let retracted_triples = attribute_set
let altered_triples = attribute_set.altered.into_iter().map(|((e, a), (_old_value, new_value))| (e, a, new_value)); .retracted
.into_iter()
.map(|((e, a), typed_value)| (e, a, typed_value));
let asserted_triples = attribute_set
.asserted
.into_iter()
.map(|((e, a), typed_value)| (e, a, typed_value));
let altered_triples = attribute_set
.altered
.into_iter()
.map(|((e, a), (_old_value, new_value))| (e, a, new_value));
let report = update_attribute_map_from_entid_triples(&mut schema.attribute_map, asserted_triples.chain(altered_triples))?; // First we process retractions which remove schema.
// This operation consumes our current list of attribute retractions, producing a filtered one.
let non_schema_retractions = update_attribute_map_from_schema_retractions(
&mut schema.attribute_map,
retracted_triples.collect(),
&ident_set.retracted,
)?;
// Now we process all other retractions.
let report = update_attribute_map_from_entid_triples(
&mut schema.attribute_map,
asserted_triples.chain(altered_triples).collect(),
non_schema_retractions,
)?;
let mut idents_altered: BTreeMap<Entid, IdentAlteration> = BTreeMap::new(); let mut idents_altered: BTreeMap<Entid, IdentAlteration> = BTreeMap::new();
@ -285,18 +427,25 @@ pub fn update_schema_from_entid_quadruples<U>(schema: &mut Schema, assertions: U
idents_altered.insert(entid, IdentAlteration::Ident(new_ident.clone())); idents_altered.insert(entid, IdentAlteration::Ident(new_ident.clone()));
} }
for (entid, ident) in ident_set.retracted { for (entid, ident) in &ident_set.retracted {
schema.entid_map.remove(&entid); schema.entid_map.remove(entid);
schema.ident_map.remove(&ident); schema.ident_map.remove(ident);
idents_altered.insert(entid, IdentAlteration::Ident(ident.clone())); idents_altered.insert(*entid, IdentAlteration::Ident(ident.clone()));
} }
if report.attributes_did_change() { // Component attributes need to change if either:
// - a component attribute changed
// - a schema attribute that was a component was retracted
// These two checks are a rather heavy-handed way of keeping schema's
// component_attributes up-to-date: most of the time we'll rebuild it
// even though it's not necessary (e.g. a schema attribute that's _not_
// a component was removed, or a non-component related attribute changed).
if report.attributes_did_change() || !ident_set.retracted.is_empty() {
schema.update_component_attributes(); schema.update_component_attributes();
} }
Ok(MetadataReport { Ok(MetadataReport {
idents_altered: idents_altered, idents_altered,
.. report ..report
}) })
} }

View file

@ -10,48 +10,57 @@
#![allow(dead_code)] #![allow(dead_code)]
use db::TypedSQLValue; use crate::db::TypedSQLValue;
use db_traits::errors::{DbErrorKind, Result};
use edn; use edn;
use errors::{ErrorKind, Result};
use edn::symbols; use edn::symbols;
use mentat_core::{
attribute, use core_traits::{attribute, Attribute, Entid, KnownEntid, TypedValue, ValueType};
Attribute,
Entid, use crate::metadata;
EntidMap, use crate::metadata::AttributeAlteration;
HasSchema, use mentat_core::{AttributeMap, EntidMap, HasSchema, IdentMap, Schema};
IdentMap,
KnownEntid,
Schema,
AttributeMap,
TypedValue,
ValueType,
};
use metadata;
use metadata::{
AttributeAlteration,
};
pub trait AttributeValidation { pub trait AttributeValidation {
fn validate<F>(&self, ident: F) -> Result<()> where F: Fn() -> String; fn validate<F>(&self, ident: F) -> Result<()>
where
F: Fn() -> String;
} }
impl AttributeValidation for Attribute { impl AttributeValidation for Attribute {
fn validate<F>(&self, ident: F) -> Result<()> where F: Fn() -> String { fn validate<F>(&self, ident: F) -> Result<()>
where
F: Fn() -> String,
{
if self.unique == Some(attribute::Unique::Value) && !self.index { if self.unique == Some(attribute::Unique::Value) && !self.index {
bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_value without :db/index true for entid: {}", ident()))) bail!(DbErrorKind::BadSchemaAssertion(format!(
":db/unique :db/unique_value without :db/index true for entid: {}",
ident()
)))
} }
if self.unique == Some(attribute::Unique::Identity) && !self.index { if self.unique == Some(attribute::Unique::Identity) && !self.index {
bail!(ErrorKind::BadSchemaAssertion(format!(":db/unique :db/unique_identity without :db/index true for entid: {}", ident()))) bail!(DbErrorKind::BadSchemaAssertion(format!(
":db/unique :db/unique_identity without :db/index true for entid: {}",
ident()
)))
} }
if self.fulltext && self.value_type != ValueType::String { if self.fulltext && self.value_type != ValueType::String {
bail!(ErrorKind::BadSchemaAssertion(format!(":db/fulltext true without :db/valueType :db.type/string for entid: {}", ident()))) bail!(DbErrorKind::BadSchemaAssertion(format!(
":db/fulltext true without :db/valueType :db.type/string for entid: {}",
ident()
)))
} }
if self.fulltext && !self.index { if self.fulltext && !self.index {
bail!(ErrorKind::BadSchemaAssertion(format!(":db/fulltext true without :db/index true for entid: {}", ident()))) bail!(DbErrorKind::BadSchemaAssertion(format!(
":db/fulltext true without :db/index true for entid: {}",
ident()
)))
} }
if self.component && self.value_type != ValueType::Ref { if self.component && self.value_type != ValueType::Ref {
bail!(ErrorKind::BadSchemaAssertion(format!(":db/isComponent true without :db/valueType :db.type/ref for entid: {}", ident()))) bail!(DbErrorKind::BadSchemaAssertion(format!(
":db/isComponent true without :db/valueType :db.type/ref for entid: {}",
ident()
)))
} }
// TODO: consider warning if we have :db/index true for :db/valueType :db.type/string, // TODO: consider warning if we have :db/index true for :db/valueType :db.type/string,
// since this may be inefficient. More generally, we should try to drive complex // since this may be inefficient. More generally, we should try to drive complex
@ -64,22 +73,27 @@ impl AttributeValidation for Attribute {
/// Return `Ok(())` if `attribute_map` defines a valid Mentat schema. /// Return `Ok(())` if `attribute_map` defines a valid Mentat schema.
fn validate_attribute_map(entid_map: &EntidMap, attribute_map: &AttributeMap) -> Result<()> { fn validate_attribute_map(entid_map: &EntidMap, attribute_map: &AttributeMap) -> Result<()> {
for (entid, attribute) in attribute_map { for (entid, attribute) in attribute_map {
let ident = || entid_map.get(entid).map(|ident| ident.to_string()).unwrap_or(entid.to_string()); let ident = || {
entid_map
.get(entid)
.map(|ident| ident.to_string())
.unwrap_or_else(|| entid.to_string())
};
attribute.validate(ident)?; attribute.validate(ident)?;
} }
Ok(()) Ok(())
} }
#[derive(Clone,Debug,Default,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub struct AttributeBuilder { pub struct AttributeBuilder {
helpful: bool, helpful: bool,
value_type: Option<ValueType>, pub value_type: Option<ValueType>,
multival: Option<bool>, pub multival: Option<bool>,
unique: Option<Option<attribute::Unique>>, pub unique: Option<Option<attribute::Unique>>,
index: Option<bool>, pub index: Option<bool>,
fulltext: Option<bool>, pub fulltext: Option<bool>,
component: Option<bool>, pub component: Option<bool>,
no_history: Option<bool>, pub no_history: Option<bool>,
} }
impl AttributeBuilder { impl AttributeBuilder {
@ -92,17 +106,32 @@ impl AttributeBuilder {
} }
} }
pub fn value_type<'a>(&'a mut self, value_type: ValueType) -> &'a mut Self { /// Make a new AttributeBuilder from an existing Attribute. This is important to allow
/// retraction. Only attributes that we allow to change are duplicated here.
pub fn modify_attribute(attribute: &Attribute) -> Self {
let mut ab = AttributeBuilder::default();
ab.multival = Some(attribute.multival);
ab.unique = Some(attribute.unique);
ab.component = Some(attribute.component);
ab
}
pub fn value_type(&mut self, value_type: ValueType) -> &mut Self {
self.value_type = Some(value_type); self.value_type = Some(value_type);
self self
} }
pub fn multival<'a>(&'a mut self, multival: bool) -> &'a mut Self { pub fn multival(&mut self, multival: bool) -> &mut Self {
self.multival = Some(multival); self.multival = Some(multival);
self self
} }
pub fn unique<'a>(&'a mut self, unique: attribute::Unique) -> &'a mut Self { pub fn non_unique(&mut self) -> &mut Self {
self.unique = Some(None);
self
}
pub fn unique(&mut self, unique: attribute::Unique) -> &mut Self {
if self.helpful && unique == attribute::Unique::Identity { if self.helpful && unique == attribute::Unique::Identity {
self.index = Some(true); self.index = Some(true);
} }
@ -110,12 +139,12 @@ impl AttributeBuilder {
self self
} }
pub fn index<'a>(&'a mut self, index: bool) -> &'a mut Self { pub fn index(&mut self, index: bool) -> &mut Self {
self.index = Some(index); self.index = Some(index);
self self
} }
pub fn fulltext<'a>(&'a mut self, fulltext: bool) -> &'a mut Self { pub fn fulltext(&mut self, fulltext: bool) -> &mut Self {
self.fulltext = Some(fulltext); self.fulltext = Some(fulltext);
if self.helpful && fulltext { if self.helpful && fulltext {
self.index = Some(true); self.index = Some(true);
@ -123,29 +152,35 @@ impl AttributeBuilder {
self self
} }
pub fn component<'a>(&'a mut self, component: bool) -> &'a mut Self { pub fn component(&mut self, component: bool) -> &mut Self {
self.component = Some(component); self.component = Some(component);
self self
} }
pub fn no_history<'a>(&'a mut self, no_history: bool) -> &'a mut Self { pub fn no_history(&mut self, no_history: bool) -> &mut Self {
self.no_history = Some(no_history); self.no_history = Some(no_history);
self self
} }
pub fn validate_install_attribute(&self) -> Result<()> { pub fn validate_install_attribute(&self) -> Result<()> {
if self.value_type.is_none() { if self.value_type.is_none() {
bail!(ErrorKind::BadSchemaAssertion("Schema attribute for new attribute does not set :db/valueType".into())); bail!(DbErrorKind::BadSchemaAssertion(
"Schema attribute for new attribute does not set :db/valueType".into()
));
} }
Ok(()) Ok(())
} }
pub fn validate_alter_attribute(&self) -> Result<()> { pub fn validate_alter_attribute(&self) -> Result<()> {
if self.value_type.is_some() { if self.value_type.is_some() {
bail!(ErrorKind::BadSchemaAssertion("Schema alteration must not set :db/valueType".into())); bail!(DbErrorKind::BadSchemaAssertion(
"Schema alteration must not set :db/valueType".into()
));
} }
if self.fulltext.is_some() { if self.fulltext.is_some() {
bail!(ErrorKind::BadSchemaAssertion("Schema alteration must not set :db/fulltext".into())); bail!(DbErrorKind::BadSchemaAssertion(
"Schema alteration must not set :db/fulltext".into()
));
} }
Ok(()) Ok(())
} }
@ -162,7 +197,7 @@ impl AttributeBuilder {
attribute.multival = multival; attribute.multival = multival;
} }
if let Some(ref unique) = self.unique { if let Some(ref unique) = self.unique {
attribute.unique = unique.clone(); attribute.unique = *unique;
} }
if let Some(index) = self.index { if let Some(index) = self.index {
attribute.index = index; attribute.index = index;
@ -185,12 +220,17 @@ impl AttributeBuilder {
mutations.push(AttributeAlteration::Cardinality); mutations.push(AttributeAlteration::Cardinality);
} }
} }
if let Some(ref unique) = self.unique { if let Some(ref unique) = self.unique {
if *unique != attribute.unique { if *unique != attribute.unique {
attribute.unique = unique.clone(); attribute.unique = *unique;
mutations.push(AttributeAlteration::Unique); mutations.push(AttributeAlteration::Unique);
} }
} else if attribute.unique != None {
attribute.unique = None;
mutations.push(AttributeAlteration::Unique);
} }
if let Some(index) = self.index { if let Some(index) = self.index {
if index != attribute.index { if index != attribute.index {
attribute.index = index; attribute.index = index;
@ -215,47 +255,71 @@ impl AttributeBuilder {
} }
pub trait SchemaBuilding { pub trait SchemaBuilding {
fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword>; fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword>;
fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result<KnownEntid>; fn require_entid(&self, ident: &symbols::Keyword) -> Result<KnownEntid>;
fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>; fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute>;
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema>; fn from_ident_map_and_attribute_map(
ident_map: IdentMap,
attribute_map: AttributeMap,
) -> Result<Schema>;
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema> fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
where U: IntoIterator<Item=(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>; where
U: IntoIterator<Item = (symbols::Keyword, symbols::Keyword, TypedValue)>;
} }
impl SchemaBuilding for Schema { impl SchemaBuilding for Schema {
fn require_ident(&self, entid: Entid) -> Result<&symbols::NamespacedKeyword> { fn require_ident(&self, entid: Entid) -> Result<&symbols::Keyword> {
self.get_ident(entid).ok_or(ErrorKind::UnrecognizedEntid(entid).into()) self.get_ident(entid)
.ok_or_else(|| DbErrorKind::UnrecognizedEntid(entid).into())
} }
fn require_entid(&self, ident: &symbols::NamespacedKeyword) -> Result<KnownEntid> { fn require_entid(&self, ident: &symbols::Keyword) -> Result<KnownEntid> {
self.get_entid(&ident).ok_or(ErrorKind::UnrecognizedIdent(ident.to_string()).into()) self.get_entid(&ident)
.ok_or_else(|| DbErrorKind::UnrecognizedIdent(ident.to_string()).into())
} }
fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute> { fn require_attribute_for_entid(&self, entid: Entid) -> Result<&Attribute> {
self.attribute_for_entid(entid).ok_or(ErrorKind::UnrecognizedEntid(entid).into()) self.attribute_for_entid(entid)
.ok_or_else(|| DbErrorKind::UnrecognizedEntid(entid).into())
} }
/// Create a valid `Schema` from the constituent maps. /// Create a valid `Schema` from the constituent maps.
fn from_ident_map_and_attribute_map(ident_map: IdentMap, attribute_map: AttributeMap) -> Result<Schema> { fn from_ident_map_and_attribute_map(
let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (v.clone(), k.clone())).collect(); ident_map: IdentMap,
attribute_map: AttributeMap,
) -> Result<Schema> {
let entid_map: EntidMap = ident_map.iter().map(|(k, v)| (*v, k.clone())).collect();
validate_attribute_map(&entid_map, &attribute_map)?; validate_attribute_map(&entid_map, &attribute_map)?;
Ok(Schema::new(ident_map, entid_map, attribute_map)) Ok(Schema::new(ident_map, entid_map, attribute_map))
} }
/// Turn vec![(NamespacedKeyword(:ident), NamespacedKeyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`. /// Turn vec![(Keyword(:ident), Keyword(:key), TypedValue(:value)), ...] into a Mentat `Schema`.
fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema> fn from_ident_map_and_triples<U>(ident_map: IdentMap, assertions: U) -> Result<Schema>
where U: IntoIterator<Item=(symbols::NamespacedKeyword, symbols::NamespacedKeyword, TypedValue)>{ where
U: IntoIterator<Item = (symbols::Keyword, symbols::Keyword, TypedValue)>,
{
let entid_assertions: Result<Vec<(Entid, Entid, TypedValue)>> = assertions
.into_iter()
.map(|(symbolic_ident, symbolic_attr, value)| {
let ident: i64 = *ident_map
.get(&symbolic_ident)
.ok_or_else(|| DbErrorKind::UnrecognizedIdent(symbolic_ident.to_string()))?;
let attr: i64 = *ident_map
.get(&symbolic_attr)
.ok_or_else(|| DbErrorKind::UnrecognizedIdent(symbolic_attr.to_string()))?;
Ok((ident, attr, value))
})
.collect();
let entid_assertions: Result<Vec<(Entid, Entid, TypedValue)>> = assertions.into_iter().map(|(symbolic_ident, symbolic_attr, value)| { let mut schema =
let ident: i64 = *ident_map.get(&symbolic_ident).ok_or(ErrorKind::UnrecognizedIdent(symbolic_ident.to_string()))?; Schema::from_ident_map_and_attribute_map(ident_map, AttributeMap::default())?;
let attr: i64 = *ident_map.get(&symbolic_attr).ok_or(ErrorKind::UnrecognizedIdent(symbolic_attr.to_string()))?; let metadata_report = metadata::update_attribute_map_from_entid_triples(
Ok((ident, attr, value)) &mut schema.attribute_map,
}).collect(); entid_assertions?,
// No retractions.
let mut schema = Schema::from_ident_map_and_attribute_map(ident_map, AttributeMap::default())?; vec![],
let metadata_report = metadata::update_attribute_map_from_entid_triples(&mut schema.attribute_map, entid_assertions?)?; )?;
// Rebuild the component attributes list if necessary. // Rebuild the component attributes list if necessary.
if metadata_report.attributes_did_change() { if metadata_report.attributes_did_change() {
@ -270,17 +334,25 @@ pub trait SchemaTypeChecking {
/// ///
/// Either assert that the given value is in the value type's value set, or (in limited cases) /// Either assert that the given value is in the value type's value set, or (in limited cases)
/// coerce the given value into the value type's value set. /// coerce the given value into the value type's value set.
fn to_typed_value(&self, value: &edn::Value, value_type: ValueType) -> Result<TypedValue>; fn to_typed_value(
&self,
value: &edn::ValueAndSpan,
value_type: ValueType,
) -> Result<TypedValue>;
} }
impl SchemaTypeChecking for Schema { impl SchemaTypeChecking for Schema {
fn to_typed_value(&self, value: &edn::Value, value_type: ValueType) -> Result<TypedValue> { fn to_typed_value(
&self,
value: &edn::ValueAndSpan,
value_type: ValueType,
) -> Result<TypedValue> {
// TODO: encapsulate entid-ident-attribute for better error messages, perhaps by including // TODO: encapsulate entid-ident-attribute for better error messages, perhaps by including
// the attribute (rather than just the attribute's value type) into this function or a // the attribute (rather than just the attribute's value type) into this function or a
// wrapper function. // wrapper function.
match TypedValue::from_edn_value(value) { match TypedValue::from_edn_value(&value.clone().without_spans()) {
// We don't recognize this EDN at all. Get out! // We don't recognize this EDN at all. Get out!
None => bail!(ErrorKind::BadEDNValuePair(value.clone(), value_type)), None => bail!(DbErrorKind::BadValuePair(format!("{}", value), value_type)),
Some(typed_value) => match (value_type, typed_value) { Some(typed_value) => match (value_type, typed_value) {
// Most types don't coerce at all. // Most types don't coerce at all.
(ValueType::Boolean, tv @ TypedValue::Boolean(_)) => Ok(tv), (ValueType::Boolean, tv @ TypedValue::Boolean(_)) => Ok(tv),
@ -290,43 +362,41 @@ impl SchemaTypeChecking for Schema {
(ValueType::Uuid, tv @ TypedValue::Uuid(_)) => Ok(tv), (ValueType::Uuid, tv @ TypedValue::Uuid(_)) => Ok(tv),
(ValueType::Instant, tv @ TypedValue::Instant(_)) => Ok(tv), (ValueType::Instant, tv @ TypedValue::Instant(_)) => Ok(tv),
(ValueType::Keyword, tv @ TypedValue::Keyword(_)) => Ok(tv), (ValueType::Keyword, tv @ TypedValue::Keyword(_)) => Ok(tv),
(ValueType::Bytes, tv @ TypedValue::Bytes(_)) => Ok(tv),
// Ref coerces a little: we interpret some things depending on the schema as a Ref. // Ref coerces a little: we interpret some things depending on the schema as a Ref.
(ValueType::Ref, TypedValue::Long(x)) => Ok(TypedValue::Ref(x)), (ValueType::Ref, TypedValue::Long(x)) => Ok(TypedValue::Ref(x)),
(ValueType::Ref, TypedValue::Keyword(ref x)) => self.require_entid(&x).map(|entid| entid.into()), (ValueType::Ref, TypedValue::Keyword(ref x)) => {
self.require_entid(&x).map(|entid| entid.into())
}
// Otherwise, we have a type mismatch. // Otherwise, we have a type mismatch.
// Enumerate all of the types here to allow the compiler to help us. // Enumerate all of the types here to allow the compiler to help us.
// We don't enumerate all `TypedValue` cases, though: that would multiply this // We don't enumerate all `TypedValue` cases, though: that would multiply this
// collection by 8! // collection by 8!
(vt @ ValueType::Boolean, _) | (vt @ ValueType::Boolean, _)
(vt @ ValueType::Long, _) | | (vt @ ValueType::Long, _)
(vt @ ValueType::Double, _) | | (vt @ ValueType::Double, _)
(vt @ ValueType::String, _) | | (vt @ ValueType::String, _)
(vt @ ValueType::Uuid, _) | | (vt @ ValueType::Uuid, _)
(vt @ ValueType::Instant, _) | | (vt @ ValueType::Instant, _)
(vt @ ValueType::Keyword, _) | | (vt @ ValueType::Keyword, _)
(vt @ ValueType::Ref, _) | (vt @ ValueType::Bytes, _)
=> bail!(ErrorKind::BadEDNValuePair(value.clone(), vt)), | (vt @ ValueType::Ref, _) => {
} bail!(DbErrorKind::BadValuePair(format!("{}", value), vt))
}
},
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use self::edn::Keyword;
use super::*; use super::*;
use self::edn::NamespacedKeyword;
use errors::Error;
fn add_attribute(schema: &mut Schema,
ident: NamespacedKeyword,
entid: Entid,
attribute: Attribute) {
fn add_attribute(schema: &mut Schema, ident: Keyword, entid: Entid, attribute: Attribute) {
schema.entid_map.insert(entid, ident.clone()); schema.entid_map.insert(entid, ident.clone());
schema.ident_map.insert(ident.clone(), entid); schema.ident_map.insert(ident, entid);
if attribute.component { if attribute.component {
schema.component_attributes.push(entid); schema.component_attributes.push(entid);
@ -339,55 +409,80 @@ mod test {
fn validate_attribute_map_success() { fn validate_attribute_map_success() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute that is not an index has no uniqueness // attribute that is not an index has no uniqueness
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 97, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::Boolean, Keyword::namespaced("foo", "bar"),
fulltext: false, 97,
unique: None, Attribute {
multival: false, index: false,
component: false, value_type: ValueType::Boolean,
no_history: false, fulltext: false,
}); unique: None,
multival: false,
component: false,
no_history: false,
},
);
// attribute is unique by value and an index // attribute is unique by value and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "baz"), 98, Attribute { add_attribute(
index: true, &mut schema,
value_type: ValueType::Long, Keyword::namespaced("foo", "baz"),
fulltext: false, 98,
unique: Some(attribute::Unique::Value), Attribute {
multival: false, index: true,
component: false, value_type: ValueType::Long,
no_history: false, fulltext: false,
}); unique: Some(attribute::Unique::Value),
multival: false,
component: false,
no_history: false,
},
);
// attribue is unique by identity and an index // attribue is unique by identity and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bat"), 99, Attribute { add_attribute(
index: true, &mut schema,
value_type: ValueType::Ref, Keyword::namespaced("foo", "bat"),
fulltext: false, 99,
unique: Some(attribute::Unique::Identity), Attribute {
multival: false, index: true,
component: false, value_type: ValueType::Ref,
no_history: false, fulltext: false,
}); unique: Some(attribute::Unique::Identity),
multival: false,
component: false,
no_history: false,
},
);
// attribute is a components and a `Ref` // attribute is a components and a `Ref`
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bak"), 100, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::Ref, Keyword::namespaced("foo", "bak"),
fulltext: false, 100,
unique: None, Attribute {
multival: false, index: false,
component: true, value_type: ValueType::Ref,
no_history: false, fulltext: false,
}); unique: None,
multival: false,
component: true,
no_history: false,
},
);
// fulltext attribute is a string and an index // fulltext attribute is a string and an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bap"), 101, Attribute { add_attribute(
index: true, &mut schema,
value_type: ValueType::String, Keyword::namespaced("foo", "bap"),
fulltext: true, 101,
unique: None, Attribute {
multival: false, index: true,
component: false, value_type: ValueType::String,
no_history: false, fulltext: true,
}); unique: None,
multival: false,
component: false,
no_history: false,
},
);
assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok()); assert!(validate_attribute_map(&schema.entid_map, &schema.attribute_map).is_ok());
} }
@ -396,114 +491,151 @@ mod test {
fn invalid_schema_unique_value_not_index() { fn invalid_schema_unique_value_not_index() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute unique by value but not index // attribute unique by value but not index
let ident = NamespacedKeyword::new("foo", "bar"); let ident = Keyword::namespaced("foo", "bar");
add_attribute(&mut schema, ident , 99, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::Boolean, ident,
fulltext: false, 99,
unique: Some(attribute::Unique::Value), Attribute {
multival: false, index: false,
component: false, value_type: ValueType::Boolean,
no_history: false, fulltext: false,
}); unique: Some(attribute::Unique::Value),
multival: false,
component: false,
no_history: false,
},
);
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map)
assert!(err.is_some()); .err()
.map(|e| e.kind());
match err.unwrap() { assert_eq!(
Error(ErrorKind::BadSchemaAssertion(message), _) => { assert_eq!(message, ":db/unique :db/unique_value without :db/index true for entid: :foo/bar"); }, err,
x => panic!("expected Bad Schema Assertion error, got {:?}", x), Some(DbErrorKind::BadSchemaAssertion(
} ":db/unique :db/unique_value without :db/index true for entid: :foo/bar".into()
))
);
} }
#[test] #[test]
fn invalid_schema_unique_identity_not_index() { fn invalid_schema_unique_identity_not_index() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute is unique by identity but not index // attribute is unique by identity but not index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::Long, Keyword::namespaced("foo", "bar"),
fulltext: false, 99,
unique: Some(attribute::Unique::Identity), Attribute {
multival: false, index: false,
component: false, value_type: ValueType::Long,
no_history: false, fulltext: false,
}); unique: Some(attribute::Unique::Identity),
multival: false,
component: false,
no_history: false,
},
);
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map)
assert!(err.is_some()); .err()
.map(|e| e.kind());
match err.unwrap() { assert_eq!(
Error(ErrorKind::BadSchemaAssertion(message), _) => { assert_eq!(message, ":db/unique :db/unique_identity without :db/index true for entid: :foo/bar"); }, err,
x => panic!("expected Bad Schema Assertion error, got {:?}", x), Some(DbErrorKind::BadSchemaAssertion(
} ":db/unique :db/unique_identity without :db/index true for entid: :foo/bar".into()
))
);
} }
#[test] #[test]
fn invalid_schema_component_not_ref() { fn invalid_schema_component_not_ref() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute that is a component is not a `Ref` // attribute that is a component is not a `Ref`
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::Boolean, Keyword::namespaced("foo", "bar"),
fulltext: false, 99,
unique: None, Attribute {
multival: false, index: false,
component: true, value_type: ValueType::Boolean,
no_history: false, fulltext: false,
}); unique: None,
multival: false,
component: true,
no_history: false,
},
);
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map)
assert!(err.is_some()); .err()
.map(|e| e.kind());
match err.unwrap() { assert_eq!(
Error(ErrorKind::BadSchemaAssertion(message), _) => { assert_eq!(message, ":db/isComponent true without :db/valueType :db.type/ref for entid: :foo/bar"); }, err,
x => panic!("expected Bad Schema Assertion error, got {:?}", x), Some(DbErrorKind::BadSchemaAssertion(
} ":db/isComponent true without :db/valueType :db.type/ref for entid: :foo/bar"
.into()
))
);
} }
#[test] #[test]
fn invalid_schema_fulltext_not_index() { fn invalid_schema_fulltext_not_index() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute that is fulltext is not an index // attribute that is fulltext is not an index
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { add_attribute(
index: false, &mut schema,
value_type: ValueType::String, Keyword::namespaced("foo", "bar"),
fulltext: true, 99,
unique: None, Attribute {
multival: false, index: false,
component: false, value_type: ValueType::String,
no_history: false, fulltext: true,
}); unique: None,
multival: false,
component: false,
no_history: false,
},
);
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map)
assert!(err.is_some()); .err()
.map(|e| e.kind());
match err.unwrap() { assert_eq!(
Error(ErrorKind::BadSchemaAssertion(message), _) => { assert_eq!(message, ":db/fulltext true without :db/index true for entid: :foo/bar"); }, err,
x => panic!("expected Bad Schema Assertion error, got {:?}", x), Some(DbErrorKind::BadSchemaAssertion(
} ":db/fulltext true without :db/index true for entid: :foo/bar".into()
))
);
} }
fn invalid_schema_fulltext_index_not_string() { fn invalid_schema_fulltext_index_not_string() {
let mut schema = Schema::default(); let mut schema = Schema::default();
// attribute that is fulltext and not a `String` // attribute that is fulltext and not a `String`
add_attribute(&mut schema, NamespacedKeyword::new("foo", "bar"), 99, Attribute { add_attribute(
index: true, &mut schema,
value_type: ValueType::Long, Keyword::namespaced("foo", "bar"),
fulltext: true, 99,
unique: None, Attribute {
multival: false, index: true,
component: false, value_type: ValueType::Long,
no_history: false, fulltext: true,
}); unique: None,
multival: false,
component: false,
no_history: false,
},
);
let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map).err(); let err = validate_attribute_map(&schema.entid_map, &schema.attribute_map)
assert!(err.is_some()); .err()
.map(|e| e.kind());
match err.unwrap() { assert_eq!(
Error(ErrorKind::BadSchemaAssertion(message), _) => { assert_eq!(message, ":db/fulltext true without :db/valueType :db.type/string for entid: :foo/bar"); }, err,
x => panic!("expected Bad Schema Assertion error, got {:?}", x), Some(DbErrorKind::BadSchemaAssertion(
} ":db/fulltext true without :db/valueType :db.type/string for entid: :foo/bar"
.into()
))
);
} }
} }

862
db/src/timelines.rs Normal file
View file

@ -0,0 +1,862 @@
// Copyright 2016 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::ops::RangeFrom;
use rusqlite::{self, params_from_iter};
use db_traits::errors::{DbErrorKind, Result};
use core_traits::{Entid, KnownEntid, TypedValue};
use mentat_core::Schema;
use edn::InternSet;
use edn::entities::OpType;
use crate::db;
use crate::db::TypedSQLValue;
use crate::tx::{transact_terms_with_action, TransactorAction};
use crate::types::PartitionMap;
use crate::internal_types::{Term, TermWithoutTempIds};
use crate::watcher::NullWatcher;
/// Collects a supplied tx range into an DESC ordered Vec of valid txs,
/// ensuring they all belong to the same timeline.
fn collect_ordered_txs_to_move(
conn: &rusqlite::Connection,
txs_from: RangeFrom<Entid>,
timeline: Entid,
) -> Result<Vec<Entid>> {
let mut stmt = conn.prepare("SELECT tx, timeline FROM timelined_transactions WHERE tx >= ? AND timeline = ? GROUP BY tx ORDER BY tx DESC")?;
let mut rows = stmt.query_and_then(
&[&txs_from.start, &timeline],
|row: &rusqlite::Row| -> Result<(Entid, Entid)> { Ok((row.get(0)?, row.get(1)?)) },
)?;
let mut txs = vec![];
// TODO do this in SQL instead?
let timeline = match rows.next() {
Some(t) => {
let t = t?;
txs.push(t.0);
t.1
}
None => bail!(DbErrorKind::TimelinesInvalidRange),
};
for t in rows {
let t = t?;
txs.push(t.0);
if t.1 != timeline {
bail!(DbErrorKind::TimelinesMixed);
}
}
Ok(txs)
}
fn move_transactions_to(
conn: &rusqlite::Connection,
tx_ids: &[Entid],
new_timeline: Entid,
) -> Result<()> {
// Move specified transactions over to a specified timeline.
conn.execute(
&format!(
"UPDATE timelined_transactions SET timeline = {} WHERE tx IN {}",
new_timeline,
crate::repeat_values(tx_ids.len(), 1)
),
params_from_iter(tx_ids.iter()),
)?;
Ok(())
}
fn remove_tx_from_datoms(conn: &rusqlite::Connection, tx_id: Entid) -> Result<()> {
conn.execute("DELETE FROM datoms WHERE e = ?", &[&tx_id])?;
Ok(())
}
fn is_timeline_empty(conn: &rusqlite::Connection, timeline: Entid) -> Result<bool> {
let mut stmt = conn.prepare(
"SELECT timeline FROM timelined_transactions WHERE timeline = ? GROUP BY timeline",
)?;
let rows = stmt.query_and_then(&[&timeline], |row| -> Result<i64> { Ok(row.get(0)?) })?;
Ok(rows.count() == 0)
}
/// Get terms for tx_id, reversing them in meaning (swap add & retract).
fn reversed_terms_for(
conn: &rusqlite::Connection,
tx_id: Entid,
) -> Result<Vec<TermWithoutTempIds>> {
let mut stmt = conn.prepare("SELECT e, a, v, value_type_tag, tx, added FROM timelined_transactions WHERE tx = ? AND timeline = ? ORDER BY tx DESC")?;
let rows = stmt.query_and_then(
&[&tx_id, &crate::TIMELINE_MAIN],
|row| -> Result<TermWithoutTempIds> {
let op = if row.get(5)? {
OpType::Retract
} else {
OpType::Add
};
Ok(Term::AddOrRetract(
op,
KnownEntid(row.get(0)?),
row.get(1)?,
TypedValue::from_sql_value_pair(row.get(2)?, row.get(3)?)?,
))
},
)?;
let mut terms = vec![];
for row in rows {
terms.push(row?);
}
Ok(terms)
}
/// Move specified transaction RangeFrom off of main timeline.
pub fn move_from_main_timeline(
conn: &rusqlite::Connection,
schema: &Schema,
partition_map: PartitionMap,
txs_from: RangeFrom<Entid>,
new_timeline: Entid,
) -> Result<(Option<Schema>, PartitionMap)> {
if new_timeline == crate::TIMELINE_MAIN {
bail!(DbErrorKind::NotYetImplemented(
"Can't move transactions to main timeline".to_string()
));
}
// We don't currently ensure that moving transactions onto a non-empty timeline
// will result in sensible end-state for that timeline.
// Let's remove that foot gun by prohibiting moving transactions to a non-empty timeline.
if !is_timeline_empty(conn, new_timeline)? {
bail!(DbErrorKind::TimelinesMoveToNonEmpty);
}
let txs_to_move = collect_ordered_txs_to_move(conn, txs_from, crate::TIMELINE_MAIN)?;
let mut last_schema = None;
for tx_id in &txs_to_move {
let reversed_terms = reversed_terms_for(conn, *tx_id)?;
// Rewind schema and datoms.
let (report, _, new_schema, _) = transact_terms_with_action(
conn,
partition_map.clone(),
schema,
schema,
NullWatcher(),
reversed_terms.into_iter().map(|t| t.rewrap()),
InternSet::new(),
TransactorAction::Materialize,
)?;
// Rewind operation generated a 'tx' and a 'txInstant' assertion, which got
// inserted into the 'datoms' table (due to TransactorAction::Materialize).
// This is problematic. If we transact a few more times, the transactor will
// generate the same 'tx', but with a different 'txInstant'.
// The end result will be a transaction which has a phantom
// retraction of a txInstant, since transactor operates against the state of
// 'datoms', and not against the 'transactions' table.
// A quick workaround is to just remove the bad txInstant datom.
// See test_clashing_tx_instants test case.
remove_tx_from_datoms(conn, report.tx_id)?;
last_schema = new_schema;
}
// Move transactions over to the target timeline.
move_transactions_to(conn, &txs_to_move, new_timeline)?;
Ok((last_schema, db::read_partition_map(conn)?))
}
#[cfg(test)]
mod tests {
use super::*;
use edn;
use std::borrow::Borrow;
use crate::debug::TestConn;
use crate::bootstrap;
// For convenience during testing.
// Real consumers will perform similar operations when appropriate.
fn update_conn(conn: &mut TestConn, schema: &Option<Schema>, pmap: &PartitionMap) {
match schema {
Some(ref s) => conn.schema = s.clone(),
None => (),
};
conn.partition_map = pmap.clone();
}
#[test]
fn test_pop_simple() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let t = r#"
[{:db/id :db/doc :db/doc "test"}]
"#;
let partition_map0 = conn.partition_map.clone();
let report1 = assert_transact!(conn, t);
let partition_map1 = conn.partition_map.clone();
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
conn.last_tx_id()..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
assert_eq!(new_partition_map, partition_map0);
conn.partition_map = partition_map0;
let report2 = assert_transact!(conn, t);
let partition_map2 = conn.partition_map.clone();
// Ensure that we can't move transactions to a non-empty timeline:
move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
conn.last_tx_id()..,
1,
)
.expect_err("Can't move transactions to a non-empty timeline");
assert_eq!(report1.tx_id, report2.tx_id);
assert_eq!(partition_map1, partition_map2);
assert_matches!(
conn.datoms(),
r#"
[[37 :db/doc "test"]]
"#
);
assert_matches!(
conn.transactions(),
r#"
[[[37 :db/doc "test" ?tx true]
[?tx :db/txInstant ?ms ?tx true]]]
"#
);
}
#[test]
fn test_pop_ident() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let t = r#"
[{:db/ident :test/entid :db/doc "test" :db.schema/version 1}]
"#;
let partition_map0 = conn.partition_map.clone();
let schema0 = conn.schema.clone();
let report1 = assert_transact!(conn, t);
let partition_map1 = conn.partition_map.clone();
let schema1 = conn.schema.clone();
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
conn.last_tx_id()..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
assert_eq!(conn.partition_map, partition_map0);
assert_eq!(conn.schema, schema0);
let report2 = assert_transact!(conn, t);
assert_eq!(report1.tx_id, report2.tx_id);
assert_eq!(conn.partition_map, partition_map1);
assert_eq!(conn.schema, schema1);
assert_matches!(
conn.datoms(),
r#"
[[?e :db/ident :test/entid]
[?e :db/doc "test"]
[?e :db.schema/version 1]]
"#
);
assert_matches!(
conn.transactions(),
r#"
[[[?e :db/ident :test/entid ?tx true]
[?e :db/doc "test" ?tx true]
[?e :db.schema/version 1 ?tx true]
[?tx :db/txInstant ?ms ?tx true]]]
"#
);
}
#[test]
fn test_clashing_tx_instants() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
// Transact a basic schema.
assert_transact!(
conn,
r#"
[{:db/ident :person/name :db/valueType :db.type/string :db/cardinality :db.cardinality/one :db/unique :db.unique/identity :db/index true}]
"#
);
// Make an assertion against our schema.
assert_transact!(conn, r#"[{:person/name "Vanya"}]"#);
// Move that assertion away from the main timeline.
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
conn.last_tx_id()..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
// Assert that our datoms are now just the schema.
assert_matches!(
conn.datoms(),
"
[[?e :db/ident :person/name]
[?e :db/valueType :db.type/string]
[?e :db/cardinality :db.cardinality/one]
[?e :db/unique :db.unique/identity]
[?e :db/index true]]"
);
// Same for transactions.
assert_matches!(
conn.transactions(),
"
[[[?e :db/ident :person/name ?tx true]
[?e :db/valueType :db.type/string ?tx true]
[?e :db/cardinality :db.cardinality/one ?tx true]
[?e :db/unique :db.unique/identity ?tx true]
[?e :db/index true ?tx true]
[?tx :db/txInstant ?ms ?tx true]]]"
);
// Re-assert our initial fact against our schema.
assert_transact!(
conn,
r#"
[[:db/add "tempid" :person/name "Vanya"]]"#
);
// Now, change that fact. This is the "clashing" transaction, if we're
// performing a timeline move using the transactor.
assert_transact!(
conn,
r#"
[[:db/add (lookup-ref :person/name "Vanya") :person/name "Ivan"]]"#
);
// Assert that our datoms are now the schema and the final assertion.
assert_matches!(
conn.datoms(),
r#"
[[?e1 :db/ident :person/name]
[?e1 :db/valueType :db.type/string]
[?e1 :db/cardinality :db.cardinality/one]
[?e1 :db/unique :db.unique/identity]
[?e1 :db/index true]
[?e2 :person/name "Ivan"]]
"#
);
// Assert that we have three correct looking transactions.
// This will fail if we're not cleaning up the 'datoms' table
// after the timeline move.
assert_matches!(
conn.transactions(),
r#"
[[
[?e1 :db/ident :person/name ?tx1 true]
[?e1 :db/valueType :db.type/string ?tx1 true]
[?e1 :db/cardinality :db.cardinality/one ?tx1 true]
[?e1 :db/unique :db.unique/identity ?tx1 true]
[?e1 :db/index true ?tx1 true]
[?tx1 :db/txInstant ?ms1 ?tx1 true]
]
[
[?e2 :person/name "Vanya" ?tx2 true]
[?tx2 :db/txInstant ?ms2 ?tx2 true]
]
[
[?e2 :person/name "Ivan" ?tx3 true]
[?e2 :person/name "Vanya" ?tx3 false]
[?tx3 :db/txInstant ?ms3 ?tx3 true]
]]
"#
);
}
#[test]
fn test_pop_schema() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let t = r#"
[{:db/id "e" :db/ident :test/one :db/valueType :db.type/long :db/cardinality :db.cardinality/one}
{:db/id "f" :db/ident :test/many :db/valueType :db.type/long :db/cardinality :db.cardinality/many}]
"#;
let partition_map0 = conn.partition_map.clone();
let schema0 = conn.schema.clone();
let report1 = assert_transact!(conn, t);
let partition_map1 = conn.partition_map.clone();
let schema1 = conn.schema.clone();
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
report1.tx_id..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
assert_eq!(conn.partition_map, partition_map0);
assert_eq!(conn.schema, schema0);
let report2 = assert_transact!(conn, t);
let partition_map2 = conn.partition_map.clone();
let schema2 = conn.schema.clone();
assert_eq!(report1.tx_id, report2.tx_id);
assert_eq!(partition_map1, partition_map2);
assert_eq!(schema1, schema2);
assert_matches!(
conn.datoms(),
r#"
[[?e1 :db/ident :test/one]
[?e1 :db/valueType :db.type/long]
[?e1 :db/cardinality :db.cardinality/one]
[?e2 :db/ident :test/many]
[?e2 :db/valueType :db.type/long]
[?e2 :db/cardinality :db.cardinality/many]]
"#
);
assert_matches!(
conn.transactions(),
r#"
[[[?e1 :db/ident :test/one ?tx1 true]
[?e1 :db/valueType :db.type/long ?tx1 true]
[?e1 :db/cardinality :db.cardinality/one ?tx1 true]
[?e2 :db/ident :test/many ?tx1 true]
[?e2 :db/valueType :db.type/long ?tx1 true]
[?e2 :db/cardinality :db.cardinality/many ?tx1 true]
[?tx1 :db/txInstant ?ms ?tx1 true]]]
"#
);
}
#[test]
fn test_pop_schema_all_attributes() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let t = r#"
[{
:db/id "e"
:db/ident :test/one
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/unique :db.unique/value
:db/index true
:db/fulltext true
}]
"#;
let partition_map0 = conn.partition_map.clone();
let schema0 = conn.schema.clone();
let report1 = assert_transact!(conn, t);
let partition_map1 = conn.partition_map.clone();
let schema1 = conn.schema.clone();
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
report1.tx_id..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
assert_eq!(conn.partition_map, partition_map0);
assert_eq!(conn.schema, schema0);
let report2 = assert_transact!(conn, t);
let partition_map2 = conn.partition_map.clone();
let schema2 = conn.schema.clone();
assert_eq!(report1.tx_id, report2.tx_id);
assert_eq!(partition_map1, partition_map2);
assert_eq!(schema1, schema2);
assert_matches!(
conn.datoms(),
r#"
[[?e1 :db/ident :test/one]
[?e1 :db/valueType :db.type/string]
[?e1 :db/cardinality :db.cardinality/one]
[?e1 :db/unique :db.unique/value]
[?e1 :db/index true]
[?e1 :db/fulltext true]]
"#
);
assert_matches!(
conn.transactions(),
r#"
[[[?e1 :db/ident :test/one ?tx1 true]
[?e1 :db/valueType :db.type/string ?tx1 true]
[?e1 :db/cardinality :db.cardinality/one ?tx1 true]
[?e1 :db/unique :db.unique/value ?tx1 true]
[?e1 :db/index true ?tx1 true]
[?e1 :db/fulltext true ?tx1 true]
[?tx1 :db/txInstant ?ms ?tx1 true]]]
"#
);
}
#[test]
fn test_pop_schema_all_attributes_component() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let t = r#"
[{
:db/id "e"
:db/ident :test/one
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/unique :db.unique/value
:db/index true
:db/isComponent true
}]
"#;
let partition_map0 = conn.partition_map.clone();
let schema0 = conn.schema.clone();
let report1 = assert_transact!(conn, t);
let partition_map1 = conn.partition_map.clone();
let schema1 = conn.schema.clone();
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
report1.tx_id..,
1,
)
.expect("moved single tx");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
assert_eq!(conn.partition_map, partition_map0);
// Assert all of schema's components individually, for some guidance in case of failures:
assert_eq!(conn.schema.entid_map, schema0.entid_map);
assert_eq!(conn.schema.ident_map, schema0.ident_map);
assert_eq!(conn.schema.attribute_map, schema0.attribute_map);
assert_eq!(
conn.schema.component_attributes,
schema0.component_attributes
);
// Assert the whole schema, just in case we missed something:
assert_eq!(conn.schema, schema0);
let report2 = assert_transact!(conn, t);
let partition_map2 = conn.partition_map.clone();
let schema2 = conn.schema.clone();
assert_eq!(report1.tx_id, report2.tx_id);
assert_eq!(partition_map1, partition_map2);
assert_eq!(schema1, schema2);
assert_matches!(
conn.datoms(),
r#"
[[?e1 :db/ident :test/one]
[?e1 :db/valueType :db.type/ref]
[?e1 :db/cardinality :db.cardinality/one]
[?e1 :db/unique :db.unique/value]
[?e1 :db/isComponent true]
[?e1 :db/index true]]
"#
);
assert_matches!(
conn.transactions(),
r#"
[[[?e1 :db/ident :test/one ?tx1 true]
[?e1 :db/valueType :db.type/ref ?tx1 true]
[?e1 :db/cardinality :db.cardinality/one ?tx1 true]
[?e1 :db/unique :db.unique/value ?tx1 true]
[?e1 :db/isComponent true ?tx1 true]
[?e1 :db/index true ?tx1 true]
[?tx1 :db/txInstant ?ms ?tx1 true]]]
"#
);
}
#[test]
fn test_pop_in_sequence() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let partition_map_after_bootstrap = conn.partition_map.clone();
assert_eq!(
(65536..65538),
conn.partition_map.allocate_entids(":db.part/user", 2)
);
let tx_report0 = assert_transact!(
conn,
r#"[
{:db/id 65536 :db/ident :test/one :db/valueType :db.type/long :db/cardinality :db.cardinality/one :db/unique :db.unique/identity :db/index true}
{:db/id 65537 :db/ident :test/many :db/valueType :db.type/long :db/cardinality :db.cardinality/many}
]"#
);
let first = "[
[65536 :db/ident :test/one]
[65536 :db/valueType :db.type/long]
[65536 :db/cardinality :db.cardinality/one]
[65536 :db/unique :db.unique/identity]
[65536 :db/index true]
[65537 :db/ident :test/many]
[65537 :db/valueType :db.type/long]
[65537 :db/cardinality :db.cardinality/many]
]";
assert_matches!(conn.datoms(), first);
let partition_map0 = conn.partition_map.clone();
assert_eq!(
(65538..65539),
conn.partition_map.allocate_entids(":db.part/user", 1)
);
let tx_report1 = assert_transact!(
conn,
r#"[
[:db/add 65538 :test/one 1]
[:db/add 65538 :test/many 2]
[:db/add 65538 :test/many 3]
]"#
);
let schema1 = conn.schema.clone();
let partition_map1 = conn.partition_map.clone();
assert_matches!(
conn.last_transaction(),
"[[65538 :test/one 1 ?tx true]
[65538 :test/many 2 ?tx true]
[65538 :test/many 3 ?tx true]
[?tx :db/txInstant ?ms ?tx true]]"
);
let second = "[
[65536 :db/ident :test/one]
[65536 :db/valueType :db.type/long]
[65536 :db/cardinality :db.cardinality/one]
[65536 :db/unique :db.unique/identity]
[65536 :db/index true]
[65537 :db/ident :test/many]
[65537 :db/valueType :db.type/long]
[65537 :db/cardinality :db.cardinality/many]
[65538 :test/one 1]
[65538 :test/many 2]
[65538 :test/many 3]
]";
assert_matches!(conn.datoms(), second);
let tx_report2 = assert_transact!(
conn,
r#"[
[:db/add 65538 :test/one 2]
[:db/add 65538 :test/many 2]
[:db/retract 65538 :test/many 3]
[:db/add 65538 :test/many 4]
]"#
);
let schema2 = conn.schema.clone();
assert_matches!(
conn.last_transaction(),
"[[65538 :test/one 1 ?tx false]
[65538 :test/one 2 ?tx true]
[65538 :test/many 3 ?tx false]
[65538 :test/many 4 ?tx true]
[?tx :db/txInstant ?ms ?tx true]]"
);
let third = "[
[65536 :db/ident :test/one]
[65536 :db/valueType :db.type/long]
[65536 :db/cardinality :db.cardinality/one]
[65536 :db/unique :db.unique/identity]
[65536 :db/index true]
[65537 :db/ident :test/many]
[65537 :db/valueType :db.type/long]
[65537 :db/cardinality :db.cardinality/many]
[65538 :test/one 2]
[65538 :test/many 2]
[65538 :test/many 4]
]";
assert_matches!(conn.datoms(), third);
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
tx_report2.tx_id..,
1,
)
.expect("moved timeline");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), second);
// Moving didn't change the schema.
assert_eq!(None, new_schema);
assert_eq!(conn.schema, schema2);
// But it did change the partition map.
assert_eq!(conn.partition_map, partition_map1);
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
tx_report1.tx_id..,
2,
)
.expect("moved timeline");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_matches!(conn.datoms(), first);
assert_eq!(None, new_schema);
assert_eq!(schema1, conn.schema);
assert_eq!(conn.partition_map, partition_map0);
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
tx_report0.tx_id..,
3,
)
.expect("moved timeline");
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_eq!(true, new_schema.is_some());
assert_eq!(bootstrap::bootstrap_schema(), conn.schema);
assert_eq!(partition_map_after_bootstrap, conn.partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
}
#[test]
fn test_move_range() {
let mut conn = TestConn::default();
conn.sanitized_partition_map();
let partition_map_after_bootstrap = conn.partition_map.clone();
assert_eq!(
(65536..65539),
conn.partition_map.allocate_entids(":db.part/user", 3)
);
let tx_report0 = assert_transact!(
conn,
r#"[
{:db/id 65536 :db/ident :test/one :db/valueType :db.type/long :db/cardinality :db.cardinality/one}
{:db/id 65537 :db/ident :test/many :db/valueType :db.type/long :db/cardinality :db.cardinality/many}
]"#
);
assert_transact!(
conn,
r#"[
[:db/add 65538 :test/one 1]
[:db/add 65538 :test/many 2]
[:db/add 65538 :test/many 3]
]"#
);
assert_transact!(
conn,
r#"[
[:db/add 65538 :test/one 2]
[:db/add 65538 :test/many 2]
[:db/retract 65538 :test/many 3]
[:db/add 65538 :test/many 4]
]"#
);
// Remove all of these transactions from the main timeline,
// ensure we get back to a "just bootstrapped" state.
let (new_schema, new_partition_map) = move_from_main_timeline(
&conn.sqlite,
&conn.schema,
conn.partition_map.clone(),
tx_report0.tx_id..,
1,
)
.expect("moved timeline");
update_conn(&mut conn, &new_schema, &new_partition_map);
update_conn(&mut conn, &new_schema, &new_partition_map);
assert_eq!(true, new_schema.is_some());
assert_eq!(bootstrap::bootstrap_schema(), conn.schema);
assert_eq!(partition_map_after_bootstrap, conn.partition_map);
assert_matches!(conn.datoms(), "[]");
assert_matches!(conn.transactions(), "[]");
}
}

File diff suppressed because it is too large Load diff

75
db/src/tx_checking.rs Normal file
View file

@ -0,0 +1,75 @@
// Copyright 2018 Mozilla
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::collections::{BTreeMap, BTreeSet};
use core_traits::{Entid, TypedValue, ValueType};
use db_traits::errors::CardinalityConflict;
use crate::internal_types::AEVTrie;
/// Map from found [e a v] to expected type.
pub(crate) type TypeDisagreements = BTreeMap<(Entid, Entid, TypedValue), ValueType>;
/// Ensure that the given terms type check.
///
/// We try to be maximally helpful by yielding every malformed datom, rather than only the first.
/// In the future, we might change this choice, or allow the consumer to specify the robustness of
/// the type checking desired, since there is a cost to providing helpful diagnostics.
pub(crate) fn type_disagreements<'schema>(aev_trie: &AEVTrie<'schema>) -> TypeDisagreements {
let mut errors: TypeDisagreements = TypeDisagreements::default();
for (&(a, attribute), evs) in aev_trie {
for (&e, ref ars) in evs {
for v in ars.add.iter().chain(ars.retract.iter()) {
if attribute.value_type != v.value_type() {
errors.insert((e, a, v.clone()), attribute.value_type);
}
}
}
}
errors
}
/// Ensure that the given terms obey the cardinality restrictions of the given schema.
///
/// That is, ensure that any cardinality one attribute is added with at most one distinct value for
/// any specific entity (although that one value may be repeated for the given entity).
/// It is an error to:
///
/// - add two distinct values for the same cardinality one attribute and entity in a single transaction
/// - add and remove the same values for the same attribute and entity in a single transaction
///
/// We try to be maximally helpful by yielding every malformed set of datoms, rather than just the
/// first set, or even the first conflict. In the future, we might change this choice, or allow the
/// consumer to specify the robustness of the cardinality checking desired.
pub(crate) fn cardinality_conflicts<'schema>(
aev_trie: &AEVTrie<'schema>,
) -> Vec<CardinalityConflict> {
let mut errors = vec![];
for (&(a, attribute), evs) in aev_trie {
for (&e, ref ars) in evs {
if !attribute.multival && ars.add.len() > 1 {
let vs = ars.add.clone();
errors.push(CardinalityConflict::CardinalityOneAddConflict { e, a, vs });
}
let vs: BTreeSet<_> = ars.retract.intersection(&ars.add).cloned().collect();
if !vs.is_empty() {
errors.push(CardinalityConflict::AddRetractConflict { e, a, vs })
}
}
}
errors
}

View file

@ -8,61 +8,51 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
use std::sync::{ use std::sync::{Arc, Weak};
Arc,
Weak,
};
use std::sync::mpsc::{ use std::sync::mpsc::{channel, Receiver, RecvError, Sender};
channel,
Receiver,
RecvError,
Sender,
};
use std::thread; use std::thread;
use indexmap::{ use indexmap::IndexMap;
IndexMap,
};
use mentat_core::{ use core_traits::{Entid, TypedValue};
Entid,
Schema,
TypedValue,
};
use mentat_tx::entities::{ use mentat_core::Schema;
OpType,
};
use errors::{ use edn::entities::OpType;
Result,
};
use types::{ use db_traits::errors::Result;
AttributeSet,
};
use watcher::TransactWatcher; use crate::types::AttributeSet;
use crate::watcher::TransactWatcher;
pub struct TxObserver { pub struct TxObserver {
notify_fn: Arc<Box<Fn(&str, IndexMap<&Entid, &AttributeSet>) + Send + Sync>>, #[allow(clippy::type_complexity)]
notify_fn: Arc<Box<dyn Fn(&str, IndexMap<&Entid, &AttributeSet>) + Send + Sync>>,
attributes: AttributeSet, attributes: AttributeSet,
} }
impl TxObserver { impl TxObserver {
pub fn new<F>(attributes: AttributeSet, notify_fn: F) -> TxObserver where F: Fn(&str, IndexMap<&Entid, &AttributeSet>) + 'static + Send + Sync { pub fn new<F>(attributes: AttributeSet, notify_fn: F) -> TxObserver
where
F: Fn(&str, IndexMap<&Entid, &AttributeSet>) + 'static + Send + Sync,
{
TxObserver { TxObserver {
notify_fn: Arc::new(Box::new(notify_fn)), notify_fn: Arc::new(Box::new(notify_fn)),
attributes, attributes,
} }
} }
pub fn applicable_reports<'r>(&self, reports: &'r IndexMap<Entid, AttributeSet>) -> IndexMap<&'r Entid, &'r AttributeSet> { pub fn applicable_reports<'r>(
reports.into_iter() &self,
.filter(|&(_txid, attrs)| !self.attributes.is_disjoint(attrs)) reports: &'r IndexMap<Entid, AttributeSet>,
.collect() ) -> IndexMap<&'r Entid, &'r AttributeSet> {
reports
.into_iter()
.filter(|&(_txid, attrs)| !self.attributes.is_disjoint(attrs))
.collect()
} }
fn notify(&self, key: &str, reports: IndexMap<&Entid, &AttributeSet>) { fn notify(&self, key: &str, reports: IndexMap<&Entid, &AttributeSet>) {
@ -80,7 +70,10 @@ pub struct TxCommand {
} }
impl TxCommand { impl TxCommand {
fn new(observers: &Arc<IndexMap<String, Arc<TxObserver>>>, reports: IndexMap<Entid, AttributeSet>) -> Self { fn new(
observers: &Arc<IndexMap<String, Arc<TxObserver>>>,
reports: IndexMap<Entid, AttributeSet>,
) -> Self {
TxCommand { TxCommand {
reports, reports,
observers: Arc::downgrade(observers), observers: Arc::downgrade(observers),
@ -90,20 +83,21 @@ impl TxCommand {
impl Command for TxCommand { impl Command for TxCommand {
fn execute(&mut self) { fn execute(&mut self) {
self.observers.upgrade().map(|observers| { if let Some(observers) = self.observers.upgrade() {
for (key, observer) in observers.iter() { for (key, observer) in observers.iter() {
let applicable_reports = observer.applicable_reports(&self.reports); let applicable_reports = observer.applicable_reports(&self.reports);
if !applicable_reports.is_empty() { if !applicable_reports.is_empty() {
observer.notify(&key, applicable_reports); observer.notify(&key, applicable_reports);
} }
} }
}); }
} }
} }
#[derive(Default)]
pub struct TxObservationService { pub struct TxObservationService {
observers: Arc<IndexMap<String, Arc<TxObserver>>>, observers: Arc<IndexMap<String, Arc<TxObserver>>>,
executor: Option<Sender<Box<Command + Send>>>, executor: Option<Sender<Box<dyn Command + Send>>>,
} }
impl TxObservationService { impl TxObservationService {
@ -115,7 +109,7 @@ impl TxObservationService {
} }
// For testing purposes // For testing purposes
pub fn is_registered(&self, key: &String) -> bool { pub fn is_registered(&self, key: &str) -> bool {
self.observers.contains_key(key) self.observers.contains_key(key)
} }
@ -123,7 +117,7 @@ impl TxObservationService {
Arc::make_mut(&mut self.observers).insert(key, observer); Arc::make_mut(&mut self.observers).insert(key, observer);
} }
pub fn deregister(&mut self, key: &String) { pub fn deregister(&mut self, key: &str) {
Arc::make_mut(&mut self.observers).remove(key); Arc::make_mut(&mut self.observers).remove(key);
} }
@ -138,7 +132,11 @@ impl TxObservationService {
} }
let executor = self.executor.get_or_insert_with(|| { let executor = self.executor.get_or_insert_with(|| {
let (tx, rx): (Sender<Box<Command + Send>>, Receiver<Box<Command + Send>>) = channel(); #[allow(clippy::type_complexity)]
let (tx, rx): (
Sender<Box<dyn Command + Send>>,
Receiver<Box<dyn Command + Send>>,
) = channel();
let mut worker = CommandExecutor::new(rx); let mut worker = CommandExecutor::new(rx);
thread::spawn(move || { thread::spawn(move || {
@ -159,6 +157,7 @@ impl Drop for TxObservationService {
} }
} }
#[derive(Default)]
pub struct InProgressObserverTransactWatcher { pub struct InProgressObserverTransactWatcher {
collected_attributes: AttributeSet, collected_attributes: AttributeSet,
pub txes: IndexMap<Entid, AttributeSet>, pub txes: IndexMap<Entid, AttributeSet>,
@ -179,21 +178,19 @@ impl TransactWatcher for InProgressObserverTransactWatcher {
} }
fn done(&mut self, t: &Entid, _schema: &Schema) -> Result<()> { fn done(&mut self, t: &Entid, _schema: &Schema) -> Result<()> {
let collected_attributes = ::std::mem::replace(&mut self.collected_attributes, Default::default()); let collected_attributes = ::std::mem::take(&mut self.collected_attributes);
self.txes.insert(*t, collected_attributes); self.txes.insert(*t, collected_attributes);
Ok(()) Ok(())
} }
} }
struct CommandExecutor { struct CommandExecutor {
receiver: Receiver<Box<Command + Send>>, receiver: Receiver<Box<dyn Command + Send>>,
} }
impl CommandExecutor { impl CommandExecutor {
fn new(rx: Receiver<Box<Command + Send>>) -> Self { fn new(rx: Receiver<Box<dyn Command + Send>>) -> Self {
CommandExecutor { CommandExecutor { receiver: rx }
receiver: rx,
}
} }
fn main(&mut self) { fn main(&mut self) {
@ -204,12 +201,10 @@ impl CommandExecutor {
// sync_channel) is disconnected, implying that no further messages will ever be // sync_channel) is disconnected, implying that no further messages will ever be
// received." // received."
// No need to log here. // No need to log here.
return return;
}, }
Ok(mut cmd) => { Ok(mut cmd) => cmd.execute(),
cmd.execute()
},
} }
} }
} }

View file

@ -10,52 +10,110 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::collections::HashMap; use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::collections::{ use std::iter::FromIterator;
BTreeMap, use std::ops::{Deref, DerefMut, Range};
BTreeSet,
};
extern crate mentat_core; extern crate mentat_core;
pub use self::mentat_core::{ use core_traits::{Entid, TypedValue, ValueType};
Attribute,
AttributeBitFlags, pub use self::mentat_core::{DateTime, Schema, Utc};
DateTime,
Entid, use edn::entities::{EntityPlace, TempId};
Schema,
TypedValue, use db_traits::errors;
Utc,
ValueType,
};
/// Represents one partition of the entid space. /// Represents one partition of the entid space.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
#[cfg_attr(feature = "syncable", derive(Serialize, Deserialize))]
pub struct Partition { pub struct Partition {
/// The first entid in the partition. /// The first entid in the partition.
pub start: i64, pub start: Entid,
/// Maximum allowed entid in the partition.
pub end: Entid,
/// `true` if entids in the partition can be excised with `:db/excise`.
pub allow_excision: bool,
/// The next entid to be allocated in the partition. /// The next entid to be allocated in the partition.
pub index: i64, /// Unless you must use this directly, prefer using provided setter and getter helpers.
pub(crate) next_entid_to_allocate: Entid,
} }
impl Partition { impl Partition {
pub fn new(start: i64, next: i64) -> Partition { pub fn new(
assert!(start <= next, "A partition represents a monotonic increasing sequence of entids."); start: Entid,
Partition { start: start, index: next } end: Entid,
next_entid_to_allocate: Entid,
allow_excision: bool,
) -> Partition {
assert!(
start <= next_entid_to_allocate && next_entid_to_allocate <= end,
"A partition represents a monotonic increasing sequence of entids."
);
Partition {
start,
end,
next_entid_to_allocate,
allow_excision,
}
} }
pub fn contains_entid(&self, e: i64) -> bool { pub fn contains_entid(&self, e: Entid) -> bool {
(e >= self.start) && (e < self.index) (e >= self.start) && (e < self.next_entid_to_allocate)
}
pub fn allows_entid(&self, e: Entid) -> bool {
(e >= self.start) && (e <= self.end)
}
pub fn next_entid(&self) -> Entid {
self.next_entid_to_allocate
}
pub fn set_next_entid(&mut self, e: Entid) {
assert!(
self.allows_entid(e),
"Partition index must be within its allocated space."
);
self.next_entid_to_allocate = e;
}
pub fn allocate_entids(&mut self, n: usize) -> Range<i64> {
let idx = self.next_entid();
self.set_next_entid(idx + n as i64);
idx..self.next_entid()
} }
} }
/// Map partition names to `Partition` instances. /// Map partition names to `Partition` instances.
pub type PartitionMap = BTreeMap<String, Partition>; #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq)]
#[cfg_attr(feature = "syncable", derive(Serialize, Deserialize))]
pub struct PartitionMap(BTreeMap<String, Partition>);
impl Deref for PartitionMap {
type Target = BTreeMap<String, Partition>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for PartitionMap {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl FromIterator<(String, Partition)> for PartitionMap {
fn from_iter<T: IntoIterator<Item = (String, Partition)>>(iter: T) -> Self {
PartitionMap(iter.into_iter().collect())
}
}
/// Represents the metadata required to query from, or apply transactions to, a Mentat store. /// Represents the metadata required to query from, or apply transactions to, a Mentat store.
/// ///
/// See https://github.com/mozilla/mentat/wiki/Thoughts:-modeling-db-conn-in-Rust. /// See https://github.com/mozilla/mentat/wiki/Thoughts:-modeling-db-conn-in-Rust.
#[derive(Clone,Debug,Default,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub struct DB { pub struct DB {
/// Map partition name->`Partition`. /// Map partition name->`Partition`.
/// ///
@ -69,8 +127,8 @@ pub struct DB {
impl DB { impl DB {
pub fn new(partition_map: PartitionMap, schema: Schema) -> DB { pub fn new(partition_map: PartitionMap, schema: Schema) -> DB {
DB { DB {
partition_map: partition_map, partition_map,
schema: schema schema,
} }
} }
} }
@ -80,6 +138,9 @@ impl DB {
/// Used to represent lookup-refs and [TEMPID a v] upserts as they are resolved. /// Used to represent lookup-refs and [TEMPID a v] upserts as they are resolved.
pub type AVPair = (Entid, TypedValue); pub type AVPair = (Entid, TypedValue);
/// Used to represent assertions and retractions.
pub(crate) type EAV = (Entid, Entid, TypedValue);
/// Map [a v] pairs to existing entids. /// Map [a v] pairs to existing entids.
/// ///
/// Used to resolve lookup-refs and upserts. /// Used to resolve lookup-refs and upserts.
@ -88,19 +149,82 @@ pub type AVMap<'a> = HashMap<&'a AVPair, Entid>;
// represents a set of entids that are correspond to attributes // represents a set of entids that are correspond to attributes
pub type AttributeSet = BTreeSet<Entid>; pub type AttributeSet = BTreeSet<Entid>;
/// A transaction report summarizes an applied transaction. /// The transactor is tied to `edn::ValueAndSpan` right now, but in the future we'd like to support
#[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)] /// `TypedValue` directly for programmatic use. `TransactableValue` encapsulates the interface
pub struct TxReport { /// value types (i.e., values in the value place) need to support to be transacted.
/// The transaction ID of the transaction. pub trait TransactableValue: Clone {
pub tx_id: Entid, /// Coerce this value place into the given type. This is where we perform schema-aware
/// coercion, for example coercing an integral value into a ref where appropriate.
fn into_typed_value(self, schema: &Schema, value_type: ValueType)
-> errors::Result<TypedValue>;
/// The timestamp when the transaction began to be committed. /// Make an entity place out of this value place. This is where we limit values in nested maps
pub tx_instant: DateTime<Utc>, /// to valid entity places.
fn into_entity_place(self) -> errors::Result<EntityPlace<Self>>;
/// A map from string literal tempid to resolved or allocated entid. fn as_tempid(&self) -> Option<TempId>;
/// }
/// Every string literal tempid presented to the transactor either resolves via upsert to an
/// existing entid, or is allocated a new entid. (It is possible for multiple distinct string #[cfg(test)]
/// literal tempids to all unify to a single freshly allocated entid.) mod tests {
pub tempids: BTreeMap<String, Entid>, use super::Partition;
#[test]
#[should_panic(expected = "A partition represents a monotonic increasing sequence of entids.")]
fn test_partition_limits_sanity1() {
Partition::new(100, 1000, 1001, true);
}
#[test]
#[should_panic(expected = "A partition represents a monotonic increasing sequence of entids.")]
fn test_partition_limits_sanity2() {
Partition::new(100, 1000, 99, true);
}
#[test]
#[should_panic(expected = "Partition index must be within its allocated space.")]
fn test_partition_limits_boundary1() {
let mut part = Partition::new(100, 1000, 100, true);
part.set_next_entid(2000);
}
#[test]
#[should_panic(expected = "Partition index must be within its allocated space.")]
fn test_partition_limits_boundary2() {
let mut part = Partition::new(100, 1000, 100, true);
part.set_next_entid(1001);
}
#[test]
#[should_panic(expected = "Partition index must be within its allocated space.")]
fn test_partition_limits_boundary3() {
let mut part = Partition::new(100, 1000, 100, true);
part.set_next_entid(99);
}
#[test]
#[should_panic(expected = "Partition index must be within its allocated space.")]
fn test_partition_limits_boundary4() {
let mut part = Partition::new(100, 1000, 100, true);
part.set_next_entid(-100);
}
#[test]
#[should_panic(expected = "Partition index must be within its allocated space.")]
fn test_partition_limits_boundary5() {
let mut part = Partition::new(100, 1000, 100, true);
part.allocate_entids(901); // One more than allowed.
}
#[test]
fn test_partition_limits_boundary6() {
let mut part = Partition::new(100, 1000, 100, true);
part.set_next_entid(100); // First entid that's allowed.
part.set_next_entid(101); // Just after first.
assert_eq!(101..111, part.allocate_entids(10));
part.set_next_entid(1000); // Last entid that's allowed.
part.set_next_entid(999); // Just before last.
}
} }

View file

@ -13,40 +13,31 @@
//! This module implements the upsert resolution algorithm described at //! This module implements the upsert resolution algorithm described at
//! https://github.com/mozilla/mentat/wiki/Transacting:-upsert-resolution-algorithm. //! https://github.com/mozilla/mentat/wiki/Transacting:-upsert-resolution-algorithm.
use std::collections::BTreeSet; use std::collections::{BTreeMap, BTreeSet};
use errors; use indexmap;
use errors::ErrorKind; use petgraph::unionfind;
use types::{
AVPair, use crate::internal_types::{
}; Population, TempIdHandle, TempIdMap, Term, TermWithTempIds, TermWithoutTempIds, TypedValueOr,
use internal_types::{
Population,
TempIdHandle,
TempIdMap,
Term,
TermWithoutTempIds,
TermWithTempIds,
}; };
use crate::types::AVPair;
use db_traits::errors::{DbErrorKind, Result};
use mentat_core::util::Either::*; use mentat_core::util::Either::*;
use mentat_core::{ use core_traits::{attribute, Attribute, Entid, TypedValue};
attribute,
Attribute, use crate::schema::SchemaBuilding;
Entid, use edn::entities::OpType;
Schema, use mentat_core::Schema;
TypedValue,
};
use mentat_tx::entities::OpType;
use schema::SchemaBuilding;
/// A "Simple upsert" that looks like [:db/add TEMPID a v], where a is :db.unique/identity. /// A "Simple upsert" that looks like [:db/add TEMPID a v], where a is :db.unique/identity.
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
struct UpsertE(TempIdHandle, Entid, TypedValue); struct UpsertE(TempIdHandle, Entid, TypedValue);
/// A "Complex upsert" that looks like [:db/add TEMPID a OTHERID], where a is :db.unique/identity /// A "Complex upsert" that looks like [:db/add TEMPID a OTHERID], where a is :db.unique/identity
#[derive(Clone,Debug,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Eq, Hash, Ord, PartialOrd, PartialEq)]
struct UpsertEV(TempIdHandle, Entid, TempIdHandle); struct UpsertEV(TempIdHandle, Entid, TempIdHandle);
/// A generation collects entities into populations at a single evolutionary step in the upsert /// A generation collects entities into populations at a single evolutionary step in the upsert
@ -55,7 +46,7 @@ struct UpsertEV(TempIdHandle, Entid, TempIdHandle);
/// The upsert resolution process is only concerned with [:db/add ...] entities until the final /// The upsert resolution process is only concerned with [:db/add ...] entities until the final
/// entid allocations. That's why we separate into special simple and complex upsert types /// entid allocations. That's why we separate into special simple and complex upsert types
/// immediately, and then collect the more general term types for final resolution. /// immediately, and then collect the more general term types for final resolution.
#[derive(Clone,Debug,Default,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub(crate) struct Generation { pub(crate) struct Generation {
/// "Simple upserts" that look like [:db/add TEMPID a v], where a is :db.unique/identity. /// "Simple upserts" that look like [:db/add TEMPID a v], where a is :db.unique/identity.
upserts_e: Vec<UpsertE>, upserts_e: Vec<UpsertE>,
@ -64,8 +55,8 @@ pub(crate) struct Generation {
upserts_ev: Vec<UpsertEV>, upserts_ev: Vec<UpsertEV>,
/// Entities that look like: /// Entities that look like:
/// - [:db/add TEMPID b OTHERID], where b is not :db.unique/identity; /// - [:db/add TEMPID b OTHERID]. b may be :db.unique/identity if it has failed to upsert.
/// - [:db/add TEMPID b v], where b is not :db.unique/identity. /// - [:db/add TEMPID b v]. b may be :db.unique/identity if it has failed to upsert.
/// - [:db/add e b OTHERID]. /// - [:db/add e b OTHERID].
allocations: Vec<TermWithTempIds>, allocations: Vec<TermWithTempIds>,
@ -78,7 +69,7 @@ pub(crate) struct Generation {
resolved: Vec<TermWithoutTempIds>, resolved: Vec<TermWithoutTempIds>,
} }
#[derive(Clone,Debug,Default,Eq,Hash,Ord,PartialOrd,PartialEq)] #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialOrd, PartialEq)]
pub(crate) struct FinalPopulations { pub(crate) struct FinalPopulations {
/// Upserts that upserted. /// Upserts that upserted.
pub upserted: Vec<TermWithoutTempIds>, pub upserted: Vec<TermWithoutTempIds>,
@ -93,11 +84,14 @@ pub(crate) struct FinalPopulations {
impl Generation { impl Generation {
/// Split entities into a generation of populations that need to evolve to have their tempids /// Split entities into a generation of populations that need to evolve to have their tempids
/// resolved or allocated, and a population of inert entities that do not reference tempids. /// resolved or allocated, and a population of inert entities that do not reference tempids.
pub(crate) fn from<I>(terms: I, schema: &Schema) -> errors::Result<(Generation, Population)> where I: IntoIterator<Item=TermWithTempIds> { pub(crate) fn from<I>(terms: I, schema: &Schema) -> Result<(Generation, Population)>
where
I: IntoIterator<Item = TermWithTempIds>,
{
let mut generation = Generation::default(); let mut generation = Generation::default();
let mut inert = vec![]; let mut inert = vec![];
let is_unique = |a: Entid| -> errors::Result<bool> { let is_unique = |a: Entid| -> Result<bool> {
let attribute: &Attribute = schema.require_attribute_for_entid(a)?; let attribute: &Attribute = schema.require_attribute_for_entid(a)?;
Ok(attribute.unique == Some(attribute::Unique::Identity)) Ok(attribute.unique == Some(attribute::Unique::Identity))
}; };
@ -108,22 +102,28 @@ impl Generation {
if op == OpType::Add && is_unique(a)? { if op == OpType::Add && is_unique(a)? {
generation.upserts_ev.push(UpsertEV(e, a, v)); generation.upserts_ev.push(UpsertEV(e, a, v));
} else { } else {
generation.allocations.push(Term::AddOrRetract(op, Right(e), a, Right(v))); generation
.allocations
.push(Term::AddOrRetract(op, Right(e), a, Right(v)));
} }
}, }
Term::AddOrRetract(op, Right(e), a, Left(v)) => { Term::AddOrRetract(op, Right(e), a, Left(v)) => {
if op == OpType::Add && is_unique(a)? { if op == OpType::Add && is_unique(a)? {
generation.upserts_e.push(UpsertE(e, a, v)); generation.upserts_e.push(UpsertE(e, a, v));
} else { } else {
generation.allocations.push(Term::AddOrRetract(op, Right(e), a, Left(v))); generation
.allocations
.push(Term::AddOrRetract(op, Right(e), a, Left(v)));
} }
}, }
Term::AddOrRetract(op, Left(e), a, Right(v)) => { Term::AddOrRetract(op, Left(e), a, Right(v)) => {
generation.allocations.push(Term::AddOrRetract(op, Left(e), a, Right(v))); generation
}, .allocations
.push(Term::AddOrRetract(op, Left(e), a, Right(v)));
}
Term::AddOrRetract(op, Left(e), a, Left(v)) => { Term::AddOrRetract(op, Left(e), a, Left(v)) => {
inert.push(Term::AddOrRetract(op, Left(e), a, Left(v))); inert.push(Term::AddOrRetract(op, Left(e), a, Left(v)));
}, }
} }
} }
@ -132,11 +132,10 @@ impl Generation {
/// Return true if it's possible to evolve this generation further. /// Return true if it's possible to evolve this generation further.
/// ///
/// There can be complex upserts but no simple upserts to help resolve them. We accept the /// Note that there can be complex upserts but no simple upserts to help resolve them, and in
/// overhead of having the database try to resolve an empty set of simple upserts, to avoid /// this case, we cannot evolve further.
/// having to special case complex upserts at entid allocation time.
pub(crate) fn can_evolve(&self) -> bool { pub(crate) fn can_evolve(&self) -> bool {
!self.upserts_e.is_empty() || !self.upserts_ev.is_empty() !self.upserts_e.is_empty()
} }
/// Evolve this generation one step further by rewriting the existing :db/add entities using the /// Evolve this generation one step further by rewriting the existing :db/add entities using the
@ -146,19 +145,34 @@ impl Generation {
pub(crate) fn evolve_one_step(self, temp_id_map: &TempIdMap) -> Generation { pub(crate) fn evolve_one_step(self, temp_id_map: &TempIdMap) -> Generation {
let mut next = Generation::default(); let mut next = Generation::default();
// We'll iterate our own allocations to resolve more things, but terms that have already
// resolved stay resolved.
next.resolved = self.resolved;
for UpsertE(t, a, v) in self.upserts_e { for UpsertE(t, a, v) in self.upserts_e {
match temp_id_map.get(&*t) { match temp_id_map.get(&*t) {
Some(&n) => next.upserted.push(Term::AddOrRetract(OpType::Add, n, a, v)), Some(&n) => next.upserted.push(Term::AddOrRetract(OpType::Add, n, a, v)),
None => next.allocations.push(Term::AddOrRetract(OpType::Add, Right(t), a, Left(v))), None => {
next.allocations
.push(Term::AddOrRetract(OpType::Add, Right(t), a, Left(v)))
}
} }
} }
for UpsertEV(t1, a, t2) in self.upserts_ev { for UpsertEV(t1, a, t2) in self.upserts_ev {
match (temp_id_map.get(&*t1), temp_id_map.get(&*t2)) { match (temp_id_map.get(&*t1), temp_id_map.get(&*t2)) {
(Some(&n1), Some(&n2)) => next.resolved.push(Term::AddOrRetract(OpType::Add, n1, a, TypedValue::Ref(n2.0))), (Some(_), Some(&n2)) => {
// Even though we can resolve entirely, it's possible that the remaining upsert
// could conflict. Moving straight to resolved doesn't give us a chance to
// search the store for the conflict.
next.upserts_e.push(UpsertE(t1, a, TypedValue::Ref(n2.0)))
}
(None, Some(&n2)) => next.upserts_e.push(UpsertE(t1, a, TypedValue::Ref(n2.0))), (None, Some(&n2)) => next.upserts_e.push(UpsertE(t1, a, TypedValue::Ref(n2.0))),
(Some(&n1), None) => next.allocations.push(Term::AddOrRetract(OpType::Add, Left(n1), a, Right(t2))), (Some(&n1), None) => {
(None, None) => next.allocations.push(Term::AddOrRetract(OpType::Add, Right(t1), a, Right(t2))), next.allocations
.push(Term::AddOrRetract(OpType::Add, Left(n1), a, Right(t2)))
}
(None, None) => next.upserts_ev.push(UpsertEV(t1, a, t2)),
} }
} }
@ -170,23 +184,40 @@ impl Generation {
match term { match term {
Term::AddOrRetract(op, Right(t1), a, Right(t2)) => { Term::AddOrRetract(op, Right(t1), a, Right(t2)) => {
match (temp_id_map.get(&*t1), temp_id_map.get(&*t2)) { match (temp_id_map.get(&*t1), temp_id_map.get(&*t2)) {
(Some(&n1), Some(&n2)) => next.resolved.push(Term::AddOrRetract(op, n1, a, TypedValue::Ref(n2.0))), (Some(&n1), Some(&n2)) => {
(None, Some(&n2)) => next.allocations.push(Term::AddOrRetract(op, Right(t1), a, Left(TypedValue::Ref(n2.0)))), next.resolved
(Some(&n1), None) => next.allocations.push(Term::AddOrRetract(op, Left(n1), a, Right(t2))), .push(Term::AddOrRetract(op, n1, a, TypedValue::Ref(n2.0)))
(None, None) => next.allocations.push(Term::AddOrRetract(op, Right(t1), a, Right(t2))), }
(None, Some(&n2)) => next.allocations.push(Term::AddOrRetract(
op,
Right(t1),
a,
Left(TypedValue::Ref(n2.0)),
)),
(Some(&n1), None) => {
next.allocations
.push(Term::AddOrRetract(op, Left(n1), a, Right(t2)))
}
(None, None) => {
next.allocations
.push(Term::AddOrRetract(op, Right(t1), a, Right(t2)))
}
} }
}
Term::AddOrRetract(op, Right(t), a, Left(v)) => match temp_id_map.get(&*t) {
Some(&n) => next.resolved.push(Term::AddOrRetract(op, n, a, v)),
None => next
.allocations
.push(Term::AddOrRetract(op, Right(t), a, Left(v))),
}, },
Term::AddOrRetract(op, Right(t), a, Left(v)) => { Term::AddOrRetract(op, Left(e), a, Right(t)) => match temp_id_map.get(&*t) {
match temp_id_map.get(&*t) { Some(&n) => {
Some(&n) => next.resolved.push(Term::AddOrRetract(op, n, a, v)), next.resolved
None => next.allocations.push(Term::AddOrRetract(op, Right(t), a, Left(v))), .push(Term::AddOrRetract(op, e, a, TypedValue::Ref(n.0)))
}
},
Term::AddOrRetract(op, Left(e), a, Right(t)) => {
match temp_id_map.get(&*t) {
Some(&n) => next.resolved.push(Term::AddOrRetract(op, e, a, TypedValue::Ref(n.0))),
None => next.allocations.push(Term::AddOrRetract(op, Left(e), a, Right(t))),
} }
None => next
.allocations
.push(Term::AddOrRetract(op, Left(e), a, Right(t))),
}, },
Term::AddOrRetract(_, Left(_), _, Left(_)) => unreachable!(), Term::AddOrRetract(_, Left(_), _, Left(_)) => unreachable!(),
} }
@ -196,7 +227,7 @@ impl Generation {
} }
// Collect id->[a v] pairs that might upsert at this evolutionary step. // Collect id->[a v] pairs that might upsert at this evolutionary step.
pub(crate) fn temp_id_avs<'a>(&'a self) -> Vec<(TempIdHandle, AVPair)> { pub(crate) fn temp_id_avs(&self) -> Vec<(TempIdHandle, AVPair)> {
let mut temp_id_avs: Vec<(TempIdHandle, AVPair)> = vec![]; let mut temp_id_avs: Vec<(TempIdHandle, AVPair)> = vec![];
// TODO: map/collect. // TODO: map/collect.
for &UpsertE(ref t, ref a, ref v) in &self.upserts_e { for &UpsertE(ref t, ref a, ref v) in &self.upserts_e {
@ -207,41 +238,128 @@ impl Generation {
temp_id_avs temp_id_avs
} }
/// After evolution is complete, yield the set of tempids that require entid allocation. These /// Evolve potential upserts that haven't resolved into allocations.
/// are the tempids that appeared in [:db/add ...] entities, but that didn't upsert to existing pub(crate) fn allocate_unresolved_upserts(&mut self) -> Result<()> {
/// entids. let mut upserts_ev = vec![];
pub(crate) fn temp_ids_in_allocations(&self) -> BTreeSet<TempIdHandle> { ::std::mem::swap(&mut self.upserts_ev, &mut upserts_ev);
self.allocations.extend(
upserts_ev.into_iter().map(|UpsertEV(t1, a, t2)| {
Term::AddOrRetract(OpType::Add, Right(t1), a, Right(t2))
}),
);
Ok(())
}
/// After evolution is complete, yield the set of tempids that require entid allocation.
///
/// Some of the tempids may be identified, so we also provide a map from tempid to a dense set
/// of contiguous integer labels.
pub(crate) fn temp_ids_in_allocations(
&self,
schema: &Schema,
) -> Result<BTreeMap<TempIdHandle, usize>> {
assert!(self.upserts_e.is_empty(), "All upserts should have been upserted, resolved, or moved to the allocated population!"); assert!(self.upserts_e.is_empty(), "All upserts should have been upserted, resolved, or moved to the allocated population!");
assert!(self.upserts_ev.is_empty(), "All upserts should have been upserted, resolved, or moved to the allocated population!"); assert!(self.upserts_ev.is_empty(), "All upserts should have been upserted, resolved, or moved to the allocated population!");
let mut temp_ids: BTreeSet<TempIdHandle> = BTreeSet::default(); let mut temp_ids: BTreeSet<TempIdHandle> = BTreeSet::default();
let mut tempid_avs: BTreeMap<(Entid, TypedValueOr<TempIdHandle>), Vec<TempIdHandle>> =
BTreeMap::default();
for term in self.allocations.iter() { for term in self.allocations.iter() {
match term { match term {
&Term::AddOrRetract(OpType::Add, Right(ref t1), _, Right(ref t2)) => { Term::AddOrRetract(OpType::Add, Right(ref t1), a, Right(ref t2)) => {
temp_ids.insert(t1.clone()); temp_ids.insert(t1.clone());
temp_ids.insert(t2.clone()); temp_ids.insert(t2.clone());
}, let attribute: &Attribute = schema.require_attribute_for_entid(*a)?;
&Term::AddOrRetract(OpType::Add, Right(ref t), _, Left(_)) => { if attribute.unique == Some(attribute::Unique::Identity) {
tempid_avs
.entry((*a, Right(t2.clone())))
.or_insert_with(Vec::new)
.push(t1.clone());
}
}
Term::AddOrRetract(OpType::Add, Right(ref t), a, ref x @ Left(_)) => {
temp_ids.insert(t.clone()); temp_ids.insert(t.clone());
}, let attribute: &Attribute = schema.require_attribute_for_entid(*a)?;
&Term::AddOrRetract(OpType::Add, Left(_), _, Right(ref t)) => { if attribute.unique == Some(attribute::Unique::Identity) {
tempid_avs
.entry((*a, x.clone()))
.or_insert_with(Vec::new)
.push(t.clone());
}
}
Term::AddOrRetract(OpType::Add, Left(_), _, Right(ref t)) => {
temp_ids.insert(t.clone()); temp_ids.insert(t.clone());
}, }
&Term::AddOrRetract(OpType::Add, Left(_), _, Left(_)) => unreachable!(), Term::AddOrRetract(OpType::Add, Left(_), _, Left(_)) => unreachable!(),
&Term::AddOrRetract(OpType::Retract, _, _, _) => { Term::AddOrRetract(OpType::Retract, _, _, _) => {
// [:db/retract ...] entities never allocate entids; they have to resolve due to // [:db/retract ...] entities never allocate entids; they have to resolve due to
// other upserts (or they fail the transaction). // other upserts (or they fail the transaction).
}, }
} }
} }
temp_ids // Now we union-find all the known tempids. Two tempids are unioned if they both appear as
// the entity of an `[a v]` upsert, including when the value column `v` is itself a tempid.
let mut uf = unionfind::UnionFind::new(temp_ids.len());
// The union-find implementation from petgraph operates on contiguous indices, so we need to
// maintain the map from our tempids to indices ourselves.
let temp_ids: BTreeMap<TempIdHandle, usize> = temp_ids
.into_iter()
.enumerate()
.map(|(i, tempid)| (tempid, i))
.collect();
debug!(
"need to label tempids aggregated using tempid_avs {:?}",
tempid_avs
);
for vs in tempid_avs.values() {
if let Some(&first_index) = vs.first().and_then(|first| temp_ids.get(first)) {
for tempid in vs {
temp_ids.get(tempid).map(|&i| uf.union(first_index, i));
}
}
}
debug!("union-find aggregation {:?}", uf.clone().into_labeling());
// Now that we have aggregated tempids, we need to label them using the smallest number of
// contiguous labels possible.
let mut tempid_map: BTreeMap<TempIdHandle, usize> = BTreeMap::default();
let mut dense_labels: indexmap::IndexSet<usize> = indexmap::IndexSet::default();
// We want to produce results that are as deterministic as possible, so we allocate labels
// for tempids in sorted order. This has the effect of making "a" allocate before "b",
// which is pleasant for testing.
for (tempid, tempid_index) in temp_ids {
let rep = uf.find_mut(tempid_index);
dense_labels.insert(rep);
dense_labels
.get_full(&rep)
.map(|(dense_index, _)| tempid_map.insert(tempid.clone(), dense_index));
}
debug!(
"labeled tempids using {} labels: {:?}",
dense_labels.len(),
tempid_map
);
Ok(tempid_map)
} }
/// After evolution is complete, use the provided allocated entids to segment `self` into /// After evolution is complete, use the provided allocated entids to segment `self` into
/// populations, each with no references to tempids. /// populations, each with no references to tempids.
pub(crate) fn into_final_populations(self, temp_id_map: &TempIdMap) -> errors::Result<FinalPopulations> { pub(crate) fn into_final_populations(
self,
temp_id_map: &TempIdMap,
) -> Result<FinalPopulations> {
assert!(self.upserts_e.is_empty()); assert!(self.upserts_e.is_empty());
assert!(self.upserts_ev.is_empty()); assert!(self.upserts_ev.is_empty());
@ -257,23 +375,29 @@ impl Generation {
match (op, temp_id_map.get(&*t1), temp_id_map.get(&*t2)) { match (op, temp_id_map.get(&*t1), temp_id_map.get(&*t2)) {
(op, Some(&n1), Some(&n2)) => Term::AddOrRetract(op, n1, a, TypedValue::Ref(n2.0)), (op, Some(&n1), Some(&n2)) => Term::AddOrRetract(op, n1, a, TypedValue::Ref(n2.0)),
(OpType::Add, _, _) => unreachable!(), // This is a coding error -- every tempid in a :db/add entity should resolve or be allocated. (OpType::Add, _, _) => unreachable!(), // This is a coding error -- every tempid in a :db/add entity should resolve or be allocated.
(OpType::Retract, _, _) => bail!(ErrorKind::NotYetImplemented(format!("[:db/retract ...] entity referenced tempid that did not upsert: one of {}, {}", t1, t2))), (OpType::Retract, _, _) => bail!(DbErrorKind::NotYetImplemented(format!("[:db/retract ...] entity referenced tempid that did not upsert: one of {}, {}", t1, t2))),
} }
}, }
Term::AddOrRetract(op, Right(t), a, Left(v)) => { Term::AddOrRetract(op, Right(t), a, Left(v)) => {
match (op, temp_id_map.get(&*t)) { match (op, temp_id_map.get(&*t)) {
(op, Some(&n)) => Term::AddOrRetract(op, n, a, v), (op, Some(&n)) => Term::AddOrRetract(op, n, a, v),
(OpType::Add, _) => unreachable!(), // This is a coding error. (OpType::Add, _) => unreachable!(), // This is a coding error.
(OpType::Retract, _) => bail!(ErrorKind::NotYetImplemented(format!("[:db/retract ...] entity referenced tempid that did not upsert: {}", t))), (OpType::Retract, _) => bail!(DbErrorKind::NotYetImplemented(format!(
"[:db/retract ...] entity referenced tempid that did not upsert: {}",
t
))),
} }
}, }
Term::AddOrRetract(op, Left(e), a, Right(t)) => { Term::AddOrRetract(op, Left(e), a, Right(t)) => {
match (op, temp_id_map.get(&*t)) { match (op, temp_id_map.get(&*t)) {
(op, Some(&n)) => Term::AddOrRetract(op, e, a, TypedValue::Ref(n.0)), (op, Some(&n)) => Term::AddOrRetract(op, e, a, TypedValue::Ref(n.0)),
(OpType::Add, _) => unreachable!(), // This is a coding error. (OpType::Add, _) => unreachable!(), // This is a coding error.
(OpType::Retract, _) => bail!(ErrorKind::NotYetImplemented(format!("[:db/retract ...] entity referenced tempid that did not upsert: {}", t))), (OpType::Retract, _) => bail!(DbErrorKind::NotYetImplemented(format!(
"[:db/retract ...] entity referenced tempid that did not upsert: {}",
t
))),
} }
}, }
Term::AddOrRetract(_, Left(_), _, Left(_)) => unreachable!(), // This is a coding error -- these should not be in allocations. Term::AddOrRetract(_, Left(_), _, Left(_)) => unreachable!(), // This is a coding error -- these should not be in allocations.
}; };
populations.allocated.push(allocated); populations.allocated.push(allocated);

View file

@ -17,19 +17,13 @@
// - When observers are registered we want to flip some flags as writes occur so that we can // - When observers are registered we want to flip some flags as writes occur so that we can
// notifying them outside the transaction. // notifying them outside the transaction.
use mentat_core::{ use core_traits::{Entid, TypedValue};
Entid,
Schema,
TypedValue,
};
use mentat_tx::entities::{ use mentat_core::Schema;
OpType,
};
use errors::{ use edn::entities::OpType;
Result,
}; use db_traits::errors::Result;
pub trait TransactWatcher { pub trait TransactWatcher {
fn datom(&mut self, op: OpType, e: Entid, a: Entid, v: &TypedValue); fn datom(&mut self, op: OpType, e: Entid, a: Entid, v: &TypedValue);
@ -44,8 +38,7 @@ pub trait TransactWatcher {
pub struct NullWatcher(); pub struct NullWatcher();
impl TransactWatcher for NullWatcher { impl TransactWatcher for NullWatcher {
fn datom(&mut self, _op: OpType, _e: Entid, _a: Entid, _v: &TypedValue) { fn datom(&mut self, _op: OpType, _e: Entid, _a: Entid, _v: &TypedValue) {}
}
fn done(&mut self, _t: &Entid, _schema: &Schema) -> Result<()> { fn done(&mut self, _t: &Entid, _schema: &Schema) -> Result<()> {
Ok(()) Ok(())

View file

@ -8,8 +8,8 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
extern crate core_traits;
extern crate edn; extern crate edn;
extern crate mentat_core;
extern crate mentat_db; extern crate mentat_db;
extern crate ordered_float; extern crate ordered_float;
extern crate rusqlite; extern crate rusqlite;
@ -18,41 +18,105 @@ use ordered_float::OrderedFloat;
use edn::symbols; use edn::symbols;
use mentat_core::{TypedValue, ValueType}; use core_traits::{TypedValue, ValueType};
use mentat_db::db::TypedSQLValue; use mentat_db::db::TypedSQLValue;
// It's not possible to test to_sql_value_pair since rusqlite::ToSqlOutput doesn't implement // It's not possible to test to_sql_value_pair since rusqlite::ToSqlOutput doesn't implement
// PartialEq. // PartialEq.
#[test] #[test]
fn test_from_sql_value_pair() { fn test_from_sql_value_pair() {
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1234), 0).unwrap(), TypedValue::Ref(1234)); assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1234), 0).unwrap(),
TypedValue::Ref(1234)
);
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(0), 1).unwrap(), TypedValue::Boolean(false)); assert_eq!(
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1), 1).unwrap(), TypedValue::Boolean(true)); TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(0), 1).unwrap(),
TypedValue::Boolean(false)
);
assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1), 1).unwrap(),
TypedValue::Boolean(true)
);
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(0), 5).unwrap(), TypedValue::Long(0)); assert_eq!(
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1234), 5).unwrap(), TypedValue::Long(1234)); TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(0), 5).unwrap(),
TypedValue::Long(0)
);
assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Integer(1234), 5).unwrap(),
TypedValue::Long(1234)
);
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Real(0.0), 5).unwrap(), TypedValue::Double(OrderedFloat(0.0))); assert_eq!(
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Real(0.5), 5).unwrap(), TypedValue::Double(OrderedFloat(0.5))); TypedValue::from_sql_value_pair(rusqlite::types::Value::Real(0.0), 5).unwrap(),
TypedValue::Double(OrderedFloat(0.0))
);
assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Real(0.5), 5).unwrap(),
TypedValue::Double(OrderedFloat(0.5))
);
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Text(":db/keyword".into()), 10).unwrap(), TypedValue::typed_string(":db/keyword")); assert_eq!(
assert_eq!(TypedValue::from_sql_value_pair(rusqlite::types::Value::Text(":db/keyword".into()), 13).unwrap(), TypedValue::typed_ns_keyword("db", "keyword")); TypedValue::from_sql_value_pair(rusqlite::types::Value::Text(":db/keyword".into()), 10)
.unwrap(),
TypedValue::typed_string(":db/keyword")
);
assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Text(":db/keyword".into()), 13)
.unwrap(),
TypedValue::typed_ns_keyword("db", "keyword")
);
assert_eq!(
TypedValue::from_sql_value_pair(rusqlite::types::Value::Blob(vec![1, 2, 3, 42]), 15)
.unwrap(),
TypedValue::Bytes((vec![1, 2, 3, 42]).into())
);
} }
#[test] #[test]
fn test_to_edn_value_pair() { fn test_to_edn_value_pair() {
assert_eq!(TypedValue::Ref(1234).to_edn_value_pair(), (edn::Value::Integer(1234), ValueType::Ref)); assert_eq!(
TypedValue::Ref(1234).to_edn_value_pair(),
(edn::Value::Integer(1234), ValueType::Ref)
);
assert_eq!(TypedValue::Boolean(false).to_edn_value_pair(), (edn::Value::Boolean(false), ValueType::Boolean)); assert_eq!(
assert_eq!(TypedValue::Boolean(true).to_edn_value_pair(), (edn::Value::Boolean(true), ValueType::Boolean)); TypedValue::Boolean(false).to_edn_value_pair(),
(edn::Value::Boolean(false), ValueType::Boolean)
);
assert_eq!(
TypedValue::Boolean(true).to_edn_value_pair(),
(edn::Value::Boolean(true), ValueType::Boolean)
);
assert_eq!(TypedValue::Long(0).to_edn_value_pair(), (edn::Value::Integer(0), ValueType::Long)); assert_eq!(
assert_eq!(TypedValue::Long(1234).to_edn_value_pair(), (edn::Value::Integer(1234), ValueType::Long)); TypedValue::Long(0).to_edn_value_pair(),
(edn::Value::Integer(0), ValueType::Long)
);
assert_eq!(
TypedValue::Long(1234).to_edn_value_pair(),
(edn::Value::Integer(1234), ValueType::Long)
);
assert_eq!(TypedValue::Double(OrderedFloat(0.0)).to_edn_value_pair(), (edn::Value::Float(OrderedFloat(0.0)), ValueType::Double)); assert_eq!(
assert_eq!(TypedValue::Double(OrderedFloat(0.5)).to_edn_value_pair(), (edn::Value::Float(OrderedFloat(0.5)), ValueType::Double)); TypedValue::Double(OrderedFloat(0.0)).to_edn_value_pair(),
(edn::Value::Float(OrderedFloat(0.0)), ValueType::Double)
);
assert_eq!(
TypedValue::Double(OrderedFloat(0.5)).to_edn_value_pair(),
(edn::Value::Float(OrderedFloat(0.5)), ValueType::Double)
);
assert_eq!(TypedValue::typed_string(":db/keyword").to_edn_value_pair(), (edn::Value::Text(":db/keyword".into()), ValueType::String)); assert_eq!(
assert_eq!(TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(), (edn::Value::NamespacedKeyword(symbols::NamespacedKeyword::new("db", "keyword")), ValueType::Keyword)); TypedValue::typed_string(":db/keyword").to_edn_value_pair(),
(edn::Value::Text(":db/keyword".into()), ValueType::String)
);
assert_eq!(
TypedValue::typed_ns_keyword("db", "keyword").to_edn_value_pair(),
(
edn::Value::Keyword(symbols::Keyword::namespaced("db", "keyword")),
ValueType::Keyword
)
);
} }

3
docs/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
_site
.sass-cache
.jekyll-metadata

24
docs/404.html Normal file
View file

@ -0,0 +1,24 @@
---
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>

View file

@ -1,3 +1,9 @@
---
layout: page
title: Contributing
permalink: /contributing/
---
# How to contribute to Project Mentat # How to contribute to Project Mentat
This project is very new, so we'll probably revise these guidelines. Please This project is very new, so we'll probably revise these guidelines. Please

32
docs/Gemfile Normal file
View file

@ -0,0 +1,32 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
# gem "jekyll", "~> 3.7.3"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima", "~> 2.5.1"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.15.1"
gem "github-pages", "~> 215"
gem "jekyll-commonmark-ghpages", "~> 0.1.6"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0" if Gem.win_platform?

277
docs/Gemfile.lock Normal file
View file

@ -0,0 +1,277 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.9)
dnsruby (1.61.7)
simpleidn (~> 0.1)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.14.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.8.1)
faraday (1.4.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.1.0)
ffi (1.15.3)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (215)
github-pages-health-check (= 1.17.2)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.6)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.7.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.2)
jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1)
jekyll-theme-minimal (= 0.1.1)
jekyll-theme-modernist (= 0.1.1)
jekyll-theme-primer (= 0.5.4)
jekyll-theme-slate (= 0.1.1)
jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.1)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.10.4, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (>= 2.0.2, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.6)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1.2)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.7.1)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.2)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.5.4)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.12.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.5.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.6.1)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.14.4)
multipart-post (2.1.1)
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
racc (~> 1.4)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
racc (1.5.2)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
ruby-enum (0.9.0)
i18n
ruby2_keywords (0.0.4)
rubyzip (2.3.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
zeitwerk (2.4.2)
PLATFORMS
ruby
DEPENDENCIES
github-pages (~> 215)
jekyll-commonmark-ghpages (~> 0.1.6)
jekyll-feed (~> 0.15.1)
minima (~> 2.5.1)
tzinfo-data
BUNDLED WITH
2.2.21

18
docs/README.md Normal file
View file

@ -0,0 +1,18 @@
# Project Mentat Documentation Site
This site is a place to provide the users of Mentat with all the documentation, examples and tutorials required in order to use Mentat inside a project.
This site will contain the following:
- API Documentation for Mentat and it's SDKs.
- Tutorials for cross compilation of Mentat for other platforms. (Coming)
- Examples of how to design data for storage in Mentat.
- Examples of how to use Mentat and it's SDKs. (Coming)
- Quick Start Guides for installing and using Mentat. (Coming)
# Build and run locally
1. Install [Jekyll](https://jekyllrb.com/docs/installation/)
2. `cd docs`
3. `bundle exec jekyll serve --incremental`
4. open local docs site at http://127.0.0.1:4000/

43
docs/_config.yml Normal file
View file

@ -0,0 +1,43 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Mentat
description: >- # this means to ignore newlines until "baseurl:"
Project Mentat is a persistent, embedded knowledge base. It draws heavily on DataScript and Datomic.
Mentat is intended to be a flexible relational (not key-value, not document-oriented) store that makes
it easy to describe, grow, and reuse your domain schema.
baseurl: /mentat # the subpath of your site, e.g. /blog
url: https://mozilla.github.io # the base hostname & protocol for your site, e.g. http://example.com
api_heading: API Documentation
list_title: Examples
# Build settings
markdown: kramdown
theme: minima
plugins:
- jekyll-feed
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
# exclude:
# - Gemfile
# - Gemfile.lock
# - node_modules
# - vendor/bundle/
# - vendor/cache/
# - vendor/gems/
# - vendor/ruby/

View file

@ -0,0 +1,24 @@
<footer class="site-footer h-card">
<data class="u-url" href="{{ "/" | relative_url }}"></data>
<div class="wrapper">
<!-- <h2 class="footer-heading"></h2> -->
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li class="p-name">{{ site.title }}</li>
</ul>
</div>
<div class="footer-col footer-col-2">
</div>
<div class="footer-col footer-col-3">
<p>Project Mentat is currently licensed under the Apache License v2.0.</p>
</div>
</div>
</div>
</footer>

View file

@ -0,0 +1,30 @@
<header class="site-header" role="banner">
<div class="wrapper">
{%- assign default_paths = site.pages | map: "path" -%}
{%- assign page_paths = site.header_pages | default: default_paths -%}
<a class="site-title" rel="author" href="{{ "/" | relative_url }}">{{ site.title | escape }}</a>
{%- if page_paths -%}
<nav class="site-nav">
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger">
<span class="menu-icon">
<svg viewBox="0 0 18 15" width="18px" height="15px">
<path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
</svg>
</span>
</label>
<div class="trigger">
{%- for path in page_paths -%}
{%- assign my_page = site.pages | where: "path", path | first -%}
{%- if my_page.title -%}
<a class="page-link" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
{%- endif -%}
{%- endfor -%}
</div>
</nav>
{%- endif -%}
</div>
</header>

21
docs/_layouts/home.html Normal file
View file

@ -0,0 +1,21 @@
---
layout: default
---
<div class="home">
{{ content }}
{%- if site.posts.size > 0 -%}
{% assign posts_by_cat = site.posts | group_by:"category" %}
{% for category in posts_by_cat %}
<h2>{{category.name | capitalize}}</h2>
<ul class="post-list">
{% for post in category.items %}
<li><a href="{{post.url | relative_url}}">{{post.title | escape}}</a></li>
{% endfor %}
</ul>
{% endfor %}
{%- endif -%}
</div>

14
docs/_layouts/page.html Normal file
View file

@ -0,0 +1,14 @@
---
layout: default
---
<article class="post">
<header class="post-header">
<h1 class="post-title">{{ page.title | escape }}</h1>
</header>
<div class="post-content">
{{ content }}
</div>
</article>

27
docs/_layouts/post.html Normal file
View file

@ -0,0 +1,27 @@
---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
<p class="post-meta">
<time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
{%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
{{ page.date | date: date_format }}
</time>
{%- if page.author -%}
<span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">{{ page.author }}</span></span>
{%- endif -%}</p>
</header>
<div class="post-content e-content" itemprop="articleBody">
{{ content }}
</div>
{%- if site.disqus.shortname -%}
{%- include disqus_comments.html -%}
{%- endif -%}
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>

View file

@ -0,0 +1,396 @@
---
layout: post
list_title: Examples
title: "Modeling data using Mentat"
date: 2018-04-17 16:07:37 +0100
category: examples
---
# Worked examples of modeling data using Mentat
Used correctly, Mentat makes it easy for you to grow to accommodate new kinds of data, for data to synchronize between devices, for multiple consumers to share data, and even for errors to be fixed.
But what does "correctly" mean?
The following discussion and set of worked examples aim to help. During discussion sections a simplified syntax is used for schema examples.
## Principles
### Think about the domain, not about your UI
Given a set of mockups, or an MVP list of requirements, it's easy to leap into defining a data model that supports exactly those things. In doing so we will likely end up with a data model that can't support future capabilities, or that has crucial mismatches with the real world.
For example, one might design a contact manager UI like macOS's — a list of string fields for a person:
* First name
* Last name
* Address line 1
* Address line 2
* Phone
* _etc._
We might model this in Mentat as simple value properties:
```edn
[:person/name :db.type/string :db.cardinality/one] ; Incorrect: people can have many names!
[:person/home_address_line_one :db.type/string :db.cardinality/one]
[:person/home_address_line_two :db.type/string :db.cardinality/one]
[:person/home_city :db.type/string :db.cardinality/one]
[:person/home_phone :db.type/string :db.cardinality/one]
```
or in JSON as a simple object:
```json
{
"name": "Alice Smith",
"home_address_line_one": "123 Main St",
"home_city": "Anywhere",
"home_phone": "555-867-5309"
}
```
We might realize that this proliferation of attributes is going in the wrong direction, and add nested structure:
```json
{
"name": "Alice Smith",
"home_address": {
"line_one": "123 Main St",
"city": "Anywhere"
}}
```
(quick, is a home phone number a property of the address or the person?)
Or we might allow for some people having multiple addresses and multiple homes:
```json
{"name": "Alice Smith",
"addresses": [{
"type": "home",
"line_one": "123 Main St",
"city": "Anywhere"
}]}
```
There are [lots of reasons the address model is wrong](https://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/), and [the same is true of names](https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/). But even the _structure_ of this is wrong, when you think about it.
A _physical place_, for our purposes, has an address. (It might have more than one.)
Each place might play a number of _roles_ to a number of people: the same house is the home of everyone who lives there, and the same business address is one of the work addresses for each employee. If I work from home, my work and business addresses are the same. It's not quite true to say that an address is a "home": an address _identifies_ a _place_, and that place _is a home to a person_.
But a typical contact application gets this wrong: the same _strings_ are duplicated (flattened and denormalized) into the independent contact records of each person. If a business moves location, or its building is renamed, we must change the addresses of multiple contacts.
A more correct model for this is _relational_:
```edn
[:person/name :db.type/string :db.cardinality/one]
[:person/lives_at :db.type/ref :db.cardinality/many] ; Points to a place.
[:person/works_at :db.type/ref :db.cardinality/many] ; Points to a place.
[:place/address :db.type/ref :db.cardinality/many] ; A place can have multiple addresses.
[:address/mailing_address :db.type/string :db.cardinality/one ; Each address can be represented once as a string.
:db.unique/identity]
[:address/city :db.type/string :db.cardinality/one] ; Perhaps this is useful?
```
Imagine that Alice works from home, and Bob works at his office on South Street. Alice's data looks like this:
```edn
[{:person/name "Alice Smith"
:person/lives_at "alice_home"
:person/works_at "alice_home"}
{:db/id "alice_home"
:place/address "main_street_123"}
{:db/id "main_street_123"
:address/mailing_address "123 Main St, Anywhere, WA 12345, USA"
:address/city "Anywhere"}]
```
and Bob's like this:
```edn
[{:person/name "Bob Salmon"
:person/works_at "bob_office"}
{:db/id "bob_office"
:place/owner "Example Holdings LLC"
:place/address "south_street_555"}
{:db/id "south_street_555"
:address/mailing_address "555 South St, Anywhere, WA 12345, USA"
:address/city "Anywhere"}]
```
Now if Alice (ID 1234) moves her business out of her house (1235) into an office in Bob's building (1236), we simply break one relationship and add a new one to a new place with the same address:
```edn
[[:db/retract 1234 :person/works_at 1235] ; Alice no longer works at home.
[:db/add 1234 :person/works_at "new_office"]
{:db/id "new_office"
:place/address [:address/mailing_address "555 South St, Anywhere, WA 12345, USA"]}]
```
If the building is now renamed to "The Office Factory", we can update its address in one step, affecting both Alice's and Bob's offices:
```edn
[[:db/retract 1236 :address/mailing_address "555 South St, Anywhere, WA 12345, USA"]
[:db/add 1236 :address/mailing_address "The Office Factory, South St, Anywhere, WA 12345, USA"]]
```
You can see here how changes are minimal and correspond to real changes in the domain — two properties that help with syncing. There is no duplication of strings.
We can find everyone who works at The Office Factory in a simple query without comparing strings across 'records':
```edn
[:find ?name
:where [?address :address/mailing_address "The Office Factory, South St, Anywhere, WA 12345, USA"]
[?office :place/address ?address]
[?person :person/works_at ?office]
[?person :person/name ?name]]
```
Let's say we later want to model move-in and move-out dates — useful for employment records and immigration paperwork!
Trying to add this to the JSON model is an exercise in frustration, because there is no stable way to identify people or places! (Go ahead, try it.)
To do it in Mentat simply requires defining a small bit of vocabulary:
```edn
[:place.change/person :db.type/ref :db.cardinality/many]
[:place.change/from :db.type/ref :db.cardinality/one] ; optional
[:place.change/to :db.type/ref :db.cardinality/one] ; optional
[:place.change/role :db.type/ref :db.cardinality/one] ; :person/lives_at or :person/works_at
[:place.change/on :db.type/instant :db.cardinality/one]
[:place.change/reason :db.type/string :db.cardinality/one] ; optional
```
so we can describe Alice's office move:
```edn
[{:place.change/person 1234
:place.change/from 1235
:place.change/to 1237
:place.change/role :person/works_at
:place.change/on #inst "2018-02-02T13:00:00Z"}]
```
or Jane's sale of her holiday home:
```edn
[{:place.change/person 2468
:place.change/reason "Sale"
:place.change/from 1235
:place.change/role :person/lives_at
:place.change/on #inst "2018-08-12T14:00:00Z"}]
```
Note that we don't need to repeat the addresses, we don't need to change the existing data, and we don't need to complicate matters for existing code.
Now we can find everyone who moved office in February:
```edn
[:find ?name
:where [?move :place.change/role :person/works_at]
[?move :place.change/on ?on]
[(>= ?on #inst "2018-02-01T00:00:00Z")]
[(< ?on #inst "2018-03-01T00:00:00Z")]
[?move :place.change/person ?person]
[?person :person/name ?name]]
```
## Tend towards recording observations, not changing state
These principles are all different aspects of normalization.
The introduction of fine-grained entities to represent data pushes us towards immutability: changes are increasingly changing an 'arrow' to point at one immutable entity or another, rather than re-describing a mutable entity.
In the previous example we introduced _places_ and _addresses_. Places and addresses themselves rarely change, allowing us to mostly isolate the churn in our data to the meaningful relationships between entities.
Another example of this approach is shown in modeling browser history.
Firefox's representation of history is, at its core, relatively simplistic; just two tables a little like this:
```sql
CREATE TABLE history (
id INTEGER PRIMARY KEY,
guid TEXT NOT NULL UNIQUE,
url TEXT NOT NULL UNIQUE,
title TEXT
);
CREATE TABLE visits (
id INTEGER PRIMARY KEY,
history_id INTEGER NOT NULL REFERENCES history(id),
type TINYINT,
timestamp INTEGER
);
```
Each time a URL is visited, an entry is added to the `visits` table and a row is added or updated in `history`. The title of the fetched page is used to update `history.title`, so that `history.title` always represents the most recently encountered title.
This works fine until more features are added.
### Forgetting
Browsers often have some capacity for deleting history. Sometimes this appears in the form of an explicit 'forget' operation — "Forget the last five minutes of browsing". Deleting visits in this way is fine: `DELETE FROM visits WHERE timestamp < ?`. But the mutability in the data model — title — trips us up. We're unable to roll back the title of the history entry.
### Syncing
But even if you are using Mentat or Datomic, and can turn to the log to reconstruct the old state, a mutable title on `history` will cause conflicts when syncing: one side's observed titles will 'lose' and be discarded in order to avoid a conflict. That's not right: those titles _were seen_. Unlike a conflicting counter or flag, these weren't abortive, temporary states; they were _observations of the world_, so there shouldn't be a winner and a loser.
### Containers
The true data model becomes apparent when we consider containers. Containers are a Firefox feature to sandbox the cookies, site data, and history of different named sub-profiles. You can have a container just for Facebook, or one for your banking; those Facebook cookies won't follow you around the web in your 'personal' container. You can simultaneously use separate Gmail accounts for work and personal email.
When Firefox added container support, it did so by annotating visits with a `container`:
```sql
CREATE TABLE visits (
id INTEGER PRIMARY KEY,
history_id INTEGER NOT NULL REFERENCES history(id),
type TINYINT,
timestamp INTEGER,
container INTEGER
);
```
This means that each container _competes for the title on `history`_. If you visit `facebook.com` in your usual logged-in container, the browser will run something like this SQL:
```
UPDATE TABLE history
SET title = '(2) Facebook'
WHERE url = 'https://www.facebook.com';
```
If you visit it in the wrong container by mistake, you'll get the Facebook login page, and Firefox will run:
```
UPDATE TABLE history
SET title = 'Facebook - Log In or Sign Up'
WHERE url = 'https://www.facebook.com';
```
Next time you open your history, _you'll see the login page title, even if you had a logged-in `facebook.com` session open in another tab_. There's no way to differentiate between the containers' views.
The correct data model for history is:
- Users visit a URL on a device in a container.
- Pages are fetched as a result of a visit (or dynamically after load). Pages can embed media and other resources.
- Pages, being HTML, have titles.
- Pages, titles, and visits are all _observations_, and as such cannot conflict.
- The _last observed_ title to show for a URL is an _aggregation_ of those events.
The entire notion of a history table — a concept centered on the URL — having a title is a subtly incorrect choice that causes problems with more modern browser features.
Modeled in Mentat:
```edn
[{:db/ident :visit/visitedOnDevice
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one}
{:db/ident :visit/visitAt
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one}
{:db/ident :site/visit
:db/valueType :db.type/ref
:db/isComponent true
:db/cardinality :db.cardinality/many}
{:db/ident :site/url
:db/valueType :db.type/string
:db/unique :db.unique/identity
:db/cardinality :db.cardinality/one
:db/index true}
{:db/ident :visit/page
:db/valueType :db.type/ref
:db/isComponent true ; Debatable.
:db/cardinality :db.cardinality/one}
{:db/ident :page/title
:db/valueType :db.type/string
:db/fulltext true
:db/index true
:db/cardinality :db.cardinality/one}
{:db/ident :visit/container
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one}]
```
Create some containers:
```edn
[{:db/ident :container/facebook}
{:db/ident :container/personal}]
```
Add a device:
```edn
[{:db/ident :device/my-desktop}]
```
Visit Facebook in each container:
```edn
[{:visit/visitedOnDevice :device/my-desktop
:visit/visitAt #inst "2018-04-06T18:46:00Z"
:visit/container :container/facebook
:db/id "fbvisit"
:visit/page "fbpage"}
{:db/id "fbpage"
:page/title "(2) Facebook"}
{:site/url "https://www.facebook.com"
:site/visit "fbvisit"}]
```
```edn
[{:visit/visitedOnDevice :device/my-desktop
:visit/visitAt #inst "2018-04-06T18:46:02Z"
:visit/container :container/personal
:db/id "personalvisit"
:visit/page "personalpage"}
{:db/id "personalpage"
:page/title "Facebook - Log In or Sign Up"}
{:site/url "https://www.facebook.com"
:site/visit "personalvisit"}]
```
Now we can show the title from the latest visit in a given container:
```edn
.q [:find (max ?visitDate) (the ?title)
:where [?site :site/url "https://www.facebook.com"]
[?site :site/visit ?visit]
[?visit :visit/container :container/facebook]
[?visit :visit/visitAt ?visitDate]
[?visit :visit/page ?page]
[?page :page/title ?title]]
=>
| (the ?title) | (max ?visitDate) |
--- ---
| "(2) Facebook" | 2018-04-06 18:46:00 UTC |
--- ---
.q [:find (the ?title) (max ?visitDate)
:where [?site :site/url "https://www.facebook.com"]
[?site :site/visit ?visit]
[?visit :visit/container :container/personal]
[?visit :visit/visitAt ?visitDate]
[?visit :visit/page ?page]
[?page :page/title ?title]]
=>
| (the ?title) | (max ?visitDate) |
--- ---
| "Facebook - Log In or Sign Up" | 2018-04-06 18:46:02 UTC |
--- ---
```
## Normalize; you can always denormalize for use.
To come.
## Use unique identities and cardinality-one attributes to make merging happen during a sync.
To come.
## Reify to handle conflict and atomicity.
To come.

122
docs/about.md Normal file
View file

@ -0,0 +1,122 @@
---
layout: page
title: About
permalink: /about/
---
# Project Mentat
Project Mentat is a persistent, embedded knowledge base. It draws heavily on [DataScript](https://github.com/tonsky/datascript) and [Datomic](http://datomic.com).
Mentat is implemented in Rust.
The first version of Project Mentat, named Datomish, [was written in ClojureScript](https://github.com/mozilla/mentat/tree/clojure), targeting both Node (on top of `promise_sqlite`) and Firefox (on top of `Sqlite.jsm`). It also worked in pure Clojure on the JVM on top of `jdbc-sqlite`. The name was changed to avoid confusion with [Datomic](http://datomic.com).
The Rust implementation gives us a smaller compiled output, better performance, more type safety, better tooling, and easier deployment into Firefox and mobile platforms.
---
## Motivation
Mentat is intended to be a flexible relational (not key-value, not document-oriented) store that makes it easy to describe, grow, and reuse your domain schema.
By abstracting away the storage schema, and by exposing change listeners outside the database (not via triggers), we hope to make domain schemas stable, and allow both the data store itself and embedding applications to use better architectures, meeting performance goals in a way that allows future evolution.
## Data storage is hard
We've observed that data storage is a particular area of difficulty for software development teams:
- It's hard to define storage schemas well. A developer must:
- Model their domain entities and relationships.
- Encode that model _efficiently_ and _correctly_ using the features available in the database.
- Plan for future extensions and performance tuning.
In a SQL database, the same schema definition defines everything from high-level domain relationships through to numeric field sizes in the same smear of keywords. It's difficult for someone unfamiliar with the domain to determine from such a schema what's a domain fact and what's an implementation concession — are all part numbers always 16 characters long, or are we trying to save space? — or, indeed, whether a missing constraint is deliberate or a bug.
The developer must think about foreign key constraints, compound uniqueness, and nullability. They must consider indexing, synchronizing, and stable identifiers. Most developers simply don't do enough work in SQL to get all of these things right. Storage thus becomes the specialty of a few individuals.
Which one of these is correct?
```edn
{:db/id :person/email
:db/valueType :db.type/string
:db/cardinality :db.cardinality/many ; People can have multiple email addresses.
:db/unique :db.unique/identity ; For our purposes, each email identifies one person.
:db/index true} ; We want fast lookups by email.
{:db/id :person/friend
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many} ; People can have many friends.
```
```sql
CREATE TABLE people (
id INTEGER PRIMARY KEY, -- Bug: because of the primary key, each person can have no more than 1 email.
email VARCHAR(64), -- Bug?: no NOT NULL, so a person can have no email.
-- Bug: nobody will ever have a long email address, right?
);
CREATE TABLE friendships (
FOREIGN KEY person REFERENCES people(id), -- Bug?: no indexing, so lookups by friend or person will be slow.
FOREIGN KEY friend REFERENCES people(id), -- Bug: no compound uniqueness constraint, so we can have dupe friendships.
);
```
They both have limitations — the Mentat schema allows only for an open world (it's possible to declare friendships with people whose email isn't known), and requires validation code to enforce email string correctness — but we think that even such a tiny SQL example is harder to understand and obscures important domain decisions.
- Queries are intimately tied to structural storage choices. That not only hides the declarative domain-level meaning of the query — it's hard to tell what a query is trying to do when it's a 100-line mess of subqueries and `LEFT OUTER JOIN`s — but it also means a simple structural schema change requires auditing _every query_ for correctness.
- Developers often capture less event-shaped than they perhaps should, simply because their initial requirements don't warrant it. It's quite common to later want to [know when a fact was recorded](https://bugzilla.mozilla.org/show_bug.cgi?id=1341939), or _in which order_ two facts were recorded (particularly for migrations), or on which device an event took place… or even that a fact was _ever_ recorded and then deleted.
- Common queries are hard. Storing values only once, upserts, complicated joins, and group-wise maxima are all difficult for non-expert developers to get right.
- It's hard to evolve storage schemas. Writing a robust SQL schema migration is hard, particularly if a bad migration has ever escaped into the wild! Teams learn to fear and avoid schema changes, and eventually they ship a table called `metadata`, with three `TEXT` columns, so they never have to write a migration again. That decision pushes storage complexity into application code. (Or they start storing unversioned JSON blobs in the database…)
- It's hard to share storage with another component, let alone share _data_ with another component. Conway's Law applies: your software system will often grow to have one database per team.
- It's hard to build efficient storage and querying architectures. Materialized views require knowledge of triggers, or the implementation of bottleneck APIs. _Ad hoc_ caches are often wrong, are almost never formally designed (do you want a write-back, write-through, or write-around cache? Do you know the difference?), and often aren't reusable. The average developer, faced with a SQL database, has little choice but to build a simple table that tries to meet every need.
## Comparison to DataScript
DataScript asks the question: "What if creating a database were as cheap as creating a Hashmap?"
Mentat is not interested in that. Instead, it's strongly interested in persistence and performance, with very little interest in immutable databases/databases as values or throwaway use.
One might say that Mentat's question is: "What if an SQLite database could store arbitrary relations, for arbitrary consumers, without them having to coordinate an up-front storage-level schema?"
(Note that [domain-level schemas are very valuable](http://martinfowler.com/articles/schemaless/).)
Another possible question would be: "What if we could bake some of the concepts of [CQRS and event sourcing](http://www.baeldung.com/cqrs-event-sourced-architecture-resources) into a persistent relational store, such that the transaction log itself were of value to queries?"
Some thought has been given to how databases as values — long-term references to a snapshot of the store at an instant in time — could work in this model. It's not impossible; it simply has different performance characteristics.
Just like DataScript, Mentat speaks Datalog for querying and takes additions and retractions as input to a transaction.
Unlike DataScript, Mentat exposes free-text indexing, thanks to SQLite.
## Comparison to Datomic
Datomic is a server-side, enterprise-grade data storage system. Datomic has a beautiful conceptual model. It's intended to be backed by a storage cluster, in which it keeps index chunks forever. Index chunks are replicated to peers, allowing it to run queries at the edges. Writes are serialized through a transactor.
Many of these design decisions are inapplicable to deployed desktop software; indeed, the use of multiple JVM processes makes Datomic's use in a small desktop app, or a mobile device, prohibitive.
Mentat was designed for embedding, initially in an experimental Electron app ([Tofino](https://github.com/mozilla/tofino)). It is less concerned with exposing consistent database states outside transaction boundaries, because that's less important here, and dropping some of these requirements allows us to leverage SQLite itself.
## Comparison to SQLite
SQLite is a traditional SQL database in most respects: schemas conflate semantic, structural, and datatype concerns, as described above; the main interface with the database is human-first textual queries; sparse and graph-structured data are 'unnatural', if not always inefficient; experimenting with and evolving data models are error-prone and complicated activities; and so on.
Mentat aims to offer many of the advantages of SQLite — single-file use, embeddability, and good performance — while building a more relaxed, reusable, and expressive data model on top.
---
## Contributing
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms.
See [CONTRIBUTING.md](/CONTRIBUTING/) for further notes.
This project is very new, so we'll probably revise these guidelines. Please
comment on an issue before putting significant effort in if you'd like to
contribute.

View file

@ -0,0 +1,60 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>All Classes</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<h1 class="bar">All&nbsp;Classes</h1>
<div class="indexContainer">
<ul>
<li><a href="org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat" target="classFrame">CacheDirection</a></li>
<li><a href="org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat" target="classFrame">CollResult</a></li>
<li><a href="org/mozilla/mentat/CollResultHandler.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">CollResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat" target="classFrame">ColResultIterator</a></li>
<li><a href="org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat" target="classFrame">EntityBuilder</a></li>
<li><a href="org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat" target="classFrame">InProgress</a></li>
<li><a href="org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat" target="classFrame">InProgressBuilder</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat" target="classFrame">InProgressTransactionResult</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.ByReference.html" title="class in org.mozilla.mentat" target="classFrame">InProgressTransactionResult.ByReference</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.ByValue.html" title="class in org.mozilla.mentat" target="classFrame">InProgressTransactionResult.ByValue</a></li>
<li><a href="org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">JNA</span></a></li>
<li><a href="org/mozilla/mentat/JNA.EntityBuilder.html" title="class in org.mozilla.mentat" target="classFrame">JNA.EntityBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.InProgress.html" title="class in org.mozilla.mentat" target="classFrame">JNA.InProgress</a></li>
<li><a href="org/mozilla/mentat/JNA.InProgressBuilder.html" title="class in org.mozilla.mentat" target="classFrame">JNA.InProgressBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.QueryBuilder.html" title="class in org.mozilla.mentat" target="classFrame">JNA.QueryBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.RelResult.html" title="class in org.mozilla.mentat" target="classFrame">JNA.RelResult</a></li>
<li><a href="org/mozilla/mentat/JNA.RelResultIter.html" title="class in org.mozilla.mentat" target="classFrame">JNA.RelResultIter</a></li>
<li><a href="org/mozilla/mentat/JNA.Store.html" title="class in org.mozilla.mentat" target="classFrame">JNA.Store</a></li>
<li><a href="org/mozilla/mentat/JNA.TxReport.html" title="class in org.mozilla.mentat" target="classFrame">JNA.TxReport</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValue.html" title="class in org.mozilla.mentat" target="classFrame">JNA.TypedValue</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValueList.html" title="class in org.mozilla.mentat" target="classFrame">JNA.TypedValueList</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValueListIter.html" title="class in org.mozilla.mentat" target="classFrame">JNA.TypedValueListIter</a></li>
<li><a href="org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat" target="classFrame">Mentat</a></li>
<li><a href="org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat" target="classFrame">Query</a></li>
<li><a href="org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat" target="classFrame">RelResult</a></li>
<li><a href="org/mozilla/mentat/RelResultHandler.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">RelResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat" target="classFrame">RelResultIterator</a></li>
<li><a href="org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat" target="classFrame">RustError</a></li>
<li><a href="org/mozilla/mentat/RustError.ByReference.html" title="class in org.mozilla.mentat" target="classFrame">RustError.ByReference</a></li>
<li><a href="org/mozilla/mentat/RustError.ByValue.html" title="class in org.mozilla.mentat" target="classFrame">RustError.ByValue</a></li>
<li><a href="org/mozilla/mentat/ScalarResultHandler.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">ScalarResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat" target="classFrame">TupleResult</a></li>
<li><a href="org/mozilla/mentat/TupleResultHandler.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">TupleResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat" target="classFrame">TxChange</a></li>
<li><a href="org/mozilla/mentat/TxChange.ByReference.html" title="class in org.mozilla.mentat" target="classFrame">TxChange.ByReference</a></li>
<li><a href="org/mozilla/mentat/TxChange.ByValue.html" title="class in org.mozilla.mentat" target="classFrame">TxChange.ByValue</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat" target="classFrame">TxChangeList</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.ByReference.html" title="class in org.mozilla.mentat" target="classFrame">TxChangeList.ByReference</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.ByValue.html" title="class in org.mozilla.mentat" target="classFrame">TxChangeList.ByValue</a></li>
<li><a href="org/mozilla/mentat/TxObserverCallback.html" title="interface in org.mozilla.mentat" target="classFrame"><span class="interfaceName">TxObserverCallback</span></a></li>
<li><a href="org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat" target="classFrame">TxReport</a></li>
<li><a href="org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat" target="classFrame">TypedValue</a></li>
</ul>
</div>
</body>
</html>

View file

@ -0,0 +1,60 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>All Classes</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<h1 class="bar">All&nbsp;Classes</h1>
<div class="indexContainer">
<ul>
<li><a href="org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat">CacheDirection</a></li>
<li><a href="org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat">CollResult</a></li>
<li><a href="org/mozilla/mentat/CollResultHandler.html" title="interface in org.mozilla.mentat"><span class="interfaceName">CollResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat">ColResultIterator</a></li>
<li><a href="org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></li>
<li><a href="org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></li>
<li><a href="org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.ByReference.html" title="class in org.mozilla.mentat">InProgressTransactionResult.ByReference</a></li>
<li><a href="org/mozilla/mentat/InProgressTransactionResult.ByValue.html" title="class in org.mozilla.mentat">InProgressTransactionResult.ByValue</a></li>
<li><a href="org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat"><span class="interfaceName">JNA</span></a></li>
<li><a href="org/mozilla/mentat/JNA.EntityBuilder.html" title="class in org.mozilla.mentat">JNA.EntityBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.InProgress.html" title="class in org.mozilla.mentat">JNA.InProgress</a></li>
<li><a href="org/mozilla/mentat/JNA.InProgressBuilder.html" title="class in org.mozilla.mentat">JNA.InProgressBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.QueryBuilder.html" title="class in org.mozilla.mentat">JNA.QueryBuilder</a></li>
<li><a href="org/mozilla/mentat/JNA.RelResult.html" title="class in org.mozilla.mentat">JNA.RelResult</a></li>
<li><a href="org/mozilla/mentat/JNA.RelResultIter.html" title="class in org.mozilla.mentat">JNA.RelResultIter</a></li>
<li><a href="org/mozilla/mentat/JNA.Store.html" title="class in org.mozilla.mentat">JNA.Store</a></li>
<li><a href="org/mozilla/mentat/JNA.TxReport.html" title="class in org.mozilla.mentat">JNA.TxReport</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValue.html" title="class in org.mozilla.mentat">JNA.TypedValue</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValueList.html" title="class in org.mozilla.mentat">JNA.TypedValueList</a></li>
<li><a href="org/mozilla/mentat/JNA.TypedValueListIter.html" title="class in org.mozilla.mentat">JNA.TypedValueListIter</a></li>
<li><a href="org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></li>
<li><a href="org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></li>
<li><a href="org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat">RelResult</a></li>
<li><a href="org/mozilla/mentat/RelResultHandler.html" title="interface in org.mozilla.mentat"><span class="interfaceName">RelResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat">RelResultIterator</a></li>
<li><a href="org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></li>
<li><a href="org/mozilla/mentat/RustError.ByReference.html" title="class in org.mozilla.mentat">RustError.ByReference</a></li>
<li><a href="org/mozilla/mentat/RustError.ByValue.html" title="class in org.mozilla.mentat">RustError.ByValue</a></li>
<li><a href="org/mozilla/mentat/ScalarResultHandler.html" title="interface in org.mozilla.mentat"><span class="interfaceName">ScalarResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></li>
<li><a href="org/mozilla/mentat/TupleResultHandler.html" title="interface in org.mozilla.mentat"><span class="interfaceName">TupleResultHandler</span></a></li>
<li><a href="org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></li>
<li><a href="org/mozilla/mentat/TxChange.ByReference.html" title="class in org.mozilla.mentat">TxChange.ByReference</a></li>
<li><a href="org/mozilla/mentat/TxChange.ByValue.html" title="class in org.mozilla.mentat">TxChange.ByValue</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.ByReference.html" title="class in org.mozilla.mentat">TxChangeList.ByReference</a></li>
<li><a href="org/mozilla/mentat/TxChangeList.ByValue.html" title="class in org.mozilla.mentat">TxChangeList.ByValue</a></li>
<li><a href="org/mozilla/mentat/TxObserverCallback.html" title="interface in org.mozilla.mentat"><span class="interfaceName">TxObserverCallback</span></a></li>
<li><a href="org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></li>
<li><a href="org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></li>
</ul>
</div>
</body>
</html>

View file

@ -0,0 +1,149 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>Constant Field Values</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="Constant Field Values";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?constant-values.html" target="_top">Frames</a></li>
<li><a href="constant-values.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 title="Constant Field Values" class="title">Constant Field Values</h1>
<h2 title="Contents">Contents</h2>
<ul>
<li><a href="#org.mozilla">org.mozilla.*</a></li>
</ul>
</div>
<div class="constantValuesContainer"><a name="org.mozilla">
<!-- -->
</a>
<h2 title="org.mozilla">org.mozilla.*</h2>
<ul class="blockList">
<li class="blockList">
<table class="constantsSummary" border="0" cellpadding="3" cellspacing="0" summary="Constant Field Values table, listing constant fields, and values">
<caption><span>org.mozilla.mentat.<a href="org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Modifier and Type</th>
<th scope="col">Constant Field</th>
<th class="colLast" scope="col">Value</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a name="org.mozilla.mentat.JNA.JNA_LIBRARY_NAME">
<!-- -->
</a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
<td><code><a href="org/mozilla/mentat/JNA.html#JNA_LIBRARY_NAME">JNA_LIBRARY_NAME</a></code></td>
<td class="colLast"><code>"mentat_ffi"</code></td>
</tr>
</tbody>
</table>
</li>
</ul>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?constant-values.html" target="_top">Frames</a></li>
<li><a href="constant-values.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,120 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>Deprecated List</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="Deprecated List";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li class="navBarCell1Rev">Deprecated</li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?deprecated-list.html" target="_top">Frames</a></li>
<li><a href="deprecated-list.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 title="Deprecated API" class="title">Deprecated API</h1>
<h2 title="Contents">Contents</h2>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li class="navBarCell1Rev">Deprecated</li>
<li><a href="index-files/index-1.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?deprecated-list.html" target="_top">Frames</a></li>
<li><a href="deprecated-list.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,217 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>API Help</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="API Help";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li class="navBarCell1Rev">Help</li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?help-doc.html" target="_top">Frames</a></li>
<li><a href="help-doc.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 class="title">How This API Document Is Organized</h1>
<div class="subTitle">This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.</div>
</div>
<div class="contentContainer">
<ul class="blockList">
<li class="blockList">
<h2>Package</h2>
<p>Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:</p>
<ul>
<li>Interfaces (italic)</li>
<li>Classes</li>
<li>Enums</li>
<li>Exceptions</li>
<li>Errors</li>
<li>Annotation Types</li>
</ul>
</li>
<li class="blockList">
<h2>Class/Interface</h2>
<p>Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:</p>
<ul>
<li>Class inheritance diagram</li>
<li>Direct Subclasses</li>
<li>All Known Subinterfaces</li>
<li>All Known Implementing Classes</li>
<li>Class/interface declaration</li>
<li>Class/interface description</li>
</ul>
<ul>
<li>Nested Class Summary</li>
<li>Field Summary</li>
<li>Constructor Summary</li>
<li>Method Summary</li>
</ul>
<ul>
<li>Field Detail</li>
<li>Constructor Detail</li>
<li>Method Detail</li>
</ul>
<p>Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</p>
</li>
<li class="blockList">
<h2>Annotation Type</h2>
<p>Each annotation type has its own separate page with the following sections:</p>
<ul>
<li>Annotation Type declaration</li>
<li>Annotation Type description</li>
<li>Required Element Summary</li>
<li>Optional Element Summary</li>
<li>Element Detail</li>
</ul>
</li>
<li class="blockList">
<h2>Enum</h2>
<p>Each enum has its own separate page with the following sections:</p>
<ul>
<li>Enum declaration</li>
<li>Enum description</li>
<li>Enum Constant Summary</li>
<li>Enum Constant Detail</li>
</ul>
</li>
<li class="blockList">
<h2>Tree (Class Hierarchy)</h2>
<p>There is a <a href="overview-tree.html">Class Hierarchy</a> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.</p>
<ul>
<li>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.</li>
<li>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</li>
</ul>
</li>
<li class="blockList">
<h2>Deprecated API</h2>
<p>The <a href="deprecated-list.html">Deprecated API</a> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</p>
</li>
<li class="blockList">
<h2>Index</h2>
<p>The <a href="index-files/index-1.html">Index</a> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</p>
</li>
<li class="blockList">
<h2>Prev/Next</h2>
<p>These links take you to the next or previous class, interface, package, or related page.</p>
</li>
<li class="blockList">
<h2>Frames/No Frames</h2>
<p>These links show and hide the HTML frames. All pages are available with or without frames.</p>
</li>
<li class="blockList">
<h2>All Classes</h2>
<p>The <a href="allclasses-noframe.html">All Classes</a> link shows all classes and interfaces except non-static nested types.</p>
</li>
<li class="blockList">
<h2>Serialized Form</h2>
<p>Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.</p>
</li>
<li class="blockList">
<h2>Constant Field Values</h2>
<p>The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.</p>
</li>
</ul>
<span class="emphasizedPhrase">This help file applies to API documentation generated using the standard doclet.</span></div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-files/index-1.html">Index</a></li>
<li class="navBarCell1Rev">Help</li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?help-doc.html" target="_top">Frames</a></li>
<li><a href="help-doc.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,255 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>A-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="A-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev Letter</li>
<li><a href="index-2.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-1.html" target="_top">Frames</a></li>
<li><a href="index-1.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:A">
<!-- -->
</a>
<h2 class="title">A</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-long-">add(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-boolean-">add(String, boolean)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-double-">add(String, double)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-java.util.Date-">add(String, Date)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-java.lang.String-">add(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#add-java.lang.String-java.util.UUID-">add(String, UUID)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-long-">add(long, String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-boolean-">add(long, String, boolean)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-double-">add(long, String, double)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-java.util.Date-">add(long, String, Date)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-java.lang.String-">add(long, String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#add-long-java.lang.String-java.util.UUID-">add(long, String, UUID)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#addKeyword-java.lang.String-java.lang.String-">addKeyword(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#addKeyword-long-java.lang.String-java.lang.String-">addKeyword(long, String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#addRef-java.lang.String-long-">addRef(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#addRef-long-java.lang.String-long-">addRef(long, String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Asserts the value of attribute `keyword` to be the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/ColResultIterator.html#advanceIterator--">advanceIterator()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat">ColResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResultIterator.html#advanceIterator--">advanceIterator()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat">RelResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asBool-java.lang.Integer-">asBool(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asBoolean--">asBoolean()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asDate-java.lang.Integer-">asDate(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asDate--">asDate()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asDouble-java.lang.Integer-">asDouble(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asDouble--">asDouble()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asEntid-java.lang.Integer-">asEntid(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the Entid at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asEntid--">asEntid()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a Entid.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asKeyword-java.lang.Integer-">asKeyword(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the keyword <a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asKeyword--">asKeyword()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a keyword <a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asLong-java.lang.Integer-">asLong(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asLong--">asLong()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asString-java.lang.Integer-">asString(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asString--">asString()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#asUUID-java.lang.Integer-">asUUID(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="https://developer.android.com/reference/java/util/UUID.html?is-external=true" title="class or interface in java.util"><code>UUID</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#asUUID--">asUUID()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>
<div class="block">This value as a <a href="https://developer.android.com/reference/java/util/UUID.html?is-external=true" title="class or interface in java.util"><code>UUID</code></a>.</div>
</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev Letter</li>
<li><a href="index-2.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-1.html" target="_top">Frames</a></li>
<li><a href="index-1.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,154 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>J-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="J-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-9.html">Prev Letter</a></li>
<li><a href="index-11.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-10.html" target="_top">Frames</a></li>
<li><a href="index-10.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:J">
<!-- -->
</a>
<h2 class="title">J</h2>
<dl>
<dt><a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">JNA</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">JNA interface for FFI to Mentat's Rust library
Each function definition here link directly to a function in Mentat's FFI crate.</div>
</dd>
<dt><a href="../org/mozilla/mentat/JNA.EntityBuilder.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.EntityBuilder</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.InProgress.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.InProgress</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.InProgressBuilder.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.InProgressBuilder</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.QueryBuilder.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.QueryBuilder</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.RelResult.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.RelResult</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.RelResultIter.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.RelResultIter</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.Store.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.Store</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.TxReport.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.TxReport</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.TypedValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.TypedValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.TypedValueList.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.TypedValueList</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/JNA.TypedValueListIter.html" title="class in org.mozilla.mentat"><span class="typeNameLink">JNA.TypedValueListIter</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#JNA_LIBRARY_NAME">JNA_LIBRARY_NAME</a></span> - Static variable in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#JNA_NATIVE_LIB">JNA_NATIVE_LIB</a></span> - Static variable in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-9.html">Prev Letter</a></li>
<li><a href="index-11.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-10.html" target="_top">Frames</a></li>
<li><a href="index-10.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,125 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>L-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="L-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-10.html">Prev Letter</a></li>
<li><a href="index-12.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-11.html" target="_top">Frames</a></li>
<li><a href="index-11.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:L">
<!-- -->
</a>
<h2 class="title">L</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.html#len">len</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-10.html">Prev Letter</a></li>
<li><a href="index-12.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-11.html" target="_top">Frames</a></li>
<li><a href="index-11.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,144 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>M-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="M-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-11.html">Prev Letter</a></li>
<li><a href="index-13.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-12.html" target="_top">Frames</a></li>
<li><a href="index-12.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:M">
<!-- -->
</a>
<h2 class="title">M</h2>
<dl>
<dt><a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Mentat</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">The primary class for accessing Mentat's API.<br/>
This class provides all of the basic API that can be found in Mentat's Store struct.<br/>
The raw pointer it holds is a pointer to a Store.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#Mentat-java.lang.String-">Mentat(String)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Open a connection to a Store in a given location.<br/>
If the store does not already exist, one will be created.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#Mentat--">Mentat()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Open a connection to an in-memory Store.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#Mentat-org.mozilla.mentat.JNA.Store-">Mentat(JNA.Store)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Create a new Mentat with the provided pointer to a Mentat Store</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#message">message</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-11.html">Prev Letter</a></li>
<li><a href="index-13.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-12.html" target="_top">Frames</a></li>
<li><a href="index-12.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,125 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>O-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="O-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-12.html">Prev Letter</a></li>
<li><a href="index-14.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-13.html" target="_top">Frames</a></li>
<li><a href="index-13.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:O">
<!-- -->
</a>
<h2 class="title">O</h2>
<dl>
<dt><a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a> - package org.mozilla.mentat</dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-12.html">Prev Letter</a></li>
<li><a href="index-14.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-13.html" target="_top">Frames</a></li>
<li><a href="index-13.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,163 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>Q-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="Q-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-13.html">Prev Letter</a></li>
<li><a href="index-15.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-14.html" target="_top">Frames</a></li>
<li><a href="index-14.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:Q">
<!-- -->
</a>
<h2 class="title">Q</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#query-java.lang.String-">query(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Start a query.</div>
</dd>
<dt><a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Query</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">This class allows you to construct a query, bind values to variables and run those queries against a mentat DB.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#Query-org.mozilla.mentat.JNA.QueryBuilder-">Query(JNA.QueryBuilder)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_boolean-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-int-">query_builder_bind_boolean(JNA.QueryBuilder, String, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_double-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-double-">query_builder_bind_double(JNA.QueryBuilder, String, double)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_kw-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-java.lang.String-">query_builder_bind_kw(JNA.QueryBuilder, String, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_long-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-long-">query_builder_bind_long(JNA.QueryBuilder, String, long)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_ref-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-long-">query_builder_bind_ref(JNA.QueryBuilder, String, long)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_ref_kw-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-java.lang.String-">query_builder_bind_ref_kw(JNA.QueryBuilder, String, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_string-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-java.lang.String-">query_builder_bind_string(JNA.QueryBuilder, String, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_timestamp-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-long-">query_builder_bind_timestamp(JNA.QueryBuilder, String, long)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_bind_uuid-org.mozilla.mentat.JNA.QueryBuilder-java.lang.String-com.sun.jna.Pointer-">query_builder_bind_uuid(JNA.QueryBuilder, String, Pointer)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_destroy-org.mozilla.mentat.JNA.QueryBuilder-">query_builder_destroy(JNA.QueryBuilder)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_execute-org.mozilla.mentat.JNA.QueryBuilder-org.mozilla.mentat.RustError.ByReference-">query_builder_execute(JNA.QueryBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_execute_coll-org.mozilla.mentat.JNA.QueryBuilder-org.mozilla.mentat.RustError.ByReference-">query_builder_execute_coll(JNA.QueryBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_execute_scalar-org.mozilla.mentat.JNA.QueryBuilder-org.mozilla.mentat.RustError.ByReference-">query_builder_execute_scalar(JNA.QueryBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#query_builder_execute_tuple-org.mozilla.mentat.JNA.QueryBuilder-org.mozilla.mentat.RustError.ByReference-">query_builder_execute_tuple(JNA.QueryBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.QueryBuilder.html#QueryBuilder--">QueryBuilder()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.QueryBuilder.html" title="class in org.mozilla.mentat">JNA.QueryBuilder</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-13.html">Prev Letter</a></li>
<li><a href="index-15.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-14.html" target="_top">Frames</a></li>
<li><a href="index-14.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,254 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>R-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="R-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-14.html">Prev Letter</a></li>
<li><a href="index-16.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-15.html" target="_top">Frames</a></li>
<li><a href="index-15.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:R">
<!-- -->
</a>
<h2 class="title">R</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#registerObserver-java.lang.String-java.lang.String:A-org.mozilla.mentat.TxObserverCallback-">registerObserver(String, String[], TxObserverCallback)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Register an callback and a set of attributes to observer for transaction observation.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.RelResult.html#RelResult--">RelResult()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.RelResult.html" title="class in org.mozilla.mentat">JNA.RelResult</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat"><span class="typeNameLink">RelResult</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Wraps a `Rel` result from a Mentat query.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResult.html#RelResult-org.mozilla.mentat.JNA.RelResult-">RelResult(JNA.RelResult)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat">RelResult</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RelResultHandler.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">RelResultHandler</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Interface defining the structure of a callback from a query returning a <a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat"><code>RelResult</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.RelResultIter.html#RelResultIter--">RelResultIter()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.RelResultIter.html" title="class in org.mozilla.mentat">JNA.RelResultIter</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat"><span class="typeNameLink">RelResultIterator</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Iterator for a <a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat"><code>RelResult</code></a></div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.html#reports">reports</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-long-">retract(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-boolean-">retract(String, boolean)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-double-">retract(String, double)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-java.util.Date-">retract(String, Date)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-java.lang.String-">retract(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retract-java.lang.String-java.util.UUID-">retract(String, UUID)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-long-">retract(long, String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-boolean-">retract(long, String, boolean)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-double-">retract(long, String, double)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-java.util.Date-">retract(long, String, Date)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-java.lang.String-">retract(long, String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retract-long-java.lang.String-java.util.UUID-">retract(long, String, UUID)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retractKeyword-java.lang.String-java.lang.String-">retractKeyword(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retractKeyword-long-java.lang.String-java.lang.String-">retractKeyword(long, String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#retractRef-java.lang.String-long-">retractRef(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#retractRef-long-java.lang.String-long-">retractRef(long, String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Retracts the value of attribute `keyword` from the provided `value`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#rollback--">rollback()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Rolls back all the transacts that have been performed on this `InProgress`, either directly
or through a Builder.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#row_at_index-org.mozilla.mentat.JNA.RelResult-int-">row_at_index(JNA.RelResult, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResult.html#rowAtIndex-int-">rowAtIndex(int)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat">RelResult</a></dt>
<dd>
<div class="block">Fetch the row at the requested index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#run-org.mozilla.mentat.RelResultHandler-">run(RelResultHandler)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Execute the query with the values bound associated with this <a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat"><code>Query</code></a> and call the provided
callback function with the results as a list of rows of <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a>s.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#run-org.mozilla.mentat.ScalarResultHandler-">run(ScalarResultHandler)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Execute the query with the values bound associated with this <a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat"><code>Query</code></a> and call the provided
callback function with the results with the result as a single <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#run-org.mozilla.mentat.CollResultHandler-">run(CollResultHandler)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Execute the query with the values bound associated with this <a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat"><code>Query</code></a> and call the provided
callback function with the results with the result as a list of single <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a>s.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#run-org.mozilla.mentat.TupleResultHandler-">run(TupleResultHandler)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Execute the query with the values bound associated with this <a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat"><code>Query</code></a> and call the provided
callback function with the results with the result as a list of single <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a>s.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#rust_c_string_destroy-com.sun.jna.Pointer-">rust_c_string_destroy(Pointer)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat"><span class="typeNameLink">RustError</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Represents a C struct containing a <code>Pointer</code>s and String that map to a Rust Result.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#RustError--">RustError()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RustError.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">RustError.ByReference</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/RustError.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">RustError.ByValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-14.html">Prev Letter</a></li>
<li><a href="index-16.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-15.html" target="_top">Frames</a></li>
<li><a href="index-15.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,159 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>S-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="S-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-15.html">Prev Letter</a></li>
<li><a href="index-17.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-16.html" target="_top">Frames</a></li>
<li><a href="index-16.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:S">
<!-- -->
</a>
<h2 class="title">S</h2>
<dl>
<dt><a href="../org/mozilla/mentat/ScalarResultHandler.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">ScalarResultHandler</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Interface defining the structure of a callback from a query returning a single <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.Store.html#Store--">Store()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.Store.html" title="class in org.mozilla.mentat">JNA.Store</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_begin_transaction-org.mozilla.mentat.JNA.Store-org.mozilla.mentat.RustError.ByReference-">store_begin_transaction(JNA.Store, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_cache_attribute_bi_directional-org.mozilla.mentat.JNA.Store-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_cache_attribute_bi_directional(JNA.Store, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_cache_attribute_forward-org.mozilla.mentat.JNA.Store-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_cache_attribute_forward(JNA.Store, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_cache_attribute_reverse-org.mozilla.mentat.JNA.Store-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_cache_attribute_reverse(JNA.Store, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_destroy-org.mozilla.mentat.JNA.Store-">store_destroy(JNA.Store)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_entid_for_attribute-org.mozilla.mentat.JNA.Store-java.lang.String-">store_entid_for_attribute(JNA.Store, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_entity_builder_from_entid-org.mozilla.mentat.JNA.Store-long-org.mozilla.mentat.RustError.ByReference-">store_entity_builder_from_entid(JNA.Store, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_entity_builder_from_temp_id-org.mozilla.mentat.JNA.Store-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_entity_builder_from_temp_id(JNA.Store, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_in_progress_builder-org.mozilla.mentat.JNA.Store-org.mozilla.mentat.RustError.ByReference-">store_in_progress_builder(JNA.Store, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_open-java.lang.String-">store_open(String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_query-org.mozilla.mentat.JNA.Store-java.lang.String-">store_query(JNA.Store, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_register_observer-org.mozilla.mentat.JNA.Store-java.lang.String-com.sun.jna.Pointer-int-org.mozilla.mentat.TxObserverCallback-">store_register_observer(JNA.Store, String, Pointer, int, TxObserverCallback)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_transact-org.mozilla.mentat.JNA.Store-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_transact(JNA.Store, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_unregister_observer-org.mozilla.mentat.JNA.Store-java.lang.String-">store_unregister_observer(JNA.Store, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#store_value_for_attribute-org.mozilla.mentat.JNA.Store-long-java.lang.String-org.mozilla.mentat.RustError.ByReference-">store_value_for_attribute(JNA.Store, long, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-15.html">Prev Letter</a></li>
<li><a href="index-17.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-16.html" target="_top">Frames</a></li>
<li><a href="index-16.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,245 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>T-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="T-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-16.html">Prev Letter</a></li>
<li><a href="index-18.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-17.html" target="_top">Frames</a></li>
<li><a href="index-17.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:T">
<!-- -->
</a>
<h2 class="title">T</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#transact--">transact()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Transacts the added assertions.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#transact-java.lang.String-">transact(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Transacts the `transaction`
This does not commit the transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#transact--">transact()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Transacts the added assertions.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#transact-java.lang.String-">transact(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Simple transact of an EDN string.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxObserverCallback.html#transactionObserverCalled-java.lang.String-org.mozilla.mentat.TxChangeList.ByReference-">transactionObserverCalled(String, TxChangeList.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/TxObserverCallback.html" title="interface in org.mozilla.mentat">TxObserverCallback</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TupleResult</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Wraps a `Tuple` result from a Mentat query.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#TupleResult-org.mozilla.mentat.JNA.TypedValueList-">TupleResult(JNA.TypedValueList)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TupleResultHandler.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">TupleResultHandler</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Interface defining the structure of a callback from a query returning a <a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat"><code>TupleResult</code></a>.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#tx_report_destroy-org.mozilla.mentat.JNA.TxReport-">tx_report_destroy(JNA.TxReport)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#tx_report_entity_for_temp_id-org.mozilla.mentat.JNA.TxReport-java.lang.String-">tx_report_entity_for_temp_id(JNA.TxReport, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#tx_report_get_entid-org.mozilla.mentat.JNA.TxReport-">tx_report_get_entid(JNA.TxReport)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#tx_report_get_tx_instant-org.mozilla.mentat.JNA.TxReport-">tx_report_get_tx_instant(JNA.TxReport)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChange</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Represents a C struct representing changes that occured during a transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#TxChange--">TxChange()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChange.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChange.ByReference</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChange.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChange.ByValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChangeList</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Represents a C struct containing a list of <a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat"><code>TxChange</code></a>s that occured.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.html#TxChangeList--">TxChangeList()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChangeList.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChangeList.ByReference</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxChangeList.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxChangeList.ByValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#txid">txid</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxObserverCallback.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">TxObserverCallback</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Protocol to be implemented by any object that wishes to register for transaction observation</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#txReport">txReport</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.TxReport.html#TxReport--">TxReport()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.TxReport.html" title="class in org.mozilla.mentat">JNA.TxReport</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TxReport</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">This class wraps a raw pointer than points to a Rust `TxReport` object.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxReport.html#TxReport-org.mozilla.mentat.JNA.TxReport-">TxReport(JNA.TxReport)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_destroy-org.mozilla.mentat.JNA.TypedValue-">typed_value_destroy(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_boolean-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_boolean(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_double-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_double(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_entid-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_entid(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_kw-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_kw(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_long-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_long(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_string-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_string(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_timestamp-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_timestamp(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_into_uuid-org.mozilla.mentat.JNA.TypedValue-">typed_value_into_uuid(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_list_destroy-org.mozilla.mentat.JNA.TypedValueList-">typed_value_list_destroy(JNA.TypedValueList)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_list_into_iter-org.mozilla.mentat.JNA.TypedValueList-">typed_value_list_into_iter(JNA.TypedValueList)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_list_iter_destroy-org.mozilla.mentat.JNA.TypedValueListIter-">typed_value_list_iter_destroy(JNA.TypedValueListIter)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_list_iter_next-org.mozilla.mentat.JNA.TypedValueListIter-">typed_value_list_iter_next(JNA.TypedValueListIter)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_result_set_destroy-org.mozilla.mentat.JNA.RelResult-">typed_value_result_set_destroy(JNA.RelResult)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_result_set_into_iter-org.mozilla.mentat.JNA.RelResult-">typed_value_result_set_into_iter(JNA.RelResult)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_result_set_iter_destroy-org.mozilla.mentat.JNA.RelResultIter-">typed_value_result_set_iter_destroy(JNA.RelResultIter)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_result_set_iter_next-org.mozilla.mentat.JNA.RelResultIter-">typed_value_result_set_iter_next(JNA.RelResultIter)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#typed_value_value_type-org.mozilla.mentat.JNA.TypedValue-">typed_value_value_type(JNA.TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.TypedValue.html#TypedValue--">TypedValue()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.TypedValue.html" title="class in org.mozilla.mentat">JNA.TypedValue</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">TypedValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">A wrapper around Mentat's `TypedValue` Rust object.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#TypedValue-org.mozilla.mentat.JNA.TypedValue-">TypedValue(JNA.TypedValue)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.TypedValueList.html#TypedValueList--">TypedValueList()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.TypedValueList.html" title="class in org.mozilla.mentat">JNA.TypedValueList</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.TypedValueListIter.html#TypedValueListIter--">TypedValueListIter()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.TypedValueListIter.html" title="class in org.mozilla.mentat">JNA.TypedValueListIter</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-16.html">Prev Letter</a></li>
<li><a href="index-18.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-17.html" target="_top">Frames</a></li>
<li><a href="index-17.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,130 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>U-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="U-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-17.html">Prev Letter</a></li>
<li><a href="index-19.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-18.html" target="_top">Frames</a></li>
<li><a href="index-18.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:U">
<!-- -->
</a>
<h2 class="title">U</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#unregisterObserver-java.lang.String-">unregisterObserver(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Unregister the observer that was registered with the provided key such that it will no longer be called
if a transaction occurs that affects the attributes that the observer was registered to observe.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#uuid_destroy-com.sun.jna.Pointer-">uuid_destroy(Pointer)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-17.html">Prev Letter</a></li>
<li><a href="index-19.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-18.html" target="_top">Frames</a></li>
<li><a href="index-18.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,155 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>V-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="V-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-18.html">Prev Letter</a></li>
<li>Next Letter</li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-19.html" target="_top">Frames</a></li>
<li><a href="index-19.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:V">
<!-- -->
</a>
<h2 class="title">V</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_boolean-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_boolean(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_double-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_double(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_entid-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_entid(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_kw-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_kw(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_long-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_long(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_string-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_string(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_timestamp-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_timestamp(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#value_at_index_into_uuid-org.mozilla.mentat.JNA.TypedValueList-int-">value_at_index_into_uuid(JNA.TypedValueList, int)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#valueForAttributeOfEntity-java.lang.String-long-">valueForAttributeOfEntity(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Retrieve a single value of an attribute for an Entity
TODO: Throw an exception if the result contains an error.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/CacheDirection.html#valueOf-java.lang.String-">valueOf(String)</a></span> - Static method in enum org.mozilla.mentat.<a href="../org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat">CacheDirection</a></dt>
<dd>
<div class="block">Returns the enum constant of this type with the specified name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/CacheDirection.html#values--">values()</a></span> - Static method in enum org.mozilla.mentat.<a href="../org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat">CacheDirection</a></dt>
<dd>
<div class="block">Returns an array containing the constants of this enum type, in
the order they are declared.</div>
</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-18.html">Prev Letter</a></li>
<li>Next Letter</li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-19.html" target="_top">Frames</a></li>
<li><a href="index-19.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,193 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>B-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="B-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-1.html">Prev Letter</a></li>
<li><a href="index-3.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-2.html" target="_top">Frames</a></li>
<li><a href="index-2.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:B">
<!-- -->
</a>
<h2 class="title">B</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#beginTransaction--">beginTransaction()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Start a new transaction
TODO: Throw an exception if the result contains an error.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-long-">bind(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a long value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-boolean-">bind(String, boolean)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a boolean value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-double-">bind(String, double)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a double value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-java.util.Date-">bind(String, Date)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a <a href="https://developer.android.com/reference/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-java.lang.String-">bind(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a <a href="https://developer.android.com/reference/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bind-java.lang.String-java.util.UUID-">bind(String, UUID)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a <a href="https://developer.android.com/reference/java/util/UUID.html?is-external=true" title="class or interface in java.util"><code>UUID</code></a> value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bindEntidReference-java.lang.String-long-">bindEntidReference(String, long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a Entid value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bindKeyword-java.lang.String-java.lang.String-">bindKeyword(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a keyword value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#bindKeywordReference-java.lang.String-java.lang.String-">bindKeywordReference(String, String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>
<div class="block">Binds a String keyword value to the provided variable name.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#builder--">builder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Creates an <a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat"><code>InProgressBuilder</code></a> using this <a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><code>InProgress</code></a> .</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#builderForEntid-long-">builderForEntid(long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Creates an `EntityBuilder` using this `InProgress` for the entity with `entid`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#builderForTempid-java.lang.String-">builderForTempid(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Creates an `EntityBuilder` using this `InProgress` for a new entity with `tempid`.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.ByReference.html#ByReference--">ByReference()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.ByReference.html" title="class in org.mozilla.mentat">InProgressTransactionResult.ByReference</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.ByReference.html#ByReference--">ByReference()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.ByReference.html" title="class in org.mozilla.mentat">RustError.ByReference</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.ByReference.html#ByReference--">ByReference()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.ByReference.html" title="class in org.mozilla.mentat">TxChange.ByReference</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.ByReference.html#ByReference--">ByReference()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.ByReference.html" title="class in org.mozilla.mentat">TxChangeList.ByReference</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.ByValue.html#ByValue--">ByValue()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.ByValue.html" title="class in org.mozilla.mentat">InProgressTransactionResult.ByValue</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.ByValue.html#ByValue--">ByValue()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.ByValue.html" title="class in org.mozilla.mentat">RustError.ByValue</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.ByValue.html#ByValue--">ByValue()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.ByValue.html" title="class in org.mozilla.mentat">TxChange.ByValue</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.ByValue.html#ByValue--">ByValue()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.ByValue.html" title="class in org.mozilla.mentat">TxChangeList.ByValue</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-1.html">Prev Letter</a></li>
<li><a href="index-3.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-2.html" target="_top">Frames</a></li>
<li><a href="index-2.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,168 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>C-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="C-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-2.html">Prev Letter</a></li>
<li><a href="index-4.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-3.html" target="_top">Frames</a></li>
<li><a href="index-3.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:C">
<!-- -->
</a>
<h2 class="title">C</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#cache-java.lang.String-org.mozilla.mentat.CacheDirection-">cache(String, CacheDirection)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Add an attribute to the cache.</div>
</dd>
<dt><a href="../org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat"><span class="typeNameLink">CacheDirection</span></a> - Enum in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#changes">changes</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#changes_len">changes_len</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat"><span class="typeNameLink">CollResult</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Wraps a `Coll` result from a Mentat query.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/CollResult.html#CollResult-org.mozilla.mentat.JNA.TypedValueList-">CollResult(JNA.TypedValueList)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat">CollResult</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/CollResultHandler.html" title="interface in org.mozilla.mentat"><span class="typeNameLink">CollResultHandler</span></a> - Interface in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Interface defining the structure of a callback from a query returning a <a href="../org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat"><code>CollResult</code></a>.</div>
</dd>
<dt><a href="../org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat"><span class="typeNameLink">ColResultIterator</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">Iterator for a <a href="../org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat"><code>CollResult</code></a></div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#commit--">commit()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>
<div class="block">Transacts the added assertions and commits.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#commit--">commit()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>
<div class="block">Commits all the transacts that have been performed on this `InProgress`, either directly
or through a Builder.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#commit--">commit()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>
<div class="block">Transacts the added assertions and commits.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/ColResultIterator.html#constructItem-org.mozilla.mentat.JNA.TypedValue-">constructItem(JNA.TypedValue)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat">ColResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResultIterator.html#constructItem-org.mozilla.mentat.JNA.TypedValueList-">constructItem(JNA.TypedValueList)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat">RelResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#consumeErrorMessage--">consumeErrorMessage()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>
<div class="block">Get and consume the error message, or null if there is none.</div>
</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-2.html">Prev Letter</a></li>
<li><a href="index-4.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-3.html" target="_top">Frames</a></li>
<li><a href="index-3.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,147 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>D-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="D-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-3.html">Prev Letter</a></li>
<li><a href="index-5.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-4.html" target="_top">Frames</a></li>
<li><a href="index-4.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:D">
<!-- -->
</a>
<h2 class="title">D</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#destroy-com.sun.jna.Pointer-">destroy(Pointer)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/ColResultIterator.html#destroyPointer-org.mozilla.mentat.JNA.TypedValueListIter-">destroyPointer(JNA.TypedValueListIter)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/ColResultIterator.html" title="class in org.mozilla.mentat">ColResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#destroyPointer-org.mozilla.mentat.JNA.EntityBuilder-">destroyPointer(JNA.EntityBuilder)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#destroyPointer-org.mozilla.mentat.JNA.InProgress-">destroyPointer(JNA.InProgress)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#destroyPointer-org.mozilla.mentat.JNA.InProgressBuilder-">destroyPointer(JNA.InProgressBuilder)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#destroyPointer-org.mozilla.mentat.JNA.Store-">destroyPointer(JNA.Store)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Query.html#destroyPointer-org.mozilla.mentat.JNA.QueryBuilder-">destroyPointer(JNA.QueryBuilder)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Query.html" title="class in org.mozilla.mentat">Query</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResult.html#destroyPointer-org.mozilla.mentat.JNA.RelResult-">destroyPointer(JNA.RelResult)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat">RelResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResultIterator.html#destroyPointer-org.mozilla.mentat.JNA.RelResultIter-">destroyPointer(JNA.RelResultIter)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResultIterator.html" title="class in org.mozilla.mentat">RelResultIterator</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#destroyPointer-org.mozilla.mentat.JNA.TypedValueList-">destroyPointer(JNA.TypedValueList)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxReport.html#destroyPointer-org.mozilla.mentat.JNA.TxReport-">destroyPointer(JNA.TxReport)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TypedValue.html#destroyPointer-org.mozilla.mentat.JNA.TypedValue-">destroyPointer(JNA.TypedValue)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat">TypedValue</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-3.html">Prev Letter</a></li>
<li><a href="index-5.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-4.html" target="_top">Frames</a></li>
<li><a href="index-4.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,190 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>E-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="E-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-4.html">Prev Letter</a></li>
<li><a href="index-6.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-5.html" target="_top">Frames</a></li>
<li><a href="index-5.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:E">
<!-- -->
</a>
<h2 class="title">E</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#entIdForAttribute-java.lang.String-">entIdForAttribute(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Get the the `Entid` of the attribute</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_boolean-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-int-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_boolean(JNA.EntityBuilder, String, int, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_double-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-double-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_double(JNA.EntityBuilder, String, double, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_keyword-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_keyword(JNA.EntityBuilder, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_long-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_long(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_ref-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_ref(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_string-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_string(JNA.EntityBuilder, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_timestamp-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_timestamp(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_add_uuid-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-com.sun.jna.Pointer-org.mozilla.mentat.RustError.ByReference-">entity_builder_add_uuid(JNA.EntityBuilder, String, Pointer, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_commit-org.mozilla.mentat.JNA.EntityBuilder-org.mozilla.mentat.RustError.ByReference-">entity_builder_commit(JNA.EntityBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_destroy-org.mozilla.mentat.JNA.EntityBuilder-">entity_builder_destroy(JNA.EntityBuilder)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_boolean-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-int-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_boolean(JNA.EntityBuilder, String, int, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_double-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-double-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_double(JNA.EntityBuilder, String, double, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_keyword-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_keyword(JNA.EntityBuilder, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_long-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_long(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_ref-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_ref(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_string-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_string(JNA.EntityBuilder, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_timestamp-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_timestamp(JNA.EntityBuilder, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_retract_uuid-org.mozilla.mentat.JNA.EntityBuilder-java.lang.String-com.sun.jna.Pointer-org.mozilla.mentat.RustError.ByReference-">entity_builder_retract_uuid(JNA.EntityBuilder, String, Pointer, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#entity_builder_transact-org.mozilla.mentat.JNA.EntityBuilder-">entity_builder_transact(JNA.EntityBuilder)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat"><span class="typeNameLink">EntityBuilder</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">This class wraps a raw pointer that points to a Rust `EntityBuilder<InProgressBuilder>` object.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/EntityBuilder.html#EntityBuilder-org.mozilla.mentat.JNA.EntityBuilder-">EntityBuilder(JNA.EntityBuilder)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat">EntityBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.EntityBuilder.html#EntityBuilder--">EntityBuilder()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.EntityBuilder.html" title="class in org.mozilla.mentat">JNA.EntityBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#entityBuilder--">entityBuilder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Creates a new transaction (<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><code>InProgress</code></a>) and returns an <a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat"><code>InProgressBuilder</code></a> for
that transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#entityBuilder-long-">entityBuilder(long)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Creates a new transaction (<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><code>InProgress</code></a>) and returns an <a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat"><code>EntityBuilder</code></a> for the
entity with `entid` for that transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/Mentat.html#entityBuilder-java.lang.String-">entityBuilder(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/Mentat.html" title="class in org.mozilla.mentat">Mentat</a></dt>
<dd>
<div class="block">Creates a new transaction (<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><code>InProgress</code></a>) and returns an <a href="../org/mozilla/mentat/EntityBuilder.html" title="class in org.mozilla.mentat"><code>EntityBuilder</code></a> for a new
entity with `tempId` for that transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#error">error</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-4.html">Prev Letter</a></li>
<li><a href="index-6.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-5.html" target="_top">Frames</a></li>
<li><a href="index-5.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,127 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>F-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="F-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-5.html">Prev Letter</a></li>
<li><a href="index-7.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-6.html" target="_top">Frames</a></li>
<li><a href="index-6.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:F">
<!-- -->
</a>
<h2 class="title">F</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#finalize--">finalize()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#finalize--">finalize()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-5.html">Prev Letter</a></li>
<li><a href="index-7.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-6.html" target="_top">Frames</a></li>
<li><a href="index-6.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,163 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>G-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="G-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-6.html">Prev Letter</a></li>
<li><a href="index-8.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-7.html" target="_top">Frames</a></li>
<li><a href="index-7.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:G">
<!-- -->
</a>
<h2 class="title">G</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResult.html#get-java.lang.Integer-">get(Integer)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResult.html" title="class in org.mozilla.mentat">TupleResult</a></dt>
<dd>
<div class="block">Return the <a href="../org/mozilla/mentat/TypedValue.html" title="class in org.mozilla.mentat"><code>TypedValue</code></a> at the specified index.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#getChanges--">getChanges()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>
<div class="block">Get the affected attributes for this transaction</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxReport.html#getEntidForTempId-java.lang.String-">getEntidForTempId(String)</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></dt>
<dd>
<div class="block">Access an `Entid` for a temporary identifier that was provided in the transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#getErrorMessage--">getErrorMessage()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>
<div class="block">Get the error message or null if there is none.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#getFieldOrder--">getFieldOrder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#getFieldOrder--">getFieldOrder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChange.html#getFieldOrder--">getFieldOrder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChange.html" title="class in org.mozilla.mentat">TxChange</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.html#getFieldOrder--">getFieldOrder()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#getInProgress--">getInProgress()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#getReport--">getReport()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxChangeList.html#getReports--">getReports()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxChangeList.html" title="class in org.mozilla.mentat">TxChangeList</a></dt>
<dd>
<div class="block">Get the changes that occured</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxReport.html#getTxId--">getTxId()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></dt>
<dd>
<div class="block">Get the identifier for the transaction.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TxReport.html#getTxInstant--">getTxInstant()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/TxReport.html" title="class in org.mozilla.mentat">TxReport</a></dt>
<dd>
<div class="block">Get the time that the transaction occured.</div>
</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-6.html">Prev Letter</a></li>
<li><a href="index-8.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-7.html" target="_top">Frames</a></li>
<li><a href="index-7.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,131 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>H-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="H-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-7.html">Prev Letter</a></li>
<li><a href="index-9.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-8.html" target="_top">Frames</a></li>
<li><a href="index-8.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:H">
<!-- -->
</a>
<h2 class="title">H</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/CollResultHandler.html#handleList-org.mozilla.mentat.CollResult-">handleList(CollResult)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/CollResultHandler.html" title="interface in org.mozilla.mentat">CollResultHandler</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/TupleResultHandler.html#handleRow-org.mozilla.mentat.TupleResult-">handleRow(TupleResult)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/TupleResultHandler.html" title="interface in org.mozilla.mentat">TupleResultHandler</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResultHandler.html#handleRows-org.mozilla.mentat.RelResult-">handleRows(RelResult)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResultHandler.html" title="interface in org.mozilla.mentat">RelResultHandler</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/ScalarResultHandler.html#handleValue-org.mozilla.mentat.TypedValue-">handleValue(TypedValue)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/ScalarResultHandler.html" title="interface in org.mozilla.mentat">ScalarResultHandler</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-7.html">Prev Letter</a></li>
<li><a href="index-9.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-8.html" target="_top">Frames</a></li>
<li><a href="index-8.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,215 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>I-Index</title>
<meta name="date" content="2018-06-28">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
<script type="text/javascript" src="../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="I-Index";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-8.html">Prev Letter</a></li>
<li><a href="index-10.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-9.html" target="_top">Frames</a></li>
<li><a href="index-9.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="contentContainer"><a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;<a name="I:I">
<!-- -->
</a>
<h2 class="title">I</h2>
<dl>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder-org.mozilla.mentat.JNA.InProgress-">in_progress_builder(JNA.InProgress)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_boolean-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-int-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_boolean(JNA.InProgressBuilder, long, String, int, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_double-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-double-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_double(JNA.InProgressBuilder, long, String, double, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_keyword-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_keyword(JNA.InProgressBuilder, long, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_long-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_long(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_ref-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_ref(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_string-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_string(JNA.InProgressBuilder, long, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_timestamp-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_timestamp(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_add_uuid-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-com.sun.jna.Pointer-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_add_uuid(JNA.InProgressBuilder, long, String, Pointer, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_commit-org.mozilla.mentat.JNA.InProgressBuilder-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_commit(JNA.InProgressBuilder, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_destroy-org.mozilla.mentat.JNA.InProgressBuilder-">in_progress_builder_destroy(JNA.InProgressBuilder)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_boolean-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-int-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_boolean(JNA.InProgressBuilder, long, String, int, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_double-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-double-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_double(JNA.InProgressBuilder, long, String, double, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_keyword-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_keyword(JNA.InProgressBuilder, long, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_long-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_long(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_ref-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_ref(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_string-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-java.lang.String-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_string(JNA.InProgressBuilder, long, String, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_timestamp-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-long-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_timestamp(JNA.InProgressBuilder, long, String, long, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_retract_uuid-org.mozilla.mentat.JNA.InProgressBuilder-long-java.lang.String-com.sun.jna.Pointer-org.mozilla.mentat.RustError.ByReference-">in_progress_builder_retract_uuid(JNA.InProgressBuilder, long, String, Pointer, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_builder_transact-org.mozilla.mentat.JNA.InProgressBuilder-">in_progress_builder_transact(JNA.InProgressBuilder)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_commit-org.mozilla.mentat.JNA.InProgress-org.mozilla.mentat.RustError.ByReference-">in_progress_commit(JNA.InProgress, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_destroy-org.mozilla.mentat.JNA.InProgress-">in_progress_destroy(JNA.InProgress)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_entity_builder_from_entid-org.mozilla.mentat.JNA.InProgress-long-">in_progress_entity_builder_from_entid(JNA.InProgress, long)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_entity_builder_from_temp_id-org.mozilla.mentat.JNA.InProgress-java.lang.String-">in_progress_entity_builder_from_temp_id(JNA.InProgress, String)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_rollback-org.mozilla.mentat.JNA.InProgress-org.mozilla.mentat.RustError.ByReference-">in_progress_rollback(JNA.InProgress, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#in_progress_transact-org.mozilla.mentat.JNA.InProgress-java.lang.String-org.mozilla.mentat.RustError.ByReference-">in_progress_transact(JNA.InProgress, String, RustError.ByReference)</a></span> - Method in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><span class="typeNameLink">InProgress</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">This class wraps a raw pointer that points to a Rust <a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat"><code>InProgress</code></a> object.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgress.html#InProgress-org.mozilla.mentat.JNA.InProgress-">InProgress(JNA.InProgress)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgress.html" title="class in org.mozilla.mentat">InProgress</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#inProgress">inProgress</a></span> - Variable in class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.InProgress.html#InProgress--">InProgress()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.InProgress.html" title="class in org.mozilla.mentat">JNA.InProgress</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat"><span class="typeNameLink">InProgressBuilder</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>
<div class="block">This class wraps a raw pointer that points to a Rust `InProgressBuilder` object.</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressBuilder.html#InProgressBuilder-org.mozilla.mentat.JNA.InProgressBuilder-">InProgressBuilder(JNA.InProgressBuilder)</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressBuilder.html" title="class in org.mozilla.mentat">InProgressBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.InProgressBuilder.html#InProgressBuilder--">InProgressBuilder()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.InProgressBuilder.html" title="class in org.mozilla.mentat">JNA.InProgressBuilder</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat"><span class="typeNameLink">InProgressTransactionResult</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/InProgressTransactionResult.html#InProgressTransactionResult--">InProgressTransactionResult()</a></span> - Constructor for class org.mozilla.mentat.<a href="../org/mozilla/mentat/InProgressTransactionResult.html" title="class in org.mozilla.mentat">InProgressTransactionResult</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/InProgressTransactionResult.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">InProgressTransactionResult.ByReference</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><a href="../org/mozilla/mentat/InProgressTransactionResult.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">InProgressTransactionResult.ByValue</span></a> - Class in <a href="../org/mozilla/mentat/package-summary.html">org.mozilla.mentat</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/JNA.html#INSTANCE">INSTANCE</a></span> - Static variable in interface org.mozilla.mentat.<a href="../org/mozilla/mentat/JNA.html" title="interface in org.mozilla.mentat">JNA</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#isFailure--">isFailure()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>
<div class="block">Does this represent failure?</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RustError.html#isSuccess--">isSuccess()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RustError.html" title="class in org.mozilla.mentat">RustError</a></dt>
<dd>
<div class="block">Does this represent success?</div>
</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/CollResult.html#iterator--">iterator()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/CollResult.html" title="class in org.mozilla.mentat">CollResult</a></dt>
<dd>&nbsp;</dd>
<dt><span class="memberNameLink"><a href="../org/mozilla/mentat/RelResult.html#iterator--">iterator()</a></span> - Method in class org.mozilla.mentat.<a href="../org/mozilla/mentat/RelResult.html" title="class in org.mozilla.mentat">RelResult</a></dt>
<dd>&nbsp;</dd>
</dl>
<a href="index-1.html">A</a>&nbsp;<a href="index-2.html">B</a>&nbsp;<a href="index-3.html">C</a>&nbsp;<a href="index-4.html">D</a>&nbsp;<a href="index-5.html">E</a>&nbsp;<a href="index-6.html">F</a>&nbsp;<a href="index-7.html">G</a>&nbsp;<a href="index-8.html">H</a>&nbsp;<a href="index-9.html">I</a>&nbsp;<a href="index-10.html">J</a>&nbsp;<a href="index-11.html">L</a>&nbsp;<a href="index-12.html">M</a>&nbsp;<a href="index-13.html">O</a>&nbsp;<a href="index-14.html">Q</a>&nbsp;<a href="index-15.html">R</a>&nbsp;<a href="index-16.html">S</a>&nbsp;<a href="index-17.html">T</a>&nbsp;<a href="index-18.html">U</a>&nbsp;<a href="index-19.html">V</a>&nbsp;</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../org/mozilla/mentat/package-summary.html">Package</a></li>
<li>Class</li>
<li><a href="../overview-tree.html">Tree</a></li>
<li><a href="../deprecated-list.html">Deprecated</a></li>
<li class="navBarCell1Rev">Index</li>
<li><a href="../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="index-8.html">Prev Letter</a></li>
<li><a href="index-10.html">Next Letter</a></li>
</ul>
<ul class="navList">
<li><a href="../index.html?index-files/index-9.html" target="_top">Frames</a></li>
<li><a href="index-9.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 28 11:01:15 BST 2018 -->
<title>Generated Documentation (Untitled)</title>
<script type="text/javascript">
tmpTargetPage = "" + window.location.search;
if (tmpTargetPage != "" && tmpTargetPage != "undefined")
tmpTargetPage = tmpTargetPage.substring(1);
if (tmpTargetPage.indexOf(":") != -1 || (tmpTargetPage != "" && !validURL(tmpTargetPage)))
tmpTargetPage = "undefined";
targetPage = tmpTargetPage;
function validURL(url) {
try {
url = decodeURIComponent(url);
}
catch (error) {
return false;
}
var pos = url.indexOf(".html");
if (pos == -1 || pos != url.length - 5)
return false;
var allowNumber = false;
var allowSep = false;
var seenDot = false;
for (var i = 0; i < url.length - 5; i++) {
var ch = url.charAt(i);
if ('a' <= ch && ch <= 'z' ||
'A' <= ch && ch <= 'Z' ||
ch == '$' ||
ch == '_' ||
ch.charCodeAt(0) > 127) {
allowNumber = true;
allowSep = true;
} else if ('0' <= ch && ch <= '9'
|| ch == '-') {
if (!allowNumber)
return false;
} else if (ch == '/' || ch == '.') {
if (!allowSep)
return false;
allowNumber = false;
allowSep = false;
if (ch == '.')
seenDot = true;
if (ch == '/' && seenDot)
return false;
} else {
return false;
}
}
return true;
}
function loadFrames() {
if (targetPage != "" && targetPage != "undefined")
top.classFrame.location = top.targetPage;
}
</script>
</head>
<frameset cols="20%,80%" title="Documentation frame" onload="top.loadFrames()">
<frame src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)">
<frame src="org/mozilla/mentat/package-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes">
<noframes>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<h2>Frame Alert</h2>
<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="org/mozilla/mentat/package-summary.html">Non-frame version</a>.</p>
</noframes>
</frameset>
</html>

View file

@ -0,0 +1,310 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 21 13:35:13 BST 2018 -->
<title>AttributeList.ByReference</title>
<meta name="date" content="2018-06-21">
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
<script type="text/javascript" src="../../../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="AttributeList.ByReference";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../org/mozilla/mentat/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../index-files/index-1.html">Index</a></li>
<li><a href="../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../org/mozilla/mentat/AttributeList.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../index.html?org/mozilla/mentat/AttributeList.ByReference.html" target="_top">Frames</a></li>
<li><a href="AttributeList.ByReference.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li><a href="#nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">Nested</a>&nbsp;|&nbsp;</li>
<li><a href="#fields.inherited.from.class.org.mozilla.mentat.AttributeList">Field</a>&nbsp;|&nbsp;</li>
<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
<li><a href="#methods.inherited.from.class.org.mozilla.mentat.AttributeList">Method</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
<li>Method</li>
</ul>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<!-- ======== START OF CLASS DATA ======== -->
<div class="header">
<div class="subTitle">org.mozilla.mentat</div>
<h2 title="Class AttributeList.ByReference" class="title">Class AttributeList.ByReference</h2>
</div>
<div class="contentContainer">
<ul class="inheritance">
<li><a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
<li>
<ul class="inheritance">
<li>com.sun.jna.Structure</li>
<li>
<ul class="inheritance">
<li><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">org.mozilla.mentat.AttributeList</a></li>
<li>
<ul class="inheritance">
<li>org.mozilla.mentat.AttributeList.ByReference</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="description">
<ul class="blockList">
<li class="blockList">
<dl>
<dt>All Implemented Interfaces:</dt>
<dd>com.sun.jna.Structure.ByReference, <a href="https://developer.android.com/reference/java/io/Closeable.html?is-external=true" title="class or interface in java.io">Closeable</a>, <a href="https://developer.android.com/reference/java/lang/AutoCloseable.html?is-external=true" title="class or interface in java.lang">AutoCloseable</a></dd>
</dl>
<dl>
<dt>Enclosing class:</dt>
<dd><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></dd>
</dl>
<hr>
<br>
<pre>public static class <span class="typeNameLabel">AttributeList.ByReference</span>
extends <a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a>
implements com.sun.jna.Structure.ByReference</pre>
</li>
</ul>
</div>
<div class="summary">
<ul class="blockList">
<li class="blockList">
<!-- ======== NESTED CLASS SUMMARY ======== -->
<ul class="blockList">
<li class="blockList"><a name="nested.class.summary">
<!-- -->
</a>
<h3>Nested Class Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Nested classes/interfaces inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.ByReference.html" title="class in org.mozilla.mentat">AttributeList.ByReference</a>, <a href="../../../org/mozilla/mentat/AttributeList.ByValue.html" title="class in org.mozilla.mentat">AttributeList.ByValue</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="nested.classes.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Nested classes/interfaces inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>com.sun.jna.Structure.StructField</code></li>
</ul>
</li>
</ul>
<!-- =========== FIELD SUMMARY =========== -->
<ul class="blockList">
<li class="blockList"><a name="field.summary">
<!-- -->
</a>
<h3>Field Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="fields.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Fields inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.html#attributes">attributes</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#len">len</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#numberOfItems">numberOfItems</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="fields.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Fields inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>ALIGN_DEFAULT, ALIGN_GNUC, ALIGN_MSVC, ALIGN_NONE, CALCULATE_SIZE</code></li>
</ul>
</li>
</ul>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<ul class="blockList">
<li class="blockList"><a name="constructor.summary">
<!-- -->
</a>
<h3>Constructor Summary</h3>
<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colOne" scope="col">Constructor and Description</th>
</tr>
<tr class="altColor">
<td class="colOne"><code><span class="memberNameLink"><a href="../../../org/mozilla/mentat/AttributeList.ByReference.html#ByReference--">ByReference</a></span>()</code>&nbsp;</td>
</tr>
</table>
</li>
</ul>
<!-- ========== METHOD SUMMARY =========== -->
<ul class="blockList">
<li class="blockList"><a name="method.summary">
<!-- -->
</a>
<h3>Method Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.html#close--">close</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#getFieldOrder--">getFieldOrder</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>allocateMemory, allocateMemory, autoAllocate, autoRead, autoRead, autoWrite, autoWrite, cacheTypeInfo, calculateSize, clear, createFieldsOrder, createFieldsOrder, createFieldsOrder, createFieldsOrder, dataEquals, dataEquals, ensureAllocated, equals, fieldOffset, getAutoRead, getAutoWrite, getFieldList, getFields, getNativeAlignment, getNativeSize, getNativeSize, getPointer, getStringEncoding, getStructAlignment, hashCode, newInstance, newInstance, read, readField, readField, setAlignType, setAutoRead, setAutoSynch, setAutoWrite, setFieldOrder, setStringEncoding, size, sortFields, toArray, toArray, toString, toString, useMemory, useMemory, write, writeField, writeField, writeField</code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;java.lang.<a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
<code><a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div class="details">
<ul class="blockList">
<li class="blockList">
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<ul class="blockList">
<li class="blockList"><a name="constructor.detail">
<!-- -->
</a>
<h3>Constructor Detail</h3>
<a name="ByReference--">
<!-- -->
</a>
<ul class="blockListLast">
<li class="blockList">
<h4>ByReference</h4>
<pre>public&nbsp;ByReference()</pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- ========= END OF CLASS DATA ========= -->
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../org/mozilla/mentat/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../index-files/index-1.html">Index</a></li>
<li><a href="../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../org/mozilla/mentat/AttributeList.ByValue.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../index.html?org/mozilla/mentat/AttributeList.ByReference.html" target="_top">Frames</a></li>
<li><a href="AttributeList.ByReference.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li><a href="#nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">Nested</a>&nbsp;|&nbsp;</li>
<li><a href="#fields.inherited.from.class.org.mozilla.mentat.AttributeList">Field</a>&nbsp;|&nbsp;</li>
<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
<li><a href="#methods.inherited.from.class.org.mozilla.mentat.AttributeList">Method</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
<li>Method</li>
</ul>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

View file

@ -0,0 +1,310 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_152-release) on Thu Jun 21 13:35:13 BST 2018 -->
<title>AttributeList.ByValue</title>
<meta name="date" content="2018-06-21">
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
<script type="text/javascript" src="../../../script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="AttributeList.ByValue";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../org/mozilla/mentat/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../index-files/index-1.html">Index</a></li>
<li><a href="../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../org/mozilla/mentat/AttributeList.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../index.html?org/mozilla/mentat/AttributeList.ByValue.html" target="_top">Frames</a></li>
<li><a href="AttributeList.ByValue.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li><a href="#nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">Nested</a>&nbsp;|&nbsp;</li>
<li><a href="#fields.inherited.from.class.org.mozilla.mentat.AttributeList">Field</a>&nbsp;|&nbsp;</li>
<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
<li><a href="#methods.inherited.from.class.org.mozilla.mentat.AttributeList">Method</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
<li>Method</li>
</ul>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<!-- ======== START OF CLASS DATA ======== -->
<div class="header">
<div class="subTitle">org.mozilla.mentat</div>
<h2 title="Class AttributeList.ByValue" class="title">Class AttributeList.ByValue</h2>
</div>
<div class="contentContainer">
<ul class="inheritance">
<li><a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
<li>
<ul class="inheritance">
<li>com.sun.jna.Structure</li>
<li>
<ul class="inheritance">
<li><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">org.mozilla.mentat.AttributeList</a></li>
<li>
<ul class="inheritance">
<li>org.mozilla.mentat.AttributeList.ByValue</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="description">
<ul class="blockList">
<li class="blockList">
<dl>
<dt>All Implemented Interfaces:</dt>
<dd>com.sun.jna.Structure.ByValue, <a href="https://developer.android.com/reference/java/io/Closeable.html?is-external=true" title="class or interface in java.io">Closeable</a>, <a href="https://developer.android.com/reference/java/lang/AutoCloseable.html?is-external=true" title="class or interface in java.lang">AutoCloseable</a></dd>
</dl>
<dl>
<dt>Enclosing class:</dt>
<dd><a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></dd>
</dl>
<hr>
<br>
<pre>public static class <span class="typeNameLabel">AttributeList.ByValue</span>
extends <a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a>
implements com.sun.jna.Structure.ByValue</pre>
</li>
</ul>
</div>
<div class="summary">
<ul class="blockList">
<li class="blockList">
<!-- ======== NESTED CLASS SUMMARY ======== -->
<ul class="blockList">
<li class="blockList"><a name="nested.class.summary">
<!-- -->
</a>
<h3>Nested Class Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Nested classes/interfaces inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.ByReference.html" title="class in org.mozilla.mentat">AttributeList.ByReference</a>, <a href="../../../org/mozilla/mentat/AttributeList.ByValue.html" title="class in org.mozilla.mentat">AttributeList.ByValue</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="nested.classes.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Nested classes/interfaces inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>com.sun.jna.Structure.StructField</code></li>
</ul>
</li>
</ul>
<!-- =========== FIELD SUMMARY =========== -->
<ul class="blockList">
<li class="blockList"><a name="field.summary">
<!-- -->
</a>
<h3>Field Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="fields.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Fields inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.html#attributes">attributes</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#len">len</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#numberOfItems">numberOfItems</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="fields.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Fields inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>ALIGN_DEFAULT, ALIGN_GNUC, ALIGN_MSVC, ALIGN_NONE, CALCULATE_SIZE</code></li>
</ul>
</li>
</ul>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<ul class="blockList">
<li class="blockList"><a name="constructor.summary">
<!-- -->
</a>
<h3>Constructor Summary</h3>
<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colOne" scope="col">Constructor and Description</th>
</tr>
<tr class="altColor">
<td class="colOne"><code><span class="memberNameLink"><a href="../../../org/mozilla/mentat/AttributeList.ByValue.html#ByValue--">ByValue</a></span>()</code>&nbsp;</td>
</tr>
</table>
</li>
</ul>
<!-- ========== METHOD SUMMARY =========== -->
<ul class="blockList">
<li class="blockList"><a name="method.summary">
<!-- -->
</a>
<h3>Method Summary</h3>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.org.mozilla.mentat.AttributeList">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;org.mozilla.mentat.<a href="../../../org/mozilla/mentat/AttributeList.html" title="class in org.mozilla.mentat">AttributeList</a></h3>
<code><a href="../../../org/mozilla/mentat/AttributeList.html#close--">close</a>, <a href="../../../org/mozilla/mentat/AttributeList.html#getFieldOrder--">getFieldOrder</a></code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.com.sun.jna.Structure">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;com.sun.jna.Structure</h3>
<code>allocateMemory, allocateMemory, autoAllocate, autoRead, autoRead, autoWrite, autoWrite, cacheTypeInfo, calculateSize, clear, createFieldsOrder, createFieldsOrder, createFieldsOrder, createFieldsOrder, dataEquals, dataEquals, ensureAllocated, equals, fieldOffset, getAutoRead, getAutoWrite, getFieldList, getFields, getNativeAlignment, getNativeSize, getNativeSize, getPointer, getStringEncoding, getStructAlignment, hashCode, newInstance, newInstance, read, readField, readField, setAlignType, setAutoRead, setAutoSynch, setAutoWrite, setFieldOrder, setStringEncoding, size, sortFields, toArray, toArray, toString, toString, useMemory, useMemory, write, writeField, writeField, writeField</code></li>
</ul>
<ul class="blockList">
<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
<!-- -->
</a>
<h3>Methods inherited from class&nbsp;java.lang.<a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
<code><a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://developer.android.com/reference/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div class="details">
<ul class="blockList">
<li class="blockList">
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<ul class="blockList">
<li class="blockList"><a name="constructor.detail">
<!-- -->
</a>
<h3>Constructor Detail</h3>
<a name="ByValue--">
<!-- -->
</a>
<ul class="blockListLast">
<li class="blockList">
<h4>ByValue</h4>
<pre>public&nbsp;ByValue()</pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- ========= END OF CLASS DATA ========= -->
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li><a href="../../../org/mozilla/mentat/package-summary.html">Package</a></li>
<li class="navBarCell1Rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../index-files/index-1.html">Index</a></li>
<li><a href="../../../help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li><a href="../../../org/mozilla/mentat/AttributeList.ByReference.html" title="class in org.mozilla.mentat"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
<li><a href="../../../org/mozilla/mentat/CacheDirection.html" title="enum in org.mozilla.mentat"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
</ul>
<ul class="navList">
<li><a href="../../../index.html?org/mozilla/mentat/AttributeList.ByValue.html" target="_top">Frames</a></li>
<li><a href="AttributeList.ByValue.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<div>
<ul class="subNavList">
<li>Summary:&nbsp;</li>
<li><a href="#nested.classes.inherited.from.class.org.mozilla.mentat.AttributeList">Nested</a>&nbsp;|&nbsp;</li>
<li><a href="#fields.inherited.from.class.org.mozilla.mentat.AttributeList">Field</a>&nbsp;|&nbsp;</li>
<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
<li><a href="#methods.inherited.from.class.org.mozilla.mentat.AttributeList">Method</a></li>
</ul>
<ul class="subNavList">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
<li>Method</li>
</ul>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more