pgproxy
Version:
Execute nodejs functions on a postgres server, as if they were local, using plv8
319 lines (283 loc) • 11.4 kB
JavaScript
let {Client} = require('pg');
let assert = require('assert');
//replace cn information with your dev db
let client = new Client({
host: '172.17.174.70',
user: 'postgres',
password: 'asdf1234',
database: 'test'
});
let PGProxy = require('../lib');
describe('PGProxy Tests', () => {
before(async () => {
await client.connect();
//await client.query('drop schema if exists test');
//await client.query('create schema test');
});
it('should create new functions', async () => {
let functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let results = await client.query(`select proname, prosrc from pg_proc where proname like 'pgproxy_%'`);
let procs = results.rows;
let found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_select_test');
assert.notEqual(found, null);
found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_system_name');
assert.notEqual(found, null);
PGProxy.destroy();
});
it('should execute and return correct values', async () => {
let functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let row = await proxy.select_test('asdf','1234');
assert.equal(row.param1, 'asdf');
assert.equal(row.param2, '1234');
let name = await proxy.system_name("This is A TEST");
assert.equal(name, 'this_is_a_test');
PGProxy.destroy();
});
it('should update existing functions with changes', async () => {
let functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2, 'changed' as param3`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let results = await client.query(`select proname, prosrc from pg_proc where proname like 'pgproxy_%'`);
let procs = results.rows;
let found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_select_test');
assert.notEqual(found, null);
found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_system_name');
assert.notEqual(found, null);
let row = await proxy.select_test('asdf','1234');
assert.equal(row.param1, 'asdf');
assert.equal(row.param2, '1234');
PGProxy.destroy();
functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select 'pass!' as param1, '${param2}' as param2, 'changed' as param3`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
row = await proxy.select_test('asdf','1234');
assert.equal(row.param1, 'pass!');
assert.equal(row.param2, '1234');
PGProxy.destroy();
});
it('should fail to execute changed functions that are not updated', async () => {
let functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let results = await client.query(`select proname, prosrc from pg_proc where proname like 'pgproxy_%'`);
let procs = results.rows;
let found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_select_test');
assert.notEqual(found, null);
found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_system_name');
assert.notEqual(found, null);
PGProxy.destroy();
functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2, 'changed' as param3`);
plv8.elog(NOTICE, "I wanna cookie");
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
proxy = await PGProxy.create(functions, {
update_changed: false,
client: client,
schema: 'test'
});
try {
let result = await proxy.select_test('nope', 'I said nope!');
assert.ok(false); //should not reach here
}
catch(err) {
assert.ok(true);
}
let name = await proxy.system_name("This is A TEST");
assert.equal(name, 'this_is_a_test');
PGProxy.destroy();
});
it('should call a function from another function', async () => {
let functions = {
select_test: (param1) => {
plv8.elog(NOTICE, 'param1: ' + param1.toString());
let name = system_name(param1);
return name;
},
system_name: (name) => {
plv8.elog(NOTICE, 'name: ' + name.toString());
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let name = await proxy.select_test("This Is A Name");
assert.equal(name, 'this_is_a_name');
PGProxy.destroy();
});
it('should execute reverse proxy functions', async () => {
let functions = {
reverse_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2`);
nodeFunction(result);
return result[0];
}
};
let resolve;
let promise = new Promise(
(_resolve, reject) => {
resolve = _resolve;
}
);
let proxy = await PGProxy.create(functions, {
client: client,
schema: 'test',
expose: {
nodeFunction: (result) => {
let row = result[0];
assert.equal(row.param1, 'asdf');
assert.equal(row.param2, '1234');
resolve();
}
}});
let row = await proxy.reverse_test('asdf','1234');
assert.equal(row.param1, 'asdf');
assert.equal(row.param2, '1234');
PGProxy.destroy();
return promise;
});
it('should purge unwanted functions', async () => {
let functions = {
select_test: (param1, param2) => {
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2, 'changed' as param3`);
return result[0];
},
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
let proxy = await PGProxy.create(functions, {client: client, schema: 'test'});
let results = await client.query(`select proname, prosrc from pg_proc where proname like 'pgproxy_%'`);
let procs = results.rows;
let found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_select_test');
assert.notEqual(found, null);
found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_system_name');
assert.notEqual(found, null);
PGProxy.destroy();
functions = {
system_name: (name) => {
return name
.toLowerCase()
.replace(/[^a-zA-Z ]/g, '')
.replace(/ /g, '_');
}
};
proxy = await PGProxy.create(functions, {client: client, schema: 'test', purge_other: true});
results = await client.query(`select proname, prosrc from pg_proc where proname like 'pgproxy_%'`);
procs = results.rows;
found = null;
found = procs.find((proc) => proc.proname == 'pgproxy_select_test');
assert.equal(found, null);
try {
let result = await proxy.select_test('nope', 'I said nope!');
assert.ok(false); //should not reach here
}
catch(err) {
assert.ok(true);
}
PGProxy.destroy();
});
after(async () => {
await client.end();
})
});
/*
create or replace function test.pgproxy_reverse_test(params json)
returns json
language 'plv8'
as
$BODY$
function generateToken() {...}
function reverseProxy(name, args) {
let payload = {fn:name, params: args, action: 'call'};
plv8.execute(`NOTIFY pgproxy, '${JSON.stringify(payload)}'`);
}
function nodeFunction() { return reverseProxy.apply({},['nodeFunction',arguments]); }
let token = generateToken();
if(params.step == 0) {
plv8.execute(`insert into pgproxy_state fn_name, step, token values 'pgproxy_reverse_test', 1, ${generateToken()},`)
}
let reverse_test = (param1, param2) => {
if(params.step)
let result = plv8.execute(`select '${param1}' as param1, '${param2}' as param2`);
nodeFunction(result);
return result[0];
};
let return_value = reverse_test.apply(plv8, params);
return JSON.stringify(return_value);
$BODY$*/