Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

refactor find, add map/reduce

  • Loading branch information...
commit e41fc7cd301f3023ea0d2018dc451c2a48052620 1 parent 5259892
@JerrySievert authored
Showing with 193 additions and 100 deletions.
  1. +9 −100 find.sql
  2. +82 −0 mapreduce.sql
  3. +102 −0 whereclause.sql
View
109 find.sql
@@ -9,7 +9,7 @@ VARCHAR AS $$
}
return obj;
-$$ LANGUAGE plv8 STRICT;
+$$ LANGUAGE plv8 IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION find_in_obj_int(data json, key varchar) RETURNS
INT AS $$
@@ -22,7 +22,7 @@ INT AS $$
}
return Number(obj);
-$$ LANGUAGE plv8 STRICT;
+$$ LANGUAGE plv8 IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION find_in_obj_exists(data json, key varchar) RETURNS
BOOLEAN AS $$
@@ -35,111 +35,20 @@ BOOLEAN AS $$
}
return (obj === undefined ? 'f' : 't');
-$$ LANGUAGE plv8 STRICT;
+$$ LANGUAGE plv8 IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION find (collection varchar, terms json) RETURNS
SETOF json AS $$
var table = 'col_' + collection;
var sql = "SELECT data FROM " + table;
- var c = [ ];
- var t = [ ];
- var b = [ ];
-
- var count = 1;
-
- function build_clause (key, value, type) {
- var clauses = [ ],
- binds = [ ],
- types = [ ];
-
- if (typeof(value) === 'object') {
- if (key === '$or') {
- var tclauses = [ ];
-
- for (var i = 0; i < value.length; i++) {
- var ret = build_clause(Object.keys(value[i])[0], value[i][Object.keys(value[i])[0]]);
-
- tclauses = tclauses.concat(ret.clauses);
- binds = binds.concat(ret.binds);
- types = types.concat(ret.types);
- }
-
- clauses.push('( ' + tclauses.join(' OR ') + ' )');
- } else {
- var keys = Object.keys(value);
-
- for (var i = 0; i < keys.length; i++) {
- var ret;
- if (keys[i] === '$gt') {
- ret = build_clause(key, value[keys[i]], '>');
- } else if (keys[i] === '$lt') {
- ret = build_clause(key, value[keys[i]], '<');
- } else if (keys[i] === '$gte') {
- ret = build_clause(key, value[keys[i]], '>=');
- } else if (keys[i] === '$lte') {
- ret = build_clause(key, value[keys[i]], '<=');
- } else if (keys[i] === '$exists') {
- ret = build_clause(key, value[keys[i]], 'exists');
- }
- clauses = clauses.concat(ret.clauses);
- binds = binds.concat(ret.binds);
- types = types.concat(ret.types);
- }
- }
- } else {
- type = type || '=';
- var lval;
-
- if (type === 'exists') {
- clauses.push("find_in_obj_exists(data, '" + key + "') = $" + count);
- types.push('boolean');
- value = value ? 't' : 'f';
- } else {
- switch (typeof(value)) {
- case 'number':
- clauses.push("find_in_obj_int(data, '" + key + "') " + type + " $" + count);
- types.push('int');
- break;
-
- case 'string':
- clauses.push("find_in_obj(data, '" + key + "') " + type + " $" + count);
- types.push('varchar');
- break;
-
- default:
- console.log("unknown type: " + typeof(value));
- }
- }
-
- binds.push(value);
-
- count++;
- }
-
- return { clauses: clauses, binds: binds, types: types };
- }
-
- if (terms !== undefined) {
- var obj = JSON.parse(terms);
- var keys = Object.keys(obj);
-
- for (var i = 0; i < keys.length; i ++) {
- var ret = build_clause(keys[i], obj[keys[i]]);
- c = c.concat(ret.clauses);
- b = b.concat(ret.binds);
- t = t.concat(ret.types);
- }
-
- if (c.length) {
- sql += " WHERE ";
-
- sql += c.join(" AND ");
- }
- }
+ var where_clause = plv8.find_function("where_clause");
+ var where = where_clause(terms);
+ where = JSON.parse(where);
- var plan = plv8.prepare(sql, t);
- var rows = plan.execute(b);
+ sql += " " + where.sql;
+ var plan = plv8.prepare(sql, where.types);
+ var rows = plan.execute(where.binds);
var ret = [ ];
View
82 mapreduce.sql
@@ -0,0 +1,82 @@
+CREATE OR REPLACE FUNCTION runCommand (options varchar) RETURNS
+json AS $$
+ options = JSON.parse(options);
+
+ var map, reduce, finalize;
+
+ if (options.map) {
+ eval("map = " + options.map);
+ }
+ if (options.reduce) {
+ eval("reduce = " + options.reduce);
+ }
+ if (options.finalize) {
+ eval("finalize = " + options.finalize);
+ }
+
+ if (map === undefined || reduce === undefined) {
+ throw new Error("not code");
+ }
+
+ var emitted = { };
+
+ function emit(key, data) {
+ if (emitted[key] === undefined) {
+ emitted[key] = [ ];
+ }
+ emitted[key].push(data);
+ }
+
+ var collection = 'col_' + options.mapreduce;
+ var sql = "SELECT data FROM " + collection;
+
+ var plan, cursor, row;
+
+ if (options.query) {
+ var where_clause = plv8.find_function("where_clause");
+ var where = where_clause(JSON.stringify(options.query));
+ where = JSON.parse(where);
+
+ sql += " " + where.sql;
+ plan = plv8.prepare(sql, where.types);
+ cursor = plan.cursor(where.binds);
+ } else {
+ plan = plv8.prepare(sql);
+ cursor = plan.cursor();
+ }
+
+ while (row = cursor.fetch()) {
+ map.apply(JSON.parse(row.data));
+ }
+
+ cursor.close();
+ plan.free();
+
+ var reduced = { };
+ for (var j in emitted) {
+ if (reduced[j] === undefined) {
+ reduced[j] = [ ];
+ }
+ reduced[j] = reduced[j].concat(reduce(j, emitted[j]));
+ delete emitted[j];
+ }
+
+ if (finalize) {
+ var final = [ ];
+ for (var x in reduced) {
+ final.push({ "_id": x, "value": finalize(x, reduced[x][0]) });
+ delete reduced[x];
+ }
+ return JSON.stringify(final);
+ } else {
+ var out = [ ];
+ for (var k in reduced) {
+ out.push({_id: k, value: reduced[k][0] });
+ }
+
+ return JSON.stringify(out);
+ }
+
+
+ return JSON.stringify(emitted);
+$$ LANGUAGE plv8 STRICT;
View
102 whereclause.sql
@@ -0,0 +1,102 @@
+CREATE OR REPLACE FUNCTION where_clause (terms json) RETURNS
+VARCHAR AS $$
+ var sql = '';
+ var c = [ ];
+ var t = [ ];
+ var b = [ ];
+
+ var count = 1;
+
+ function build_clause (key, value, type) {
+ var clauses = [ ],
+ binds = [ ],
+ types = [ ];
+
+ if (typeof(value) === 'object') {
+ if (key === '$or') {
+ var tclauses = [ ];
+
+ for (var i = 0; i < value.length; i++) {
+ var ret = build_clause(Object.keys(value[i])[0], value[i][Object.keys(value[i])[0]]);
+
+ tclauses = tclauses.concat(ret.clauses);
+ binds = binds.concat(ret.binds);
+ types = types.concat(ret.types);
+ }
+
+ clauses.push('( ' + tclauses.join(' OR ') + ' )');
+ } else {
+ var keys = Object.keys(value);
+
+ for (var i = 0; i < keys.length; i++) {
+ var ret;
+ if (keys[i] === '$gt') {
+ ret = build_clause(key, value[keys[i]], '>');
+ } else if (keys[i] === '$lt') {
+ ret = build_clause(key, value[keys[i]], '<');
+ } else if (keys[i] === '$gte') {
+ ret = build_clause(key, value[keys[i]], '>=');
+ } else if (keys[i] === '$lte') {
+ ret = build_clause(key, value[keys[i]], '<=');
+ } else if (keys[i] === '$exists') {
+ ret = build_clause(key, value[keys[i]], 'exists');
+ }
+
+ clauses = clauses.concat(ret.clauses);
+ binds = binds.concat(ret.binds);
+ types = types.concat(ret.types);
+ }
+ }
+ } else {
+ type = type || '=';
+ var lval;
+
+ if (type === 'exists') {
+ clauses.push("find_in_obj_exists(data, '" + key + "') = $" + count);
+ types.push('boolean');
+ value = value ? 't' : 'f';
+ } else {
+ switch (typeof(value)) {
+ case 'number':
+ clauses.push("find_in_obj_int(data, '" + key + "') " + type + " $" + count);
+ types.push('int');
+ break;
+
+ case 'string':
+ clauses.push("find_in_obj(data, '" + key + "') " + type + " $" + count);
+ types.push('varchar');
+ break;
+
+ default:
+ console.log("unknown type: " + typeof(value));
+ }
+ }
+
+ binds.push(value);
+
+ count++;
+ }
+
+ return { clauses: clauses, binds: binds, types: types };
+ }
+
+ if (terms !== undefined) {
+ var obj = JSON.parse(terms);
+ var keys = Object.keys(obj);
+
+ for (var i = 0; i < keys.length; i ++) {
+ var ret = build_clause(keys[i], obj[keys[i]]);
+ c = c.concat(ret.clauses);
+ b = b.concat(ret.binds);
+ t = t.concat(ret.types);
+ }
+
+ if (c.length) {
+ sql += " WHERE ";
+
+ sql += c.join(" AND ");
+ }
+ }
+
+ return JSON.stringify({ types: t, binds: b, sql: sql });
+$$ LANGUAGE plv8 STRICT;
Please sign in to comment.
Something went wrong with that request. Please try again.