Commit f9bdfa9b authored by Bryan Kaperick's avatar Bryan Kaperick

Finished revisions to buildquery.

parent c6db8c50
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
*/ */
function HistoryStorage(spec) { function HistoryStorage(spec) {
this._sub_storage = jIO.createJIO(spec.sub_storage); this._sub_storage = jIO.createJIO(spec.sub_storage);
this._include_revisions = spec.include_revisions;
} }
HistoryStorage.prototype.get = function (id_in) { HistoryStorage.prototype.get = function (id_in) {
...@@ -358,7 +359,7 @@ ...@@ -358,7 +359,7 @@
// Query for all edits putting or removing documents (and nothing about // Query for all edits putting or removing documents (and nothing about
// attachments) // attachments)
meta_options = { meta_options = {
query: "(op: remove) OR (op: put)", query: "",//(op: remove) OR (op: put)",
sort_on: options.sort_on sort_on: options.sort_on
}; };
return this._sub_storage.allDocs(meta_options) return this._sub_storage.allDocs(meta_options)
...@@ -376,44 +377,115 @@ ...@@ -376,44 +377,115 @@
query_matches, query_matches,
docs_to_query, docs_to_query,
i; i;
// If !rev_query, then by default only consider latest revisions of
// documents
results = results.filter(function (docum) {
if (rev_query) {
return docum.op === "put";
}
if (!seen.hasOwnProperty(docum.doc_id)) {
seen[docum.doc_id] = {};
return docum.op === "put";
}
return false;
});
// If any documents have property _doc_id, __doc_id, etc, then set
// doc_id_name to the first string which is not a property of any
// of the documents
doc_id_name = "_doc_id"; doc_id_name = "_doc_id";
timestamp_name = "_timestamp"; timestamp_name = "_timestamp";
for (i = 0; i < results.length; i += 1) { for (i = 0; i < results.length; i += 1) {
while (results[i].doc.hasOwnProperty(doc_id_name)) { if (results[i].op === "put") {
doc_id_name = "_" + doc_id_name; while (results[i].doc.hasOwnProperty(doc_id_name)) {
} doc_id_name = "_" + doc_id_name;
while (results[i].doc.hasOwnProperty(timestamp_name)) { }
timestamp_name = "_" + timestamp_name; while (results[i].doc.hasOwnProperty(timestamp_name)) {
timestamp_name = "_" + timestamp_name;
}
} }
} }
docs_to_query = results.map(function (docum) { if (rev_query) {
// If it's a "remove" operation then it has no doc property // Only query on documents which are puts are putAttachments
if (!docum.hasOwnProperty("doc")) { results = results.map(function (docum, ind) {
docum.doc = {}; var data_key;
} if (docum.op === "put") {
docum.doc[doc_id_name] = docum.doc_id; return docum;
docum.doc[timestamp_name] = docum.timestamp; }
return docum.doc; if (docum.op === "putAttachment") {
}); docum.doc = {};
for (i = ind + 1; i < results.length; i += 1) {
if (results[i].doc_id === docum.doc_id) {
if (results[i].op === "put") {
for (data_key in results[i].doc) {
if (results[i].doc.hasOwnProperty(data_key)) {
docum.doc[data_key] = results[i].doc[data_key];
}
}
return docum;
}
if (results[i].doc_id === "remove") {
//console.log("not returning putAttachment at ",
// docum.timestamp,
// " because it was attached to a removed document");
return false;
}
}
}
}
return false;
});
} else {
results = results.map(function (docum, ind) {
var data_key;
if (docum.op === "put") {
if (!seen.hasOwnProperty(docum.doc_id)) {
seen[docum.doc_id] = {};
//console.log("returning put at ", docum.timestamp,
// " because it is most recent edit to " + docum.doc_id);
return docum;
}
//console.log("not returning put at ", docum.timestamp,
// " because it was edited later");
} else if (docum.op === "remove") {
seen[docum.doc_id] = {};
} else if (docum.op === "putAttachment") {
if (!seen.hasOwnProperty(docum.doc_id)) {
seen[docum.doc_id] = {};
docum.doc = {};
for (i = ind + 1; i < results.length; i += 1) {
if (results[i].doc_id === docum.doc_id) {
if (results[i].op === "put") {
for (data_key in results[i].doc) {
if (results[i].doc.hasOwnProperty(data_key)) {
docum.doc[data_key] = results[i].doc[data_key];
}
}
/**console.log("returning putAttachment at ",
docum.timestamp,
" because it is most recent edit to attachment " +
docum.name + " of document " + docum.doc_id);
**/
return docum;
}
if (results[i].doc_id === "remove") {
/**console.log("not returning putAttachment at ",
docum.timestamp,
" because it was attached to a removed document");
**/
return false;
}
}
}
}
} else if (docum.op === "removeAttachment") {
seen[docum.doc_id] = {};
}
return false;
});
}
docs_to_query = results
.filter(function (docum) {
return docum;
})
.map(function (docum) {
docum.doc[timestamp_name] = docum.timestamp;
docum.doc[doc_id_name] = docum.doc_id;
return docum.doc;
});
options.select_list.push(doc_id_name); options.select_list.push(doc_id_name);
options.select_list.push(timestamp_name); options.select_list.push(timestamp_name);
options.sort_on[options.sort_on.length - 1] = [
timestamp_name, "descending"
];
query_matches = options.query.exec(docs_to_query, options); query_matches = options.query.exec(docs_to_query, options);
return query_matches; return query_matches;
}) })
......
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
"attacheddata": blob2, "attacheddata": blob2,
"other_attacheddata": other_blob "other_attacheddata": other_blob
}, "allAttachments works as expected."); }, "allAttachments works as expected.");
return jio.removeAttachment("doc", "attacheddata"); return jio.removeAttachment("doc", "attacheddata"); //
}) })
.push(function () { .push(function () {
return jio.get("doc"); return jio.get("doc");
...@@ -279,7 +279,7 @@ ...@@ -279,7 +279,7 @@
deepEqual(results, { deepEqual(results, {
"other_attacheddata": blob2 "other_attacheddata": blob2
}, "allAttachments works as expected with a removed attachment"); }, "allAttachments works as expected with a removed attachment");
return jio.putAttachment("doc", "attacheddata", blob3); return jio.putAttachment("doc", "attacheddata", blob3); //
}) })
.push(function () { .push(function () {
return not_history.allDocs(); return not_history.allDocs();
...@@ -320,7 +320,7 @@ ...@@ -320,7 +320,7 @@
}) })
.push(function (result) { .push(function (result) {
deepEqual(result, { deepEqual(result, {
"title": "foo0" "key": "val"
}, "Get second document accessible from jio storage"); }, "Get second document accessible from jio storage");
return not_history.allDocs(); return not_history.allDocs();
...@@ -1314,19 +1314,19 @@ ...@@ -1314,19 +1314,19 @@
doc: {}, doc: {},
id: "doc", id: "doc",
value: {date: 1}, value: {date: 1},
timestamp: timestamps[1] timestamp: timestamps[2]
}, },
{ {
doc: {}, doc: {},
id: "third_doc", id: "third_doc",
value: {date: 2}, value: {date: 2},
timestamp: timestamps[5] timestamp: timestamps[6]
}, },
{ {
doc: {}, doc: {},
id: "second_doc", id: "second_doc",
value: {date: 2}, value: {date: 2},
timestamp: timestamps[3] timestamp: timestamps[4]
} }
], ],
"Query gives correct results in correct order"); "Query gives correct results in correct order");
...@@ -1543,9 +1543,7 @@ ...@@ -1543,9 +1543,7 @@
return jio.allDocs({ return jio.allDocs({
query: "NOT (date: >= 2 AND date: <= 3)", query: "NOT (date: >= 2 AND date: <= 3)",
select_list: ["date", "non-existent-key", "type", "title"], select_list: ["date", "non-existent-key", "type", "title"],
sort_on: [["date", "descending"], sort_on: [["date", "descending"]
["non-existent-key", "ascending"],
["_timestamp", "ascending"]
], ],
include_revisions: true include_revisions: true
}); });
...@@ -1554,13 +1552,13 @@ ...@@ -1554,13 +1552,13 @@
deepEqual(results.data.rows, [ deepEqual(results.data.rows, [
{ {
doc: {}, doc: {},
id: "doc", id: "second_doc",
value: { value: {
date: 4, date: 4,
title: "doc", title: "second_doc",
type: "foo2" type: "bar2"
}, },
timestamp: timestamps[5] timestamp: timestamps[9]
}, },
{ {
doc: {}, doc: {},
...@@ -1572,6 +1570,37 @@ ...@@ -1572,6 +1570,37 @@
}, },
timestamp: timestamps[8] timestamp: timestamps[8]
}, },
{
doc: {},
id: "doc",
value: {
date: 4,
title: "doc",
type: "foo2"
},
timestamp: timestamps[6]
},
{
doc: {},
id: "doc",
value: {
date: 4,
title: "doc",
type: "foo2"
},
timestamp: timestamps[5]
},
{
doc: {},
id: "doc",
value: {
date: 1,
title: "doc",
type: "foo"
},
timestamp: timestamps[2]
},
{ {
doc: {}, doc: {},
id: "doc", id: "doc",
...@@ -1597,4 +1626,394 @@ ...@@ -1597,4 +1626,394 @@
}) })
.always(function () {start(); }); .always(function () {start(); });
}); });
module("HistoryStorage.Full-Example", {
setup: function () {
// create storage of type "history" with memory as substorage
var dbname = "db_" + Date.now();
this.blob1 = new Blob(['a']);
this.blob2 = new Blob(['b']);
this.blob3 = new Blob(['ccc']);
this.other_blob = new Blob(['1']);
this.jio = jIO.createJIO({
type: "history",
sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: dbname
}
}
}
});
this.not_history = jIO.createJIO({
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: dbname
}
}
});
}
});
test("Retrieving history with attachments",
function () {
stop();
expect(1);
var jio = this.jio,
not_history = this.not_history,
timestamps,
blobs1 = [
new Blob(['a']),
new Blob(['ab']),
new Blob(['abc']),
new Blob(['abcd']),
new Blob(['abcde'])
],
blobs2 = [
new Blob(['abcdef']),
new Blob(['abcdefg']),
new Blob(['abcdefgh']),
new Blob(['abcdefghi']),
new Blob(['abcdefghij'])
];
putFullDoc(jio, "doc", {title: "bar"}, "data", blobs1[0])
.push(function () {
return putFullDoc(jio, "doc", {title: "bar0"}, "data", blobs1[1]);
})
.push(function () {
return putFullDoc(jio, "doc", {title: "bar1"}, "data", blobs1[2]);
})
.push(function () {
return putFullDoc(jio, "doc2", {title: "foo0"}, "data", blobs2[0]);
})
.push(function () {
return putFullDoc(jio, "doc2", {title: "foo1"}, "data", blobs2[0]);
})
.push(function () {
return putFullDoc(jio, "doc", {title: "bar2"}, "data", blobs1[3]);
})
.push(function () {
return putFullDoc(jio, "doc", {title: "bar3"}, "data", blobs1[4]);
})
// Get timestamps
.push(function () {
return not_history.allDocs({
sort_on: [["timestamp", "ascending"]]
});
})
.push(function (results) {
timestamps = results.data.rows.map(function (d) {
return d.id;
});
})
.push(function () {
return jio.allDocs({
select_list: ["title"],
include_revisions: true
});
})
.push(function (results) {
deepEqual(results.data.rows, [
{
doc: {},
id: "doc",
value: {title: "bar3"},
timestamp: timestamps[13]
},
{
doc: {},
id: "doc",
value: {title: "bar3"},
timestamp: timestamps[12]
},
{
doc: {},
id: "doc",
value: {title: "bar2"},
timestamp: timestamps[11]
},
{
doc: {},
id: "doc",
value: {title: "bar2"},
timestamp: timestamps[10]
},
{
doc: {},
id: "doc2",
value: {title: "foo1"},
timestamp: timestamps[9]
},
{
doc: {},
id: "doc2",
value: {title: "foo1"},
timestamp: timestamps[8]
},
{
doc: {},
id: "doc2",
value: {title: "foo0"},
timestamp: timestamps[7]
},
{
doc: {},
id: "doc2",
value: {title: "foo0"},
timestamp: timestamps[6]
},
{
doc: {},
id: "doc",
value: {title: "bar1"},
timestamp: timestamps[5]
},
{
doc: {},
id: "doc",
value: {title: "bar1"},
timestamp: timestamps[4]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[3]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[2]
},
{
doc: {},
id: "doc",
value: {title: "bar"},
timestamp: timestamps[1]
},
{
doc: {},
id: "doc",
value: {title: "bar"},
timestamp: timestamps[0]
}
],
"allDocs with include_revisions should return all revisions");
})
.fail(function (error) {
//console.log(error);
ok(false, error);
})
.always(function () {start(); });
});
test("Retrieving history with attachments with less straightforward ordering",
function () {
stop();
expect(1);
var jio = this.jio,
not_history = this.not_history,
timestamps,
blobs1 = [
new Blob(['a']),
new Blob(['ab']),
new Blob(['abc']),
new Blob(['abcd']),
new Blob(['abcde'])
];
jio.put("doc", {title: "bar"})
.push(function () {
return jio.put("doc", {title: "bar0"});
})
.push(function () {
return jio.putAttachment("doc", "data", blobs1[0]);
})
.push(function () {
return jio.put("doc2", {title: "foo0"});
})
.push(function () {
return jio.putAttachment("doc", "data", blobs1[1]);
})
// Get timestamps
.push(function () {
return not_history.allDocs({
sort_on: [["timestamp", "ascending"]]
});
})
.push(function (results) {
timestamps = results.data.rows.map(function (d) {
return d.id;
});
})
.push(function () {
return jio.allDocs({
select_list: ["title"],
include_revisions: true
});
})
.push(function (results) {
deepEqual(results.data.rows, [
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[4]
},
{
doc: {},
id: "doc2",
value: {title: "foo0"},
timestamp: timestamps[3]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[2]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[1]
},
{
doc: {},
id: "doc",
value: {title: "bar"},
timestamp: timestamps[0]
}
],
"allDocs with include_revisions should return all revisions");
})
.fail(function (error) {
//console.log(error);
ok(false, error);
})
.always(function () {start(); });
});
test("Retrieving history with attachments with removals",
function () {
stop();
expect(2);
var jio = this.jio,
not_history = this.not_history,
timestamps,
blobs1 = [
new Blob(['a']),
new Blob(['ab']),
new Blob(['abc']),
new Blob(['abcd']),
new Blob(['abcde'])
];
jio.put("doc", {title: "bar"})
.push(function () {
return jio.put("doc", {title: "bar0"});
})
.push(function () {
return jio.putAttachment("doc", "data", blobs1[0]);
})
.push(function () {
return jio.put("doc2", {title: "foo0"});
})
.push(function () {
return jio.putAttachment("doc", "data", blobs1[1]);
})
// Get timestamps
.push(function () {
return not_history.allDocs({
sort_on: [["timestamp", "ascending"]]
});
})
.push(function (results) {
timestamps = results.data.rows.map(function (d) {
return d.id;
});
})
.push(function () {
return jio.allDocs({
select_list: ["title"],
include_revisions: false
});
})
.push(function (results) {
deepEqual(results.data.rows, [
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[4]
},
{
doc: {},
id: "doc2",
value: {title: "foo0"},
timestamp: timestamps[3]
}
],
"allDocs with include_revisions false should return all revisions");
})
.push(function () {
return jio.allDocs({
select_list: ["title"],
include_revisions: true
});
})
.push(function (results) {
deepEqual(results.data.rows, [
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[4]
},
{
doc: {},
id: "doc2",
value: {title: "foo0"},
timestamp: timestamps[3]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[2]
},
{
doc: {},
id: "doc",
value: {title: "bar0"},
timestamp: timestamps[1]
},
{
doc: {},
id: "doc",
value: {title: "bar"},
timestamp: timestamps[0]
}
],
"allDocs with include_revisions true should return all revisions");
})
.fail(function (error) {
//console.log(error);
ok(false, error);
})
.always(function () {start(); });
});
}(jIO, RSVP, Blob, QUnit)); }(jIO, RSVP, Blob, QUnit));
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment