1 var guid = (function() {
3 return Math.floor((1 + Math.random()) * 0x10000)
8 return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
9 s4() + '-' + s4() + s4() + s4();
13 function ManifoldQuery(action, object, timestamp, filters, params, fields, unique, query_uuid, aq, sq) {
14 // get, update, delete, create
16 // slice, user, network...
18 // timestamp, now, latest(cache) : date of the results queried
20 // key(field),op(=<>),value
26 // 0,1 : list of element of an object or single object
28 // query_uuid : unique identifier of a query
30 // Query : root query (no sub-Query)
32 // {} : Assoc Table of sub-queries ["resources"->subQ1, "users"->subQ2]
35 /*-------------------------------------------------------------
36 Query properties are SQL like :
37 ---------------------------------------------------------------
38 SELECT fields FROM object WHERE filter;
39 UPDATE object SET field=value WHERE filter; / returns SELECT
40 DELETE FROM object WHERE filter
41 INSERT INTO object VALUES(field=value)
42 -------------------------------------------------------------*/
44 this.__repr = function () {
45 res = "ManifoldQuery ";
46 // res += " id=" + this.query_uuid;
47 res += " a=" + this.action;
48 res += " o=" + this.object;
49 res += " ts=" + this.timestamp;
50 res += " flts=" + this.filters;
51 res += " flds=" + this.fields;
52 res += " prms=" + this.params;
56 this.clone = function() {
58 var q = new ManifoldQuery();
59 q.action = this.action;
60 q.object = this.object;
61 q.timestamp = this.timestamp;
62 q.filters = this.filters.slice();
63 q.fields = this.fields.slice();
64 q.query_uuid = this.query_uuid;
66 if (this.analyzed_query)
67 q.analyzed_query = this.analyzed_query.clone();
69 q.analyzed_query = null;
71 if (this.subqueries) {
73 for (method in this.subqueries)
74 q.subqueries[method] = this.subqueries[method].clone();
77 // deep extend not working for custom objects
78 // $.extend(true, q, this);
82 this.add_filter = function(key, op, value) {
83 this.filters.push(new Array(key, op, value));
85 this.update_filter = function(key, op, value) {
86 // Need to be improved...
87 // remove all occurrences of key if operation is not defined
89 this.filters = jQuery.grep(this.filters, function(val, i) {
92 // Else remove the key+op filters
94 this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
96 this.filters.push(new Array(key, op, value));
99 this.remove_filter = function (key,op,value) {
100 // if operator is null then remove all occurences of this key
102 this.filters = jQuery.grep(this.filters, function(val, i) {
103 return val[0] != key;
106 this.filters = jQuery.grep(this.filters, function(val, i) {return (val[0] != key || val[1] != op);});
110 // FIXME These functions computing diff's between queries are meant to be shared
111 this.diff_fields = function(otherQuery) {
112 var f1 = this.fields;
113 var f2 = otherQuery.fields;
115 /* added elements are the ones in f2 not in f1 */
116 var added = jQuery.grep(f2, function (x) { return jQuery.inArray(x, f1) == -1 });
117 /* removed elements are the ones in f1 not in f2 */
118 var removed = jQuery.grep(f1, function (x) { return jQuery.inArray(x, f2) == -1 });
120 return {'added':added, 'removed':removed};
123 // FIXME Modify filter to filters
124 this.diff_filter = function(otherQuery) {
125 var f1 = this.filters;
126 var f2 = otherQuery.filters;
128 /* added elements are the ones in f2 not in f1 */
129 var added = jQuery.grep(f2, function (x) { return !arrayInArray(x, f1)});
130 /* removed elements are the ones in f1 not in f2 */
131 var removed = jQuery.grep(f1, function (x) { return !arrayInArray(x, f2)});
133 return {'added':added, 'removed':removed};
136 // Callaback received 3 parameters: query, data, parent_query
137 this.iter_subqueries = function(callback, data)
139 rec = function(query, callback, data, parent_query) {
140 callback(query, data, parent_query);
141 jQuery.each(query.subqueries, function(object, subquery) {
142 rec(subquery, callback, data, query);
146 if (!!this.analyzed_query)
147 query = this.analyzed_query;
151 rec(query, callback, data, null);
154 this.select = function(field)
156 this.fields.push(field);
159 this.unselect = function(field)
161 this.fields = $.grep(this.fields, function(x) { return x != field; });
164 // we send queries as a json string now
165 // this.as_POST = function() {
166 // return {'action': this.action, 'object': this.object, 'timestamp': this.timestamp,
167 // 'filters': this.filters, 'params': this.params, 'fields': this.fields};
169 this.analyze_subqueries = function() {
170 /* adapted from the PHP function in com_tophat/includes/query.php */
171 var q = new ManifoldQuery();
172 q.query_uuid = this.query_uuid;
173 q.action = this.action;
174 q.object = this.object;
175 q.timestamp = this.timestamp;
178 jQuery.each(this.filters, function(i, filter) {
182 var pos = k.indexOf('.');
184 var object = k.substr(0, pos);
185 var field = k.substr(pos+1);
186 if (!q.subqueries[object]) {
187 q.subqueries[object] = new ManifoldQuery();
188 q.subqueries[object].action = q.action;
189 q.subqueries[object].object = object;
190 q.subqueries[object].timestamp = q.timestamp;
192 q.subqueries[object].filters.push(Array(field, op, v));
194 q.filters.push(filter);
199 jQuery.each(this.params, function(param, value) {
200 var pos = param.indexOf('.');
202 var object = param.substr(0, pos);
203 var field = param.substr(pos+1);
204 if (!q.subqueries[object]) {
205 q.subqueries[object] = new ManifoldQuery();
206 q.subqueries[object].action = q.action;
207 q.subqueries[object].object = object;
208 q.subqueries[object].timestamp = q.timestamp;
210 q.subqueries[object].params[field] = value;
212 q.params[field] = value;
217 jQuery.each(this.fields, function(i, v) {
218 var pos = v.indexOf('.');
220 var object = v.substr(0, pos);
221 var field = v.substr(pos+1);
222 if (!q.subqueries[object]) {
223 q.subqueries[object] = new ManifoldQuery();
224 q.subqueries[object].action = q.action;
225 q.subqueries[object].object = object;
226 q.subqueries[object].timestamp = q.timestamp;
228 q.subqueries[object].fields.push(field);
233 this.analyzed_query = q;
237 if (typeof action == "undefined")
240 this.action = action;
242 if (typeof object == "undefined")
245 this.object = object;
247 if (typeof timestamp == "undefined")
248 this.timestamp = "now";
250 this.timestamp = timestamp;
252 if (typeof filters == "undefined")
255 this.filters = filters;
257 if (typeof params == "undefined")
260 this.params = params;
262 if (typeof fields == "undefined")
265 this.fields = fields;
267 if (typeof unique == "undefined")
270 this.unique = unique;
272 if (typeof unique == "undefined")
273 this.query_uuid = guid();
275 this.query_uuid = query_uuid;
277 if (typeof aq == "undefined")
278 this.analyzed_query = null;
280 this.analyzed_query = aq;
282 if (typeof sq == "undefined")
283 this.subqueries = {};
285 this.subqueries = sq;