不要怂,就是干,撸起袖子干!

Commit 2692a95d by Scott Tadman

Improvements to Postgres function escaping, use dynamic delimiter to avoid confl…

…ict with data payload
1 parent 7790c4fa
...@@ -210,9 +210,11 @@ module.exports = (function() { ...@@ -210,9 +210,11 @@ module.exports = (function() {
//options.exception = 'WHEN unique_violation THEN NULL;'; //options.exception = 'WHEN unique_violation THEN NULL;';
//valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc() RETURNS SETOF <%= table %> AS $body$ BEGIN RETURN QUERY ' + valueQuery + '; EXCEPTION ' + options.exception + ' END; $body$ LANGUAGE plpgsql; SELECT * FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();'; //valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc() RETURNS SETOF <%= table %> AS $body$ BEGIN RETURN QUERY ' + valueQuery + '; EXCEPTION ' + options.exception + ' END; $body$ LANGUAGE plpgsql; SELECT * FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc();';
// >= 9.2 // >= 9.2 - Use a UUID but prefix with 'func_' (numbers first not allowed)
var delimiter = '$func_' + Utils.generateUUID().replace(/-/g, '') + '$';
options.exception = 'WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL;'; options.exception = 'WHEN unique_violation THEN GET STACKED DIAGNOSTICS sequelize_caught_exception = PG_EXCEPTION_DETAIL;';
valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response <%= table %>, OUT sequelize_caught_exception text) RETURNS RECORD AS $$ BEGIN ' + valueQuery + ' INTO response; EXCEPTION ' + options.exception + ' END $$ LANGUAGE plpgsql; SELECT (testfunc.response).*, testfunc.sequelize_caught_exception FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc()'; valueQuery = 'CREATE OR REPLACE FUNCTION pg_temp.testfunc(OUT response <%= table %>, OUT sequelize_caught_exception text) RETURNS RECORD AS ' + delimiter + ' BEGIN ' + valueQuery + ' INTO response; EXCEPTION ' + options.exception + ' END ' + delimiter + ' LANGUAGE plpgsql; SELECT (testfunc.response).*, testfunc.sequelize_caught_exception FROM pg_temp.testfunc(); DROP FUNCTION IF EXISTS pg_temp.testfunc()';
} }
if (this._dialect.supports['ON DUPLICATE KEY'] && options.onDuplicate) { if (this._dialect.supports['ON DUPLICATE KEY'] && options.onDuplicate) {
...@@ -241,12 +243,7 @@ module.exports = (function() { ...@@ -241,12 +243,7 @@ module.exports = (function() {
identityWrapperRequired = true; identityWrapperRequired = true;
} }
value = this.escape(value, (modelAttributeMap && modelAttributeMap[key]) || undefined); values.push(this.escape(value, (modelAttributeMap && modelAttributeMap[key]) || undefined));
if (options.exception) {
// $ inside value strings are illegal when using $$ as literal strings/delimiters for function bodys
value = value.toString().replace(/\$/g, '\\$');
}
values.push(value);
} }
} }
} }
......
...@@ -227,7 +227,7 @@ if (dialect.match(/^postgres/)) { ...@@ -227,7 +227,7 @@ if (dialect.match(/^postgres/)) {
}); });
}); });
it('should be ablo to query using dot syntax', function() { it('should be able to query using dot syntax', function() {
var self = this; var self = this;
return this.sequelize.Promise.all([ return this.sequelize.Promise.all([
...@@ -240,6 +240,44 @@ if (dialect.match(/^postgres/)) { ...@@ -240,6 +240,44 @@ if (dialect.match(/^postgres/)) {
expect(user.emergency_contact.name).to.equal('joe'); expect(user.emergency_contact.name).to.equal('joe');
}); });
}); });
it('should be able to store values that require JSON escaping', function() {
var self = this;
var text = "Multi-line '$string' needing \"escaping\" for $$";
return this.User.create({ username: 'swen', emergency_contact: { value: text } })
.then(function(user) {
expect(user.isNewRecord).to.equal(false);
})
.then(function() {
return self.User.find({ where: { username: 'swen' } });
})
.then(function() {
return self.User.find({ where: sequelize.json('emergency_contact.value', text) });
})
.then(function(user) {
expect(user.username).to.equal('swen');
});
});
it('should be able to findOrCreate with values that require JSON escaping', function() {
var self = this;
var text = "Multi-line '$string' needing \"escaping\" for $$";
return this.User.findOrCreate({ where: { username: 'swen' }, defaults: { emergency_contact: { value: text } } })
.then(function(user) {
expect(!user.isNewRecord).to.equal(true);
})
.then(function() {
return self.User.find({ where: { username: 'swen' } });
})
.then(function() {
return self.User.find({ where: sequelize.json('emergency_contact.value', text) });
})
.then(function(user) {
expect(user.username).to.equal('swen');
});
});
}); });
describe('hstore', function() { describe('hstore', function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!