diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/changelog 1.16.2+~1.2.3+~1.10.4-1/debian/changelog
--- 1.16.1+~1.2.3+~1.10.4-1/debian/changelog	2022-05-12 07:34:04.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/changelog	2022-08-02 10:14:55.000000000 +0000
@@ -1,3 +1,20 @@
+node-n3 (1.16.2+~1.2.3+~1.10.4-1) unstable; urgency=medium
+
+  [ upstream ]
+  * new release
+
+  [ Jonas Smedegaard ]
+  * update git-buildpackage config:
+    + use DEP-14 git branches
+    + enable automatic DEP-14 branch name handling
+    + add usage config
+  * lint-check source code during build;
+    build-depend on eslint;
+    update TODOs
+  * update lintian overrides
+
+ -- Jonas Smedegaard <dr@jones.dk>  Tue, 02 Aug 2022 12:14:55 +0200
+
 node-n3 (1.16.1+~1.2.3+~1.10.4-1) unstable; urgency=medium
 
   [ upstream ]
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/control 1.16.2+~1.2.3+~1.10.4-1/debian/control
--- 1.16.1+~1.2.3+~1.10.4-1/debian/control	2022-05-12 07:32:27.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/control	2022-08-02 10:12:03.000000000 +0000
@@ -12,10 +12,9 @@ Build-Depends:
 # node-chai <!nocheck>,
 # node-chai-things <!nocheck>,
 # node-docco <!nodoc>,
-# eslint <!nocheck>,
+ eslint <!nocheck>,
 # mocha <!nocheck>,
  node-babel7,
-# node-nyc <!nocheck>,
 # node-rdf-test-suite <!nocheck>,
  node-source-map,
 # node-streamify-string <!nocheck>,
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/gbp.conf 1.16.2+~1.2.3+~1.10.4-1/debian/gbp.conf
--- 1.16.1+~1.2.3+~1.10.4-1/debian/gbp.conf	2021-12-15 12:57:15.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/gbp.conf	2022-04-27 06:23:42.000000000 +0000
@@ -1,8 +1,15 @@
-# Configuration file for git-buildpackage and friends
+# clone this source:       gbp clone $PKG_GIT_URL
+# track upstream source:   git remote add upstream-git $UPSTREAM_GIT_URL
+# update this source:      gbp pull
+# update upstream source:  git fetch upstream-git --tags
+# import upstream release: gbp import-orig --upstream-vcs-tag=$VERSION --uscan
+# build package:           gbp buildpackage
+# publish source release:  gbp tag && gbp push
 
 [DEFAULT]
 pristine-tar = True
 sign-tags = True
 filter = */.git*
-debian-branch = debian/master
-component = ['Xqueue', 'Xtypes']
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+dist = DEP14
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/rules 1.16.2+~1.2.3+~1.10.4-1/debian/rules
--- 1.16.1+~1.2.3+~1.10.4-1/debian/rules	2021-12-15 12:57:15.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/rules	2022-08-02 10:14:39.000000000 +0000
@@ -3,6 +3,14 @@
 # resolve DEB_VERSION
 include /usr/share/dpkg/pkg-info.mk
 
+ESLINT = eslint
+# normalize output with TAP where possible unless terse requested
+ifeq (,$(filter terse,$(DEB_BUILD_OPTIONS)))
+ESLINT += --format tap
+else
+ESLINT += --format unix
+endif
+
 STEM = rdflib
 UGLIFY_SOURCES = lib/index.js $(filter-out lib/index.js,$(wildcard lib/*.js))
 
@@ -15,10 +23,17 @@ debian/js/$(STEM).js: lib/index.js
 	mkdir -p debian/js
 	cat $(UGLIFY_SOURCES) > debian/js/$(STEM).js
 
-# TODO: enable when node-arrayify-stream and node-streamify-stream is in Debian
+# TODO: enable mocha test when chai-things is in Debian
+# TODO: check spec when node-arrayify-stream and node-streamify-stream are in Debian
 override_dh_auto_test:
+	$(ESLINT) src perf test spec
+#	standard Xqueue
 	tape Xqueue/test/*.js
 #	mocha
+#	rdf-test-suite spec/parser.js http://w3c.github.io/rdf-tests/turtle/manifest.ttl -i '{ \"format\": \"turtle\" }' -c .rdf-test-suite-cache/
+#	rdf-test-suite spec/parser.js http://w3c.github.io/rdf-tests/ntriples/manifest.ttl -i '{ \"format\": \"n-triples\" }' -c .rdf-test-suite-cache/
+#	rdf-test-suite spec/parser.js http://w3c.github.io/rdf-tests/nquads/manifest.ttl -i '{ \"format\": \"n-quads\" }' -c .rdf-test-suite-cache/
+#	rdf-test-suite spec/parser.js http://w3c.github.io/rdf-tests/trig/manifest.ttl -i '{ \"format\": \"trig\" }' -c .rdf-test-suite-cache/
 
 override_dh_gencontrol:
 	dh_gencontrol -- \
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/source/lintian-overrides 1.16.2+~1.2.3+~1.10.4-1/debian/source/lintian-overrides
--- 1.16.1+~1.2.3+~1.10.4-1/debian/source/lintian-overrides	2021-12-15 12:57:15.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/source/lintian-overrides	2022-08-02 10:14:55.000000000 +0000
@@ -3,4 +3,4 @@ missing-license-paragraph-in-dep5-copyri
 missing-license-text-in-dep5-copyright GPL-3\+ *
 
 # long strings are handwritten (not minification of other source)
-source-is-missing src/N3Lexer.js
+source-is-missing [src/N3Lexer.js]
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/debian/TODO 1.16.2+~1.2.3+~1.10.4-1/debian/TODO
--- 1.16.1+~1.2.3+~1.10.4-1/debian/TODO	2021-12-15 12:57:15.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/debian/TODO	2022-08-02 10:01:00.000000000 +0000
@@ -1,8 +1,10 @@
-  * Build documentation when node-docco is in Debian.
-  * Enable testsuite when needed packages are in Debian:
-    + node-arrayify-stream
-    + node-streamify-stream
-  * Improve testsuite when needed packages are in Debian:
-    + node-nyc is in Debian.
-    + eslint
-    + node-rdf-test-suite
+  * Build documentation when needed package is in Debian:
+    * node-docco
+  * Check main testsuite when needed package is in Debian:
+    * chai-things
+  * Lint-check "queue" when needed package is in Debian:
+    * standard
+  * Check spec tests when needed packages are in Debian:
+    * node-arrayify-stream
+    * node-streamify-stream
+    * node-rdf-test-suite
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/package.json 1.16.2+~1.2.3+~1.10.4-1/package.json
--- 1.16.1+~1.2.3+~1.10.4-1/package.json	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/package.json	2022-05-12 10:17:44.000000000 +0000
@@ -1,6 +1,6 @@
 {
   "name": "n3",
-  "version": "1.16.1",
+  "version": "1.16.2",
   "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
   "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
   "keywords": [
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/package-lock.json 1.16.2+~1.2.3+~1.10.4-1/package-lock.json
--- 1.16.1+~1.2.3+~1.10.4-1/package-lock.json	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/package-lock.json	2022-05-12 10:17:44.000000000 +0000
@@ -1,12 +1,12 @@
 {
   "name": "n3",
-  "version": "1.16.1",
+  "version": "1.16.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "n3",
-      "version": "1.16.1",
+      "version": "1.16.2",
       "license": "MIT",
       "dependencies": {
         "queue-microtask": "^1.1.2",
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/perf/N3Store-perf.js 1.16.2+~1.2.3+~1.10.4-1/perf/N3Store-perf.js
--- 1.16.1+~1.2.3+~1.10.4-1/perf/N3Store-perf.js	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/perf/N3Store-perf.js	2022-05-12 10:17:44.000000000 +0000
@@ -85,3 +85,92 @@ for (k = 0; k < dim; k++)
 for (l = 0; l < dim; l++)
   assert.equal(store.getQuads(null, null, null, prefix + l).length, dimCubed);
 console.timeEnd(TEST);
+
+console.log('N3 Store tests for sparsely connected entities');
+
+store = new N3.Store();
+TEST = `- Adding ${dimQuads} with all different IRIs`;
+console.time(TEST);
+for (let i = 0; i < dimQuads; i++) {
+  store.addQuad(
+    prefix + i,
+    prefix + i,
+    prefix + i
+  );
+}
+console.timeEnd(TEST);
+
+
+TEST = `* Retrieving all ${dimQuads} quads`;
+console.time(TEST);
+for (const quad of store.match(undefined, undefined, undefined)) {
+  assert(quad);
+}
+console.timeEnd(TEST);
+
+TEST = '* Retrieving single by subject';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(prefix + 1, undefined, undefined)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+
+TEST = '* Retrieving single by predicate';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(undefined, prefix + 1, undefined)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+TEST = '* Retrieving single by object';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(undefined, undefined, prefix + 1)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+
+TEST = '* Retrieving single by subject-predicate';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(prefix + 1, prefix + 1, undefined)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+
+TEST = '* Retrieving single by subject-object';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(prefix + 1, undefined, prefix + 1)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+TEST = '* Retrieving single by predicate-object';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(undefined, prefix + 1, prefix + 1)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
+
+
+TEST = '* Retrieving single by subject-predicate-object';
+console.time(TEST);
+for (let i = 0; i < 1000000; i++) {
+  for (const quad of store.match(prefix + 1, prefix + 1, prefix + 1)) {
+    assert(quad);
+  }
+}
+console.timeEnd(TEST);
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/README.md 1.16.2+~1.2.3+~1.10.4-1/README.md
--- 1.16.1+~1.2.3+~1.10.4-1/README.md	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/README.md	2022-05-12 10:17:44.000000000 +0000
@@ -282,12 +282,12 @@ Then, we find triples with `:Mickey` as
 
 ```JavaScript
 const store = new N3.Store();
-store.addQuad(
+store.add(
   namedNode('http://ex.org/Pluto'),
   namedNode('http://ex.org/type'),
   namedNode('http://ex.org/Dog')
 );
-store.addQuad(
+store.add(
   namedNode('http://ex.org/Mickey'),
   namedNode('http://ex.org/type'),
   namedNode('http://ex.org/Mouse')
@@ -297,12 +297,25 @@ store.addQuad(
 for (const quad of store)
   console.log(quad);
 // Retrieve Mickey's quads
-for (const quad of store.readQuads(namedNode('http://ex.org/Mickey'), null, null))
+for (const quad of store.match(namedNode('http://ex.org/Mickey'), null, null))
   console.log(quad);
 ```
 
+### [`DatasetCore` Interface](https://rdf.js.org/dataset-spec/#datasetcore-interface)
+This store adheres to the `DatasetCore` interface which exposes the following properties
+
+Attributes:
+ - `size` — A non-negative integer that specifies the number of quads in the set.
+
+Methods:
+ - `add` — Adds the specified quad to the dataset. Existing quads, as defined in `Quad.equals`, will be ignored.
+ - `delete` — Removes the specified quad from the dataset.
+ - `has` — Determines whether a dataset includes a certain quad.
+ - `match` — Returns a new dataset that is comprised of all quads in the current instance matching the given arguments.
+ - `[Symbol.iterator]` — Implements the iterator protocol to allow iteration over all `quads` in the dataset as in the example above.
+
 ### Addition and deletion of quads
-The store provides the following manipulation methods
+The store provides the following manipulation methods in addition to implementing the standard [`DatasetCore` Interface](https://rdf.js.org/dataset-spec/#datasetcore-interface)
 ([documentation](http://rdfjs.github.io/N3.js/docs/N3Store.html)):
 - `addQuad` to insert one quad
 - `addQuads` to insert an array of quads
@@ -386,6 +399,7 @@ The N3.js submodules are compatible with
   [`Store`](http://rdf.js.org/stream-spec/#store-interface)
   [`Source`](http://rdf.js.org/stream-spec/#source-interface)
   [`Sink`](http://rdf.js.org/stream-spec/#sink-interface)
+  [`DatasetCore`](https://rdf.js.org/dataset-spec/#datasetcore-interface)
 
 ## License and contributions
 The N3.js library is copyrighted by [Ruben Verborgh](https://ruben.verborgh.org/)
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/src/N3Store.js 1.16.2+~1.2.3+~1.10.4-1/src/N3Store.js
--- 1.16.1+~1.2.3+~1.10.4-1/src/N3Store.js	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/src/N3Store.js	2022-05-12 10:17:44.000000000 +0000
@@ -87,30 +87,24 @@ export default class N3Store {
   // Finally, `graphId` will be the graph of the created quads.
   *_findInIndex(index0, key0, key1, key2, name0, name1, name2, graphId) {
     let tmp, index1, index2;
-    // Depending on the number of variables, keys or reverse index are faster
-    const varCount = !key0 + !key1 + !key2,
-        entityKeys = varCount > 1 ? Object.keys(this._ids) : this._entities;
+    const entityKeys = this._entities;
     const graph = termFromId(graphId, this._factory);
+    const parts = { subject: null, predicate: null, object: null };
 
     // If a key is specified, use only that part of index 0.
     if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
     for (const value0 in index0) {
-      const entity0 = entityKeys[value0];
-
       if (index1 = index0[value0]) {
+        parts[name0] = termFromId(entityKeys[value0], this._factory);
         // If a key is specified, use only that part of index 1.
         if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1];
         for (const value1 in index1) {
-          const entity1 = entityKeys[value1];
-
           if (index2 = index1[value1]) {
+            parts[name1] = termFromId(entityKeys[value1], this._factory);
             // If a key is specified, use only that part of index 2, if it exists.
             const values = key2 ? (key2 in index2 ? [key2] : []) : Object.keys(index2);
             // Create quads for all items found in index 2.
             for (let l = 0; l < values.length; l++) {
-              const parts = { subject: null, predicate: null, object: null };
-              parts[name0] = termFromId(entity0, this._factory);
-              parts[name1] = termFromId(entity1, this._factory);
               parts[name2] = termFromId(entityKeys[values[l]], this._factory);
               yield this._factory.quad(parts.subject, parts.predicate, parts.object, graph);
             }
@@ -378,24 +372,24 @@ export default class N3Store {
           if (objectId)
             // If subject and object are given, the object index will be the fastest
             yield* this._findInIndex(content.objects, objectId, subjectId, predicateId,
-                              'object', 'subject', 'predicate', graphId, null, true);
+                              'object', 'subject', 'predicate', graphId);
           else
             // If only subject and possibly predicate are given, the subject index will be the fastest
             yield* this._findInIndex(content.subjects, subjectId, predicateId, null,
-                              'subject', 'predicate', 'object', graphId, null, true);
+                              'subject', 'predicate', 'object', graphId);
         }
         else if (predicateId)
           // If only predicate and possibly object are given, the predicate index will be the fastest
           yield* this._findInIndex(content.predicates, predicateId, objectId, null,
-                            'predicate', 'object', 'subject', graphId, null, true);
+                            'predicate', 'object', 'subject', graphId);
         else if (objectId)
           // If only object is given, the object index will be the fastest
           yield* this._findInIndex(content.objects, objectId, null, null,
-                            'object', 'subject', 'predicate', graphId, null, true);
+                            'object', 'subject', 'predicate', graphId);
         else
           // If nothing is given, iterate subjects and predicates first
           yield* this._findInIndex(content.subjects, null, null, null,
-                            'subject', 'predicate', 'object', graphId, null, true);
+                            'subject', 'predicate', 'object', graphId);
       }
     }
   }
@@ -787,11 +781,13 @@ class DatasetCoreAndReadableStream exten
   get filtered() {
     if (!this._filtered) {
       const { n3Store, graph, object, predicate, subject } = this;
-      const quads = n3Store.getQuads(subject, predicate, object, graph);
-      this._filtered = new N3Store(quads, { factory: n3Store._factory });
+      const newStore = this._filtered = new N3Store({ factory: n3Store._factory });
+      for (const quad of n3Store.readQuads(subject, predicate, object, graph))
+        newStore.addQuad(quad);
     }
     return this._filtered;
   }
+
   get size() {
     return this.filtered.size;
   }
diff -pruN 1.16.1+~1.2.3+~1.10.4-1/test/N3Store-test.js 1.16.2+~1.2.3+~1.10.4-1/test/N3Store-test.js
--- 1.16.1+~1.2.3+~1.10.4-1/test/N3Store-test.js	2022-04-14 19:29:25.000000000 +0000
+++ 1.16.2+~1.2.3+~1.10.4-1/test/N3Store-test.js	2022-05-12 10:17:44.000000000 +0000
@@ -7,7 +7,7 @@ import {
   termFromId, termToId,
 } from '../src/';
 import namespaces from '../src/IRIs';
-import chai from 'chai';
+import chai, { expect } from 'chai';
 import { Readable } from 'readable-stream';
 import arrayifyStream from 'arrayify-stream';
 
@@ -1636,6 +1636,34 @@ describe('Store', () => {
       });
     });
   });
+
+  describe('handles concurrent read/write', () => {
+    let store;
+    beforeEach(() => {
+      store = new Store([
+        new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o1')),
+        new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o3')),
+      ]);
+    });
+
+    it('should include added elements in match if iteration has not yet started', () => {
+      const m = store.match(null, null, null, null);
+      store.add(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o2')));
+      [...m].should.have.length(3);
+      [...store.match(null, null, null, null)].should.have.length(3);
+    });
+
+    it('should still include results of original match after iterating while adding new data', () => {
+      const m = store.match(null, null, null, null)[Symbol.iterator]();
+      m.next().value.should.deep.equal(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o1')));
+      store.add(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o0')));
+      store.add(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o2')));
+      store.add(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o4')));
+      m.next().value.should.deep.equal(new Quad(new NamedNode('s1'), new NamedNode('p1'), new NamedNode('o3')));
+      m.next().done.should.be.true;
+      [...store.match(null, null, null, null)].should.have.length(5);
+    });
+  });
 });
 
 function alwaysTrue()  { return true;  }
