Commit b53f05b1 authored by Tristan Cavelier's avatar Tristan Cavelier

ComplexQueries put in JIO

See docs/query.rst for more informations
parent be091ae3
......@@ -54,26 +54,25 @@ module.exports = function (grunt) {
// duplicate files are ignored
src: [
'src/jio/intro.js',
// core
'src/jio/core/globals.js',
'src/jio/core/util.js',
'src/jio/core/**/*.js',
'src/jio/features/**/*.js',
'src/jio/outro.js'
],
dest: 'jio.js'
},
queries: {
src: [
'src/queries/begin.js',
// queries
'src/queries/core/globals.js',
'src/queries/core/query.js',
'src/queries/parser-begin.js',
'src/queries/build/parser.js',
'src/queries/parser-end.js',
'src/queries/core/globals.js',
'src/queries/core/tools.js',
'src/queries/core/**/*.js',
'src/queries/end.js'
'src/jio/outro.js'
],
dest: 'complex_queries.js'
dest: 'jio.js'
}
},
uglify: {
......@@ -88,10 +87,6 @@ module.exports = function (grunt) {
jiodate: {
src: 'src/jio.date/jiodate.js',
dest: 'jiodate.min.js'
},
queries: {
src: 'complex_queries.js',
dest: 'complex_queries.min.js'
}
},
qunit: {
......
......@@ -5,8 +5,6 @@ QUERIES_DIR = src/queries
JIO = jio.js
JIO_MIN = jio.min.js
JIODATE_MIN = jiodate.min.js
COMPLEX = complex_queries.js
COMPLEX_MIN = complex_queries.min.js
PARSER_PAR = $(QUERIES_DIR)/core/parser.par
PARSER_OUT = $(QUERIES_DIR)/build/parser.js
UGLIFY = ./node_modules/grunt-contrib-uglify/node_modules/uglify-js/bin/uglifyjs
......@@ -28,7 +26,7 @@ zip:
@mkdir $(TMPDIR)/jio
@mkdir $(TMPDIR)/jio/storage
@cp jio.js $(TMPDIR)/jio/
@cp complex_queries.js $(TMPDIR)/jio/
@cp jioquery.js $(TMPDIR)/jio/
@cp src/sha1.amd.js $(TMPDIR)/jio/
@cp src/sha2.amd.js $(TMPDIR)/jio/
@cp src/sha256.amd.js $(TMPDIR)/jio/
......@@ -57,7 +55,6 @@ zip:
@mkdir $(TMPDIR)/jio/storage
@echo "Minimizing JS..."
@cp jio.min.js $(TMPDIR)/jio/
@cp complex_queries.min.js $(TMPDIR)/jio/
@$(UGLIFY) src/sha1.amd.js >$(TMPDIR)/jio/sha1.amd.min.js 2>/dev/null
@$(UGLIFY) src/sha2.amd.js >$(TMPDIR)/jio/sha2.amd.min.js 2>/dev/null
@$(UGLIFY) src/sha256.amd.js >$(TMPDIR)/jio/sha256.amd.min.js 2>/dev/null
......@@ -92,6 +89,4 @@ realclean:
rm -f "$(JIO)"
rm -f "$(JIO_MIN)"
rm -f "$(JIODATE_MIN)"
rm -f "$(COMPLEX)"
rm -f "$(COMPLEX_MIN)"
rm -f "$(PARSER_OUT)"
......@@ -16,7 +16,6 @@ depending on type of storages being used):
<script src="jio.js"></script>
<!-- jio storage libraries -->
<script src="complex-queries.js"></script>
<script src="localstorage.js"></script>
<script ...>
......@@ -309,13 +308,12 @@ var jio_instance = jIO.createJIO({
For more information on the specific storages including guidelines on how to
create your own connector, please also refer to the [documentation](https://www.j-io.org/documentation/jio-documentation).
### Complex Queries
### jIO Query
jIO uses complex-queries manager, which can be run on top of the allDocs()
method to query documents in the storage tree. A sample query would look like
this (note that not all storages support allDocs and complex queries, and
that pre-querying of documents on distant storages should best be done
server-side):
jIO can use queries, which can be run in the allDocs() method to query document
lists. A sample query would look like this (note that not all storages support
allDocs and jio queries, and that pre-querying of documents on distant storages
should best be done server-side):
```javascript
// run allDocs with query option on an existing jIO
......@@ -342,7 +340,7 @@ jio_instance.allDocs({
});
```
To find out more about complex queries, please refer to the documentation.
To find out more about queries, please refer to the documentation.
### Task Management
......
......@@ -5,7 +5,7 @@ Quick start
-----------
The source repository includes ready-to-use files, so in case you do
not want to build jIO yourself, just use *jio.js* as well as *complex_queries.js*
not want to build jIO yourself, just use *sha256.amd.js*, *rsvp.js*, *jio.js*
plus the storages and dependencies you need and you will be good to go.
If you want to modify or build jIO yourself, you need to
......@@ -21,15 +21,15 @@ If you want to modify or build jIO yourself, you need to
``# npm -g install grunt-cli``
* Install the dependencies.
``$ npm install``
* Compile the JS/CC parser.
``$ make`` (until we find out how to compile it with grunt)
* Run build.
``$ grunt``
......@@ -311,4 +311,3 @@ Or you can just clear all rules before adding new ones:
// ...
}]
});
......@@ -15,7 +15,6 @@ Getting started
<script src="jio.js"></script>
<!-- storages + dependencies -->
<script src="complex_queries.js"></script>
<script src="localstorage.js"></script>
<script src="davstorage.js"></script>
......@@ -33,7 +32,6 @@ Getting started
rsvp: 'rsvp-custom',
jio: 'jio',
// storages + dependencies
complex_queries: 'complex_queries',
localstorage: 'localstorage',
davstorage: 'davstorage'
}
......@@ -110,7 +108,6 @@ Core
* sha256.amd.js
* rsvp-custom.js, AMD only version: rsvp-custom.amd.js
* jio.js
* complex_queries.js
Storage dependencies
^^^^^^^^^^^^^^^^^^^^
......
......@@ -9,7 +9,8 @@ A storage to enable interoperability between all kind of storages.
A global ID (GID) is a document id which represents a unique document. This ID
is then used to find this unique document on all types of backends.
This storage uses sub storage ``.allDocs()`` and complex queries to find unique documents, and converts their ids to gids.
This storage uses sub storage ``.allDocs()`` and queries to find unique
documents, and converts their ids to gids.
Where it can be used
--------------------
......@@ -125,7 +126,7 @@ Storage Requirements
--------------------
* This storage is not compatible with *RevisionStorage* and *ReplicateRevisionStorage*.
* Sub storages have to support options for ``complex queries`` and ``include_docs``.
* Sub storages have to support options for queries and ``include_docs``.
Dependencies
......@@ -158,5 +159,3 @@ Offline application usage::
`-- Local Storage
**CAUTION: All gid storage must have the same description!**
......@@ -41,10 +41,9 @@ jIO documentation
revision_storages
available_storages
gid_storage
complex_queries
query
keys
metadata
developers
style_guide
authors
......@@ -161,7 +161,7 @@ property, that behaves like the ``compareFunction`` described in
If the < or > comparison makes no sense for the objects, the function should return ``undefined``.
The ``.cmp()`` property is also used, if present, by the sorting feature of complex queries.
The ``.cmp()`` property is also used, if present, by the sorting feature of queries.
......@@ -262,7 +262,7 @@ A schema can be used:
.. code-block:: javascript
complex_queries.QueryFactory.create({...}, key_schema).exec(...);
jIO.QueryFactory.create({...}, key_schema).exec(...);
* In the ``jIO.createJIO()`` method. The same schema will be used
......
......@@ -400,7 +400,7 @@ Posting a job announcement
Getting a list of document created by someone
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With complex query:
With query:
.. code-block:: javascript
......@@ -410,7 +410,7 @@ With complex query:
Getting all documents about jIO in the resilience project
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With complex query:
With query:
.. code-block:: javascript
......
jIO Complex Queries
===================
jIO Query
=========
What are Complex Queries?
-------------------------
What are Queries?
-----------------
In jIO, a complex query can ask a storage server to select, filter, sort, or
limit a document list before sending it back. If the server is not able to do
so, the complex query tool can do the filtering by itself on the client. Only the
``.allDocs()`` method can use complex queries.
In jIO, a query can ask a storage server to select, filter, sort, or limit a
document list before sending it back. If the server is not able to do so, the
jio query tool can do the filtering by itself on the client. Only the
``.allDocs()`` method can use jio queries.
A query can either be a string (using a specific language useful for writing
queries), or it can be a tree of objects (useful to browse queries). To handle
complex queries, jIO uses a parsed grammar file which is compiled using `JSCC <http://jscc.phorward-software.com/>`_.
A query can either be a string (using a specific language useful for writing
queries), or it can be a tree of objects (useful to browse queries). To handle
queries, jIO uses a parsed grammar file which is compiled using `JSCC
<http://jscc.phorward-software.com/>`_.
Why use Complex Queries?
------------------------
Why use JIO Queries?
--------------------
Complex queries can be used like database queries, for tasks such as:
JIO queries can be used like database queries, for tasks such as:
* search a specific document
* sort a list of documents in a certain order
* avoid retrieving a list of ten thousand documents
* limit the list to show only N documents per page
For some storages (like localStorage), complex queries can be a powerful tool
to query accessible documents. When querying documents on a distant storage,
some server-side logic should be run to avoid returning too many documents
to the client. If distant storages are static, an alternative would be to use
an indexStorage with appropriate indices as complex queries will always try
to run the query on the index before querying documents itself.
For some storages (like localStorage), jio queries can be a powerful tool to
query accessible documents. When querying documents on a distant storage, some
server-side logic should be run to avoid returning too many documents to the
client. If distant storages are static, an alternative would be to use an
indexStorage with appropriate indices as jio queries will always try to run the
query on the index before querying documents itself.
How to use Complex Queries with jIO?
------------------------------------
How to use Queries with jIO?
----------------------------
Complex queries can be triggered by including the option named **query** in the ``.allDocs()`` method call.
Queries can be triggered by including the option named **query** in the ``.allDocs()`` method call.
Example:
......@@ -75,31 +76,29 @@ Example:
jio_instance.allDocs(options, callback);
How to use Complex Queries outside jIO?
---------------------------------------
.. XXX 404 page missing on complex_example.html
How to use Queries outside jIO?
-------------------------------
Complex Queries provides an API - which namespace is complex_queries.
Refer to the `Complex Queries sample page <http://git.erp5.org/gitweb/jio.git/blob/HEAD:/examples/complex_example.html?js=1>`_
Refer to the `JIO Query sample page <http://git.erp5.org/gitweb/jio.git/blob/HEAD:/examples/example-queries.html?js=1>`_
for how to use these methods, in and outside jIO. The module provides:
.. code-block:: javascript
{
parseStringToObject: [Function: parseStringToObject],
stringEscapeRegexpCharacters: [Function: stringEscapeRegexpCharacters],
select: [Function: select],
sortOn: [Function: sortOn],
limit: [Function: limit],
searchTextToRegExp: [Function: searchTextToRegExp],
jIO: {
QueryFactory: { [Function: QueryFactory] create: [Function] },
Query: [Function: Query],
Query: { [Function: Query],
parseStringToObject: [Function],
stringEscapeRegexpCharacters: [Function],
select: [Function],
sortOn: [Function],
limit: [Function],
searchTextToRegExp: [Function],
}
SimpleQuery: {
[Function: SimpleQuery] super_: [Function: Query]
[Function: SimpleQuery] super_: [Function: Query]
},
ComplexQuery: {
[Function: ComplexQuery] super_: [Function: Query]
[Function: ComplexQuery] super_: [Function: Query]
}
}
......@@ -119,7 +118,7 @@ Basic example:
var query = 'title: "Document number 1"';
// running the query
var result = complex_queries.QueryFactory.create(query).exec(object_list);
var result = jIO.QueryFactory.create(query).exec(object_list);
// console.log(result);
// [ { "title": "Document number 1", "creator": "John Doe"} ]
......@@ -128,7 +127,7 @@ Other example:
.. code-block:: javascript
var result = complex_queries.QueryFactory.create(query).exec(
var result = jIO.QueryFactory.create(query).exec(
object_list,
{
"select": ['title', 'year'],
......@@ -138,18 +137,18 @@ Other example:
}
);
// this case is equal to:
var result = complex_queries.QueryFactory.
create(query).exec(object_list);
complex_queries.sortOn([
['title', 'ascending'],
['year', 'descending']
], result);
complex_queries.limit([20, 20], result);
complex_queries.select(['title', 'year'], result);
var result = jIO.QueryFactory.
create(query).exec(object_list);
jIO.Query.sortOn([
['title', 'ascending'],
['year', 'descending']
], result);
jIO.Query.limit([20, 20], result);
jIO.Query.select(['title', 'year'], result);
Complex Queries in storage connectors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Query in storage connectors
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The query exec method must only be used if the server is not able to pre-select
documents. As mentioned before, you could use an indexStorage to maintain
......@@ -160,7 +159,7 @@ are available in the index.
Matching properties
^^^^^^^^^^^^^^^^^^^
Complex Queries select items which exactly match the value given in the query
Queries select items which exactly match the value given in the query
but you can also use wildcards (``%``). If you don't want to use a wildcard,
just set the operator to ``=``.
......@@ -184,14 +183,14 @@ component (change ``limit: [0, 10]`` to ``limit: [10, 10]`` or ``sort_on: [['tit
'ascending']]`` to ``sort_on: [['creator', 'ascending']]``) and each component must
have its own default properties to keep their own behavior.
Convert Complex Queries into another type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Query into another type
^^^^^^^^^^^^^^^^^^^^^^^
Example, convert Query object into a human readable string:
.. code-block:: javascript
var query = complex_queries.QueryFactory.
var query = jIO.QueryFactory.
create('year: < 2000 OR title: "%a"'),
option = {
limit: [0, 10]
......@@ -240,7 +239,7 @@ JSON Schemas and Grammar
Below you can find schemas for constructing queries.
* Complex Queries JSON Schema:
* Complex Query JSON Schema:
.. code-block:: javascript
......@@ -274,7 +273,7 @@ Below you can find schemas for constructing queries.
}
* Simple Queries JSON Schema:
* Simple Query JSON Schema:
.. code-block:: javascript
......@@ -308,7 +307,7 @@ Below you can find schemas for constructing queries.
* Complex Queries Grammar::
* JIO Query Grammar::
search_text
: and_expression
......
......@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Complex Queries Example</title>
<title>JIO Query Example</title>
<style type="text/css" media="screen">
table, textarea, input {
width: 100%;
......@@ -39,7 +39,6 @@
<button onclick="jsonToSearchText()">JSON to Search text</button>
<button onclick="query()">Query</button>
<script type="text/javascript" src="../lib/rsvp/rsvp-custom.js"></script>
<script type="text/javascript" src="../complex_queries.js"></script>
<script type="text/javascript"
src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
......@@ -48,7 +47,7 @@ function searchTextToJson() {
$("#obj").attr(
"value",
JSON.stringify(
complex_queries.QueryFactory.create(
jIO.QueryFactory.create(
$("#str").attr("value")
).serialized()
)
......@@ -57,7 +56,7 @@ function searchTextToJson() {
function jsonToSearchText() {
$("#str").attr(
"value",
complex_queries.QueryFactory.create(
jIO.QueryFactory.create(
JSON.parse(
$("#obj").attr("value")
)
......@@ -66,7 +65,7 @@ function jsonToSearchText() {
}
function query() {
var list = JSON.parse($("#list").attr("value"));
complex_queries.QueryFactory.create(
jIO.QueryFactory.create(
JSON.parse(
$("#obj").attr("value")
)
......
......@@ -19,7 +19,6 @@ var log = function (o) {
<script src="../src/sha256.amd.js"></script>
<script src="../lib/rsvp/rsvp-custom.js"></script>
<script src="../jio.js"></script>
<script src="../complex_queries.js"></script>
<script src="../src/jio.storage/localstorage.js"></script>
<script type="text/javascript">
<!--
......
......@@ -130,7 +130,6 @@ document.addEventListener("keypress", function (event) {
<script src="../lib/rsvp/rsvp-custom.js"></script>
<script src="../src/sha256.amd.js"></script>
<script src="../jio.js"></script>
<script src="../complex_queries.js"></script>
<script src="../src/jio.storage/localstorage.js"></script>
<script src="http://git.erp5.org/gitweb/uritemplate-js.git/blob_plain/HEAD:/bin/uritemplate-min.js"></script>
<script src="../lib/uri/URI.js"></script>
......
......@@ -10,7 +10,7 @@
// }
/*jslint indent: 2, nomen: true, unparam: true */
/*global jIO, complex_queries, console, UriTemplate, FormData, RSVP, URI,
/*global jIO, console, UriTemplate, FormData, RSVP, URI,
ProgressEvent, define */
(function (dependencies, module) {
......@@ -18,13 +18,12 @@
if (typeof define === 'function' && define.amd) {
return define(dependencies, module);
}
module(RSVP, jIO, complex_queries, URI);
module(RSVP, jIO, URI);
}([
'rsvp',
'jio',
'complex_queries',
'uri'
], function (RSVP, jIO, complex_queries, URI) {
], function (RSVP, jIO, URI) {
"use strict";
function ERP5Storage(spec) {
......@@ -176,7 +175,7 @@
ERP5Storage.prototype.allDocs = function (command, param, options) {
if (typeof options.query !== "string") {
options.query = (options.query ?
complex_queries.objectToSearchText(options.query) :
jIO.Query.objectToSearchText(options.query) :
undefined);
}
return this._getSiteDocument()
......
......@@ -23,7 +23,7 @@
* JIO GID Storage. Type = 'gid'.
* Identifies document with their global identifier representation
*
* Sub storages must support complex queries and include_docs options.
* Sub storages must support queries and include_docs options.
*
* Storage Description:
*
......@@ -216,12 +216,12 @@
}
/**
* Convert a gid to a complex query.
* Convert a gid to a jio query.
*
* @param {Object,String} gid The gid
* @return {Object} A complex serialized object
* @return {Object} A jio serialized query
*/
function gidToComplexQuery(gid) {
function gidToJIOQuery(gid) {
var k, i, result = [], meta, content;
if (typeof gid === 'string') {
gid = JSON.parse(gid);
......@@ -300,7 +300,7 @@
* Generic command for post or put one.
*
* This command will check if the document already exist with an allDocs
* and a complex query. If exist, then post will fail. Put will update the
* and a jio query. If exist, then post will fail. Put will update the
* retrieved document thanks to its real id. If no documents are found, post
* and put will create a new document with the sub storage id generator.
*
......@@ -310,7 +310,7 @@
* @param {String} method The command method
*/
priv.putOrPost = function (command, metadata, method) {
var gid, complex_query, doc = tool.deepClone(metadata);
var gid, jio_query, doc = tool.deepClone(metadata);
gid = gidFormat(doc, priv.constraints);
if (gid === undefined || (doc._id && gid !== doc._id)) {
return command.error(
......@@ -319,9 +319,9 @@
"Cannot " + method + " document"
);
}
complex_query = gidToComplexQuery(gid);
jio_query = gidToJIOQuery(gid);
command.storage(priv.sub_storage).allDocs({
"query": complex_query
"query": jio_query
}).then(function (response) {
var update_method = method;
response = response.data;
......@@ -359,7 +359,7 @@
* Generic command for putAttachment, getAttachment or removeAttachment.
*
* This command will check if the document exist with an allDocs and a
* complex query. If not exist, then it returns 404. Otherwise the
* jio query. If not exist, then it returns 404. Otherwise the
* action will be done on the attachment of the found document.
*
* @method putGetOrRemoveAttachment
......@@ -369,7 +369,7 @@
* @param {String} method The command method
*/
priv.putGetOrRemoveAttachment = function (command, doc, method) {
var gid_object, complex_query;
var gid_object, jio_query;
gid_object = gidParse(doc._id, priv.constraints);
if (gid_object === undefined) {
return command.error(
......@@ -378,9 +378,9 @@
"Cannot " + method + " attachment"
);
}
complex_query = gidToComplexQuery(gid_object);
jio_query = gidToJIOQuery(gid_object);
command.storage(priv.sub_storage).allDocs({
"query": complex_query
"query": jio_query
}).then(function (response) {
response = response.data;
if (response.total_rows === 0) {
......@@ -429,7 +429,7 @@
/**
* Puts an attachment to a document thank to its gid, a sub allDocs and a
* complex query.
* jio query.
*
* @method putAttachment
* @param {Command} command The JIO command
......@@ -439,13 +439,13 @@
};
/**
* Gets a document thank to its gid, a sub allDocs and a complex query.
* Gets a document thank to its gid, a sub allDocs and a jio query.
*
* @method get
* @param {Object} command The JIO command
*/
that.get = function (command, param) {
var gid_object, complex_query;
var gid_object, jio_query;
gid_object = gidParse(param._id, priv.constraints);
if (gid_object === undefined) {
return command.error(
......@@ -454,9 +454,9 @@
"Cannot get document"
);
}
complex_query = gidToComplexQuery(gid_object);
jio_query = gidToJIOQuery(gid_object);
command.storage(priv.sub_storage).allDocs({
"query": complex_query,
"query": jio_query,
"include_docs": true
}).then(function (response) {
response = response.data;
......@@ -477,7 +477,7 @@
/**
* Gets an attachment from a document thank to its gid, a sub allDocs and a
* complex query.
* jio query.
*
* @method getAttachment
* @param {Command} command The JIO command
......@@ -487,13 +487,13 @@
};
/**
* Remove a document thank to its gid, sub allDocs and a complex query.
* Remove a document thank to its gid, sub allDocs and a jio query.
*
* @method remove
* @param {Command} command The JIO command.
*/
that.remove = function (command, doc) {
var gid_object, complex_query;
var gid_object, jio_query;
gid_object = gidParse(doc._id, priv.constraints);
if (gid_object === undefined) {
return command.error(
......@@ -502,9 +502,9 @@
"Cannot remove document"
);
}
complex_query = gidToComplexQuery(gid_object);
jio_query = gidToJIOQuery(gid_object);
command.storage(priv.sub_storage).allDocs({
"query": complex_query
"query": jio_query
}).then(function (response) {
response = response.data;
if (response.total_rows === 0) {
......@@ -533,7 +533,7 @@
/**
* Removes an attachment to a document thank to its gid, a sub allDocs and a
* complex query.
* jio query.
*
* @method removeAttachment
* @param {Command} command The JIO command
......
......@@ -17,7 +17,7 @@
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, regexp: true */
/*global window, exports, require, define, jIO, RSVP, complex_queries */
/*global window, exports, require, define, jIO, RSVP */
/**
* JIO Index Storage.
......@@ -122,18 +122,16 @@
return module(
exports,
require('jio'),
require('rsvp'),
require('complex_queries')
require('rsvp')
);
}
window.index_storage = {};
module(window.index_storage, jIO, RSVP, complex_queries);
module(window.index_storage, jIO, RSVP);
}([
'exports',
'jio',
'rsvp',
'complex_queries'
], function (exports, jIO, RSVP, complex_queries) {
'rsvp'
], function (exports, jIO, RSVP) {
"use strict";
/**
......@@ -747,7 +745,7 @@
db[i]["_" + now] = db[i];
}
}
complex_queries.QueryFactory.create(option.query || '').
jIO.QueryFactory.create(option.query || '').
exec(db, option).then(function () {
for (i = 0; i < db.length; i += 1) {
id = db[i]._id;
......
......@@ -5,7 +5,7 @@
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, regexp: true */
/*global jIO, localStorage, setTimeout, complex_queries, window, define,
/*global jIO, localStorage, setTimeout, window, define,
exports, require */
/**
......@@ -54,15 +54,14 @@
return define(dependencies, module);
}
if (typeof exports === 'object') {
return module(exports, require('jio'), require('complex_queries'));
return module(exports, require('jio'));
}
window.local_storage = {};