Last active
May 13, 2019 17:40
-
-
Save simianhacker/5323651 to your computer and use it in GitHub Desktop.
Here is a set of functions for working with a PostgreSQL+JSON+PLV8 database.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path(json, text) | |
-- DROP FUNCTION json_path(json, text); | |
CREATE OR REPLACE FUNCTION json_path(data json, path text) | |
RETURNS text AS | |
$BODY$ | |
/* JSONPath 0.8.0 - XPath for JSON | |
* | |
* Copyright (c) 2007 Stefan Goessner (goessner.net) | |
* Licensed under the MIT (MIT-LICENSE.txt) licence. | |
*/ | |
function jsonPath(obj, expr, arg) { | |
var P = { | |
resultType: arg && arg.resultType || "VALUE", | |
result: [], | |
normalize: function(expr) { | |
var subx = []; | |
return expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";}) | |
.replace(/'?\.'?|\['?/g, ";") | |
.replace(/;;;|;;/g, ";..;") | |
.replace(/;$|'?\]|'$/g, "") | |
.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];}); | |
}, | |
asPath: function(path) { | |
var x = path.split(";"), p = "$"; | |
for (var i=1,n=x.length; i<n; i++) | |
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']"); | |
return p; | |
}, | |
store: function(p, v) { | |
if (p) P.result[P.result.length] = P.resultType == "PATH" ? P.asPath(p) : v; | |
return !!p; | |
}, | |
trace: function(expr, val, path) { | |
if (expr) { | |
var x = expr.split(";"), loc = x.shift(); | |
x = x.join(";"); | |
if (val && val.hasOwnProperty(loc)) | |
P.trace(x, val[loc], path + ";" + loc); | |
else if (loc === "*") | |
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); }); | |
else if (loc === "..") { | |
P.trace(x, val, path); | |
P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); }); | |
} | |
else if (/,/.test(loc)) { // [name1,name2,...] | |
for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++) | |
P.trace(s[i]+";"+x, val, path); | |
} | |
else if (/^\(.*?\)$/.test(loc)) // [(expr)] | |
P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path); | |
else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)] | |
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m)) P.trace(m+";"+x,v,p); }); | |
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] phyton slice syntax | |
P.slice(loc, x, val, path); | |
} | |
else | |
P.store(path, val); | |
}, | |
walk: function(loc, expr, val, path, f) { | |
if (val instanceof Array) { | |
for (var i=0,n=val.length; i<n; i++) | |
if (i in val) | |
f(i,loc,expr,val,path); | |
} | |
else if (typeof val === "object") { | |
for (var m in val) | |
if (val.hasOwnProperty(m)) | |
f(m,loc,expr,val,path); | |
} | |
}, | |
slice: function(loc, expr, val, path) { | |
if (val instanceof Array) { | |
var len=val.length, start=0, end=len, step=1; | |
loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);}); | |
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start); | |
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end); | |
for (var i=start; i<end; i+=step) | |
P.trace(i+";"+expr, val, path); | |
} | |
}, | |
eval: function(x, _v, _vname) { | |
try { return $ && _v && eval(x.replace(/@/g, "_v")); } | |
catch(e) { throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/@/g, "_v").replace(/\^/g, "_a")); } | |
} | |
}; | |
var $ = obj; | |
if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) { | |
P.trace(P.normalize(expr).replace(/^\$;/,""), obj, "$"); | |
return P.result.length ? P.result : false; | |
} | |
} | |
var obj = JSON.parse(data); | |
var results = jsonPath(obj, path); | |
if(results.length === 1) { | |
return JSON.stringify(results[0]); | |
} else { | |
return JSON.stringify(results); | |
} | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_float(json, text) | |
-- DROP FUNCTION json_path_float(json, text); | |
CREATE OR REPLACE FUNCTION json_path_float(data json, path text) | |
RETURNS double precision AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return parseFloat(JSON.parse(results[0]['value'])); | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_float(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_intarray(json, text) | |
-- DROP FUNCTION json_path_intarray(json, text); | |
CREATE OR REPLACE FUNCTION json_path_intarray(data json, path text) | |
RETURNS integer[] AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return JSON.parse(results[0]['value']); | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_intarray(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_integer(json, text) | |
-- DROP FUNCTION json_path_integer(json, text); | |
CREATE OR REPLACE FUNCTION json_path_integer(data json, path text) | |
RETURNS integer AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return parseInt(JSON.parse(results[0]['value']),10); | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_integer(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_textarray(json, text) | |
-- DROP FUNCTION json_path_textarray(json, text); | |
CREATE OR REPLACE FUNCTION json_path_textarray(data json, path text) | |
RETURNS text[] AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return JSON.parse(results[0]['value']); | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_textarray(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_timestamp(json, text) | |
-- DROP FUNCTION json_path_timestamp(json, text); | |
CREATE OR REPLACE FUNCTION json_path_timestamp(data json, path text) | |
RETURNS timestamp without time zone AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return results[0]['value']; | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_timestamp(json, text) | |
OWNER TO ccowan; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Function: json_path_uuid(json, text) | |
-- DROP FUNCTION json_path_uuid(json, text); | |
CREATE OR REPLACE FUNCTION json_path_uuid(data json, path text) | |
RETURNS uuid AS | |
$BODY$ | |
var results = plv8.execute('SELECT json_path($1::json, $2) as value', [data, path]); | |
return JSON.parse(results[0]['value']); | |
$BODY$ | |
LANGUAGE plv8 IMMUTABLE | |
COST 100; | |
ALTER FUNCTION json_path_uuid(json, text) | |
OWNER TO ccowan; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment