knex/lib/raw.js

140 lines
3.4 KiB
JavaScript
Raw Normal View History

2015-05-09 13:58:18 -04:00
// Raw
// -------
const { EventEmitter } = require('events');
const debug = require('debug');
const assign = require('lodash/assign');
const isPlainObject = require('lodash/isPlainObject');
const reduce = require('lodash/reduce');
2020-12-20 01:43:36 +02:00
const {
replaceRawArrBindings,
replaceKeyBindings,
} = require('./formatter/rawFormatter');
const helpers = require('./util/helpers');
const saveAsyncStack = require('./util/save-async-stack');
const { nanoid } = require('./util/nanoid');
const { isNumber, isObject } = require('./util/is');
const {
augmentWithBuilderInterface,
} = require('./builder-interface-augmenter');
2016-06-17 09:19:20 -07:00
const debugBindings = debug('knex:bindings');
2016-09-16 16:04:11 -04:00
2021-01-31 13:40:13 +03:00
class Raw extends EventEmitter {
constructor(client) {
super();
2015-05-09 13:58:18 -04:00
2021-01-31 13:40:13 +03:00
this.client = client;
2015-05-09 13:58:18 -04:00
2021-01-31 13:40:13 +03:00
this.sql = '';
this.bindings = [];
2015-05-09 13:58:18 -04:00
2021-01-31 13:40:13 +03:00
// Todo: Deprecate
this._wrappedBefore = undefined;
this._wrappedAfter = undefined;
if (client && client.config) {
this._debug = client.config.debug;
saveAsyncStack(this, 4);
}
}
set(sql, bindings) {
this.sql = sql;
this.bindings =
(isObject(bindings) && !bindings.toSQL) || bindings === undefined
? bindings
: [bindings];
return this;
2021-01-31 13:40:13 +03:00
}
2015-05-09 13:58:18 -04:00
timeout(ms, { cancel } = {}) {
if (isNumber(ms) && ms > 0) {
this._timeout = ms;
2016-05-26 11:06:33 -07:00
if (cancel) {
this.client.assertCanCancelQuery();
this._cancelOnTimeout = true;
2016-05-26 11:06:33 -07:00
}
}
return this;
2021-01-31 13:40:13 +03:00
}
2015-05-09 13:58:18 -04:00
// Wraps the current sql with `before` and `after`.
wrap(before, after) {
this._wrappedBefore = before;
this._wrappedAfter = after;
return this;
2021-01-31 13:40:13 +03:00
}
2015-05-09 13:58:18 -04:00
// Calls `toString` on the Knex object.
toString() {
return this.toQuery();
2021-01-31 13:40:13 +03:00
}
2015-05-09 13:58:18 -04:00
// Returns the raw sql for the query.
toSQL(method, tz) {
let obj;
2015-05-09 13:58:18 -04:00
if (Array.isArray(this.bindings)) {
obj = replaceRawArrBindings(this, this.client);
} else if (this.bindings && isPlainObject(this.bindings)) {
obj = replaceKeyBindings(this, this.client);
2015-05-09 13:58:18 -04:00
} else {
obj = {
2015-05-09 13:58:18 -04:00
method: 'raw',
sql: this.sql,
bindings: this.bindings === undefined ? [] : [this.bindings],
};
2015-05-09 13:58:18 -04:00
}
2015-05-09 13:58:18 -04:00
if (this._wrappedBefore) {
obj.sql = this._wrappedBefore + obj.sql;
2015-05-09 13:58:18 -04:00
}
if (this._wrappedAfter) {
obj.sql = obj.sql + this._wrappedAfter;
2015-05-09 13:58:18 -04:00
}
obj.options = reduce(this._options, assign, {});
if (this._timeout) {
obj.timeout = this._timeout;
2016-05-26 11:06:33 -07:00
if (this._cancelOnTimeout) {
obj.cancelOnTimeout = this._cancelOnTimeout;
2016-05-26 11:06:33 -07:00
}
}
obj.bindings = obj.bindings || [];
if (helpers.containsUndefined(obj.bindings)) {
2019-10-06 20:21:32 +02:00
const undefinedBindingIndices = helpers.getUndefinedIndices(
this.bindings
);
debugBindings(obj.bindings);
throw new Error(
`Undefined binding(s) detected for keys [${undefinedBindingIndices}] when compiling RAW query: ${obj.sql}`
);
}
obj.__knexQueryUid = nanoid();
Object.defineProperties(obj, {
toNative: {
value: () => ({
sql: this.client.positionBindings(obj.sql),
bindings: this.client.prepBindings(obj.bindings),
}),
enumerable: false,
},
});
return obj;
2021-01-31 13:40:13 +03:00
}
}
2015-05-09 13:58:18 -04:00
// Workaround to avoid circular dependency between wrappingFormatter.unwrapRaw and rawFormatter
Raw.prototype.isRawInstance = true;
2015-05-09 13:58:18 -04:00
// Allow the `Raw` object to be utilized with full access to the relevant
// promise API.
augmentWithBuilderInterface(Raw);
Add queryContext to schema and query builders (#2314) * feat(query-builder): add hookContext for wrapIdentifier * refactor: use isUndefined * test(transaction): test passing of hookContext * feat(runnner): pass context to postProcessResponse * test(runner): test postProcessResponse for raw responses * test(raw): test passing of hookContext * feat: add hookContext to Raw and SchemaBuilder * test(transaction): fix test for hookContext * chore: fix lint error * fix: check for hookContext before calling it * test(transaction): fix hookContext test * chore: remove whitespace * test(hookContext): test cloning of context object * refactor: hookContext -> queryContext * minor: use more descriptive variable name i.e. refactor: `context` => `queryContext` * fix: remove unnecessary checks for query builder * fix(Raw): pass query builder to formatter * fix(SchemaCompiler): pass schema builder to formatter * refactor: add addQueryContext helper * feat: add queryContext to TableBuilder and ColumnBuilder * fix(TableCompiler): pass table builder to formatter * fix(ColumnCompiler): pass column builder to formatter * fix(pushQuery): fix passing builder to formatter * test(Schema|Table|ColumnCompiler): test passing queryContext * fix(SchemaCompiler): pass queryContext to TableCompiler * fix(TableCompiler): pass queryContext to ColumnCompiler * test: add queryContext tests for all schema dialects * test(TableCompiler): test overwriting queryContext from SchemaCompiler * test(Raw): test passing queryContext to wrapIdentifier * tests: run all the tests
2018-02-01 23:41:01 +01:00
helpers.addQueryContext(Raw);
2015-05-09 13:58:18 -04:00
module.exports = Raw;