Commit c2b45671 authored by Vincent Bechu's avatar Vincent Bechu

mappingstorage: add properties map_all_property, query_limit on id and tests

parent 4a08108d
/*jslint indent:2, maxlen: 80, nomen: true */ /*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO */ /*global jIO, RSVP */
(function (jIO) { (function (jIO, RSVP) {
"use strict"; "use strict";
function MappingStorage(spec) { function MappingStorage(spec) {
this._mapping_dict = spec.mapping_dict || {}; this._mapping_dict = spec.mapping_dict || {};
this._default_dict = spec.default_dict || {}; this._default_dict = spec.default_dict || {};
this._sub_storage = jIO.createJIO(spec.sub_storage); this._sub_storage = jIO.createJIO(spec.sub_storage);
this._map_all_property = spec.map_all_property || false;
this._id_is_mapped = (this._mapping_dict.id !== undefined
&& this._mapping_dict.id.equal !== "id");
} }
MappingStorage.prototype._getSubStorageId = function (index) { function getSubStorageId(storage, index) {
var option = {}; var query;
option.query = this._mapping_dict.id.equal + ': "' + index + '"'; return new RSVP.Queue()
return this._sub_storage.allDocs(option) .push(function () {
.push(function (data) { var property;
if (data.data.rows.length > 0) { if (!storage._id_is_mapped) {
return data.data.rows[0].id; return index;
} }
return undefined; if (storage._mapping_dict.id.equal !== undefined) {
query = storage._mapping_dict.id.equal + ': "' + index + '"';
if (storage._mapping_dict.id.query_limit !== undefined) {
query += ' AND ' + storage._mapping_dict.id.query_limit;
}
for (property in storage._default_dict) {
if (storage._default_dict.hasOwnProperty(property)) {
query += ' AND ' + property + ': "'
+ storage._default_dict[property].equal + '"';
}
}
return storage._sub_storage.allDocs({"query": query})
.push(function (data) {
if (data.data.rows.length === 0) {
return undefined;
}
if (data.data.rows.length > 1) {
throw new TypeError("id must be unique field");
}
return data.data.rows[0].id;
});
}
throw new jIO.util.jIOError(
"Unsuported option: " + storage._mapping_dict.id,
400
);
}); });
}; }
MappingStorage.prototype._mapDocFromStorage = function (object) { function unmapProperty(storage, property, doc, mapped_doc) {
var result = {}, if (storage._mapping_dict[property].equal !== undefined) {
that = this, doc[storage._mapping_dict[property].equal] = mapped_doc[property];
prop; return storage._mapping_dict[property].equal;
for (prop in that._mapping_dict) { }
if (that._mapping_dict.hasOwnProperty(prop)) { throw new jIO.util.jIOError(
if (prop !== "id") { "Unsuported option(s): " + storage._mapping_dict[property],
result[prop] = object[that._mapping_dict[prop].equal]; 400
);
}
function mapProperty(storage, property, doc, mapped_doc) {
if (storage._mapping_dict[property].equal !== undefined) {
if (doc.hasOwnProperty(storage._mapping_dict[property].equal)) {
mapped_doc[property] = doc[storage._mapping_dict[property].equal];
return storage._mapping_dict[property].equal;
}
return;
}
throw new jIO.util.jIOError(
"Unsuported option(s): " + storage._mapping_dict[property],
400
);
}
function unmapDefaultProperty(storage, doc, property) {
if (storage._default_dict[property].equal !== undefined) {
doc[property] = storage._default_dict[property].equal;
return property;
}
throw new jIO.util.jIOError(
"Unsuported option(s): " + storage._mapping_dict[property],
400
);
}
function mapDocument(storage, doc, delete_id) {
var mapped_doc = {},
property,
property_list = [];
for (property in storage._mapping_dict) {
if (storage._mapping_dict.hasOwnProperty(property)) {
property_list.push(mapProperty(storage, property, doc, mapped_doc));
}
}
if (storage._map_all_property) {
for (property in doc) {
if (doc.hasOwnProperty(property)) {
if (property_list.indexOf(property) < 0) {
mapped_doc[property] = doc[property];
}
} }
} }
} }
return result; if (delete_id) {
}; delete mapped_doc.id;
}
return mapped_doc;
}
function unmapDocument(storage, mapped_doc) {
var doc = {}, property;
for (property in storage._default_dict) {
if (storage._default_dict.hasOwnProperty(property)) {
unmapDefaultProperty(storage, doc, property);
}
}
for (property in mapped_doc) {
if (mapped_doc.hasOwnProperty(property)) {
if (storage._mapping_dict[property] !== undefined) {
unmapProperty(storage, property, doc, mapped_doc);
} else {
if (storage._map_all_property
&& !storage._default_dict.hasOwnProperty(property)) {
doc[property] = mapped_doc[property];
}
}
}
}
return doc;
}
MappingStorage.prototype.get = function (index) { MappingStorage.prototype.get = function (index) {
var that = this; var that = this;
if (this._mapping_dict.id === undefined || return getSubStorageId(this, index)
this._mapping_dict.id.equal === "id") {
return this._sub_storage.get(index)
.push(function (result) {
return that._mapDocFromStorage(result);
});
}
return this._getSubStorageId(index)
.push(function (id) { .push(function (id) {
return that._sub_storage.get(id); if (id !== undefined) {
return that._sub_storage.get(id);
}
throw new jIO.util.jIOError("Cannot find document " + id, 404);
}) })
.push(function (result) { .push(function (doc) {
return that._mapDocFromStorage(result); return mapDocument(that, doc, true);
})
.push(undefined, function (error) {
throw error;
}); });
}; };
MappingStorage.prototype.put = function (index, doc) { MappingStorage.prototype.post = function () {
var prop, that = this, if (!this._id_is_mapped) {
doc_mapped = JSON.parse(JSON.stringify(this._default_dict)); return this._sub_storage.post.apply(this._sub_storage, arguments);
for (prop in doc) {
if (doc.hasOwnProperty(prop)) {
doc_mapped[this._mapping_dict[prop].equal] = doc[prop];
}
}
if (this._mapping_dict.id === undefined ||
this._mapping_dict.id.equal === "id") {
return this._sub_storage.put(index, doc_mapped);
} }
doc_mapped[this._mapping_dict.id.equal] = index; throw new jIO.util.jIOError("Can't use post with id mapped", 400);
return this._getSubStorageId(index) };
MappingStorage.prototype.put = function (index, doc) {
var that = this,
mapped_doc = unmapDocument(this, doc);
return getSubStorageId(this, index)
.push(function (id) { .push(function (id) {
if (id === undefined) { if (that._mapping_dict.id && that._mapping_dict.id.equal !== "id") {
return that._sub_storage.post(doc_mapped) mapped_doc[that._mapping_dict.id.equal] = index;
.push(function () {
return index;
});
} }
return that._sub_storage.put(id, doc_mapped); if (id !== undefined) {
return that._sub_storage.put(id, mapped_doc);
}
return that._sub_storage.post(mapped_doc);
})
.push(function () {
return index;
}); });
}; };
MappingStorage.prototype.remove = function (index) { MappingStorage.prototype.remove = function (index) {
var that = this; var that = this;
if (this._mapping_dict.id === undefined return getSubStorageId(this, index)
|| this._mapping_dict.id.equal === "id") {
return this._sub_storage.remove.apply(this._sub_storage,
arguments);
}
return this._getSubStorageId(index)
.push(function (id) { .push(function (id) {
return that._sub_storage.remove(id); return that._sub_storage.remove(id);
}) })
...@@ -95,77 +186,67 @@ ...@@ -95,77 +186,67 @@
}; };
MappingStorage.prototype.putAttachment = function (doc_id) { MappingStorage.prototype.putAttachment = function (doc_id) {
var that = this; var that = this, argument_list = arguments;
if (this._mapping_dict.id === undefined return getSubStorageId(this, doc_id)
|| this._mapping_dict.id.equal === "id") {
return this._sub_storage.putAttachment.apply(this._sub_storage,
arguments);
}
return this._getSubStorageId(doc_id)
.push(function (id) { .push(function (id) {
doc_id = id; argument_list[0] = id;
return that._sub_storage.putAttachment.apply(that._sub_storage, return that._sub_storage.putAttachment.apply(that._sub_storage,
arguments); argument_list);
}); });
}; };
MappingStorage.prototype.getAttachment = function (doc_id) { MappingStorage.prototype.getAttachment = function (doc_id) {
var that = this; var that = this, argument_list = arguments;
if (this._mapping_dict.id === undefined return getSubStorageId(this, doc_id)
|| this._mapping_dict.id.equal === "id") {
return this._sub_storage.getAttachment.apply(this._sub_storage,
arguments);
}
return this._getSubStorageId(doc_id)
.push(function (id) { .push(function (id) {
doc_id = id; argument_list[0] = id;
return that._sub_storage.getAttachment.apply(that._sub_storage, return that._sub_storage.getAttachment.apply(that._sub_storage,
arguments); argument_list);
}); });
}; };
MappingStorage.prototype.removeAttachment = function (doc_id) { MappingStorage.prototype.removeAttachment = function (doc_id) {
var that = this; var that = this, argument_list = arguments;
if (this._mapping_dict.id === undefined return getSubStorageId(this, doc_id)
|| this._mapping_dict.id.equal === "id") {
return this._sub_storage.removeAttachment.apply(this._sub_storage,
arguments);
}
return this._getSubStorageId(doc_id)
.push(function (id) { .push(function (id) {
doc_id = id; argument_list[0] = id;
return that._sub_storage.removeAttachment.apply(that._sub_storage, return that._sub_storage.removeAttachment.apply(that._sub_storage,
arguments); argument_list);
}); });
}; };
MappingStorage.prototype.hasCapacity = function (name) { MappingStorage.prototype.hasCapacity = function () {
if (name === "include_docs") {
return true;
}
return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments);
}; };
MappingStorage.prototype.buildQuery = function (option) { MappingStorage.prototype.buildQuery = function (option) {
var that = this, i, select_list = [], sort_on = [], query, prop; var that = this,
i,
query,
select_list = [],
sort_on = [];
function mapQuery(one_query) { function mapQuery(one_query) {
var i, query_list = []; var i, result = "", key;
if (one_query.type === "complex") { if (one_query.type === "complex") {
for (i = 0; i < one_query.query_list.length; i += 1) { for (i = 0; i < one_query.query_list.length; i += 1) {
query_list.push(mapQuery(one_query.query_list[i])); result += "(" + mapQuery(one_query.query_list[i]) + ")";
if (i < one_query.query_list.length - 1) {
result += " " + one_query.operator + " ";
}
}
return result;
}
if (that._mapping_dict.hasOwnProperty(one_query.key)) {
key = that._mapping_dict[one_query.key].equal;
} else {
if (that._map_all_property) {
key = one_query.key;
} }
return {
operator: one_query.operator,
query_list: query_list,
type: "complex"
};
} }
return { return (key ? key + ":" : "") +
key: that._mapping_dict[one_query.key].equal, (one_query.operator ? " " + one_query.operator : "") +
type: "simple", ' "' + one_query.value + '"';
value: one_query.value
};
} }
if (option.sort_on !== undefined) { if (option.sort_on !== undefined) {
...@@ -176,25 +257,27 @@ ...@@ -176,25 +257,27 @@
} }
if (option.select_list !== undefined) { if (option.select_list !== undefined) {
for (i = 0; i < option.select_list.length; i += 1) { for (i = 0; i < option.select_list.length; i += 1) {
select_list.push(this._mapping_dict[option.select_list[i]].equal); if (this._mapping_dict.hasOwnProperty(option.select_list[i])) {
} select_list.push(this._mapping_dict[option.select_list[i]].equal);
} } else {
if (option.include_docs) { if (this._map_all_property) {
select_list = []; select_list.push(option.select_list[i]);
for (prop in this._mapping_dict) { }
if (this._mapping_dict.hasOwnProperty(prop)) {
select_list.push(this._mapping_dict[prop].equal);
} }
} }
} }
if (this._mapping_dict.id !== undefined if (this._id_is_mapped) {
&& this._mapping_dict.id.equal !== "id") {
select_list.push(this._mapping_dict.id.equal); select_list.push(this._mapping_dict.id.equal);
} }
query = jIO.Query.parseStringToObject(option.query); if (option.query !== undefined) {
query = mapQuery(jIO.QueryFactory.create(option.query));
}
if (this._mapping_dict.id.query_limit !== undefined) {
query += 'AND( ' + this._mapping_dict.id.query_limit + ' )';
}
return this._sub_storage.allDocs( return this._sub_storage.allDocs(
{ {
query: mapQuery(query), query: query,
select_list: select_list, select_list: select_list,
sort_on: sort_on, sort_on: sort_on,
limit: option.limit limit: option.limit
...@@ -202,14 +285,13 @@ ...@@ -202,14 +285,13 @@
) )
.push(function (result) { .push(function (result) {
for (i = 0; i < result.data.total_rows; i += 1) { for (i = 0; i < result.data.total_rows; i += 1) {
if (that._mapping_dict.id !== undefined result.data.rows[i].value =
&& that._mapping_dict.id.equal !== "id") { mapDocument(that, result.data.rows[i].value, false);
if (result.data.rows[i].id !== undefined) {
result.data.rows[i].id = result.data.rows[i].id =
result.data.rows[i].value[that._mapping_dict.id.equal]; result.data.rows[i].value.id;
delete result.data.rows[i].value[that._mapping_dict.id.equal]; delete result.data.rows[i].value.id;
} }
result.data.rows[i].value =
that._mapDocFromStorage(result.data.rows[i].value);
} }
return result.data.rows; return result.data.rows;
}); });
...@@ -217,4 +299,4 @@ ...@@ -217,4 +299,4 @@
jIO.addStorage('mapping', MappingStorage); jIO.addStorage('mapping', MappingStorage);
}(jIO)); }(jIO, RSVP));
\ No newline at end of file \ No newline at end of file
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
deepEqual(jio.__storage._mapping_dict, {"bar": {"equal": "foo"}}); deepEqual(jio.__storage._mapping_dict, {"bar": {"equal": "foo"}});
deepEqual(jio.__storage._default_dict, {"foo": {"equal": "bar"}}); deepEqual(jio.__storage._default_dict, {"foo": {"equal": "bar"}});
equal(jio.__storage._map_all_property, false);
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -160,6 +161,98 @@ ...@@ -160,6 +161,98 @@
}); });
}); });
test("get with id mapped and query_limit", function () {
stop();
expect(3);
var jio = jIO.createJIO({
type: "mapping",
sub_storage: {
type: "mappingstorage2713"
},
mapping_dict: {
"title": {"equal": "otherTitle"},
"id": {"equal": "otherId", "query_limit": 'otherTitle: "foo"'}
}
});
Storage2713.prototype.hasCapacity = function () {
return true;
};
Storage2713.prototype.buildQuery = function (options) {
deepEqual(
options,
{query: 'otherId: "42" AND otherTitle: "foo"'},
"allDoc 2713 called"
);
return [{id: "2713"}];
};
Storage2713.prototype.get = function (id) {
equal(id, "2713", "get 2713 called");
return {"otherTitle": "foo"};
};
jio.get("42")
.then(function (result) {
deepEqual(result, {
"title": "foo"
});
}).fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
test("get with map_all_property", function () {
stop();
expect(3);
var jio = jIO.createJIO({
type: "mapping",
sub_storage: {
type: "mappingstorage2713"
},
mapping_dict: {
"id": {"equal": "otherId"}
},
map_all_property: true
});
Storage2713.prototype.hasCapacity = function () {
return true;
};
Storage2713.prototype.buildQuery = function (options) {
deepEqual(
options,
{query: 'otherId: "42"'},
"allDoc 2713 called"
);
return [{id: "2713"}];
};
Storage2713.prototype.get = function (id) {
equal(id, "2713", "get 2713 called");
return {"title": "foo"};
};
jio.get("42")
.then(function (result) {
deepEqual(result, {
"title": "foo"
});
}).fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// mappingStorage.put // mappingStorage.put
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -203,7 +296,7 @@ ...@@ -203,7 +296,7 @@
sub_storage: { sub_storage: {
type: "mappingstorage2713" type: "mappingstorage2713"
}, },
default_dict: {"title": "foobar"} default_dict: {"title": {"equal": "foobar"}}
}); });
Storage2713.prototype.put = function (id, param) { Storage2713.prototype.put = function (id, param) {
...@@ -226,7 +319,7 @@ ...@@ -226,7 +319,7 @@
test("put with id and prop mapped", function () { test("put with id and prop mapped", function () {
stop(); stop();
expect(2); expect(3);
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "mapping", type: "mapping",
sub_storage: { sub_storage: {
...@@ -244,6 +337,15 @@ ...@@ -244,6 +337,15 @@
return "bar"; return "bar";
}; };
Storage2713.prototype.hasCapacity = function () {
return true;
};
Storage2713.prototype.buildQuery = function (option) {
deepEqual(option, {"query": 'otherId: "42"'}, "allDocs 2713 called");
return [];
};
jio.put("42", {"title": "foo"}) jio.put("42", {"title": "foo"})
.then(function (result) { .then(function (result) {
equal(result, "42"); equal(result, "42");
...@@ -256,6 +358,38 @@ ...@@ -256,6 +358,38 @@
}); });
}); });
test("put with map_all_property", function () {
stop();
expect(3);
var jio = jIO.createJIO({
type: "mapping",
sub_storage: {
type: "mappingstorage2713"
},
mapping_dict: {
"id": {"equal": "id"}
},
map_all_property: true
});
Storage2713.prototype.put = function (id, doc) {
deepEqual(doc,
{"title": "foo", "smth": "bar", "smth2": "bar2"}, "post 2713 called");
equal(id, "42", "put 2713 called");
return id;
};
jio.put("42", {"title": "foo", "smth": "bar", "smth2": "bar2"})
.then(function (result) {
equal(result, "42");
})
.fail(function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// mappingStorage.remove // mappingStorage.remove
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -409,11 +543,11 @@ ...@@ -409,11 +543,11 @@
Storage2713.prototype.removeAttachment = function (doc_id, attachment) { Storage2713.prototype.removeAttachment = function (doc_id, attachment) {
equal(doc_id, "42", "putAttachment 2713 called"); equal(doc_id, "42", "putAttachment 2713 called");
equal(attachment, "2713", "getAttachment 2713 called"); equal(attachment, "2713", "getAttachment 2713 called");
return attachment; return doc_id;
}; };
jio.removeAttachment("42", "2713") jio.removeAttachment("42", "2713")
.then(function (result) { .then(function (result) {
deepEqual(result, "2713"); deepEqual(result, "42");
}) })
.fail(function (error) { .fail(function (error) {
ok(false, error); ok(false, error);
...@@ -424,17 +558,23 @@ ...@@ -424,17 +558,23 @@
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// mappingStorage.buildQuery // mappingStorage.allDocs
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
module("mappingStorage.buildQuery"); module("mappingStorage.buildQuery");
test("buildQuery with id and prop mapped", function () { test("allDocs with complex query, id and prop mapped", function () {
stop(); stop();
expect(2); expect(1);
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "mapping", type: "mapping",
sub_storage: { sub_storage: {
type: "mappingstorage2713" type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "memory"
}
}
}, },
mapping_dict: { mapping_dict: {
"id": {"equal": "otherId"}, "id": {"equal": "otherId"},
...@@ -443,72 +583,146 @@ ...@@ -443,72 +583,146 @@
} }
}); });
Storage2713.prototype.hasCapacity = function () { jio.put("42",
return true; {
}; "title": "foo",
"smth": "bar"
})
.push(function () {
return jio.allDocs({
query: '(title: "foo") AND (smth: "bar")',
select_list: ["title", "smth"],
sort_on: [["title", "descending"]]
});
})
.push(function (result) {
deepEqual(result,
{
"data": {
"rows": [
{
"id": "42",
"value": {
"title": "foo",
"smth": "bar"
},
"doc": {}
}
],
"total_rows": 1
}
}, "allDocs check");
})
.push(undefined, function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
Storage2713.prototype.buildQuery = function (options) { test("allDocs without option, id and prop mapped", function () {
deepEqual(options, stop();
{ expect(1);
"include_docs": false,
"limit": undefined,
"query": {
"operator": "AND",
"query_list": [
{
"key": "otherTitle",
"type": "simple",
"value": "foo"
},
{
"key": "otherSmth",
"type": "simple",
"value": "bar"
}
],
"type": "complex"
},
"select_list": [
"otherTitle",
"otherId"
],
"sort_on": [
[
"otherSmth",
"descending"
]
]
}, "allDocs 2713 called");
return [{
id: "2713",
value: {"otherId": "42", "otherTitle": "foo", "otherSmth": "bar"}
}];
};
jio.allDocs({ var jio = jIO.createJIO({
query: '(title: "foo") AND (smth: "bar")', type: "mapping",
sort_on: [["smth", "descending"]], sub_storage: {
select_list: ["title"], type: "query",
include_docs: false sub_storage: {
}) type: "uuid",
.then(function (result) { sub_storage: {
type: "memory"
}
}
},
mapping_dict: {
"id": {"equal": "otherId"},
"title": {"equal": "otherTitle"}
}
});
jio.put("42",
{
"title": "foo",
"smth": "bar"
})
.push(function () {
return jio.allDocs();
})
.push(function (result) {
deepEqual(result, deepEqual(result,
{ {
"data": { "data": {
"rows": [ "rows": [
{ {
"id": "42", "id": "42",
"value": { "value": {},
"smth": "bar", "doc": {}
"title": "foo"
}
} }
], ],
"total_rows": 1 "total_rows": 1
} }
}, "allDocs check"); }, "allDocs check");
}) })
.fail(function (error) { .push(undefined, function (error) {
ok(false, error);
})
.always(function () {
start();
});
});
test("allDocs id and prop mapped and map_all_property", function () {
stop();
expect(1);
var jio = jIO.createJIO({
type: "mapping",
sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "memory"
}
}
},
mapping_dict: {
"id": {"equal": "otherId"},
"title": {"equal": "otherTitle"}
},
map_all_property: true
});
jio.put("42",
{
"title": "foo",
"smth": "bar",
"stmth2": "bar2"
})
.push(function () {
return jio.allDocs({
query: 'title: "foo"',
select_list: ["title", "smth2", "smth"]
});
})
.push(function (result) {
deepEqual(result,
{
"data": {
"rows": [
{
"id": "42",
"value": {"title": "foo", "smth": "bar", "smth2": "bar2"},
"doc": {}
}
],
"total_rows": 1
}
}, "allDocs check");
})
.push(undefined, function (error) {
ok(false, error); ok(false, error);
}) })
.always(function () { .always(function () {
......
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