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

Commit 091e99dd by Matt Liszewski

add option for prepending postgres queries with search_path

1 parent bc9213f5
......@@ -46,7 +46,8 @@ PostgresDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supp
GEOMETRY: true,
JSON: true,
JSONB: true,
deferrableConstraints: true
deferrableConstraints: true,
searchPath : true
});
ConnectionManager.prototype.defaultVersion = '9.4.0';
......
......@@ -15,6 +15,11 @@ var QueryGenerator = {
options: {},
dialect: 'postgres',
setSearchPath: function(searchPath) {
var query = 'SET search_path to <%= searchPath%>;';
return Utils._.template(query)({searchPath: searchPath});
},
createSchema: function(schema) {
var query = 'CREATE SCHEMA <%= schema%>;';
return Utils._.template(query)({schema: schema});
......
......@@ -90,9 +90,13 @@ Query.prototype.parseDialectSpecificFields = parseDialectSpecificFields;
Query.prototype.run = function(sql) {
this.sql = sql;
if(!Utils._.isEmpty(this.options.searchPath)){
this.sql = this.sequelize.queryInterface.QueryGenerator.setSearchPath(this.options.searchPath) + sql;
}
var self = this
, receivedError = false
, query = this.client.query(sql)
, query = this.client.query(this.sql)
, rows = [];
this.sequelize.log('Executing (' + (this.client.uuid || 'default') + '): ' + this.sql, this.options);
......
......@@ -478,6 +478,7 @@ Instance.prototype._setInclude = function(key, value, options) {
* @param {Boolean} [options.validate=true] If false, validations won't be run.
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Transaction} [options.transaction]
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<this|Errors.ValidationError>}
*/
......@@ -804,6 +805,7 @@ Instance.prototype.updateAttributes = Instance.prototype.update;
* @param {Boolean} [options.force=false] If set to true, paranoid models will actually be deleted
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Transaction} [options.transaction]
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<undefined>}
*/
......@@ -900,6 +902,7 @@ Instance.prototype.restore = function(options) {
* @param {Integer} [options.by=1] The number to increment by
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Transaction} [options.transaction]
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<this>}
*/
......@@ -973,6 +976,7 @@ Instance.prototype.increment = function(fields, options) {
* @param {Integer} [options.by=1] The number to decrement by
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Transaction} [options.transaction]
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise}
*/
......
......@@ -1291,6 +1291,7 @@ Model.prototype.all = function(options) {
* @param {Boolean} [options.raw] Return raw result. See sequelize.query for more information.
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Object} [options.having]
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @see {Sequelize#query}
* @return {Promise<Array<Instance>>}
......@@ -1422,6 +1423,7 @@ Model.$findSeperate = function(results, options) {
* @param {Number|String|Buffer} [options] A hash of options to describe the scope of the search, or a number to search by id.
* @param {Object} ' [options]
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @see {Model#findAll} for an explanation of options
* @return {Promise<Instance>}
......@@ -1454,6 +1456,7 @@ Model.prototype.findByPrimary = Model.prototype.findById;
*
* @param {Object} [options] A hash of options to describe the scope of the search
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @see {Model#findAll} for an explanation of options
* @return {Promise<Instance>}
......@@ -1529,6 +1532,7 @@ Model.prototype.aggregate = function(field, aggregateFunction, options) {
* @param {Object} [options.group] For creating complex counts. Will return multiple rows as needed.
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<Integer>}
*/
......@@ -1760,6 +1764,7 @@ Model.prototype.bulkBuild = function(valueSets, options) { // testhint options:n
* @param {String} [options.onDuplicate]
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<Instance>}
*/
......@@ -1959,6 +1964,7 @@ Model.prototype.findCreateFind = function(options) {
* @param {Array} [options.fields=Object.keys(this.attributes)] The fields to insert / update. Defaults to all fields
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @alias insertOrUpdate
* @return {Promise<created>} Returns a boolean indicating whether the row was created or updated.
......@@ -2020,6 +2026,7 @@ Model.prototype.insertOrUpdate = Model.prototype.upsert;
* @param {Array} [options.updateOnDuplicate] Fields to update if row key already exists (on duplicate key update)? (only supported by mysql & mariadb). By default, all fields are updated.
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
*
* @return {Promise<Array<Instance>>}
*/
......@@ -2169,6 +2176,7 @@ Model.prototype.bulkCreate = function(records, options) {
* @param {Boolean|function} [options.cascade = false] Only used in conjuction with TRUNCATE. Truncates all tables that have foreign-key references to the named table, or to any tables added to the group due to CASCADE.
* @param {Transaction} [options.transaction] Transaction to run query under
* @param {Boolean|function} [options.logging] A function that logs sql queries, or false for no logging
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
* @return {Promise}
*
* @see {Model#destroy} for more information
......
......@@ -147,6 +147,7 @@ QueryInterface.prototype.createTable = function(tableName, attributes, options,
else if (!!vals[idx - 1]) {
options.after = vals[idx - 1];
}
options.supportsSearchPath = false;
promises.push(self.sequelize.query(self.QueryGenerator.pgEnumAdd(tableName, keys[i], value, options), options));
}
});
......@@ -214,6 +215,7 @@ QueryInterface.prototype.dropTable = function(tableName, options) {
for (i = 0; i < keyLen; i++) {
if (instanceTable.rawAttributes[keys[i]].type instanceof DataTypes.ENUM) {
sql = self.QueryGenerator.pgEnumDrop(getTableName, keys[i]);
options.supportsSearchPath = false;
promises.push(self.sequelize.query(sql, { logging: options.logging, raw: true, transaction : options.transaction }));
}
}
......@@ -442,7 +444,7 @@ QueryInterface.prototype.addIndex = function(tableName, attributes, options, raw
options = options || {};
options.fields = attributes;
var sql = this.QueryGenerator.addIndexQuery(tableName, options, rawTablename);
return this.sequelize.query(sql, { logging: options.logging });
return this.sequelize.query(sql, { logging: options.logging, supportsSearchPath: false });
};
QueryInterface.prototype.showIndex = function(tableName, options) {
......@@ -901,7 +903,8 @@ QueryInterface.prototype.commitTransaction = function(transaction, options) {
options = Utils._.extend({
transaction: transaction,
parent: options.transaction
parent: options.transaction,
supportsSearchPath: false
}, options || {});
var sql = this.QueryGenerator.commitTransactionQuery(options);
......@@ -920,7 +923,8 @@ QueryInterface.prototype.rollbackTransaction = function(transaction, options) {
options = Utils._.extend({
transaction: transaction,
parent: options.transaction
parent: options.transaction,
supportsSearchPath: false
}, options || {});
var sql = this.QueryGenerator.rollbackTransactionQuery(transaction, options);
......
......@@ -667,6 +667,8 @@ Sequelize.prototype.import = function(path) {
* @param {Function} [options.logging=false] A function that gets executed while running the query to log the sql.
* @param {Instance} [options.instance] A sequelize instance used to build the return instance
* @param {Model} [options.model] A sequelize model used to build the returned model instances (used to be called callee)
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
* @param {Boolean} [options.supportsSearchPath] If false do not prepend the query with the search_path (Postgres only)
* @param {Object} [options.mapToModel=false] Map returned fields to model's fields if `options.model` or `options.instance` is present. Mapping will occur before building the model instance.
* @param {Object} [options.fieldMap] Map returned fields to arbitrary names for `SELECT` query type.
*
......@@ -724,7 +726,8 @@ Sequelize.prototype.query = function(sql, options) {
options = Utils._.extend(Utils._.clone(this.options.query), options);
options = Utils._.defaults(options, {
logging: this.options.hasOwnProperty('logging') ? this.options.logging : console.log
logging: this.options.hasOwnProperty('logging') ? this.options.logging : console.log,
searchPath: this.options.hasOwnProperty('searchPath') ? this.options.searchPath : 'DEFAULT',
});
if (options.transaction === undefined && Sequelize.cls) {
......@@ -747,6 +750,17 @@ Sequelize.prototype.query = function(sql, options) {
this.test.$runningQueries++;
}
//if dialect doesn't support search_path or dialect option
//to prepend searchPath is not true delete the searchPath option
if (!self.dialect.supports.searchPath || !this.options.dialectOptions || !this.options.dialectOptions.prependSearchPath ||
options.supportsSearchPath === false) {
delete options.searchPath;
} else if (!options.searchPath) {
//if user wants to always prepend searchPath (dialectOptions.preprendSearchPath = true)
//then set to DEFAULT if none is provided
options.searchPath = 'DEFAULT';
}
return Promise.resolve(
options.transaction ? options.transaction.connection : self.connectionManager.getConnection(options)
).then(function (connection) {
......@@ -875,6 +889,7 @@ Sequelize.prototype.dropAllSchemas = function(options) {
* @param {RegEx} [options.match] Match a regex against the database name before syncing, a safety check for cases where force: true is used in tests but not live code
* @param {Boolean|function} [options.logging=console.log] A function that logs sql queries, or false for no logging
* @param {String} [options.schema='public'] The schema that the tables should be created in. This can be overriden for each table in sequelize.define
* @param {String} [options.searchPath=DEFAULT] An optional parameter to specify the schema search_path (Postgres only)
* @param {Boolean} [options.hooks=true] If hooks is true then beforeSync, afterSync, beforBulkSync, afterBulkSync hooks will be called
* @return {Promise}
*/
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!