mirror of
https://github.com/xfarrow/blink
synced 2025-06-27 09:03:02 +02:00
Change endpoint from persons to people
This commit is contained in:
120
backend/apis/nodejs/node_modules/knex/lib/builder-interface-augmenter.js
generated
vendored
Normal file
120
backend/apis/nodejs/node_modules/knex/lib/builder-interface-augmenter.js
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
const clone = require('lodash/clone');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const { callbackify } = require('util');
|
||||
const finallyMixin = require('./util/finally-mixin');
|
||||
const { formatQuery } = require('./execution/internal/query-executioner');
|
||||
|
||||
function augmentWithBuilderInterface(Target) {
|
||||
Target.prototype.toQuery = function (tz) {
|
||||
let data = this.toSQL(this._method, tz);
|
||||
if (!Array.isArray(data)) data = [data];
|
||||
if (!data.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return data
|
||||
.map((statement) => {
|
||||
return formatQuery(statement.sql, statement.bindings, tz, this.client);
|
||||
})
|
||||
.reduce((a, c) => a.concat(a.endsWith(';') ? '\n' : ';\n', c));
|
||||
};
|
||||
|
||||
// Create a new instance of the `Runner`, passing in the current object.
|
||||
Target.prototype.then = function (/* onFulfilled, onRejected */) {
|
||||
let result = this.client.runner(this).run();
|
||||
|
||||
if (this.client.config.asyncStackTraces) {
|
||||
result = result.catch((err) => {
|
||||
err.originalStack = err.stack;
|
||||
const firstLine = err.stack.split('\n')[0];
|
||||
|
||||
// a hack to get a callstack into the client code despite this
|
||||
// node.js bug https://github.com/nodejs/node/issues/11865
|
||||
// see lib/util/save-async-stack.js for more details
|
||||
const { error, lines } = this._asyncStack;
|
||||
const stackByLines = error.stack.split('\n');
|
||||
const asyncStack = stackByLines.slice(lines);
|
||||
asyncStack.unshift(firstLine);
|
||||
|
||||
// put the fake more helpful "async" stack on the thrown error
|
||||
err.stack = asyncStack.join('\n');
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
return result.then.apply(result, arguments);
|
||||
};
|
||||
|
||||
// Add additional "options" to the builder. Typically used for client specific
|
||||
// items, like the `mysql` and `sqlite3` drivers.
|
||||
Target.prototype.options = function (opts) {
|
||||
this._options = this._options || [];
|
||||
this._options.push(clone(opts) || {});
|
||||
return this;
|
||||
};
|
||||
|
||||
// Sets an explicit "connection" we wish to use for this query.
|
||||
Target.prototype.connection = function (connection) {
|
||||
this._connection = connection;
|
||||
this.client.processPassedConnection(connection);
|
||||
return this;
|
||||
};
|
||||
|
||||
// Set a debug flag for the current schema query stack.
|
||||
Target.prototype.debug = function (enabled) {
|
||||
this._debug = arguments.length ? enabled : true;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Set the transaction object for this query.
|
||||
Target.prototype.transacting = function (transaction) {
|
||||
if (transaction && transaction.client) {
|
||||
if (!transaction.client.transacting) {
|
||||
transaction.client.logger.warn(
|
||||
`Invalid transaction value: ${transaction.client}`
|
||||
);
|
||||
} else {
|
||||
this.client = transaction.client;
|
||||
}
|
||||
}
|
||||
if (isEmpty(transaction)) {
|
||||
this.client.logger.error(
|
||||
'Invalid value on transacting call, potential bug'
|
||||
);
|
||||
throw Error(
|
||||
'Invalid transacting value (null, undefined or empty object)'
|
||||
);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
// Initializes a stream.
|
||||
Target.prototype.stream = function (options) {
|
||||
return this.client.runner(this).stream(options);
|
||||
};
|
||||
|
||||
// Initialize a stream & pipe automatically.
|
||||
Target.prototype.pipe = function (writable, options) {
|
||||
return this.client.runner(this).pipe(writable, options);
|
||||
};
|
||||
|
||||
Target.prototype.asCallback = function (cb) {
|
||||
const promise = this.then();
|
||||
callbackify(() => promise)(cb);
|
||||
return promise;
|
||||
};
|
||||
|
||||
Target.prototype.catch = function (onReject) {
|
||||
return this.then().catch(onReject);
|
||||
};
|
||||
|
||||
Object.defineProperty(Target.prototype, Symbol.toStringTag, {
|
||||
get: () => 'object',
|
||||
});
|
||||
|
||||
finallyMixin(Target.prototype);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
augmentWithBuilderInterface,
|
||||
};
|
495
backend/apis/nodejs/node_modules/knex/lib/client.js
generated
vendored
Normal file
495
backend/apis/nodejs/node_modules/knex/lib/client.js
generated
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
const { Pool, TimeoutError } = require('tarn');
|
||||
const { EventEmitter } = require('events');
|
||||
const { promisify } = require('util');
|
||||
const { makeEscape } = require('./util/string');
|
||||
const cloneDeep = require('lodash/cloneDeep');
|
||||
const defaults = require('lodash/defaults');
|
||||
const uniqueId = require('lodash/uniqueId');
|
||||
|
||||
const Runner = require('./execution/runner');
|
||||
const Transaction = require('./execution/transaction');
|
||||
const {
|
||||
executeQuery,
|
||||
enrichQueryObject,
|
||||
} = require('./execution/internal/query-executioner');
|
||||
const QueryBuilder = require('./query/querybuilder');
|
||||
const QueryCompiler = require('./query/querycompiler');
|
||||
const SchemaBuilder = require('./schema/builder');
|
||||
const SchemaCompiler = require('./schema/compiler');
|
||||
const TableBuilder = require('./schema/tablebuilder');
|
||||
const TableCompiler = require('./schema/tablecompiler');
|
||||
const ColumnBuilder = require('./schema/columnbuilder');
|
||||
const ColumnCompiler = require('./schema/columncompiler');
|
||||
const { KnexTimeoutError } = require('./util/timeout');
|
||||
const { outputQuery, unwrapRaw } = require('./formatter/wrappingFormatter');
|
||||
const { compileCallback } = require('./formatter/formatterUtils');
|
||||
const Raw = require('./raw');
|
||||
const Ref = require('./ref');
|
||||
const Formatter = require('./formatter');
|
||||
const Logger = require('./logger');
|
||||
const { POOL_CONFIG_OPTIONS } = require('./constants');
|
||||
const ViewBuilder = require('./schema/viewbuilder.js');
|
||||
const ViewCompiler = require('./schema/viewcompiler.js');
|
||||
const isPlainObject = require('lodash/isPlainObject');
|
||||
const { setHiddenProperty } = require('./util/security.js');
|
||||
|
||||
const debug = require('debug')('knex:client');
|
||||
|
||||
// The base client provides the general structure
|
||||
// for a dialect specific client object.
|
||||
|
||||
class Client extends EventEmitter {
|
||||
constructor(config = {}) {
|
||||
super();
|
||||
this.config = config;
|
||||
this.logger = new Logger(config);
|
||||
|
||||
if (this.config.connection && this.config.connection.password) {
|
||||
setHiddenProperty(this.config.connection);
|
||||
}
|
||||
|
||||
//Client is a required field, so throw error if it's not supplied.
|
||||
//If 'this.dialect' is set, then this is a 'super()' call, in which case
|
||||
//'client' does not have to be set as it's already assigned on the client prototype.
|
||||
|
||||
if (this.dialect && !this.config.client) {
|
||||
this.logger.warn(
|
||||
`Using 'this.dialect' to identify the client is deprecated and support for it will be removed in the future. Please use configuration option 'client' instead.`
|
||||
);
|
||||
}
|
||||
|
||||
const dbClient = this.config.client || this.dialect;
|
||||
if (!dbClient) {
|
||||
throw new Error(
|
||||
`knex: Required configuration option 'client' is missing.`
|
||||
);
|
||||
}
|
||||
|
||||
if (config.version) {
|
||||
this.version = config.version;
|
||||
}
|
||||
|
||||
if (config.connection && config.connection instanceof Function) {
|
||||
this.connectionConfigProvider = config.connection;
|
||||
this.connectionConfigExpirationChecker = () => true; // causes the provider to be called on first use
|
||||
} else {
|
||||
this.connectionSettings = cloneDeep(config.connection || {});
|
||||
if (config.connection && config.connection.password) {
|
||||
setHiddenProperty(this.connectionSettings, config.connection);
|
||||
}
|
||||
this.connectionConfigExpirationChecker = null;
|
||||
}
|
||||
if (this.driverName && config.connection) {
|
||||
this.initializeDriver();
|
||||
if (!config.pool || (config.pool && config.pool.max !== 0)) {
|
||||
this.initializePool(config);
|
||||
}
|
||||
}
|
||||
this.valueForUndefined = this.raw('DEFAULT');
|
||||
if (config.useNullAsDefault) {
|
||||
this.valueForUndefined = null;
|
||||
}
|
||||
}
|
||||
formatter(builder) {
|
||||
return new Formatter(this, builder);
|
||||
}
|
||||
|
||||
queryBuilder() {
|
||||
return new QueryBuilder(this);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
schemaBuilder() {
|
||||
return new SchemaBuilder(this);
|
||||
}
|
||||
|
||||
schemaCompiler(builder) {
|
||||
return new SchemaCompiler(this, builder);
|
||||
}
|
||||
|
||||
tableBuilder(type, tableName, tableNameLike, fn) {
|
||||
return new TableBuilder(this, type, tableName, tableNameLike, fn);
|
||||
}
|
||||
|
||||
viewBuilder(type, viewBuilder, fn) {
|
||||
return new ViewBuilder(this, type, viewBuilder, fn);
|
||||
}
|
||||
|
||||
tableCompiler(tableBuilder) {
|
||||
return new TableCompiler(this, tableBuilder);
|
||||
}
|
||||
|
||||
viewCompiler(viewCompiler) {
|
||||
return new ViewCompiler(this, viewCompiler);
|
||||
}
|
||||
|
||||
columnBuilder(tableBuilder, type, args) {
|
||||
return new ColumnBuilder(this, tableBuilder, type, args);
|
||||
}
|
||||
|
||||
columnCompiler(tableBuilder, columnBuilder) {
|
||||
return new ColumnCompiler(this, tableBuilder, columnBuilder);
|
||||
}
|
||||
|
||||
runner(builder) {
|
||||
return new Runner(this, builder);
|
||||
}
|
||||
|
||||
transaction(container, config, outerTx) {
|
||||
return new Transaction(this, container, config, outerTx);
|
||||
}
|
||||
|
||||
raw() {
|
||||
return new Raw(this).set(...arguments);
|
||||
}
|
||||
|
||||
ref() {
|
||||
return new Ref(this, ...arguments);
|
||||
}
|
||||
query(connection, queryParam) {
|
||||
const queryObject = enrichQueryObject(connection, queryParam, this);
|
||||
return executeQuery(connection, queryObject, this);
|
||||
}
|
||||
|
||||
stream(connection, queryParam, stream, options) {
|
||||
const queryObject = enrichQueryObject(connection, queryParam, this);
|
||||
return this._stream(connection, queryObject, stream, options);
|
||||
}
|
||||
|
||||
prepBindings(bindings) {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
positionBindings(sql) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
postProcessResponse(resp, queryContext) {
|
||||
if (this.config.postProcessResponse) {
|
||||
return this.config.postProcessResponse(resp, queryContext);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
wrapIdentifier(value, queryContext) {
|
||||
return this.customWrapIdentifier(
|
||||
value,
|
||||
this.wrapIdentifierImpl,
|
||||
queryContext
|
||||
);
|
||||
}
|
||||
|
||||
customWrapIdentifier(value, origImpl, queryContext) {
|
||||
if (this.config.wrapIdentifier) {
|
||||
return this.config.wrapIdentifier(value, origImpl, queryContext);
|
||||
}
|
||||
return origImpl(value);
|
||||
}
|
||||
|
||||
wrapIdentifierImpl(value) {
|
||||
return value !== '*' ? `"${value.replace(/"/g, '""')}"` : '*';
|
||||
}
|
||||
|
||||
initializeDriver() {
|
||||
try {
|
||||
this.driver = this._driver();
|
||||
} catch (e) {
|
||||
const message = `Knex: run\n$ npm install ${this.driverName} --save`;
|
||||
this.logger.error(`${message}\n${e.message}\n${e.stack}`);
|
||||
throw new Error(`${message}\n${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
poolDefaults() {
|
||||
return { min: 2, max: 10, propagateCreateError: true };
|
||||
}
|
||||
|
||||
getPoolSettings(poolConfig) {
|
||||
poolConfig = defaults({}, poolConfig, this.poolDefaults());
|
||||
|
||||
POOL_CONFIG_OPTIONS.forEach((option) => {
|
||||
if (option in poolConfig) {
|
||||
this.logger.warn(
|
||||
[
|
||||
`Pool config option "${option}" is no longer supported.`,
|
||||
`See https://github.com/Vincit/tarn.js for possible pool config options.`,
|
||||
].join(' ')
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const DEFAULT_ACQUIRE_TIMEOUT = 60000;
|
||||
const timeouts = [
|
||||
this.config.acquireConnectionTimeout,
|
||||
poolConfig.acquireTimeoutMillis,
|
||||
].filter((timeout) => timeout !== undefined);
|
||||
|
||||
if (!timeouts.length) {
|
||||
timeouts.push(DEFAULT_ACQUIRE_TIMEOUT);
|
||||
}
|
||||
|
||||
// acquire connection timeout can be set on config or config.pool
|
||||
// choose the smallest, positive timeout setting and set on poolConfig
|
||||
poolConfig.acquireTimeoutMillis = Math.min(...timeouts);
|
||||
|
||||
const updatePoolConnectionSettingsFromProvider = async () => {
|
||||
if (!this.connectionConfigProvider) {
|
||||
return; // static configuration, nothing to update
|
||||
}
|
||||
if (
|
||||
!this.connectionConfigExpirationChecker ||
|
||||
!this.connectionConfigExpirationChecker()
|
||||
) {
|
||||
return; // not expired, reuse existing connection
|
||||
}
|
||||
const providerResult = await this.connectionConfigProvider();
|
||||
if (providerResult.expirationChecker) {
|
||||
this.connectionConfigExpirationChecker =
|
||||
providerResult.expirationChecker;
|
||||
delete providerResult.expirationChecker; // MySQL2 driver warns on receiving extra properties
|
||||
} else {
|
||||
this.connectionConfigExpirationChecker = null;
|
||||
}
|
||||
this.connectionSettings = providerResult;
|
||||
};
|
||||
|
||||
return Object.assign(poolConfig, {
|
||||
create: async () => {
|
||||
await updatePoolConnectionSettingsFromProvider();
|
||||
const connection = await this.acquireRawConnection();
|
||||
connection.__knexUid = uniqueId('__knexUid');
|
||||
if (poolConfig.afterCreate) {
|
||||
await promisify(poolConfig.afterCreate)(connection);
|
||||
}
|
||||
return connection;
|
||||
},
|
||||
|
||||
destroy: (connection) => {
|
||||
if (connection !== void 0) {
|
||||
return this.destroyRawConnection(connection);
|
||||
}
|
||||
},
|
||||
|
||||
validate: (connection) => {
|
||||
if (connection.__knex__disposed) {
|
||||
this.logger.warn(`Connection Error: ${connection.__knex__disposed}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.validateConnection(connection);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
initializePool(config = this.config) {
|
||||
if (this.pool) {
|
||||
this.logger.warn('The pool has already been initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
const tarnPoolConfig = {
|
||||
...this.getPoolSettings(config.pool),
|
||||
};
|
||||
// afterCreate is an internal knex param, tarn.js does not support it
|
||||
if (tarnPoolConfig.afterCreate) {
|
||||
delete tarnPoolConfig.afterCreate;
|
||||
}
|
||||
|
||||
this.pool = new Pool(tarnPoolConfig);
|
||||
}
|
||||
|
||||
validateConnection(connection) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Acquire a connection from the pool.
|
||||
async acquireConnection() {
|
||||
if (!this.pool) {
|
||||
throw new Error('Unable to acquire a connection');
|
||||
}
|
||||
try {
|
||||
const connection = await this.pool.acquire().promise;
|
||||
debug('acquired connection from pool: %s', connection.__knexUid);
|
||||
if (connection.config) {
|
||||
if (connection.config.password) {
|
||||
setHiddenProperty(connection.config);
|
||||
}
|
||||
if (
|
||||
connection.config.authentication &&
|
||||
connection.config.authentication.options &&
|
||||
connection.config.authentication.options.password
|
||||
) {
|
||||
setHiddenProperty(connection.config.authentication.options);
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
} catch (error) {
|
||||
let convertedError = error;
|
||||
if (error instanceof TimeoutError) {
|
||||
convertedError = new KnexTimeoutError(
|
||||
'Knex: Timeout acquiring a connection. The pool is probably full. ' +
|
||||
'Are you missing a .transacting(trx) call?'
|
||||
);
|
||||
}
|
||||
throw convertedError;
|
||||
}
|
||||
}
|
||||
|
||||
// Releases a connection back to the connection pool,
|
||||
// returning a promise resolved when the connection is released.
|
||||
releaseConnection(connection) {
|
||||
debug('releasing connection to pool: %s', connection.__knexUid);
|
||||
const didRelease = this.pool.release(connection);
|
||||
|
||||
if (!didRelease) {
|
||||
debug('pool refused connection: %s', connection.__knexUid);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// Destroy the current connection pool for the client.
|
||||
async destroy(callback) {
|
||||
try {
|
||||
if (this.pool && this.pool.destroy) {
|
||||
await this.pool.destroy();
|
||||
}
|
||||
this.pool = undefined;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
} catch (err) {
|
||||
if (typeof callback === 'function') {
|
||||
return callback(err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the database being used by this client.
|
||||
database() {
|
||||
return this.connectionSettings.database;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return '[object KnexClient]';
|
||||
}
|
||||
|
||||
assertCanCancelQuery() {
|
||||
if (!this.canCancelQuery) {
|
||||
throw new Error('Query cancelling not supported for this dialect');
|
||||
}
|
||||
}
|
||||
|
||||
cancelQuery() {
|
||||
throw new Error('Query cancelling not supported for this dialect');
|
||||
}
|
||||
|
||||
// Formatter part
|
||||
|
||||
alias(first, second) {
|
||||
return first + ' as ' + second;
|
||||
}
|
||||
|
||||
// Checks whether a value is a function... if it is, we compile it
|
||||
// otherwise we check whether it's a raw
|
||||
parameter(value, builder, bindingsHolder) {
|
||||
if (typeof value === 'function') {
|
||||
return outputQuery(
|
||||
compileCallback(value, undefined, this, bindingsHolder),
|
||||
true,
|
||||
builder,
|
||||
this
|
||||
);
|
||||
}
|
||||
return unwrapRaw(value, true, builder, this, bindingsHolder) || '?';
|
||||
}
|
||||
|
||||
// Turns a list of values into a list of ?'s, joining them with commas unless
|
||||
// a "joining" value is specified (e.g. ' and ')
|
||||
parameterize(values, notSetValue, builder, bindingsHolder) {
|
||||
if (typeof values === 'function')
|
||||
return this.parameter(values, builder, bindingsHolder);
|
||||
values = Array.isArray(values) ? values : [values];
|
||||
let str = '',
|
||||
i = -1;
|
||||
while (++i < values.length) {
|
||||
if (i > 0) str += ', ';
|
||||
let value = values[i];
|
||||
// json columns can have object in values.
|
||||
if (isPlainObject(value)) {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
str += this.parameter(
|
||||
value === undefined ? notSetValue : value,
|
||||
builder,
|
||||
bindingsHolder
|
||||
);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// Formats `values` into a parenthesized list of parameters for a `VALUES`
|
||||
// clause.
|
||||
//
|
||||
// [1, 2] -> '(?, ?)'
|
||||
// [[1, 2], [3, 4]] -> '((?, ?), (?, ?))'
|
||||
// knex('table') -> '(select * from "table")'
|
||||
// knex.raw('select ?', 1) -> '(select ?)'
|
||||
//
|
||||
values(values, builder, bindingsHolder) {
|
||||
if (Array.isArray(values)) {
|
||||
if (Array.isArray(values[0])) {
|
||||
return `(${values
|
||||
.map(
|
||||
(value) =>
|
||||
`(${this.parameterize(
|
||||
value,
|
||||
undefined,
|
||||
builder,
|
||||
bindingsHolder
|
||||
)})`
|
||||
)
|
||||
.join(', ')})`;
|
||||
}
|
||||
return `(${this.parameterize(
|
||||
values,
|
||||
undefined,
|
||||
builder,
|
||||
bindingsHolder
|
||||
)})`;
|
||||
}
|
||||
|
||||
if (values && values.isRawInstance) {
|
||||
return `(${this.parameter(values, builder, bindingsHolder)})`;
|
||||
}
|
||||
|
||||
return this.parameter(values, builder, bindingsHolder);
|
||||
}
|
||||
|
||||
processPassedConnection(connection) {
|
||||
// Default implementation is noop
|
||||
}
|
||||
|
||||
toPathForJson(jsonPath) {
|
||||
// By default, we want a json path, so if this function is not overriden,
|
||||
// we return the path.
|
||||
return jsonPath;
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client.prototype, {
|
||||
_escapeBinding: makeEscape({
|
||||
escapeString(str) {
|
||||
return `'${str.replace(/'/g, "''")}'`;
|
||||
},
|
||||
}),
|
||||
|
||||
canCancelQuery: false,
|
||||
});
|
||||
|
||||
module.exports = Client;
|
61
backend/apis/nodejs/node_modules/knex/lib/constants.js
generated
vendored
Normal file
61
backend/apis/nodejs/node_modules/knex/lib/constants.js
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
// The client names we'll allow in the `{name: lib}` pairing.
|
||||
const CLIENT_ALIASES = Object.freeze({
|
||||
pg: 'postgres',
|
||||
postgresql: 'postgres',
|
||||
sqlite: 'sqlite3',
|
||||
});
|
||||
|
||||
const SUPPORTED_CLIENTS = Object.freeze(
|
||||
[
|
||||
'mssql',
|
||||
'mysql',
|
||||
'mysql2',
|
||||
'oracledb',
|
||||
'postgres',
|
||||
'pgnative',
|
||||
'redshift',
|
||||
'sqlite3',
|
||||
'cockroachdb',
|
||||
'better-sqlite3',
|
||||
].concat(Object.keys(CLIENT_ALIASES))
|
||||
);
|
||||
|
||||
const DRIVER_NAMES = Object.freeze({
|
||||
MsSQL: 'mssql',
|
||||
MySQL: 'mysql',
|
||||
MySQL2: 'mysql2',
|
||||
Oracle: 'oracledb',
|
||||
PostgreSQL: 'pg',
|
||||
PgNative: 'pgnative',
|
||||
Redshift: 'pg-redshift',
|
||||
SQLite: 'sqlite3',
|
||||
CockroachDB: 'cockroachdb',
|
||||
BetterSQLite3: 'better-sqlite3',
|
||||
});
|
||||
|
||||
const POOL_CONFIG_OPTIONS = Object.freeze([
|
||||
'maxWaitingClients',
|
||||
'testOnBorrow',
|
||||
'fifo',
|
||||
'priorityRange',
|
||||
'autostart',
|
||||
'evictionRunIntervalMillis',
|
||||
'numTestsPerRun',
|
||||
'softIdleTimeoutMillis',
|
||||
'Promise',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Regex that only matches comma's in strings that aren't wrapped in parentheses. Can be used to
|
||||
* safely split strings like `id int, name string, body text, primary key (id, name)` into definition
|
||||
* rows
|
||||
*/
|
||||
const COMMA_NO_PAREN_REGEX = /,[\s](?![^(]*\))/g;
|
||||
|
||||
module.exports = {
|
||||
CLIENT_ALIASES,
|
||||
SUPPORTED_CLIENTS,
|
||||
POOL_CONFIG_OPTIONS,
|
||||
COMMA_NO_PAREN_REGEX,
|
||||
DRIVER_NAMES,
|
||||
};
|
77
backend/apis/nodejs/node_modules/knex/lib/dialects/better-sqlite3/index.js
generated
vendored
Normal file
77
backend/apis/nodejs/node_modules/knex/lib/dialects/better-sqlite3/index.js
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// better-sqlite3 Client
|
||||
// -------
|
||||
const Client_SQLite3 = require('../sqlite3');
|
||||
|
||||
class Client_BetterSQLite3 extends Client_SQLite3 {
|
||||
_driver() {
|
||||
return require('better-sqlite3');
|
||||
}
|
||||
|
||||
// Get a raw connection from the database, returning a promise with the connection object.
|
||||
async acquireRawConnection() {
|
||||
const options = this.connectionSettings.options || {};
|
||||
|
||||
return new this.driver(this.connectionSettings.filename, {
|
||||
nativeBinding: options.nativeBinding,
|
||||
readonly: !!options.readonly,
|
||||
});
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool when
|
||||
// a connection times out or the pool is shutdown.
|
||||
async destroyRawConnection(connection) {
|
||||
return connection.close();
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings and any
|
||||
// other necessary prep work.
|
||||
async _query(connection, obj) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
if (!connection) {
|
||||
throw new Error('No connection provided');
|
||||
}
|
||||
|
||||
const statement = connection.prepare(obj.sql);
|
||||
const bindings = this._formatBindings(obj.bindings);
|
||||
|
||||
if (statement.reader) {
|
||||
const response = await statement.all(bindings);
|
||||
obj.response = response;
|
||||
return obj;
|
||||
}
|
||||
|
||||
const response = await statement.run(bindings);
|
||||
obj.response = response;
|
||||
obj.context = {
|
||||
lastID: response.lastInsertRowid,
|
||||
changes: response.changes,
|
||||
};
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
_formatBindings(bindings) {
|
||||
if (!bindings) {
|
||||
return [];
|
||||
}
|
||||
return bindings.map((binding) => {
|
||||
if (binding instanceof Date) {
|
||||
return binding.valueOf();
|
||||
}
|
||||
|
||||
if (typeof binding === 'boolean') {
|
||||
return Number(binding);
|
||||
}
|
||||
|
||||
return binding;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_BetterSQLite3.prototype, {
|
||||
// The "dialect", for reference .
|
||||
driverName: 'better-sqlite3',
|
||||
});
|
||||
|
||||
module.exports = Client_BetterSQLite3;
|
14
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js
generated
vendored
Normal file
14
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
const ColumnCompiler_PG = require('../postgres/schema/pg-columncompiler.js');
|
||||
|
||||
class ColumnCompiler_CRDB extends ColumnCompiler_PG {
|
||||
uuid(options = { primaryKey: false }) {
|
||||
return (
|
||||
'uuid' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options)
|
||||
? ' primary key default gen_random_uuid()'
|
||||
: '')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ColumnCompiler_CRDB;
|
11
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js
generated
vendored
Normal file
11
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
const QueryBuilder = require('../../query/querybuilder');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
|
||||
module.exports = class QueryBuilder_CockroachDB extends QueryBuilder {
|
||||
upsert(values, returning, options) {
|
||||
this._method = 'upsert';
|
||||
if (!isEmpty(returning)) this.returning(returning, options);
|
||||
this._single.upsert = values;
|
||||
return this;
|
||||
}
|
||||
};
|
122
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js
generated
vendored
Normal file
122
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
const QueryCompiler_PG = require('../postgres/query/pg-querycompiler');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
wrap: wrap_,
|
||||
operator: operator_,
|
||||
} = require('../../formatter/wrappingFormatter');
|
||||
|
||||
class QueryCompiler_CRDB extends QueryCompiler_PG {
|
||||
truncate() {
|
||||
return `truncate ${this.tableName}`;
|
||||
}
|
||||
|
||||
upsert() {
|
||||
let sql = this._upsert();
|
||||
if (sql === '') return sql;
|
||||
const { returning } = this.single;
|
||||
if (returning) sql += this._returning(returning);
|
||||
return {
|
||||
sql: sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
_upsert() {
|
||||
const upsertValues = this.single.upsert || [];
|
||||
const sql = this.with() + `upsert into ${this.tableName} `;
|
||||
const body = this._insertBody(upsertValues);
|
||||
return body === '' ? '' : sql + body;
|
||||
}
|
||||
|
||||
_groupOrder(item, type) {
|
||||
// CockroachDB don't support PostgreSQL order nulls first/last syntax, we take the generic one.
|
||||
return this._basicGroupOrder(item, type);
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
let castValue = '';
|
||||
if (!isNaN(statement.value) && parseInt(statement.value)) {
|
||||
castValue = '::int';
|
||||
} else if (!isNaN(statement.value) && parseFloat(statement.value)) {
|
||||
castValue = '::float';
|
||||
} else {
|
||||
castValue = " #>> '{}'";
|
||||
}
|
||||
return `json_extract_path(${this._columnClause(
|
||||
statement
|
||||
)}, ${this.client.toArrayPathFromJsonPath(
|
||||
statement.jsonPath,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})${castValue} ${operator_(
|
||||
statement.operator,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)} ${this._jsonValueClause(statement)}`;
|
||||
}
|
||||
|
||||
// Json common functions
|
||||
_jsonExtract(nameFunction, params) {
|
||||
let extractions;
|
||||
if (Array.isArray(params.column)) {
|
||||
extractions = params.column;
|
||||
} else {
|
||||
extractions = [params];
|
||||
}
|
||||
return extractions
|
||||
.map((extraction) => {
|
||||
const jsonCol = `json_extract_path(${columnize_(
|
||||
extraction.column || extraction[0],
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.toArrayPathFromJsonPath(
|
||||
extraction.path || extraction[1],
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
const alias = extraction.alias || extraction[2];
|
||||
return alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(alias))
|
||||
: jsonCol;
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
_onJsonPathEquals(nameJoinFunction, clause) {
|
||||
return (
|
||||
'json_extract_path(' +
|
||||
wrap_(
|
||||
clause.columnFirst,
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
', ' +
|
||||
this.client.toArrayPathFromJsonPath(
|
||||
clause.jsonPathFirst,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
') = json_extract_path(' +
|
||||
wrap_(
|
||||
clause.columnSecond,
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
', ' +
|
||||
this.client.toArrayPathFromJsonPath(
|
||||
clause.jsonPathSecond,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
')'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryCompiler_CRDB;
|
37
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js
generated
vendored
Normal file
37
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const TableCompiler = require('../postgres/schema/pg-tablecompiler');
|
||||
|
||||
class TableCompiler_CRDB extends TableCompiler {
|
||||
constructor(client, tableBuilder) {
|
||||
super(client, tableBuilder);
|
||||
}
|
||||
|
||||
addColumns(columns, prefix, colCompilers) {
|
||||
if (prefix === this.alterColumnsPrefix) {
|
||||
// alter columns
|
||||
for (const col of colCompilers) {
|
||||
this.client.logger.warn(
|
||||
'Experimental alter column in use, see issue: https://github.com/cockroachdb/cockroach/issues/49329'
|
||||
);
|
||||
this.pushQuery({
|
||||
sql: 'SET enable_experimental_alter_column_type_general = true',
|
||||
bindings: [],
|
||||
});
|
||||
super._addColumn(col);
|
||||
}
|
||||
} else {
|
||||
// base class implementation for normal add
|
||||
super.addColumns(columns, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
dropUnique(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
this.pushQuery(`drop index ${this.tableName()}@${indexName} cascade `);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TableCompiler_CRDB;
|
15
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js
generated
vendored
Normal file
15
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
const ViewCompiler_PG = require('../postgres/schema/pg-viewcompiler.js');
|
||||
|
||||
class ViewCompiler_CRDB extends ViewCompiler_PG {
|
||||
renameColumn(from, to) {
|
||||
throw new Error('rename column of views is not supported by this dialect.');
|
||||
}
|
||||
|
||||
defaultTo(column, defaultValue) {
|
||||
throw new Error(
|
||||
'change default values of views is not supported by this dialect.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_CRDB;
|
86
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/index.js
generated
vendored
Normal file
86
backend/apis/nodejs/node_modules/knex/lib/dialects/cockroachdb/index.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
// CockroachDB Client
|
||||
// -------
|
||||
const Client_PostgreSQL = require('../postgres');
|
||||
const Transaction = require('../postgres/execution/pg-transaction');
|
||||
const QueryCompiler = require('./crdb-querycompiler');
|
||||
const ColumnCompiler = require('./crdb-columncompiler');
|
||||
const TableCompiler = require('./crdb-tablecompiler');
|
||||
const ViewCompiler = require('./crdb-viewcompiler');
|
||||
const QueryBuilder = require('./crdb-querybuilder');
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler"
|
||||
// objects, which extend the base 'lib/query/builder' and
|
||||
// 'lib/query/compiler', respectively.
|
||||
class Client_CockroachDB extends Client_PostgreSQL {
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
queryBuilder() {
|
||||
return new QueryBuilder(this);
|
||||
}
|
||||
|
||||
_parseVersion(versionString) {
|
||||
return versionString.split(' ')[2];
|
||||
}
|
||||
|
||||
async cancelQuery(connectionToKill) {
|
||||
try {
|
||||
return await this._wrappedCancelQueryCall(null, connectionToKill);
|
||||
} catch (err) {
|
||||
this.logger.warn(`Connection Error: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
_wrappedCancelQueryCall(emptyConnection, connectionToKill) {
|
||||
// FixMe https://github.com/cockroachdb/cockroach/issues/41335
|
||||
if (
|
||||
connectionToKill.activeQuery.processID === 0 &&
|
||||
connectionToKill.activeQuery.secretKey === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return connectionToKill.cancel(
|
||||
connectionToKill,
|
||||
connectionToKill.activeQuery
|
||||
);
|
||||
}
|
||||
|
||||
toArrayPathFromJsonPath(jsonPath, builder, bindingsHolder) {
|
||||
return jsonPath
|
||||
.replace(/^(\$\.)/, '') // remove the first dollar
|
||||
.replace(/\[([0-9]+)]/, '.$1')
|
||||
.split('.')
|
||||
.map(
|
||||
function (v) {
|
||||
return this.parameter(v, builder, bindingsHolder);
|
||||
}.bind(this)
|
||||
)
|
||||
.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_CockroachDB.prototype, {
|
||||
// The "dialect", for reference elsewhere.
|
||||
driverName: 'cockroachdb',
|
||||
});
|
||||
|
||||
module.exports = Client_CockroachDB;
|
34
backend/apis/nodejs/node_modules/knex/lib/dialects/index.js
generated
vendored
Normal file
34
backend/apis/nodejs/node_modules/knex/lib/dialects/index.js
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
exports.getDialectByNameOrAlias = void 0;
|
||||
const { resolveClientNameWithAliases } = require('../util/helpers');
|
||||
const dbNameToDialectLoader = Object.freeze({
|
||||
'better-sqlite3': () => require('./better-sqlite3'),
|
||||
cockroachdb: () => require('./cockroachdb'),
|
||||
mssql: () => require('./mssql'),
|
||||
mysql: () => require('./mysql'),
|
||||
mysql2: () => require('./mysql2'),
|
||||
oracle: () => require('./oracle'),
|
||||
oracledb: () => require('./oracledb'),
|
||||
pgnative: () => require('./pgnative'),
|
||||
postgres: () => require('./postgres'),
|
||||
redshift: () => require('./redshift'),
|
||||
sqlite3: () => require('./sqlite3'),
|
||||
});
|
||||
/**
|
||||
* Gets the Dialect object with the given client name or throw an
|
||||
* error if not found.
|
||||
*
|
||||
* NOTE: This is a replacement for prior practice of doing dynamic
|
||||
* string construction for imports of Dialect objects.
|
||||
*/
|
||||
function getDialectByNameOrAlias(clientName) {
|
||||
const resolvedClientName = resolveClientNameWithAliases(clientName);
|
||||
const dialectLoader = dbNameToDialectLoader[resolvedClientName];
|
||||
if (!dialectLoader) {
|
||||
throw new Error(`Invalid clientName given: ${clientName}`);
|
||||
}
|
||||
return dialectLoader();
|
||||
}
|
||||
exports.getDialectByNameOrAlias = getDialectByNameOrAlias;
|
||||
//# sourceMappingURL=index.js.map
|
500
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/index.js
generated
vendored
Normal file
500
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/index.js
generated
vendored
Normal file
@ -0,0 +1,500 @@
|
||||
// MSSQL Client
|
||||
// -------
|
||||
const map = require('lodash/map');
|
||||
const isNil = require('lodash/isNil');
|
||||
|
||||
const Client = require('../../client');
|
||||
const MSSQL_Formatter = require('./mssql-formatter');
|
||||
const Transaction = require('./transaction');
|
||||
const QueryCompiler = require('./query/mssql-querycompiler');
|
||||
const SchemaCompiler = require('./schema/mssql-compiler');
|
||||
const TableCompiler = require('./schema/mssql-tablecompiler');
|
||||
const ViewCompiler = require('./schema/mssql-viewcompiler');
|
||||
const ColumnCompiler = require('./schema/mssql-columncompiler');
|
||||
const QueryBuilder = require('../../query/querybuilder');
|
||||
const { setHiddenProperty } = require('../../util/security');
|
||||
|
||||
const debug = require('debug')('knex:mssql');
|
||||
|
||||
const SQL_INT4 = { MIN: -2147483648, MAX: 2147483647 };
|
||||
const SQL_BIGINT_SAFE = { MIN: -9007199254740991, MAX: 9007199254740991 };
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler" objects, which
|
||||
// extend the base 'lib/query/builder' and 'lib/query/compiler', respectively.
|
||||
class Client_MSSQL extends Client {
|
||||
constructor(config = {}) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('knex').Config} options
|
||||
*/
|
||||
_generateConnection() {
|
||||
const settings = this.connectionSettings;
|
||||
settings.options = settings.options || {};
|
||||
|
||||
/** @type {import('tedious').ConnectionConfig} */
|
||||
const cfg = {
|
||||
authentication: {
|
||||
type: settings.type || 'default',
|
||||
options: {
|
||||
userName: settings.userName || settings.user,
|
||||
password: settings.password,
|
||||
domain: settings.domain,
|
||||
token: settings.token,
|
||||
clientId: settings.clientId,
|
||||
clientSecret: settings.clientSecret,
|
||||
tenantId: settings.tenantId,
|
||||
msiEndpoint: settings.msiEndpoint,
|
||||
},
|
||||
},
|
||||
server: settings.server || settings.host,
|
||||
options: {
|
||||
database: settings.database,
|
||||
encrypt: settings.encrypt || false,
|
||||
port: settings.port || 1433,
|
||||
connectTimeout: settings.connectionTimeout || settings.timeout || 15000,
|
||||
requestTimeout: !isNil(settings.requestTimeout)
|
||||
? settings.requestTimeout
|
||||
: 15000,
|
||||
rowCollectionOnDone: false,
|
||||
rowCollectionOnRequestCompletion: false,
|
||||
useColumnNames: false,
|
||||
tdsVersion: settings.options.tdsVersion || '7_4',
|
||||
appName: settings.options.appName || 'knex',
|
||||
trustServerCertificate: false,
|
||||
...settings.options,
|
||||
},
|
||||
};
|
||||
|
||||
if (cfg.authentication.options.password) {
|
||||
setHiddenProperty(cfg.authentication.options);
|
||||
}
|
||||
|
||||
// tedious always connect via tcp when port is specified
|
||||
if (cfg.options.instanceName) delete cfg.options.port;
|
||||
|
||||
if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000;
|
||||
if (cfg.options.requestTimeout === Infinity) cfg.options.requestTimeout = 0;
|
||||
if (cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0;
|
||||
|
||||
if (settings.debug) {
|
||||
cfg.options.debug = {
|
||||
packet: true,
|
||||
token: true,
|
||||
data: true,
|
||||
payload: true,
|
||||
};
|
||||
}
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
_driver() {
|
||||
const tds = require('tedious');
|
||||
|
||||
return tds;
|
||||
}
|
||||
|
||||
formatter() {
|
||||
return new MSSQL_Formatter(this, ...arguments);
|
||||
}
|
||||
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
queryCompiler() {
|
||||
return new QueryCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
queryBuilder() {
|
||||
const b = new QueryBuilder(this);
|
||||
return b;
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
wrapIdentifierImpl(value) {
|
||||
if (value === '*') {
|
||||
return '*';
|
||||
}
|
||||
|
||||
return `[${value.replace(/[[\]]+/g, '')}]`;
|
||||
}
|
||||
|
||||
// Get a raw connection, called by the `pool` whenever a new
|
||||
// connection needs to be added to the pool.
|
||||
acquireRawConnection() {
|
||||
return new Promise((resolver, rejecter) => {
|
||||
debug('connection::connection new connection requested');
|
||||
const Driver = this._driver();
|
||||
const settings = Object.assign({}, this._generateConnection());
|
||||
|
||||
const connection = new Driver.Connection(settings);
|
||||
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
debug('connection::connect error: %s', err.message);
|
||||
return rejecter(err);
|
||||
}
|
||||
|
||||
debug('connection::connect connected to server');
|
||||
|
||||
connection.connected = true;
|
||||
connection.on('error', (e) => {
|
||||
debug('connection::error message=%s', e.message);
|
||||
connection.__knex__disposed = e;
|
||||
connection.connected = false;
|
||||
});
|
||||
|
||||
connection.once('end', () => {
|
||||
connection.connected = false;
|
||||
connection.__knex__disposed = 'Connection to server was terminated.';
|
||||
debug('connection::end connection ended.');
|
||||
});
|
||||
|
||||
return resolver(connection);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
validateConnection(connection) {
|
||||
return connection && connection.connected;
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool
|
||||
// when a connection times out or the pool is shutdown.
|
||||
destroyRawConnection(connection) {
|
||||
debug('connection::destroy');
|
||||
|
||||
return new Promise((resolve) => {
|
||||
connection.once('end', () => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
connection.close();
|
||||
});
|
||||
}
|
||||
|
||||
// Position the bindings for the query.
|
||||
positionBindings(sql) {
|
||||
let questionCount = -1;
|
||||
return sql.replace(/\\?\?/g, (match) => {
|
||||
if (match === '\\?') {
|
||||
return '?';
|
||||
}
|
||||
|
||||
questionCount += 1;
|
||||
return `@p${questionCount}`;
|
||||
});
|
||||
}
|
||||
|
||||
_chomp(connection) {
|
||||
if (connection.state.name === 'LoggedIn') {
|
||||
const nextRequest = this.requestQueue.pop();
|
||||
if (nextRequest) {
|
||||
debug(
|
||||
'connection::query executing query, %d more in queue',
|
||||
this.requestQueue.length
|
||||
);
|
||||
|
||||
connection.execSql(nextRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_enqueueRequest(request, connection) {
|
||||
this.requestQueue.push(request);
|
||||
this._chomp(connection);
|
||||
}
|
||||
|
||||
_makeRequest(query, callback) {
|
||||
const Driver = this._driver();
|
||||
const sql = typeof query === 'string' ? query : query.sql;
|
||||
let rowCount = 0;
|
||||
|
||||
if (!sql) throw new Error('The query is empty');
|
||||
|
||||
debug('request::request sql=%s', sql);
|
||||
|
||||
const request = new Driver.Request(sql, (err, remoteRowCount) => {
|
||||
if (err) {
|
||||
debug('request::error message=%s', err.message);
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
rowCount = remoteRowCount;
|
||||
debug('request::callback rowCount=%d', rowCount);
|
||||
});
|
||||
|
||||
request.on('prepared', () => {
|
||||
debug('request %s::request prepared', this.id);
|
||||
});
|
||||
|
||||
request.on('done', (rowCount, more) => {
|
||||
debug('request::done rowCount=%d more=%s', rowCount, more);
|
||||
});
|
||||
|
||||
request.on('doneProc', (rowCount, more) => {
|
||||
debug(
|
||||
'request::doneProc id=%s rowCount=%d more=%s',
|
||||
request.id,
|
||||
rowCount,
|
||||
more
|
||||
);
|
||||
});
|
||||
|
||||
request.on('doneInProc', (rowCount, more) => {
|
||||
debug(
|
||||
'request::doneInProc id=%s rowCount=%d more=%s',
|
||||
request.id,
|
||||
rowCount,
|
||||
more
|
||||
);
|
||||
});
|
||||
|
||||
request.once('requestCompleted', () => {
|
||||
debug('request::completed id=%s', request.id);
|
||||
return callback(null, rowCount);
|
||||
});
|
||||
|
||||
request.on('error', (err) => {
|
||||
debug('request::error id=%s message=%s', request.id, err.message);
|
||||
return callback(err);
|
||||
});
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
// Grab a connection, run the query via the MSSQL streaming interface,
|
||||
// and pass that through to the stream we've sent back to the client.
|
||||
_stream(connection, query, /** @type {NodeJS.ReadWriteStream} */ stream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = this._makeRequest(query, (err) => {
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
|
||||
request.on('row', (row) => {
|
||||
stream.write(
|
||||
row.reduce(
|
||||
(prev, curr) => ({
|
||||
...prev,
|
||||
[curr.metadata.colName]: curr.value,
|
||||
}),
|
||||
{}
|
||||
)
|
||||
);
|
||||
});
|
||||
request.on('error', (err) => {
|
||||
stream.emit('error', err);
|
||||
reject(err);
|
||||
});
|
||||
request.once('requestCompleted', () => {
|
||||
stream.end();
|
||||
resolve();
|
||||
});
|
||||
|
||||
this._assignBindings(request, query.bindings);
|
||||
this._enqueueRequest(request, connection);
|
||||
});
|
||||
}
|
||||
|
||||
_assignBindings(request, bindings) {
|
||||
if (Array.isArray(bindings)) {
|
||||
for (let i = 0; i < bindings.length; i++) {
|
||||
const binding = bindings[i];
|
||||
this._setReqInput(request, i, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_scaleForBinding(binding) {
|
||||
if (binding % 1 === 0) {
|
||||
throw new Error(`The binding value ${binding} must be a decimal number.`);
|
||||
}
|
||||
|
||||
return { scale: 10 };
|
||||
}
|
||||
|
||||
_typeForBinding(binding) {
|
||||
const Driver = this._driver();
|
||||
|
||||
if (
|
||||
this.connectionSettings.options &&
|
||||
this.connectionSettings.options.mapBinding
|
||||
) {
|
||||
const result = this.connectionSettings.options.mapBinding(binding);
|
||||
if (result) {
|
||||
return [result.value, result.type];
|
||||
}
|
||||
}
|
||||
|
||||
switch (typeof binding) {
|
||||
case 'string':
|
||||
return [binding, Driver.TYPES.NVarChar];
|
||||
case 'boolean':
|
||||
return [binding, Driver.TYPES.Bit];
|
||||
case 'number': {
|
||||
if (binding % 1 !== 0) {
|
||||
return [binding, Driver.TYPES.Float];
|
||||
}
|
||||
|
||||
if (binding < SQL_INT4.MIN || binding > SQL_INT4.MAX) {
|
||||
if (binding < SQL_BIGINT_SAFE.MIN || binding > SQL_BIGINT_SAFE.MAX) {
|
||||
throw new Error(
|
||||
`Bigint must be safe integer or must be passed as string, saw ${binding}`
|
||||
);
|
||||
}
|
||||
|
||||
return [binding, Driver.TYPES.BigInt];
|
||||
}
|
||||
|
||||
return [binding, Driver.TYPES.Int];
|
||||
}
|
||||
default: {
|
||||
if (binding instanceof Date) {
|
||||
return [binding, Driver.TYPES.DateTime];
|
||||
}
|
||||
|
||||
if (binding instanceof Buffer) {
|
||||
return [binding, Driver.TYPES.VarBinary];
|
||||
}
|
||||
|
||||
return [binding, Driver.TYPES.NVarChar];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings
|
||||
// and any other necessary prep work.
|
||||
_query(connection, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const rows = [];
|
||||
const request = this._makeRequest(query, (err, count) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
query.response = rows;
|
||||
|
||||
process.nextTick(() => this._chomp(connection));
|
||||
|
||||
resolve(query);
|
||||
});
|
||||
|
||||
request.on('row', (row) => {
|
||||
debug('request::row');
|
||||
rows.push(row);
|
||||
});
|
||||
|
||||
this._assignBindings(request, query.bindings);
|
||||
this._enqueueRequest(request, connection);
|
||||
});
|
||||
}
|
||||
|
||||
// sets a request input parameter. Detects bigints and decimals and sets type appropriately.
|
||||
_setReqInput(req, i, inputBinding) {
|
||||
const [binding, tediousType] = this._typeForBinding(inputBinding);
|
||||
const bindingName = 'p'.concat(i);
|
||||
let options;
|
||||
|
||||
if (typeof binding === 'number' && binding % 1 !== 0) {
|
||||
options = this._scaleForBinding(binding);
|
||||
}
|
||||
|
||||
debug(
|
||||
'request::binding pos=%d type=%s value=%s',
|
||||
i,
|
||||
tediousType.name,
|
||||
binding
|
||||
);
|
||||
|
||||
if (Buffer.isBuffer(binding)) {
|
||||
options = {
|
||||
length: 'max',
|
||||
};
|
||||
}
|
||||
|
||||
req.addParameter(bindingName, tediousType, binding, options);
|
||||
}
|
||||
|
||||
// Process the response as returned from the query.
|
||||
processResponse(query, runner) {
|
||||
if (query == null) return;
|
||||
let { response } = query;
|
||||
const { method } = query;
|
||||
|
||||
if (query.output) {
|
||||
return query.output.call(runner, response);
|
||||
}
|
||||
|
||||
response = response.map((row) =>
|
||||
row.reduce((columns, r) => {
|
||||
const colName = r.metadata.colName;
|
||||
|
||||
if (columns[colName]) {
|
||||
if (!Array.isArray(columns[colName])) {
|
||||
columns[colName] = [columns[colName]];
|
||||
}
|
||||
|
||||
columns[colName].push(r.value);
|
||||
} else {
|
||||
columns[colName] = r.value;
|
||||
}
|
||||
|
||||
return columns;
|
||||
}, {})
|
||||
);
|
||||
|
||||
if (query.output) return query.output.call(runner, response);
|
||||
switch (method) {
|
||||
case 'select':
|
||||
return response;
|
||||
case 'first':
|
||||
return response[0];
|
||||
case 'pluck':
|
||||
return map(response, query.pluck);
|
||||
case 'insert':
|
||||
case 'del':
|
||||
case 'update':
|
||||
case 'counter':
|
||||
if (query.returning) {
|
||||
if (query.returning === '@@rowcount') {
|
||||
return response[0][''];
|
||||
}
|
||||
}
|
||||
return response;
|
||||
default:
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_MSSQL.prototype, {
|
||||
requestQueue: [],
|
||||
|
||||
dialect: 'mssql',
|
||||
|
||||
driverName: 'mssql',
|
||||
});
|
||||
|
||||
module.exports = Client_MSSQL;
|
34
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/mssql-formatter.js
generated
vendored
Normal file
34
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/mssql-formatter.js
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
const Formatter = require('../../formatter');
|
||||
|
||||
class MSSQL_Formatter extends Formatter {
|
||||
// Accepts a string or array of columns to wrap as appropriate.
|
||||
columnizeWithPrefix(prefix, target) {
|
||||
const columns = typeof target === 'string' ? [target] : target;
|
||||
let str = '',
|
||||
i = -1;
|
||||
while (++i < columns.length) {
|
||||
if (i > 0) str += ', ';
|
||||
str += prefix + this.wrap(columns[i]);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns its argument with single quotes escaped, so it can be included into a single-quoted string.
|
||||
*
|
||||
* For example, it converts "has'quote" to "has''quote".
|
||||
*
|
||||
* This assumes QUOTED_IDENTIFIER ON so it is only ' that need escaping,
|
||||
* never ", because " cannot be used to quote a string when that's on;
|
||||
* otherwise we'd need to be aware of whether the string is quoted with " or '.
|
||||
*
|
||||
* This assumption is consistent with the SQL Knex generates.
|
||||
* @param {string} string
|
||||
* @returns {string}
|
||||
*/
|
||||
escapingStringDelimiters(string) {
|
||||
return (string || '').replace(/'/g, "''");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MSSQL_Formatter;
|
601
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js
generated
vendored
Normal file
601
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,601 @@
|
||||
// MSSQL Query Compiler
|
||||
// ------
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
|
||||
const compact = require('lodash/compact');
|
||||
const identity = require('lodash/identity');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const Raw = require('../../../raw.js');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
const components = [
|
||||
'comments',
|
||||
'columns',
|
||||
'join',
|
||||
'lock',
|
||||
'where',
|
||||
'union',
|
||||
'group',
|
||||
'having',
|
||||
'order',
|
||||
'limit',
|
||||
'offset',
|
||||
];
|
||||
|
||||
class QueryCompiler_MSSQL extends QueryCompiler {
|
||||
constructor(client, builder, formatter) {
|
||||
super(client, builder, formatter);
|
||||
|
||||
const { onConflict } = this.single;
|
||||
if (onConflict) {
|
||||
throw new Error('.onConflict() is not supported for mssql.');
|
||||
}
|
||||
|
||||
this._emptyInsertValue = 'default values';
|
||||
}
|
||||
|
||||
with() {
|
||||
// WITH RECURSIVE is a syntax error:
|
||||
// SQL Server does not syntactically distinguish recursive and non-recursive CTEs.
|
||||
// So mark all statements as non-recursive, generate the SQL, then restore.
|
||||
// This approach ensures any changes in base class with() get propagated here.
|
||||
const undoList = [];
|
||||
if (this.grouped.with) {
|
||||
for (const stmt of this.grouped.with) {
|
||||
if (stmt.recursive) {
|
||||
undoList.push(stmt);
|
||||
stmt.recursive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = super.with();
|
||||
|
||||
// Restore the recursive markings, in case this same query gets cloned and passed to other drivers.
|
||||
for (const stmt of undoList) {
|
||||
stmt.recursive = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
select() {
|
||||
const sql = this.with();
|
||||
const statements = components.map((component) => this[component](this));
|
||||
return sql + compact(statements).join(' ');
|
||||
}
|
||||
|
||||
//#region Insert
|
||||
// Compiles an "insert" query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
if (
|
||||
this.single.options &&
|
||||
this.single.options.includeTriggerModifications
|
||||
) {
|
||||
return this.insertWithTriggers();
|
||||
} else {
|
||||
return this.standardInsert();
|
||||
}
|
||||
}
|
||||
|
||||
insertWithTriggers() {
|
||||
const insertValues = this.single.insert || [];
|
||||
const { returning } = this.single;
|
||||
let sql =
|
||||
this.with() +
|
||||
`${this._buildTempTable(returning)}insert into ${this.tableName} `;
|
||||
const returningSql = returning
|
||||
? this._returning('insert', returning, true) + ' '
|
||||
: '';
|
||||
|
||||
if (Array.isArray(insertValues)) {
|
||||
if (insertValues.length === 0) {
|
||||
return '';
|
||||
}
|
||||
} else if (typeof insertValues === 'object' && isEmpty(insertValues)) {
|
||||
return {
|
||||
sql:
|
||||
sql +
|
||||
returningSql +
|
||||
this._emptyInsertValue +
|
||||
this._buildReturningSelect(returning),
|
||||
returning,
|
||||
};
|
||||
}
|
||||
sql += this._buildInsertData(insertValues, returningSql);
|
||||
|
||||
if (returning) {
|
||||
sql += this._buildReturningSelect(returning);
|
||||
}
|
||||
|
||||
return {
|
||||
sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
_buildInsertData(insertValues, returningSql) {
|
||||
let sql = '';
|
||||
const insertData = this._prepInsert(insertValues);
|
||||
if (typeof insertData === 'string') {
|
||||
sql += insertData;
|
||||
} else {
|
||||
if (insertData.columns.length) {
|
||||
sql += `(${this.formatter.columnize(insertData.columns)}`;
|
||||
sql +=
|
||||
`) ${returningSql}values (` +
|
||||
this._buildInsertValues(insertData) +
|
||||
')';
|
||||
} else if (insertValues.length === 1 && insertValues[0]) {
|
||||
sql += returningSql + this._emptyInsertValue;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
standardInsert() {
|
||||
const insertValues = this.single.insert || [];
|
||||
let sql = this.with() + `insert into ${this.tableName} `;
|
||||
const { returning } = this.single;
|
||||
const returningSql = returning
|
||||
? this._returning('insert', returning) + ' '
|
||||
: '';
|
||||
|
||||
if (Array.isArray(insertValues)) {
|
||||
if (insertValues.length === 0) {
|
||||
return '';
|
||||
}
|
||||
} else if (typeof insertValues === 'object' && isEmpty(insertValues)) {
|
||||
return {
|
||||
sql: sql + returningSql + this._emptyInsertValue,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
sql += this._buildInsertData(insertValues, returningSql);
|
||||
|
||||
return {
|
||||
sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Update
|
||||
// Compiles an `update` query, allowing for a return value.
|
||||
update() {
|
||||
if (
|
||||
this.single.options &&
|
||||
this.single.options.includeTriggerModifications
|
||||
) {
|
||||
return this.updateWithTriggers();
|
||||
} else {
|
||||
return this.standardUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
updateWithTriggers() {
|
||||
const top = this.top();
|
||||
const withSQL = this.with();
|
||||
const updates = this._prepUpdate(this.single.update);
|
||||
const join = this.join();
|
||||
const where = this.where();
|
||||
const order = this.order();
|
||||
const { returning } = this.single;
|
||||
const declaredTemp = this._buildTempTable(returning);
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
declaredTemp +
|
||||
`update ${top ? top + ' ' : ''}${this.tableName}` +
|
||||
' set ' +
|
||||
updates.join(', ') +
|
||||
(returning ? ` ${this._returning('update', returning, true)}` : '') +
|
||||
(join ? ` from ${this.tableName} ${join}` : '') +
|
||||
(where ? ` ${where}` : '') +
|
||||
(order ? ` ${order}` : '') +
|
||||
(!returning
|
||||
? this._returning('rowcount', '@@rowcount')
|
||||
: this._buildReturningSelect(returning)),
|
||||
returning: returning || '@@rowcount',
|
||||
};
|
||||
}
|
||||
|
||||
_formatGroupsItemValue(value, nulls) {
|
||||
const column = super._formatGroupsItemValue(value);
|
||||
// MSSQL dont support 'is null' syntax in order by,
|
||||
// so we override this function and add MSSQL specific syntax.
|
||||
if (nulls && !(value instanceof Raw)) {
|
||||
const collNulls = `IIF(${column} is null,`;
|
||||
if (nulls === 'first') {
|
||||
return `${collNulls}0,1)`;
|
||||
} else if (nulls === 'last') {
|
||||
return `${collNulls}1,0)`;
|
||||
}
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
standardUpdate() {
|
||||
const top = this.top();
|
||||
const withSQL = this.with();
|
||||
const updates = this._prepUpdate(this.single.update);
|
||||
const join = this.join();
|
||||
const where = this.where();
|
||||
const order = this.order();
|
||||
const { returning } = this.single;
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
`update ${top ? top + ' ' : ''}${this.tableName}` +
|
||||
' set ' +
|
||||
updates.join(', ') +
|
||||
(returning ? ` ${this._returning('update', returning)}` : '') +
|
||||
(join ? ` from ${this.tableName} ${join}` : '') +
|
||||
(where ? ` ${where}` : '') +
|
||||
(order ? ` ${order}` : '') +
|
||||
(!returning ? this._returning('rowcount', '@@rowcount') : ''),
|
||||
returning: returning || '@@rowcount',
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Delete
|
||||
// Compiles a `delete` query.
|
||||
del() {
|
||||
if (
|
||||
this.single.options &&
|
||||
this.single.options.includeTriggerModifications
|
||||
) {
|
||||
return this.deleteWithTriggers();
|
||||
} else {
|
||||
return this.standardDelete();
|
||||
}
|
||||
}
|
||||
|
||||
deleteWithTriggers() {
|
||||
// Make sure tableName is processed by the formatter first.
|
||||
const withSQL = this.with();
|
||||
const { tableName } = this;
|
||||
const wheres = this.where();
|
||||
const joins = this.join();
|
||||
const { returning } = this.single;
|
||||
const returningStr = returning
|
||||
? ` ${this._returning('del', returning, true)}`
|
||||
: '';
|
||||
const deleteSelector = joins ? `${tableName}${returningStr} ` : '';
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
`${this._buildTempTable(
|
||||
returning
|
||||
)}delete ${deleteSelector}from ${tableName}` +
|
||||
(!joins ? returningStr : '') +
|
||||
(joins ? ` ${joins}` : '') +
|
||||
(wheres ? ` ${wheres}` : '') +
|
||||
(!returning
|
||||
? this._returning('rowcount', '@@rowcount')
|
||||
: this._buildReturningSelect(returning)),
|
||||
returning: returning || '@@rowcount',
|
||||
};
|
||||
}
|
||||
|
||||
standardDelete() {
|
||||
// Make sure tableName is processed by the formatter first.
|
||||
const withSQL = this.with();
|
||||
const { tableName } = this;
|
||||
const wheres = this.where();
|
||||
const joins = this.join();
|
||||
const { returning } = this.single;
|
||||
const returningStr = returning
|
||||
? ` ${this._returning('del', returning)}`
|
||||
: '';
|
||||
// returning needs to be before "from" when using join
|
||||
const deleteSelector = joins ? `${tableName}${returningStr} ` : '';
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
`delete ${deleteSelector}from ${tableName}` +
|
||||
(!joins ? returningStr : '') +
|
||||
(joins ? ` ${joins}` : '') +
|
||||
(wheres ? ` ${wheres}` : '') +
|
||||
(!returning ? this._returning('rowcount', '@@rowcount') : ''),
|
||||
returning: returning || '@@rowcount',
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// Compiles the columns in the query, specifying if an item was distinct.
|
||||
columns() {
|
||||
let distinctClause = '';
|
||||
if (this.onlyUnions()) return '';
|
||||
const top = this.top();
|
||||
const hints = this._hintComments();
|
||||
const columns = this.grouped.columns || [];
|
||||
let i = -1,
|
||||
sql = [];
|
||||
if (columns) {
|
||||
while (++i < columns.length) {
|
||||
const stmt = columns[i];
|
||||
if (stmt.distinct) distinctClause = 'distinct ';
|
||||
if (stmt.distinctOn) {
|
||||
distinctClause = this.distinctOn(stmt.value);
|
||||
continue;
|
||||
}
|
||||
if (stmt.type === 'aggregate') {
|
||||
sql.push(...this.aggregate(stmt));
|
||||
} else if (stmt.type === 'aggregateRaw') {
|
||||
sql.push(this.aggregateRaw(stmt));
|
||||
} else if (stmt.type === 'analytic') {
|
||||
sql.push(this.analytic(stmt));
|
||||
} else if (stmt.type === 'json') {
|
||||
sql.push(this.json(stmt));
|
||||
} else if (stmt.value && stmt.value.length > 0) {
|
||||
sql.push(this.formatter.columnize(stmt.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sql.length === 0) sql = ['*'];
|
||||
const select = this.onlyJson() ? '' : 'select ';
|
||||
return (
|
||||
`${select}${hints}${distinctClause}` +
|
||||
(top ? top + ' ' : '') +
|
||||
sql.join(', ') +
|
||||
(this.tableName ? ` from ${this.tableName}` : '')
|
||||
);
|
||||
}
|
||||
|
||||
_returning(method, value, withTrigger) {
|
||||
switch (method) {
|
||||
case 'update':
|
||||
case 'insert':
|
||||
return value
|
||||
? `output ${this.formatter.columnizeWithPrefix('inserted.', value)}${
|
||||
withTrigger ? ' into #out' : ''
|
||||
}`
|
||||
: '';
|
||||
case 'del':
|
||||
return value
|
||||
? `output ${this.formatter.columnizeWithPrefix('deleted.', value)}${
|
||||
withTrigger ? ' into #out' : ''
|
||||
}`
|
||||
: '';
|
||||
case 'rowcount':
|
||||
return value ? ';select @@rowcount' : '';
|
||||
}
|
||||
}
|
||||
|
||||
_buildTempTable(values) {
|
||||
// If value is nothing then return an empty string
|
||||
if (values && values.length > 0) {
|
||||
let selections = '';
|
||||
|
||||
// Build values that will be returned from this procedure
|
||||
if (Array.isArray(values)) {
|
||||
selections = values
|
||||
.map((value) => `[t].${this.formatter.columnize(value)}`)
|
||||
.join(',');
|
||||
} else {
|
||||
selections = `[t].${this.formatter.columnize(values)}`;
|
||||
}
|
||||
|
||||
// Force #out to be correctly populated with the correct column structure.
|
||||
let sql = `select top(0) ${selections} into #out `;
|
||||
sql += `from ${this.tableName} as t `;
|
||||
sql += `left join ${this.tableName} on 0=1;`;
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
_buildReturningSelect(values) {
|
||||
// If value is nothing then return an empty string
|
||||
if (values && values.length > 0) {
|
||||
let selections = '';
|
||||
|
||||
// Build columns to return
|
||||
if (Array.isArray(values)) {
|
||||
selections = values
|
||||
.map((value) => `${this.formatter.columnize(value)}`)
|
||||
.join(',');
|
||||
} else {
|
||||
selections = this.formatter.columnize(values);
|
||||
}
|
||||
|
||||
// Get the returned values
|
||||
let sql = `; select ${selections} from #out; `;
|
||||
// Drop the temp table to prevent memory leaks
|
||||
sql += `drop table #out;`;
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// Compiles a `truncate` query.
|
||||
truncate() {
|
||||
return `truncate table ${this.tableName}`;
|
||||
}
|
||||
|
||||
forUpdate() {
|
||||
// this doesn't work exacltly as it should, one should also mention index while locking
|
||||
// https://stackoverflow.com/a/9818448/360060
|
||||
return 'with (UPDLOCK)';
|
||||
}
|
||||
|
||||
forShare() {
|
||||
// http://www.sqlteam.com/article/introduction-to-locking-in-sql-server
|
||||
return 'with (HOLDLOCK)';
|
||||
}
|
||||
|
||||
// Compiles a `columnInfo` query.
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
let schema = this.single.schema;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
if (schema) {
|
||||
schema = this.client.customWrapIdentifier(schema, identity);
|
||||
}
|
||||
|
||||
// GOTCHA: INFORMATION_SCHEMA.COLUMNS must be capitalized to work when the database has a case-sensitive collation. [#4573]
|
||||
let sql = `select [COLUMN_NAME], [COLUMN_DEFAULT], [DATA_TYPE], [CHARACTER_MAXIMUM_LENGTH], [IS_NULLABLE] from INFORMATION_SCHEMA.COLUMNS where table_name = ? and table_catalog = ?`;
|
||||
const bindings = [table, this.client.database()];
|
||||
|
||||
if (schema) {
|
||||
sql += ' and table_schema = ?';
|
||||
bindings.push(schema);
|
||||
} else {
|
||||
sql += ` and table_schema = 'dbo'`;
|
||||
}
|
||||
|
||||
return {
|
||||
sql,
|
||||
bindings: bindings,
|
||||
output(resp) {
|
||||
const out = resp.reduce((columns, val) => {
|
||||
columns[val[0].value] = {
|
||||
defaultValue: val[1].value,
|
||||
type: val[2].value,
|
||||
maxLength: val[3].value,
|
||||
nullable: val[4].value === 'YES',
|
||||
};
|
||||
return columns;
|
||||
}, {});
|
||||
return (column && out[column]) || out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
top() {
|
||||
const noLimit = !this.single.limit && this.single.limit !== 0;
|
||||
const noOffset = !this.single.offset;
|
||||
if (noLimit || !noOffset) return '';
|
||||
return `top (${this._getValueOrParameterFromAttribute('limit')})`;
|
||||
}
|
||||
|
||||
limit() {
|
||||
return '';
|
||||
}
|
||||
|
||||
offset() {
|
||||
const noLimit = !this.single.limit && this.single.limit !== 0;
|
||||
const noOffset = !this.single.offset;
|
||||
if (noOffset) return '';
|
||||
let offset = `offset ${
|
||||
noOffset ? '0' : this._getValueOrParameterFromAttribute('offset')
|
||||
} rows`;
|
||||
if (!noLimit) {
|
||||
offset += ` fetch next ${this._getValueOrParameterFromAttribute(
|
||||
'limit'
|
||||
)} rows only`;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
whereLike(statement) {
|
||||
return `${this._columnClause(
|
||||
statement
|
||||
)} collate SQL_Latin1_General_CP1_CS_AS ${this._not(
|
||||
statement,
|
||||
'like '
|
||||
)}${this._valueClause(statement)}`;
|
||||
}
|
||||
|
||||
whereILike(statement) {
|
||||
return `${this._columnClause(
|
||||
statement
|
||||
)} collate SQL_Latin1_General_CP1_CI_AS ${this._not(
|
||||
statement,
|
||||
'like '
|
||||
)}${this._valueClause(statement)}`;
|
||||
}
|
||||
|
||||
jsonExtract(params) {
|
||||
// JSON_VALUE return NULL if we query object or array
|
||||
// JSON_QUERY return NULL if we query literal/single value
|
||||
return this._jsonExtract(
|
||||
params.singleValue ? 'JSON_VALUE' : 'JSON_QUERY',
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
return this._jsonSet('JSON_MODIFY', params);
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
return this._jsonSet('JSON_MODIFY', params);
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
const jsonCol = `JSON_MODIFY(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)},${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}, NULL)`;
|
||||
return params.alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
||||
: jsonCol;
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
return this._whereJsonPath('JSON_VALUE', statement);
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
throw new Error(
|
||||
'Json superset where clause not actually supported by MSSQL'
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
throw new Error('Json subset where clause not actually supported by MSSQL');
|
||||
}
|
||||
|
||||
_getExtracts(statement, operator) {
|
||||
const column = columnize_(
|
||||
statement.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
);
|
||||
return (
|
||||
Array.isArray(statement.values) ? statement.values : [statement.values]
|
||||
)
|
||||
.map(function (value) {
|
||||
return (
|
||||
'JSON_VALUE(' +
|
||||
column +
|
||||
',' +
|
||||
this.client.parameter(value, this.builder, this.bindingsHolder) +
|
||||
')'
|
||||
);
|
||||
}, this)
|
||||
.join(operator);
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('JSON_VALUE', clause);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the QueryBuilder & QueryCompiler on the client object,
|
||||
// in case anyone wants to modify things to suit their own purposes.
|
||||
module.exports = QueryCompiler_MSSQL;
|
185
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js
generated
vendored
Normal file
185
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
// MSSQL Column Compiler
|
||||
// -------
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
const { toNumber } = require('../../../util/helpers');
|
||||
const { formatDefault } = require('../../../formatter/formatterUtils');
|
||||
const { operator: operator_ } = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class ColumnCompiler_MSSQL extends ColumnCompiler {
|
||||
constructor(client, tableCompiler, columnBuilder) {
|
||||
super(client, tableCompiler, columnBuilder);
|
||||
this.modifiers = ['nullable', 'defaultTo', 'first', 'after', 'comment'];
|
||||
this._addCheckModifiers();
|
||||
}
|
||||
|
||||
// Types
|
||||
// ------
|
||||
|
||||
double(precision, scale) {
|
||||
return 'float';
|
||||
}
|
||||
|
||||
floating(precision, scale) {
|
||||
// ignore precicion / scale which is mysql specific stuff
|
||||
return `float`;
|
||||
}
|
||||
|
||||
integer() {
|
||||
// mssql does not support length
|
||||
return 'int';
|
||||
}
|
||||
|
||||
tinyint() {
|
||||
// mssql does not support length
|
||||
return 'tinyint';
|
||||
}
|
||||
|
||||
varchar(length) {
|
||||
return `nvarchar(${toNumber(length, 255)})`;
|
||||
}
|
||||
|
||||
timestamp({ useTz = false } = {}) {
|
||||
return useTz ? 'datetimeoffset' : 'datetime2';
|
||||
}
|
||||
|
||||
bit(length) {
|
||||
if (length > 1) {
|
||||
this.client.logger.warn('Bit field is exactly 1 bit length for MSSQL');
|
||||
}
|
||||
return 'bit';
|
||||
}
|
||||
|
||||
binary(length) {
|
||||
return length ? `varbinary(${toNumber(length)})` : 'varbinary(max)';
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
// ------
|
||||
|
||||
first() {
|
||||
this.client.logger.warn('Column first modifier not available for MSSQL');
|
||||
return '';
|
||||
}
|
||||
|
||||
after(column) {
|
||||
this.client.logger.warn('Column after modifier not available for MSSQL');
|
||||
return '';
|
||||
}
|
||||
|
||||
defaultTo(value, { constraintName } = {}) {
|
||||
const formattedValue = formatDefault(value, this.type, this.client);
|
||||
constraintName =
|
||||
typeof constraintName !== 'undefined'
|
||||
? constraintName
|
||||
: `${
|
||||
this.tableCompiler.tableNameRaw
|
||||
}_${this.getColumnName()}_default`.toLowerCase();
|
||||
if (this.columnBuilder._method === 'alter') {
|
||||
this.pushAdditional(function () {
|
||||
this.pushQuery(
|
||||
`ALTER TABLE ${this.tableCompiler.tableName()} ADD CONSTRAINT ${this.formatter.wrap(
|
||||
constraintName
|
||||
)} DEFAULT ${formattedValue} FOR ${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)}`
|
||||
);
|
||||
});
|
||||
return '';
|
||||
}
|
||||
if (!constraintName) {
|
||||
return `DEFAULT ${formattedValue}`;
|
||||
}
|
||||
return `CONSTRAINT ${this.formatter.wrap(
|
||||
constraintName
|
||||
)} DEFAULT ${formattedValue}`;
|
||||
}
|
||||
|
||||
comment(/** @type {string} */ comment) {
|
||||
if (!comment) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without database collation info.
|
||||
// (Yes, even if the column has its own collation, the sqlvariant still uses the database collation.)
|
||||
// I'm not sure we even need to raise a warning, as MSSQL will return an error when the limit is exceeded itself.
|
||||
if (comment && comment.length > 7500 / 2) {
|
||||
this.client.logger.warn(
|
||||
'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.'
|
||||
);
|
||||
}
|
||||
|
||||
// See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#b-adding-an-extended-property-to-a-column-in-a-table
|
||||
const value = this.formatter.escapingStringDelimiters(comment);
|
||||
const level0name = this.tableCompiler.schemaNameRaw || 'dbo';
|
||||
const level1name = this.formatter.escapingStringDelimiters(
|
||||
this.tableCompiler.tableNameRaw
|
||||
);
|
||||
const level2name = this.formatter.escapingStringDelimiters(
|
||||
this.args[0] || this.defaults('columnName')
|
||||
);
|
||||
|
||||
const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}', N'Column', N'${level2name}'`;
|
||||
|
||||
this.pushAdditional(function () {
|
||||
const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', N'Column', N'${level2name}'))`;
|
||||
this.pushQuery(
|
||||
`IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}`
|
||||
);
|
||||
});
|
||||
return '';
|
||||
}
|
||||
|
||||
checkLength(operator, length, constraintName) {
|
||||
return this._check(
|
||||
`LEN(${this.formatter.wrap(this.getColumnName())}) ${operator_(
|
||||
operator,
|
||||
this.columnBuilder,
|
||||
this.bindingsHolder
|
||||
)} ${toNumber(length)}`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
checkRegex(regex, constraintName) {
|
||||
return this._check(
|
||||
`${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)} LIKE ${this.client._escapeBinding('%' + regex + '%')}`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
increments(options = { primaryKey: true }) {
|
||||
return (
|
||||
'int identity(1,1) not null' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
|
||||
bigincrements(options = { primaryKey: true }) {
|
||||
return (
|
||||
'bigint identity(1,1) not null' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_MSSQL.prototype.bigint = 'bigint';
|
||||
ColumnCompiler_MSSQL.prototype.mediumint = 'int';
|
||||
ColumnCompiler_MSSQL.prototype.smallint = 'smallint';
|
||||
ColumnCompiler_MSSQL.prototype.text = 'nvarchar(max)';
|
||||
ColumnCompiler_MSSQL.prototype.mediumtext = 'nvarchar(max)';
|
||||
ColumnCompiler_MSSQL.prototype.longtext = 'nvarchar(max)';
|
||||
ColumnCompiler_MSSQL.prototype.json = ColumnCompiler_MSSQL.prototype.jsonb =
|
||||
'nvarchar(max)';
|
||||
|
||||
// TODO: mssql supports check constraints as of SQL Server 2008
|
||||
// so make enu here more like postgres
|
||||
ColumnCompiler_MSSQL.prototype.enu = 'nvarchar(100)';
|
||||
ColumnCompiler_MSSQL.prototype.uuid = ({ useBinaryUuid = false } = {}) =>
|
||||
useBinaryUuid ? 'binary(16)' : 'uniqueidentifier';
|
||||
|
||||
ColumnCompiler_MSSQL.prototype.datetime = 'datetime2';
|
||||
ColumnCompiler_MSSQL.prototype.bool = 'bit';
|
||||
|
||||
module.exports = ColumnCompiler_MSSQL;
|
91
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js
generated
vendored
Normal file
91
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// MySQL Schema Compiler
|
||||
// -------
|
||||
const SchemaCompiler = require('../../../schema/compiler');
|
||||
|
||||
class SchemaCompiler_MSSQL extends SchemaCompiler {
|
||||
constructor(client, builder) {
|
||||
super(client, builder);
|
||||
}
|
||||
|
||||
dropTableIfExists(tableName) {
|
||||
const name = this.formatter.wrap(prefixedTableName(this.schema, tableName));
|
||||
this.pushQuery(
|
||||
`if object_id('${name}', 'U') is not null DROP TABLE ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
dropViewIfExists(viewName) {
|
||||
const name = this.formatter.wrap(prefixedTableName(this.schema, viewName));
|
||||
this.pushQuery(
|
||||
`if object_id('${name}', 'V') is not null DROP VIEW ${name}`
|
||||
);
|
||||
}
|
||||
|
||||
// Rename a table on the schema.
|
||||
renameTable(tableName, to) {
|
||||
this.pushQuery(
|
||||
`exec sp_rename ${this.client.parameter(
|
||||
prefixedTableName(this.schema, tableName),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.parameter(to, this.builder, this.bindingsHolder)}`
|
||||
);
|
||||
}
|
||||
|
||||
renameView(viewTable, to) {
|
||||
this.pushQuery(
|
||||
`exec sp_rename ${this.client.parameter(
|
||||
prefixedTableName(this.schema, viewTable),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.parameter(to, this.builder, this.bindingsHolder)}`
|
||||
);
|
||||
}
|
||||
|
||||
// Check whether a table exists on the query.
|
||||
hasTable(tableName) {
|
||||
const formattedTable = this.client.parameter(
|
||||
prefixedTableName(this.schema, tableName),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
);
|
||||
const bindings = [tableName];
|
||||
let sql =
|
||||
`SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ` +
|
||||
`WHERE TABLE_NAME = ${formattedTable}`;
|
||||
|
||||
if (this.schema) {
|
||||
sql += ' AND TABLE_SCHEMA = ?';
|
||||
bindings.push(this.schema);
|
||||
}
|
||||
|
||||
this.pushQuery({ sql, bindings, output: (resp) => resp.length > 0 });
|
||||
}
|
||||
|
||||
// Check whether a column exists on the schema.
|
||||
hasColumn(tableName, column) {
|
||||
const formattedColumn = this.client.parameter(
|
||||
column,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
);
|
||||
const formattedTable = this.client.parameter(
|
||||
this.formatter.wrap(prefixedTableName(this.schema, tableName)),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
);
|
||||
const sql =
|
||||
`select object_id from sys.columns ` +
|
||||
`where name = ${formattedColumn} ` +
|
||||
`and object_id = object_id(${formattedTable})`;
|
||||
this.pushQuery({ sql, output: (resp) => resp.length > 0 });
|
||||
}
|
||||
}
|
||||
|
||||
SchemaCompiler_MSSQL.prototype.dropTablePrefix = 'DROP TABLE ';
|
||||
|
||||
function prefixedTableName(prefix, table) {
|
||||
return prefix ? `${prefix}.${table}` : table;
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_MSSQL;
|
378
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js
generated
vendored
Normal file
378
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,378 @@
|
||||
/* eslint max-len:0 */
|
||||
|
||||
// MSSQL Table Builder & Compiler
|
||||
// -------
|
||||
const TableCompiler = require('../../../schema/tablecompiler');
|
||||
const helpers = require('../../../util/helpers');
|
||||
const { isObject } = require('../../../util/is');
|
||||
|
||||
// Table Compiler
|
||||
// ------
|
||||
|
||||
class TableCompiler_MSSQL extends TableCompiler {
|
||||
constructor(client, tableBuilder) {
|
||||
super(client, tableBuilder);
|
||||
}
|
||||
|
||||
createQuery(columns, ifNot, like) {
|
||||
let createStatement = ifNot
|
||||
? `if object_id('${this.tableName()}', 'U') is null `
|
||||
: '';
|
||||
|
||||
if (like) {
|
||||
// This query copy only columns and not all indexes and keys like other databases.
|
||||
createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`;
|
||||
} else {
|
||||
createStatement +=
|
||||
'CREATE TABLE ' +
|
||||
this.tableName() +
|
||||
(this._formatting ? ' (\n ' : ' (') +
|
||||
columns.sql.join(this._formatting ? ',\n ' : ', ') +
|
||||
this._addChecks() +
|
||||
')';
|
||||
}
|
||||
|
||||
this.pushQuery(createStatement);
|
||||
|
||||
if (this.single.comment) {
|
||||
this.comment(this.single.comment);
|
||||
}
|
||||
if (like) {
|
||||
this.addColumns(columns, this.addColumnsPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
comment(/** @type {string} */ comment) {
|
||||
if (!comment) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without server collation info.
|
||||
// When I checked in SQL Server 2019, the ctext column in sys.syscomments is defined as a varbinary(8000), so it doesn't even have its own defined collation.
|
||||
if (comment.length > 7500 / 2) {
|
||||
this.client.logger.warn(
|
||||
'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.'
|
||||
);
|
||||
}
|
||||
|
||||
// See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#f-adding-an-extended-property-to-a-table
|
||||
const value = this.formatter.escapingStringDelimiters(comment);
|
||||
const level0name = this.formatter.escapingStringDelimiters(
|
||||
this.schemaNameRaw || 'dbo'
|
||||
);
|
||||
const level1name = this.formatter.escapingStringDelimiters(
|
||||
this.tableNameRaw
|
||||
);
|
||||
const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}'`;
|
||||
const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', NULL, NULL))`;
|
||||
this.pushQuery(
|
||||
`IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compiles column add. Multiple columns need only one ADD clause (not one ADD per column) so core addColumns doesn't work. #1348
|
||||
addColumns(columns, prefix) {
|
||||
prefix = prefix || this.addColumnsPrefix;
|
||||
|
||||
if (columns.sql.length > 0) {
|
||||
this.pushQuery({
|
||||
sql:
|
||||
(this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
|
||||
this.tableName() +
|
||||
' ' +
|
||||
prefix +
|
||||
columns.sql.join(', '),
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
alterColumns(columns, colBuilder) {
|
||||
for (let i = 0, l = colBuilder.length; i < l; i++) {
|
||||
const builder = colBuilder[i];
|
||||
if (builder.modified.defaultTo) {
|
||||
const schema = this.schemaNameRaw || 'dbo';
|
||||
const baseQuery = `
|
||||
DECLARE @constraint varchar(100) = (SELECT default_constraints.name
|
||||
FROM sys.all_columns
|
||||
INNER JOIN sys.tables
|
||||
ON all_columns.object_id = tables.object_id
|
||||
INNER JOIN sys.schemas
|
||||
ON tables.schema_id = schemas.schema_id
|
||||
INNER JOIN sys.default_constraints
|
||||
ON all_columns.default_object_id = default_constraints.object_id
|
||||
WHERE schemas.name = '${schema}'
|
||||
AND tables.name = '${
|
||||
this.tableNameRaw
|
||||
}'
|
||||
AND all_columns.name = '${builder.getColumnName()}')
|
||||
|
||||
IF @constraint IS NOT NULL EXEC('ALTER TABLE ${
|
||||
this.tableNameRaw
|
||||
} DROP CONSTRAINT ' + @constraint)`;
|
||||
this.pushQuery(baseQuery);
|
||||
}
|
||||
}
|
||||
// in SQL server only one column can be altered at a time
|
||||
columns.sql.forEach((sql) => {
|
||||
this.pushQuery({
|
||||
sql:
|
||||
(this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
|
||||
this.tableName() +
|
||||
' ' +
|
||||
(this.lowerCase
|
||||
? this.alterColumnPrefix.toLowerCase()
|
||||
: this.alterColumnPrefix) +
|
||||
sql,
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Compiles column drop. Multiple columns need only one DROP clause (not one DROP per column) so core dropColumn doesn't work. #1348
|
||||
dropColumn() {
|
||||
const _this2 = this;
|
||||
const columns = helpers.normalizeArr.apply(null, arguments);
|
||||
const columnsArray = Array.isArray(columns) ? columns : [columns];
|
||||
const drops = columnsArray.map((column) => _this2.formatter.wrap(column));
|
||||
const schema = this.schemaNameRaw || 'dbo';
|
||||
|
||||
for (const column of columns) {
|
||||
const baseQuery = `
|
||||
DECLARE @constraint varchar(100) = (SELECT default_constraints.name
|
||||
FROM sys.all_columns
|
||||
INNER JOIN sys.tables
|
||||
ON all_columns.object_id = tables.object_id
|
||||
INNER JOIN sys.schemas
|
||||
ON tables.schema_id = schemas.schema_id
|
||||
INNER JOIN sys.default_constraints
|
||||
ON all_columns.default_object_id = default_constraints.object_id
|
||||
WHERE schemas.name = '${schema}'
|
||||
AND tables.name = '${this.tableNameRaw}'
|
||||
AND all_columns.name = '${column}')
|
||||
|
||||
IF @constraint IS NOT NULL EXEC('ALTER TABLE ${this.tableNameRaw} DROP CONSTRAINT ' + @constraint)`;
|
||||
this.pushQuery(baseQuery);
|
||||
}
|
||||
this.pushQuery(
|
||||
(this.lowerCase ? 'alter table ' : 'ALTER TABLE ') +
|
||||
this.tableName() +
|
||||
' ' +
|
||||
this.dropColumnPrefix +
|
||||
drops.join(', ')
|
||||
);
|
||||
}
|
||||
|
||||
changeType() {}
|
||||
|
||||
// Renames a column on the table.
|
||||
renameColumn(from, to) {
|
||||
this.pushQuery(
|
||||
`exec sp_rename ${this.client.parameter(
|
||||
this.tableName() + '.' + from,
|
||||
this.tableBuilder,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.parameter(
|
||||
to,
|
||||
this.tableBuilder,
|
||||
this.bindingsHolder
|
||||
)}, 'COLUMN'`
|
||||
);
|
||||
}
|
||||
|
||||
dropFKRefs(runner, refs) {
|
||||
const formatter = this.client.formatter(this.tableBuilder);
|
||||
return Promise.all(
|
||||
refs.map(function (ref) {
|
||||
const constraintName = formatter.wrap(ref.CONSTRAINT_NAME);
|
||||
const tableName = formatter.wrap(ref.TABLE_NAME);
|
||||
return runner.query({
|
||||
sql: `ALTER TABLE ${tableName} DROP CONSTRAINT ${constraintName}`,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
createFKRefs(runner, refs) {
|
||||
const formatter = this.client.formatter(this.tableBuilder);
|
||||
|
||||
return Promise.all(
|
||||
refs.map(function (ref) {
|
||||
const tableName = formatter.wrap(ref.TABLE_NAME);
|
||||
const keyName = formatter.wrap(ref.CONSTRAINT_NAME);
|
||||
const column = formatter.columnize(ref.COLUMN_NAME);
|
||||
const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME);
|
||||
const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME);
|
||||
const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`;
|
||||
const onDelete = ` ON DELETE ${ref.DELETE_RULE}`;
|
||||
|
||||
return runner.query({
|
||||
sql:
|
||||
`ALTER TABLE ${tableName} ADD CONSTRAINT ${keyName}` +
|
||||
' FOREIGN KEY (' +
|
||||
column +
|
||||
') REFERENCES ' +
|
||||
inTable +
|
||||
' (' +
|
||||
references +
|
||||
')' +
|
||||
onUpdate +
|
||||
onDelete,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
index(columns, indexName, options) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
|
||||
let predicate;
|
||||
if (isObject(options)) {
|
||||
({ predicate } = options);
|
||||
}
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: '';
|
||||
this.pushQuery(
|
||||
`CREATE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
||||
columns
|
||||
)})${predicateQuery}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a primary key.
|
||||
*
|
||||
* @param {undefined | string | string[]} columns
|
||||
* @param {string | {constraintName: string, deferrable?: 'not deferrable'|'deferred'|'immediate' }} constraintName
|
||||
*/
|
||||
primary(columns, constraintName) {
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`mssql: primary key constraint [${constraintName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
if (!this.forCreate) {
|
||||
this.pushQuery(
|
||||
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
|
||||
columns
|
||||
)})`
|
||||
);
|
||||
} else {
|
||||
this.pushQuery(
|
||||
`CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize(
|
||||
columns
|
||||
)})`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique index.
|
||||
*
|
||||
* @param {string | string[]} columns
|
||||
* @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false, predicate?: QueryBuilder }} indexName
|
||||
*/
|
||||
unique(columns, indexName) {
|
||||
/** @type {string | undefined} */
|
||||
let deferrable;
|
||||
let useConstraint = false;
|
||||
let predicate;
|
||||
if (isObject(indexName)) {
|
||||
({ indexName, deferrable, useConstraint, predicate } = indexName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`mssql: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
if (useConstraint && predicate) {
|
||||
throw new Error('mssql cannot create constraint with predicate');
|
||||
}
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
|
||||
if (!Array.isArray(columns)) {
|
||||
columns = [columns];
|
||||
}
|
||||
|
||||
if (useConstraint) {
|
||||
// mssql supports unique indexes and unique constraints.
|
||||
// unique indexes cannot be used with foreign key relationships hence unique constraints are used instead.
|
||||
this.pushQuery(
|
||||
`ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize(
|
||||
columns
|
||||
)})`
|
||||
);
|
||||
} else {
|
||||
// default to making unique index that allows null https://stackoverflow.com/a/767702/360060
|
||||
// to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: ' WHERE ' +
|
||||
columns
|
||||
.map((column) => this.formatter.columnize(column) + ' IS NOT NULL')
|
||||
.join(' AND ');
|
||||
this.pushQuery(
|
||||
`CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize(
|
||||
columns
|
||||
)})${predicateQuery}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Compile a drop index command.
|
||||
dropIndex(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
|
||||
}
|
||||
|
||||
// Compile a drop foreign key command.
|
||||
dropForeign(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('foreign', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${indexName}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compile a drop primary key command.
|
||||
dropPrimary(constraintName) {
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
this.pushQuery(
|
||||
`ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${constraintName}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compile a drop unique key command.
|
||||
dropUnique(column, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, column);
|
||||
this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`);
|
||||
}
|
||||
}
|
||||
|
||||
TableCompiler_MSSQL.prototype.createAlterTableMethods = ['foreign', 'primary'];
|
||||
TableCompiler_MSSQL.prototype.lowerCase = false;
|
||||
|
||||
TableCompiler_MSSQL.prototype.addColumnsPrefix = 'ADD ';
|
||||
TableCompiler_MSSQL.prototype.dropColumnPrefix = 'DROP COLUMN ';
|
||||
TableCompiler_MSSQL.prototype.alterColumnPrefix = 'ALTER COLUMN ';
|
||||
|
||||
module.exports = TableCompiler_MSSQL;
|
55
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js
generated
vendored
Normal file
55
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class ViewCompiler_MSSQL extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
|
||||
createQuery(columns, selectQuery, materialized, replace) {
|
||||
const createStatement = 'CREATE ' + (replace ? 'OR ALTER ' : '') + 'VIEW ';
|
||||
let sql = createStatement + this.viewName();
|
||||
|
||||
const columnList = columns
|
||||
? ' (' +
|
||||
columnize_(
|
||||
columns,
|
||||
this.viewBuilder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
')'
|
||||
: '';
|
||||
|
||||
sql += columnList;
|
||||
sql += ' AS ';
|
||||
sql += selectQuery.toString();
|
||||
this.pushQuery({
|
||||
sql,
|
||||
});
|
||||
}
|
||||
|
||||
renameColumn(from, to) {
|
||||
this.pushQuery(
|
||||
`exec sp_rename ${this.client.parameter(
|
||||
this.viewName() + '.' + from,
|
||||
this.viewBuilder,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.parameter(
|
||||
to,
|
||||
this.viewBuilder,
|
||||
this.bindingsHolder
|
||||
)}, 'COLUMN'`
|
||||
);
|
||||
}
|
||||
|
||||
createOrReplace() {
|
||||
this.createQuery(this.columns, this.selectQuery, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_MSSQL;
|
176
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/transaction.js
generated
vendored
Normal file
176
backend/apis/nodejs/node_modules/knex/lib/dialects/mssql/transaction.js
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
const Transaction = require('../../execution/transaction');
|
||||
const debug = require('debug')('knex:tx');
|
||||
|
||||
class Transaction_MSSQL extends Transaction {
|
||||
begin(/** @type {import('tedious').Connection} */ conn) {
|
||||
debug('transaction::begin id=%s', this.txid);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.beginTransaction(
|
||||
(err) => {
|
||||
if (err) {
|
||||
debug(
|
||||
'transaction::begin error id=%s message=%s',
|
||||
this.txid,
|
||||
err.message
|
||||
);
|
||||
return reject(err);
|
||||
}
|
||||
resolve();
|
||||
},
|
||||
this.outerTx ? this.txid : undefined,
|
||||
nameToIsolationLevelEnum(this.isolationLevel)
|
||||
);
|
||||
}).then(this._resolver, this._rejecter);
|
||||
}
|
||||
|
||||
savepoint(conn) {
|
||||
debug('transaction::savepoint id=%s', this.txid);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.saveTransaction(
|
||||
(err) => {
|
||||
if (err) {
|
||||
debug(
|
||||
'transaction::savepoint id=%s message=%s',
|
||||
this.txid,
|
||||
err.message
|
||||
);
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
this.trxClient.emit('query', {
|
||||
__knexUid: this.trxClient.__knexUid,
|
||||
__knexTxId: this.trxClient.__knexTxId,
|
||||
autogenerated: true,
|
||||
sql: this.outerTx
|
||||
? `SAVE TRANSACTION [${this.txid}]`
|
||||
: `SAVE TRANSACTION`,
|
||||
});
|
||||
resolve();
|
||||
},
|
||||
this.outerTx ? this.txid : undefined
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
commit(conn, value) {
|
||||
debug('transaction::commit id=%s', this.txid);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
conn.commitTransaction(
|
||||
(err) => {
|
||||
if (err) {
|
||||
debug(
|
||||
'transaction::commit error id=%s message=%s',
|
||||
this.txid,
|
||||
err.message
|
||||
);
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
this._completed = true;
|
||||
resolve(value);
|
||||
},
|
||||
this.outerTx ? this.txid : undefined
|
||||
);
|
||||
}).then(() => this._resolver(value), this._rejecter);
|
||||
}
|
||||
|
||||
release(conn, value) {
|
||||
return this._resolver(value);
|
||||
}
|
||||
|
||||
rollback(conn, error) {
|
||||
this._completed = true;
|
||||
debug('transaction::rollback id=%s', this.txid);
|
||||
|
||||
return new Promise((_resolve, reject) => {
|
||||
if (!conn.inTransaction) {
|
||||
return reject(
|
||||
error || new Error('Transaction rejected with non-error: undefined')
|
||||
);
|
||||
}
|
||||
|
||||
if (conn.state.name !== 'LoggedIn') {
|
||||
return reject(
|
||||
new Error(
|
||||
"Can't rollback transaction. There is a request in progress"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
conn.rollbackTransaction(
|
||||
(err) => {
|
||||
if (err) {
|
||||
debug(
|
||||
'transaction::rollback error id=%s message=%s',
|
||||
this.txid,
|
||||
err.message
|
||||
);
|
||||
}
|
||||
|
||||
reject(
|
||||
err ||
|
||||
error ||
|
||||
new Error('Transaction rejected with non-error: undefined')
|
||||
);
|
||||
},
|
||||
this.outerTx ? this.txid : undefined
|
||||
);
|
||||
}).catch((err) => {
|
||||
if (!error && this.doNotRejectOnRollback) {
|
||||
this._resolver();
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
try {
|
||||
err.originalError = error;
|
||||
} catch (_err) {
|
||||
// This is to handle https://github.com/knex/knex/issues/4128
|
||||
}
|
||||
}
|
||||
this._rejecter(err);
|
||||
});
|
||||
}
|
||||
|
||||
rollbackTo(conn, error) {
|
||||
return this.rollback(conn, error).then(
|
||||
() =>
|
||||
void this.trxClient.emit('query', {
|
||||
__knexUid: this.trxClient.__knexUid,
|
||||
__knexTxId: this.trxClient.__knexTxId,
|
||||
autogenerated: true,
|
||||
sql: `ROLLBACK TRANSACTION`,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction_MSSQL;
|
||||
|
||||
function nameToIsolationLevelEnum(level) {
|
||||
if (!level) return;
|
||||
level = level.toUpperCase().replace(' ', '_');
|
||||
const knownEnum = isolationEnum[level];
|
||||
if (!knownEnum) {
|
||||
throw new Error(
|
||||
`Unknown Isolation level, was expecting one of: ${JSON.stringify(
|
||||
humanReadableKeys
|
||||
)}`
|
||||
);
|
||||
}
|
||||
return knownEnum;
|
||||
}
|
||||
|
||||
// Based on: https://github.com/tediousjs/node-mssql/blob/master/lib/isolationlevel.js
|
||||
const isolationEnum = {
|
||||
READ_UNCOMMITTED: 0x01,
|
||||
READ_COMMITTED: 0x02,
|
||||
REPEATABLE_READ: 0x03,
|
||||
SERIALIZABLE: 0x04,
|
||||
SNAPSHOT: 0x05,
|
||||
};
|
||||
const humanReadableKeys = Object.keys(isolationEnum).map((key) =>
|
||||
key.toLowerCase().replace('_', ' ')
|
||||
);
|
206
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/index.js
generated
vendored
Normal file
206
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/index.js
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
// MySQL Client
|
||||
// -------
|
||||
const defer = require('lodash/defer');
|
||||
const map = require('lodash/map');
|
||||
const { promisify } = require('util');
|
||||
const Client = require('../../client');
|
||||
|
||||
const Transaction = require('./transaction');
|
||||
const QueryBuilder = require('./query/mysql-querybuilder');
|
||||
const QueryCompiler = require('./query/mysql-querycompiler');
|
||||
const SchemaCompiler = require('./schema/mysql-compiler');
|
||||
const TableCompiler = require('./schema/mysql-tablecompiler');
|
||||
const ColumnCompiler = require('./schema/mysql-columncompiler');
|
||||
|
||||
const { makeEscape } = require('../../util/string');
|
||||
const ViewCompiler = require('./schema/mysql-viewcompiler');
|
||||
const ViewBuilder = require('./schema/mysql-viewbuilder');
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler"
|
||||
// objects, which extend the base 'lib/query/builder' and
|
||||
// 'lib/query/compiler', respectively.
|
||||
class Client_MySQL extends Client {
|
||||
_driver() {
|
||||
return require('mysql');
|
||||
}
|
||||
|
||||
queryBuilder() {
|
||||
return new QueryBuilder(this);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
wrapIdentifierImpl(value) {
|
||||
return value !== '*' ? `\`${value.replace(/`/g, '``')}\`` : '*';
|
||||
}
|
||||
|
||||
// Get a raw connection, called by the `pool` whenever a new
|
||||
// connection needs to be added to the pool.
|
||||
acquireRawConnection() {
|
||||
return new Promise((resolver, rejecter) => {
|
||||
const connection = this.driver.createConnection(this.connectionSettings);
|
||||
connection.on('error', (err) => {
|
||||
connection.__knex__disposed = err;
|
||||
});
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
// if connection is rejected, remove listener that was registered above...
|
||||
connection.removeAllListeners();
|
||||
return rejecter(err);
|
||||
}
|
||||
resolver(connection);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool
|
||||
// when a connection times out or the pool is shutdown.
|
||||
async destroyRawConnection(connection) {
|
||||
try {
|
||||
const end = promisify((cb) => connection.end(cb));
|
||||
return await end();
|
||||
} catch (err) {
|
||||
connection.__knex__disposed = err;
|
||||
} finally {
|
||||
// see discussion https://github.com/knex/knex/pull/3483
|
||||
defer(() => connection.removeAllListeners());
|
||||
}
|
||||
}
|
||||
|
||||
validateConnection(connection) {
|
||||
return (
|
||||
connection.state === 'connected' || connection.state === 'authenticated'
|
||||
);
|
||||
}
|
||||
|
||||
// Grab a connection, run the query via the MySQL streaming interface,
|
||||
// and pass that through to the stream we've sent back to the client.
|
||||
_stream(connection, obj, stream, options) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
options = options || {};
|
||||
const queryOptions = Object.assign({ sql: obj.sql }, obj.options);
|
||||
return new Promise((resolver, rejecter) => {
|
||||
stream.on('error', rejecter);
|
||||
stream.on('end', resolver);
|
||||
const queryStream = connection
|
||||
.query(queryOptions, obj.bindings)
|
||||
.stream(options);
|
||||
|
||||
queryStream.on('error', (err) => {
|
||||
rejecter(err);
|
||||
stream.emit('error', err);
|
||||
});
|
||||
|
||||
queryStream.pipe(stream);
|
||||
});
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings
|
||||
// and any other necessary prep work.
|
||||
_query(connection, obj) {
|
||||
if (!obj || typeof obj === 'string') obj = { sql: obj };
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
if (!obj.sql) {
|
||||
resolver();
|
||||
return;
|
||||
}
|
||||
const queryOptions = Object.assign({ sql: obj.sql }, obj.options);
|
||||
connection.query(
|
||||
queryOptions,
|
||||
obj.bindings,
|
||||
function (err, rows, fields) {
|
||||
if (err) return rejecter(err);
|
||||
obj.response = [rows, fields];
|
||||
resolver(obj);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Process the response as returned from the query.
|
||||
processResponse(obj, runner) {
|
||||
if (obj == null) return;
|
||||
const { response } = obj;
|
||||
const { method } = obj;
|
||||
const rows = response[0];
|
||||
const fields = response[1];
|
||||
if (obj.output) return obj.output.call(runner, rows, fields);
|
||||
switch (method) {
|
||||
case 'select':
|
||||
return rows;
|
||||
case 'first':
|
||||
return rows[0];
|
||||
case 'pluck':
|
||||
return map(rows, obj.pluck);
|
||||
case 'insert':
|
||||
return [rows.insertId];
|
||||
case 'del':
|
||||
case 'update':
|
||||
case 'counter':
|
||||
return rows.affectedRows;
|
||||
default:
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
async cancelQuery(connectionToKill) {
|
||||
const conn = await this.acquireRawConnection();
|
||||
try {
|
||||
return await this._wrappedCancelQueryCall(conn, connectionToKill);
|
||||
} finally {
|
||||
await this.destroyRawConnection(conn);
|
||||
if (conn.__knex__disposed) {
|
||||
this.logger.warn(`Connection Error: ${conn.__knex__disposed}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_wrappedCancelQueryCall(conn, connectionToKill) {
|
||||
return this._query(conn, {
|
||||
sql: 'KILL QUERY ?',
|
||||
bindings: [connectionToKill.threadId],
|
||||
options: {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_MySQL.prototype, {
|
||||
dialect: 'mysql',
|
||||
|
||||
driverName: 'mysql',
|
||||
|
||||
_escapeBinding: makeEscape(),
|
||||
|
||||
canCancelQuery: true,
|
||||
});
|
||||
|
||||
module.exports = Client_MySQL;
|
14
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js
generated
vendored
Normal file
14
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
const QueryBuilder = require('../../../query/querybuilder');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
|
||||
module.exports = class QueryBuilder_MySQL extends QueryBuilder {
|
||||
upsert(values, returning, options) {
|
||||
this._method = 'upsert';
|
||||
if (!isEmpty(returning)) {
|
||||
this.returning(returning, options);
|
||||
}
|
||||
|
||||
this._single.upsert = values;
|
||||
return this;
|
||||
}
|
||||
};
|
292
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js
generated
vendored
Normal file
292
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
// MySQL Query Compiler
|
||||
// ------
|
||||
const assert = require('assert');
|
||||
const identity = require('lodash/identity');
|
||||
const isPlainObject = require('lodash/isPlainObject');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
const { wrapAsIdentifier } = require('../../../formatter/formatterUtils');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
wrap: wrap_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
const isPlainObjectOrArray = (value) =>
|
||||
isPlainObject(value) || Array.isArray(value);
|
||||
|
||||
class QueryCompiler_MySQL extends QueryCompiler {
|
||||
constructor(client, builder, formatter) {
|
||||
super(client, builder, formatter);
|
||||
|
||||
const { returning } = this.single;
|
||||
if (returning) {
|
||||
this.client.logger.warn(
|
||||
'.returning() is not supported by mysql and will not have any effect.'
|
||||
);
|
||||
}
|
||||
|
||||
this._emptyInsertValue = '() values ()';
|
||||
}
|
||||
// Compiles an `delete` allowing comments
|
||||
del() {
|
||||
const sql = super.del();
|
||||
if (sql === '') return sql;
|
||||
const comments = this.comments();
|
||||
return (comments === '' ? '' : comments + ' ') + sql;
|
||||
}
|
||||
|
||||
// Compiles an `insert` query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
let sql = super.insert();
|
||||
if (sql === '') return sql;
|
||||
const comments = this.comments();
|
||||
sql = (comments === '' ? '' : comments + ' ') + sql;
|
||||
|
||||
const { ignore, merge, insert } = this.single;
|
||||
if (ignore) sql = sql.replace('insert into', 'insert ignore into');
|
||||
if (merge) {
|
||||
sql += this._merge(merge.updates, insert);
|
||||
const wheres = this.where();
|
||||
if (wheres) {
|
||||
throw new Error(
|
||||
'.onConflict().merge().where() is not supported for mysql'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
upsert() {
|
||||
const upsertValues = this.single.upsert || [];
|
||||
const sql = this.with() + `replace into ${this.tableName} `;
|
||||
const body = this._insertBody(upsertValues);
|
||||
return body === '' ? '' : sql + body;
|
||||
}
|
||||
|
||||
// Compiles merge for onConflict, allowing for different merge strategies
|
||||
_merge(updates, insert) {
|
||||
const sql = ' on duplicate key update ';
|
||||
if (updates && Array.isArray(updates)) {
|
||||
// update subset of columns
|
||||
return (
|
||||
sql +
|
||||
updates
|
||||
.map((column) =>
|
||||
wrapAsIdentifier(column, this.formatter.builder, this.client)
|
||||
)
|
||||
.map((column) => `${column} = values(${column})`)
|
||||
.join(', ')
|
||||
);
|
||||
} else if (updates && typeof updates === 'object') {
|
||||
const updateData = this._prepUpdate(updates);
|
||||
return sql + updateData.join(',');
|
||||
} else {
|
||||
const insertData = this._prepInsert(insert);
|
||||
if (typeof insertData === 'string') {
|
||||
throw new Error(
|
||||
'If using merge with a raw insert query, then updates must be provided'
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
sql +
|
||||
insertData.columns
|
||||
.map((column) => wrapAsIdentifier(column, this.builder, this.client))
|
||||
.map((column) => `${column} = values(${column})`)
|
||||
.join(', ')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update method, including joins, wheres, order & limits.
|
||||
update() {
|
||||
const comments = this.comments();
|
||||
const withSQL = this.with();
|
||||
const join = this.join();
|
||||
const updates = this._prepUpdate(this.single.update);
|
||||
const where = this.where();
|
||||
const order = this.order();
|
||||
const limit = this.limit();
|
||||
return (
|
||||
(comments === '' ? '' : comments + ' ') +
|
||||
withSQL +
|
||||
`update ${this.tableName}` +
|
||||
(join ? ` ${join}` : '') +
|
||||
' set ' +
|
||||
updates.join(', ') +
|
||||
(where ? ` ${where}` : '') +
|
||||
(order ? ` ${order}` : '') +
|
||||
(limit ? ` ${limit}` : '')
|
||||
);
|
||||
}
|
||||
|
||||
forUpdate() {
|
||||
return 'for update';
|
||||
}
|
||||
|
||||
forShare() {
|
||||
return 'lock in share mode';
|
||||
}
|
||||
|
||||
// Only supported on MySQL 8.0+
|
||||
skipLocked() {
|
||||
return 'skip locked';
|
||||
}
|
||||
|
||||
// Supported on MySQL 8.0+ and MariaDB 10.3.0+
|
||||
noWait() {
|
||||
return 'nowait';
|
||||
}
|
||||
|
||||
// Compiles a `columnInfo` query.
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
return {
|
||||
sql: 'select * from information_schema.columns where table_name = ? and table_schema = ?',
|
||||
bindings: [table, this.client.database()],
|
||||
output(resp) {
|
||||
const out = resp.reduce(function (columns, val) {
|
||||
columns[val.COLUMN_NAME] = {
|
||||
defaultValue:
|
||||
val.COLUMN_DEFAULT === 'NULL' ? null : val.COLUMN_DEFAULT,
|
||||
type: val.DATA_TYPE,
|
||||
maxLength: val.CHARACTER_MAXIMUM_LENGTH,
|
||||
nullable: val.IS_NULLABLE === 'YES',
|
||||
};
|
||||
return columns;
|
||||
}, {});
|
||||
return (column && out[column]) || out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
limit() {
|
||||
const noLimit = !this.single.limit && this.single.limit !== 0;
|
||||
if (noLimit && !this.single.offset) return '';
|
||||
|
||||
// Workaround for offset only.
|
||||
// see: http://stackoverflow.com/questions/255517/mysql-offset-infinite-rows
|
||||
const limit =
|
||||
this.single.offset && noLimit
|
||||
? '18446744073709551615'
|
||||
: this._getValueOrParameterFromAttribute('limit');
|
||||
return `limit ${limit}`;
|
||||
}
|
||||
|
||||
whereBasic(statement) {
|
||||
assert(
|
||||
!isPlainObjectOrArray(statement.value),
|
||||
'The values in where clause must not be object or array.'
|
||||
);
|
||||
|
||||
return super.whereBasic(statement);
|
||||
}
|
||||
|
||||
whereRaw(statement) {
|
||||
assert(
|
||||
isEmpty(statement.value.bindings) ||
|
||||
!Object.values(statement.value.bindings).some(isPlainObjectOrArray),
|
||||
'The values in where clause must not be object or array.'
|
||||
);
|
||||
|
||||
return super.whereRaw(statement);
|
||||
}
|
||||
|
||||
whereLike(statement) {
|
||||
return `${this._columnClause(statement)} ${this._not(
|
||||
statement,
|
||||
'like '
|
||||
)}${this._valueClause(statement)} COLLATE utf8_bin`;
|
||||
}
|
||||
|
||||
whereILike(statement) {
|
||||
return `${this._columnClause(statement)} ${this._not(
|
||||
statement,
|
||||
'like '
|
||||
)}${this._valueClause(statement)}`;
|
||||
}
|
||||
|
||||
// Json functions
|
||||
jsonExtract(params) {
|
||||
return this._jsonExtract(['json_extract', 'json_unquote'], params);
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
return this._jsonSet('json_set', params);
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
return this._jsonSet('json_insert', params);
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
const jsonCol = `json_remove(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)},${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
return params.alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
||||
: jsonCol;
|
||||
}
|
||||
|
||||
whereJsonObject(statement) {
|
||||
return this._not(
|
||||
statement,
|
||||
`json_contains(${this._columnClause(statement)}, ${this._jsonValueClause(
|
||||
statement
|
||||
)})`
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
return this._whereJsonPath('json_extract', statement);
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
return this._not(
|
||||
statement,
|
||||
`json_contains(${wrap_(
|
||||
statement.column,
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)},${this._jsonValueClause(statement)})`
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
return this._not(
|
||||
statement,
|
||||
`json_contains(${this._jsonValueClause(statement)},${wrap_(
|
||||
statement.column,
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)})`
|
||||
);
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('json_extract', clause);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the QueryBuilder & QueryCompiler on the client object,
|
||||
// in case anyone wants to modify things to suit their own purposes.
|
||||
module.exports = QueryCompiler_MySQL;
|
193
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js
generated
vendored
Normal file
193
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
// MySQL Column Compiler
|
||||
// -------
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
const { isObject } = require('../../../util/is');
|
||||
const { toNumber } = require('../../../util/helpers');
|
||||
|
||||
const commentEscapeRegex = /(?<!\\)'/g;
|
||||
|
||||
class ColumnCompiler_MySQL extends ColumnCompiler {
|
||||
constructor(client, tableCompiler, columnBuilder) {
|
||||
super(client, tableCompiler, columnBuilder);
|
||||
this.modifiers = [
|
||||
'unsigned',
|
||||
'nullable',
|
||||
'defaultTo',
|
||||
'comment',
|
||||
'collate',
|
||||
'first',
|
||||
'after',
|
||||
];
|
||||
this._addCheckModifiers();
|
||||
}
|
||||
|
||||
// Types
|
||||
// ------
|
||||
|
||||
double(precision, scale) {
|
||||
if (!precision) return 'double';
|
||||
return `double(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`;
|
||||
}
|
||||
|
||||
integer(length) {
|
||||
length = length ? `(${toNumber(length, 11)})` : '';
|
||||
return `int${length}`;
|
||||
}
|
||||
|
||||
tinyint(length) {
|
||||
length = length ? `(${toNumber(length, 1)})` : '';
|
||||
return `tinyint${length}`;
|
||||
}
|
||||
|
||||
text(column) {
|
||||
switch (column) {
|
||||
case 'medium':
|
||||
case 'mediumtext':
|
||||
return 'mediumtext';
|
||||
case 'long':
|
||||
case 'longtext':
|
||||
return 'longtext';
|
||||
default:
|
||||
return 'text';
|
||||
}
|
||||
}
|
||||
|
||||
mediumtext() {
|
||||
return this.text('medium');
|
||||
}
|
||||
|
||||
longtext() {
|
||||
return this.text('long');
|
||||
}
|
||||
|
||||
enu(allowed) {
|
||||
return `enum('${allowed.join("', '")}')`;
|
||||
}
|
||||
|
||||
datetime(precision) {
|
||||
if (isObject(precision)) {
|
||||
({ precision } = precision);
|
||||
}
|
||||
|
||||
return typeof precision === 'number'
|
||||
? `datetime(${precision})`
|
||||
: 'datetime';
|
||||
}
|
||||
|
||||
timestamp(precision) {
|
||||
if (isObject(precision)) {
|
||||
({ precision } = precision);
|
||||
}
|
||||
|
||||
return typeof precision === 'number'
|
||||
? `timestamp(${precision})`
|
||||
: 'timestamp';
|
||||
}
|
||||
|
||||
time(precision) {
|
||||
if (isObject(precision)) {
|
||||
({ precision } = precision);
|
||||
}
|
||||
|
||||
return typeof precision === 'number' ? `time(${precision})` : 'time';
|
||||
}
|
||||
|
||||
bit(length) {
|
||||
return length ? `bit(${toNumber(length)})` : 'bit';
|
||||
}
|
||||
|
||||
binary(length) {
|
||||
return length ? `varbinary(${toNumber(length)})` : 'blob';
|
||||
}
|
||||
|
||||
json() {
|
||||
return 'json';
|
||||
}
|
||||
|
||||
jsonb() {
|
||||
return 'json';
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
// ------
|
||||
|
||||
defaultTo(value) {
|
||||
// MySQL defaults to null by default, but breaks down if you pass it explicitly
|
||||
// Note that in MySQL versions up to 5.7, logic related to updating
|
||||
// timestamps when no explicit value is passed is quite insane - https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp
|
||||
if (value === null || value === undefined) {
|
||||
return;
|
||||
}
|
||||
if ((this.type === 'json' || this.type === 'jsonb') && isObject(value)) {
|
||||
// Default value for json will work only it is an expression
|
||||
return `default ('${JSON.stringify(value)}')`;
|
||||
}
|
||||
const defaultVal = super.defaultTo.apply(this, arguments);
|
||||
if (this.type !== 'blob' && this.type.indexOf('text') === -1) {
|
||||
return defaultVal;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
unsigned() {
|
||||
return 'unsigned';
|
||||
}
|
||||
|
||||
comment(comment) {
|
||||
if (comment && comment.length > 255) {
|
||||
this.client.logger.warn(
|
||||
'Your comment is longer than the max comment length for MySQL'
|
||||
);
|
||||
}
|
||||
return comment && `comment '${comment.replace(commentEscapeRegex, "\\'")}'`;
|
||||
}
|
||||
|
||||
first() {
|
||||
return 'first';
|
||||
}
|
||||
|
||||
after(column) {
|
||||
return `after ${this.formatter.wrap(column)}`;
|
||||
}
|
||||
|
||||
collate(collation) {
|
||||
return collation && `collate '${collation}'`;
|
||||
}
|
||||
|
||||
checkRegex(regex, constraintName) {
|
||||
return this._check(
|
||||
`${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)} REGEXP ${this.client._escapeBinding(regex)}`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
increments(options = { primaryKey: true }) {
|
||||
return (
|
||||
'int unsigned not null' +
|
||||
// In MySQL autoincrement are always a primary key. If you already have a primary key, we
|
||||
// initialize this column as classic int column then modify it later in table compiler
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options)
|
||||
? ' auto_increment primary key'
|
||||
: '')
|
||||
);
|
||||
}
|
||||
|
||||
bigincrements(options = { primaryKey: true }) {
|
||||
return (
|
||||
'bigint unsigned not null' +
|
||||
// In MySQL autoincrement are always a primary key. If you already have a primary key, we
|
||||
// initialize this column as classic int column then modify it later in table compiler
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options)
|
||||
? ' auto_increment primary key'
|
||||
: '')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_MySQL.prototype.bigint = 'bigint';
|
||||
ColumnCompiler_MySQL.prototype.mediumint = 'mediumint';
|
||||
ColumnCompiler_MySQL.prototype.smallint = 'smallint';
|
||||
|
||||
module.exports = ColumnCompiler_MySQL;
|
60
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js
generated
vendored
Normal file
60
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
// MySQL Schema Compiler
|
||||
// -------
|
||||
const SchemaCompiler = require('../../../schema/compiler');
|
||||
|
||||
class SchemaCompiler_MySQL extends SchemaCompiler {
|
||||
constructor(client, builder) {
|
||||
super(client, builder);
|
||||
}
|
||||
|
||||
// Rename a table on the schema.
|
||||
renameTable(tableName, to) {
|
||||
this.pushQuery(
|
||||
`rename table ${this.formatter.wrap(tableName)} to ${this.formatter.wrap(
|
||||
to
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
renameView(from, to) {
|
||||
this.renameTable(from, to);
|
||||
}
|
||||
|
||||
// Check whether a table exists on the query.
|
||||
hasTable(tableName) {
|
||||
let sql = 'select * from information_schema.tables where table_name = ?';
|
||||
const bindings = [tableName];
|
||||
|
||||
if (this.schema) {
|
||||
sql += ' and table_schema = ?';
|
||||
bindings.push(this.schema);
|
||||
} else {
|
||||
sql += ' and table_schema = database()';
|
||||
}
|
||||
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings,
|
||||
output: function output(resp) {
|
||||
return resp.length > 0;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Check whether a column exists on the schema.
|
||||
hasColumn(tableName, column) {
|
||||
this.pushQuery({
|
||||
sql: `show columns from ${this.formatter.wrap(tableName)}`,
|
||||
output(resp) {
|
||||
return resp.some((row) => {
|
||||
return (
|
||||
this.client.wrapIdentifier(row.Field.toLowerCase()) ===
|
||||
this.client.wrapIdentifier(column.toLowerCase())
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_MySQL;
|
405
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js
generated
vendored
Normal file
405
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,405 @@
|
||||
/* eslint max-len:0*/
|
||||
|
||||
// MySQL Table Builder & Compiler
|
||||
// -------
|
||||
const TableCompiler = require('../../../schema/tablecompiler');
|
||||
const { isObject, isString } = require('../../../util/is');
|
||||
|
||||
// Table Compiler
|
||||
// ------
|
||||
|
||||
class TableCompiler_MySQL extends TableCompiler {
|
||||
constructor(client, tableBuilder) {
|
||||
super(client, tableBuilder);
|
||||
}
|
||||
|
||||
createQuery(columns, ifNot, like) {
|
||||
const createStatement = ifNot
|
||||
? 'create table if not exists '
|
||||
: 'create table ';
|
||||
const { client } = this;
|
||||
let conn = {};
|
||||
let columnsSql = ' (' + columns.sql.join(', ');
|
||||
|
||||
columnsSql += this.primaryKeys() || '';
|
||||
columnsSql += this._addChecks();
|
||||
columnsSql += ')';
|
||||
|
||||
let sql =
|
||||
createStatement +
|
||||
this.tableName() +
|
||||
(like && this.tableNameLike()
|
||||
? ' like ' + this.tableNameLike()
|
||||
: columnsSql);
|
||||
|
||||
// Check if the connection settings are set.
|
||||
if (client.connectionSettings) {
|
||||
conn = client.connectionSettings;
|
||||
}
|
||||
|
||||
const charset = this.single.charset || conn.charset || '';
|
||||
const collation = this.single.collate || conn.collate || '';
|
||||
const engine = this.single.engine || '';
|
||||
|
||||
if (charset && !like) sql += ` default character set ${charset}`;
|
||||
if (collation) sql += ` collate ${collation}`;
|
||||
if (engine) sql += ` engine = ${engine}`;
|
||||
|
||||
if (this.single.comment) {
|
||||
const comment = this.single.comment || '';
|
||||
const MAX_COMMENT_LENGTH = 1024;
|
||||
if (comment.length > MAX_COMMENT_LENGTH)
|
||||
this.client.logger.warn(
|
||||
`The max length for a table comment is ${MAX_COMMENT_LENGTH} characters`
|
||||
);
|
||||
sql += ` comment = '${comment}'`;
|
||||
}
|
||||
|
||||
this.pushQuery(sql);
|
||||
if (like) {
|
||||
this.addColumns(columns, this.addColumnsPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
// Compiles the comment on the table.
|
||||
comment(comment) {
|
||||
this.pushQuery(`alter table ${this.tableName()} comment = '${comment}'`);
|
||||
}
|
||||
|
||||
changeType() {
|
||||
// alter table + table + ' modify ' + wrapped + '// type';
|
||||
}
|
||||
|
||||
// Renames a column on the table.
|
||||
renameColumn(from, to) {
|
||||
const compiler = this;
|
||||
const table = this.tableName();
|
||||
const wrapped = this.formatter.wrap(from) + ' ' + this.formatter.wrap(to);
|
||||
|
||||
this.pushQuery({
|
||||
sql:
|
||||
`show full fields from ${table} where field = ` +
|
||||
this.client.parameter(from, this.tableBuilder, this.bindingsHolder),
|
||||
output(resp) {
|
||||
const column = resp[0];
|
||||
const runner = this;
|
||||
return compiler.getFKRefs(runner).then(([refs]) =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!refs.length) {
|
||||
resolve();
|
||||
}
|
||||
resolve(compiler.dropFKRefs(runner, refs));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
let sql = `alter table ${table} change ${wrapped} ${column.Type}`;
|
||||
|
||||
if (String(column.Null).toUpperCase() !== 'YES') {
|
||||
sql += ` NOT NULL`;
|
||||
} else {
|
||||
// This doesn't matter for most cases except Timestamp, where this is important
|
||||
sql += ` NULL`;
|
||||
}
|
||||
if (column.Default !== void 0 && column.Default !== null) {
|
||||
sql += ` DEFAULT '${column.Default}'`;
|
||||
}
|
||||
if (column.Collation !== void 0 && column.Collation !== null) {
|
||||
sql += ` COLLATE '${column.Collation}'`;
|
||||
}
|
||||
// Add back the auto increment if the column it, fix issue #2767
|
||||
if (column.Extra == 'auto_increment') {
|
||||
sql += ` AUTO_INCREMENT`;
|
||||
}
|
||||
|
||||
return runner.query({
|
||||
sql,
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
if (!refs.length) {
|
||||
return;
|
||||
}
|
||||
return compiler.createFKRefs(
|
||||
runner,
|
||||
refs.map(function (ref) {
|
||||
if (ref.REFERENCED_COLUMN_NAME === from) {
|
||||
ref.REFERENCED_COLUMN_NAME = to;
|
||||
}
|
||||
if (ref.COLUMN_NAME === from) {
|
||||
ref.COLUMN_NAME = to;
|
||||
}
|
||||
return ref;
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
primaryKeys() {
|
||||
const pks = (this.grouped.alterTable || []).filter(
|
||||
(k) => k.method === 'primary'
|
||||
);
|
||||
if (pks.length > 0 && pks[0].args.length > 0) {
|
||||
const columns = pks[0].args[0];
|
||||
let constraintName = pks[0].args[1] || '';
|
||||
if (constraintName) {
|
||||
constraintName = ' constraint ' + this.formatter.wrap(constraintName);
|
||||
}
|
||||
|
||||
if (this.grouped.columns) {
|
||||
const incrementsCols = this._getIncrementsColumnNames();
|
||||
if (incrementsCols.length) {
|
||||
incrementsCols.forEach((c) => {
|
||||
if (!columns.includes(c)) {
|
||||
columns.unshift(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
const bigIncrementsCols = this._getBigIncrementsColumnNames();
|
||||
if (bigIncrementsCols.length) {
|
||||
bigIncrementsCols.forEach((c) => {
|
||||
if (!columns.includes(c)) {
|
||||
columns.unshift(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return `,${constraintName} primary key (${this.formatter.columnize(
|
||||
columns
|
||||
)})`;
|
||||
}
|
||||
}
|
||||
|
||||
getFKRefs(runner) {
|
||||
const bindingsHolder = {
|
||||
bindings: [],
|
||||
};
|
||||
|
||||
const sql =
|
||||
'SELECT KCU.CONSTRAINT_NAME, KCU.TABLE_NAME, KCU.COLUMN_NAME, ' +
|
||||
' KCU.REFERENCED_TABLE_NAME, KCU.REFERENCED_COLUMN_NAME, ' +
|
||||
' RC.UPDATE_RULE, RC.DELETE_RULE ' +
|
||||
'FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU ' +
|
||||
'JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ' +
|
||||
' USING(CONSTRAINT_NAME)' +
|
||||
'WHERE KCU.REFERENCED_TABLE_NAME = ' +
|
||||
this.client.parameter(
|
||||
this.tableNameRaw,
|
||||
this.tableBuilder,
|
||||
bindingsHolder
|
||||
) +
|
||||
' ' +
|
||||
' AND KCU.CONSTRAINT_SCHEMA = ' +
|
||||
this.client.parameter(
|
||||
this.client.database(),
|
||||
this.tableBuilder,
|
||||
bindingsHolder
|
||||
) +
|
||||
' ' +
|
||||
' AND RC.CONSTRAINT_SCHEMA = ' +
|
||||
this.client.parameter(
|
||||
this.client.database(),
|
||||
this.tableBuilder,
|
||||
bindingsHolder
|
||||
);
|
||||
|
||||
return runner.query({
|
||||
sql,
|
||||
bindings: bindingsHolder.bindings,
|
||||
});
|
||||
}
|
||||
|
||||
dropFKRefs(runner, refs) {
|
||||
const formatter = this.client.formatter(this.tableBuilder);
|
||||
|
||||
return Promise.all(
|
||||
refs.map(function (ref) {
|
||||
const constraintName = formatter.wrap(ref.CONSTRAINT_NAME);
|
||||
const tableName = formatter.wrap(ref.TABLE_NAME);
|
||||
return runner.query({
|
||||
sql: `alter table ${tableName} drop foreign key ${constraintName}`,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
createFKRefs(runner, refs) {
|
||||
const formatter = this.client.formatter(this.tableBuilder);
|
||||
|
||||
return Promise.all(
|
||||
refs.map(function (ref) {
|
||||
const tableName = formatter.wrap(ref.TABLE_NAME);
|
||||
const keyName = formatter.wrap(ref.CONSTRAINT_NAME);
|
||||
const column = formatter.columnize(ref.COLUMN_NAME);
|
||||
const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME);
|
||||
const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME);
|
||||
const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`;
|
||||
const onDelete = ` ON DELETE ${ref.DELETE_RULE}`;
|
||||
|
||||
return runner.query({
|
||||
sql:
|
||||
`alter table ${tableName} add constraint ${keyName} ` +
|
||||
'foreign key (' +
|
||||
column +
|
||||
') references ' +
|
||||
inTable +
|
||||
' (' +
|
||||
references +
|
||||
')' +
|
||||
onUpdate +
|
||||
onDelete,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
index(columns, indexName, options) {
|
||||
let storageEngineIndexType;
|
||||
let indexType;
|
||||
|
||||
if (isString(options)) {
|
||||
indexType = options;
|
||||
} else if (isObject(options)) {
|
||||
({ indexType, storageEngineIndexType } = options);
|
||||
}
|
||||
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
storageEngineIndexType = storageEngineIndexType
|
||||
? ` using ${storageEngineIndexType}`
|
||||
: '';
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add${
|
||||
indexType ? ` ${indexType}` : ''
|
||||
} index ${indexName}(${this.formatter.columnize(
|
||||
columns
|
||||
)})${storageEngineIndexType}`
|
||||
);
|
||||
}
|
||||
|
||||
primary(columns, constraintName) {
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`mysql: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because mysql does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
|
||||
const primaryCols = columns;
|
||||
let incrementsCols = [];
|
||||
let bigIncrementsCols = [];
|
||||
if (this.grouped.columns) {
|
||||
incrementsCols = this._getIncrementsColumnNames();
|
||||
if (incrementsCols) {
|
||||
incrementsCols.forEach((c) => {
|
||||
if (!primaryCols.includes(c)) {
|
||||
primaryCols.unshift(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
bigIncrementsCols = this._getBigIncrementsColumnNames();
|
||||
if (bigIncrementsCols) {
|
||||
bigIncrementsCols.forEach((c) => {
|
||||
if (!primaryCols.includes(c)) {
|
||||
primaryCols.unshift(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (this.method !== 'create' && this.method !== 'createIfNot') {
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add primary key ${constraintName}(${this.formatter.columnize(
|
||||
primaryCols
|
||||
)})`
|
||||
);
|
||||
}
|
||||
if (incrementsCols.length) {
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} modify column ${this.formatter.columnize(
|
||||
incrementsCols
|
||||
)} int unsigned not null auto_increment`
|
||||
);
|
||||
}
|
||||
if (bigIncrementsCols.length) {
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} modify column ${this.formatter.columnize(
|
||||
bigIncrementsCols
|
||||
)} bigint unsigned not null auto_increment`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unique(columns, indexName) {
|
||||
let storageEngineIndexType;
|
||||
let deferrable;
|
||||
if (isObject(indexName)) {
|
||||
({ indexName, deferrable, storageEngineIndexType } = indexName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`mysql: unique index \`${indexName}\` will not be deferrable ${deferrable} because mysql does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
storageEngineIndexType = storageEngineIndexType
|
||||
? ` using ${storageEngineIndexType}`
|
||||
: '';
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add unique ${indexName}(${this.formatter.columnize(
|
||||
columns
|
||||
)})${storageEngineIndexType}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compile a drop index command.
|
||||
dropIndex(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
this.pushQuery(`alter table ${this.tableName()} drop index ${indexName}`);
|
||||
}
|
||||
|
||||
// Compile a drop foreign key command.
|
||||
dropForeign(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('foreign', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop foreign key ${indexName}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compile a drop primary key command.
|
||||
dropPrimary() {
|
||||
this.pushQuery(`alter table ${this.tableName()} drop primary key`);
|
||||
}
|
||||
|
||||
// Compile a drop unique key command.
|
||||
dropUnique(column, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, column);
|
||||
this.pushQuery(`alter table ${this.tableName()} drop index ${indexName}`);
|
||||
}
|
||||
}
|
||||
|
||||
TableCompiler_MySQL.prototype.addColumnsPrefix = 'add ';
|
||||
TableCompiler_MySQL.prototype.alterColumnsPrefix = 'modify ';
|
||||
TableCompiler_MySQL.prototype.dropColumnPrefix = 'drop ';
|
||||
|
||||
module.exports = TableCompiler_MySQL;
|
21
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js
generated
vendored
Normal file
21
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
const ViewBuilder = require('../../../schema/viewbuilder.js');
|
||||
|
||||
class ViewBuilder_MySQL extends ViewBuilder {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
checkOption() {
|
||||
this._single.checkOption = 'default_option';
|
||||
}
|
||||
|
||||
localCheckOption() {
|
||||
this._single.checkOption = 'local';
|
||||
}
|
||||
|
||||
cascadedCheckOption() {
|
||||
this._single.checkOption = 'cascaded';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewBuilder_MySQL;
|
15
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js
generated
vendored
Normal file
15
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
|
||||
class ViewCompiler_MySQL extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
|
||||
createOrReplace() {
|
||||
this.createQuery(this.columns, this.selectQuery, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_MySQL;
|
46
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/transaction.js
generated
vendored
Normal file
46
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql/transaction.js
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
const Transaction = require('../../execution/transaction');
|
||||
const Debug = require('debug');
|
||||
|
||||
const debug = Debug('knex:tx');
|
||||
|
||||
class Transaction_MySQL extends Transaction {
|
||||
query(conn, sql, status, value) {
|
||||
const t = this;
|
||||
const q = this.trxClient
|
||||
.query(conn, sql)
|
||||
.catch((err) => {
|
||||
if (err.errno === 1305) {
|
||||
this.trxClient.logger.warn(
|
||||
'Transaction was implicitly committed, do not mix transactions and ' +
|
||||
'DDL with MySQL (#805)'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
status = 2;
|
||||
value = err;
|
||||
t._completed = true;
|
||||
debug('%s error running transaction query', t.txid);
|
||||
})
|
||||
.then(function (res) {
|
||||
if (status === 1) t._resolver(value);
|
||||
if (status === 2) {
|
||||
if (value === undefined) {
|
||||
if (t.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) {
|
||||
t._resolver();
|
||||
return;
|
||||
}
|
||||
value = new Error(`Transaction rejected with non-error: ${value}`);
|
||||
}
|
||||
t._rejecter(value);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
if (status === 1 || status === 2) {
|
||||
t._completed = true;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction_MySQL;
|
53
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql2/index.js
generated
vendored
Normal file
53
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql2/index.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// MySQL2 Client
|
||||
// -------
|
||||
const Client_MySQL = require('../mysql');
|
||||
const Transaction = require('./transaction');
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler"
|
||||
// objects, which extend the base 'lib/query/builder' and
|
||||
// 'lib/query/compiler', respectively.
|
||||
class Client_MySQL2 extends Client_MySQL {
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('mysql2');
|
||||
}
|
||||
|
||||
initializeDriver() {
|
||||
try {
|
||||
this.driver = this._driver();
|
||||
} catch (e) {
|
||||
let message = `Knex: run\n$ npm install ${this.driverName}`;
|
||||
|
||||
const nodeMajorVersion = process.version.replace(/^v/, '').split('.')[0];
|
||||
if (nodeMajorVersion <= 12) {
|
||||
message += `@3.2.0`;
|
||||
this.logger.error(
|
||||
'Mysql2 version 3.2.0 is the latest version to support Node.js 12 or lower.'
|
||||
);
|
||||
}
|
||||
message += ` --save`;
|
||||
this.logger.error(`${message}\n${e.message}\n${e.stack}`);
|
||||
throw new Error(`${message}\n${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
validateConnection(connection) {
|
||||
return (
|
||||
connection &&
|
||||
!connection._fatalError &&
|
||||
!connection._protocolError &&
|
||||
!connection._closing &&
|
||||
!connection.stream.destroyed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_MySQL2.prototype, {
|
||||
// The "dialect", for reference elsewhere.
|
||||
driverName: 'mysql2',
|
||||
});
|
||||
|
||||
module.exports = Client_MySQL2;
|
44
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql2/transaction.js
generated
vendored
Normal file
44
backend/apis/nodejs/node_modules/knex/lib/dialects/mysql2/transaction.js
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
const Transaction = require('../../execution/transaction');
|
||||
const debug = require('debug')('knex:tx');
|
||||
|
||||
class Transaction_MySQL2 extends Transaction {
|
||||
query(conn, sql, status, value) {
|
||||
const t = this;
|
||||
const q = this.trxClient
|
||||
.query(conn, sql)
|
||||
.catch((err) => {
|
||||
if (err.code === 'ER_SP_DOES_NOT_EXIST') {
|
||||
this.trxClient.logger.warn(
|
||||
'Transaction was implicitly committed, do not mix transactions and ' +
|
||||
'DDL with MySQL (#805)'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
status = 2;
|
||||
value = err;
|
||||
t._completed = true;
|
||||
debug('%s error running transaction query', t.txid);
|
||||
})
|
||||
.then(function (res) {
|
||||
if (status === 1) t._resolver(value);
|
||||
if (status === 2) {
|
||||
if (value === undefined) {
|
||||
if (t.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) {
|
||||
t._resolver();
|
||||
return;
|
||||
}
|
||||
value = new Error(`Transaction rejected with non-error: ${value}`);
|
||||
}
|
||||
t._rejecter(value);
|
||||
return res;
|
||||
}
|
||||
});
|
||||
if (status === 1 || status === 2) {
|
||||
t._completed = true;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction_MySQL2;
|
5
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md
generated
vendored
Normal file
5
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Warning: Dead Code
|
||||
|
||||
The `oracle` dialect is mostly dead code at this point. However, a handful of its methods are still referenced by the `oracledb` dialect. So, we are in the process of migrating those methods over to the `oracledb` dialect where they belong. Once that task is completed, we will officially remove the `oracle` dialect.
|
||||
|
||||
In short: do not use the `oracle` dialect. Use the `oracledb` dialect instead.
|
92
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/index.js
generated
vendored
Normal file
92
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/index.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
// Oracle Client
|
||||
// -------
|
||||
const { ReturningHelper } = require('./utils');
|
||||
const { isConnectionError } = require('./utils');
|
||||
const Client = require('../../client');
|
||||
const SchemaCompiler = require('./schema/oracle-compiler');
|
||||
const ColumnBuilder = require('./schema/oracle-columnbuilder');
|
||||
const ColumnCompiler = require('./schema/oracle-columncompiler');
|
||||
const TableCompiler = require('./schema/oracle-tablecompiler');
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler"
|
||||
// objects, which extend the base 'lib/query/builder' and
|
||||
// 'lib/query/compiler', respectively.
|
||||
class Client_Oracle extends Client {
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
columnBuilder() {
|
||||
return new ColumnBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
// Return the database for the Oracle client.
|
||||
database() {
|
||||
return this.connectionSettings.database;
|
||||
}
|
||||
|
||||
// Position the bindings for the query.
|
||||
positionBindings(sql) {
|
||||
let questionCount = 0;
|
||||
return sql.replace(/\?/g, function () {
|
||||
questionCount += 1;
|
||||
return `:${questionCount}`;
|
||||
});
|
||||
}
|
||||
|
||||
_stream(connection, obj, stream, options) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
stream.on('error', (err) => {
|
||||
if (isConnectionError(err)) {
|
||||
connection.__knex__disposed = err;
|
||||
}
|
||||
rejecter(err);
|
||||
});
|
||||
stream.on('end', resolver);
|
||||
const queryStream = connection.queryStream(
|
||||
obj.sql,
|
||||
obj.bindings,
|
||||
options
|
||||
);
|
||||
queryStream.pipe(stream);
|
||||
queryStream.on('error', function (error) {
|
||||
rejecter(error);
|
||||
stream.emit('error', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Formatter part
|
||||
|
||||
alias(first, second) {
|
||||
return first + ' ' + second;
|
||||
}
|
||||
|
||||
parameter(value, builder, formatter) {
|
||||
// Returning helper uses always ROWID as string
|
||||
if (value instanceof ReturningHelper && this.driver) {
|
||||
value = new this.driver.OutParam(this.driver.OCCISTRING);
|
||||
} else if (typeof value === 'boolean') {
|
||||
value = value ? 1 : 0;
|
||||
}
|
||||
return super.parameter(value, builder, formatter);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_Oracle.prototype, {
|
||||
dialect: 'oracle',
|
||||
|
||||
driverName: 'oracle',
|
||||
});
|
||||
|
||||
module.exports = Client_Oracle;
|
343
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js
generated
vendored
Normal file
343
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,343 @@
|
||||
/* eslint max-len:0 */
|
||||
|
||||
// Oracle Query Builder & Compiler
|
||||
// ------
|
||||
const compact = require('lodash/compact');
|
||||
const identity = require('lodash/identity');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const isPlainObject = require('lodash/isPlainObject');
|
||||
const reduce = require('lodash/reduce');
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
const { ReturningHelper } = require('../utils');
|
||||
const { isString } = require('../../../util/is');
|
||||
|
||||
const components = [
|
||||
'comments',
|
||||
'columns',
|
||||
'join',
|
||||
'where',
|
||||
'union',
|
||||
'group',
|
||||
'having',
|
||||
'order',
|
||||
'lock',
|
||||
];
|
||||
|
||||
// Query Compiler
|
||||
// -------
|
||||
|
||||
// Set the "Formatter" to use for the queries,
|
||||
// ensuring that all parameterized values (even across sub-queries)
|
||||
// are properly built into the same query.
|
||||
class QueryCompiler_Oracle extends QueryCompiler {
|
||||
constructor(client, builder, formatter) {
|
||||
super(client, builder, formatter);
|
||||
|
||||
const { onConflict } = this.single;
|
||||
if (onConflict) {
|
||||
throw new Error('.onConflict() is not supported for oracledb.');
|
||||
}
|
||||
|
||||
// Compiles the `select` statement, or nested sub-selects
|
||||
// by calling each of the component compilers, trimming out
|
||||
// the empties, and returning a generated query string.
|
||||
this.first = this.select;
|
||||
}
|
||||
|
||||
// Compiles an "insert" query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
let insertValues = this.single.insert || [];
|
||||
let { returning } = this.single;
|
||||
|
||||
if (!Array.isArray(insertValues) && isPlainObject(this.single.insert)) {
|
||||
insertValues = [this.single.insert];
|
||||
}
|
||||
|
||||
// always wrap returning argument in array
|
||||
if (returning && !Array.isArray(returning)) {
|
||||
returning = [returning];
|
||||
}
|
||||
|
||||
if (
|
||||
Array.isArray(insertValues) &&
|
||||
insertValues.length === 1 &&
|
||||
isEmpty(insertValues[0])
|
||||
) {
|
||||
return this._addReturningToSqlAndConvert(
|
||||
`insert into ${this.tableName} (${this.formatter.wrap(
|
||||
this.single.returning
|
||||
)}) values (default)`,
|
||||
returning,
|
||||
this.tableName
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isEmpty(this.single.insert) &&
|
||||
typeof this.single.insert !== 'function'
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const insertData = this._prepInsert(insertValues);
|
||||
|
||||
const sql = {};
|
||||
|
||||
if (isString(insertData)) {
|
||||
return this._addReturningToSqlAndConvert(
|
||||
`insert into ${this.tableName} ${insertData}`,
|
||||
returning
|
||||
);
|
||||
}
|
||||
|
||||
if (insertData.values.length === 1) {
|
||||
return this._addReturningToSqlAndConvert(
|
||||
`insert into ${this.tableName} (${this.formatter.columnize(
|
||||
insertData.columns
|
||||
)}) values (${this.client.parameterize(
|
||||
insertData.values[0],
|
||||
undefined,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`,
|
||||
returning,
|
||||
this.tableName
|
||||
);
|
||||
}
|
||||
|
||||
const insertDefaultsOnly = insertData.columns.length === 0;
|
||||
|
||||
sql.sql =
|
||||
'begin ' +
|
||||
insertData.values
|
||||
.map((value) => {
|
||||
let returningHelper;
|
||||
const parameterizedValues = !insertDefaultsOnly
|
||||
? this.client.parameterize(
|
||||
value,
|
||||
this.client.valueForUndefined,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)
|
||||
: '';
|
||||
const returningValues = Array.isArray(returning)
|
||||
? returning
|
||||
: [returning];
|
||||
let subSql = `insert into ${this.tableName} `;
|
||||
|
||||
if (returning) {
|
||||
returningHelper = new ReturningHelper(returningValues.join(':'));
|
||||
sql.outParams = (sql.outParams || []).concat(returningHelper);
|
||||
}
|
||||
|
||||
if (insertDefaultsOnly) {
|
||||
// no columns given so only the default value
|
||||
subSql += `(${this.formatter.wrap(
|
||||
this.single.returning
|
||||
)}) values (default)`;
|
||||
} else {
|
||||
subSql += `(${this.formatter.columnize(
|
||||
insertData.columns
|
||||
)}) values (${parameterizedValues})`;
|
||||
}
|
||||
subSql += returning
|
||||
? ` returning ROWID into ${this.client.parameter(
|
||||
returningHelper,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}`
|
||||
: '';
|
||||
|
||||
// pre bind position because subSql is an execute immediate parameter
|
||||
// later position binding will only convert the ? params
|
||||
|
||||
subSql = this.formatter.client.positionBindings(subSql);
|
||||
|
||||
const parameterizedValuesWithoutDefault = parameterizedValues
|
||||
.replace('DEFAULT, ', '')
|
||||
.replace(', DEFAULT', '');
|
||||
return (
|
||||
`execute immediate '${subSql.replace(/'/g, "''")}` +
|
||||
(parameterizedValuesWithoutDefault || returning ? "' using " : '') +
|
||||
parameterizedValuesWithoutDefault +
|
||||
(parameterizedValuesWithoutDefault && returning ? ', ' : '') +
|
||||
(returning ? 'out ?' : '') +
|
||||
';'
|
||||
);
|
||||
})
|
||||
.join(' ') +
|
||||
'end;';
|
||||
|
||||
if (returning) {
|
||||
sql.returning = returning;
|
||||
// generate select statement with special order by to keep the order because 'in (..)' may change the order
|
||||
sql.returningSql =
|
||||
`select ${this.formatter.columnize(returning)}` +
|
||||
' from ' +
|
||||
this.tableName +
|
||||
' where ROWID in (' +
|
||||
sql.outParams.map((v, i) => `:${i + 1}`).join(', ') +
|
||||
')' +
|
||||
' order by case ROWID ' +
|
||||
sql.outParams
|
||||
.map((v, i) => `when CHARTOROWID(:${i + 1}) then ${i}`)
|
||||
.join(' ') +
|
||||
' end';
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
// Update method, including joins, wheres, order & limits.
|
||||
update() {
|
||||
const updates = this._prepUpdate(this.single.update);
|
||||
const where = this.where();
|
||||
let { returning } = this.single;
|
||||
const sql =
|
||||
`update ${this.tableName}` +
|
||||
' set ' +
|
||||
updates.join(', ') +
|
||||
(where ? ` ${where}` : '');
|
||||
|
||||
if (!returning) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
// always wrap returning argument in array
|
||||
if (!Array.isArray(returning)) {
|
||||
returning = [returning];
|
||||
}
|
||||
|
||||
return this._addReturningToSqlAndConvert(sql, returning, this.tableName);
|
||||
}
|
||||
|
||||
// Compiles a `truncate` query.
|
||||
truncate() {
|
||||
return `truncate table ${this.tableName}`;
|
||||
}
|
||||
|
||||
forUpdate() {
|
||||
return 'for update';
|
||||
}
|
||||
|
||||
forShare() {
|
||||
// lock for share is not directly supported by oracle
|
||||
// use LOCK TABLE .. IN SHARE MODE; instead
|
||||
this.client.logger.warn(
|
||||
'lock for share is not supported by oracle dialect'
|
||||
);
|
||||
return '';
|
||||
}
|
||||
|
||||
// Compiles a `columnInfo` query.
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
// Node oracle drivers doesn't support LONG type (which is data_default type)
|
||||
const sql = `select * from xmltable( '/ROWSET/ROW'
|
||||
passing dbms_xmlgen.getXMLType('
|
||||
select char_col_decl_length, column_name, data_type, data_default, nullable
|
||||
from all_tab_columns where table_name = ''${table}'' ')
|
||||
columns
|
||||
CHAR_COL_DECL_LENGTH number, COLUMN_NAME varchar2(200), DATA_TYPE varchar2(106),
|
||||
DATA_DEFAULT clob, NULLABLE varchar2(1))`;
|
||||
|
||||
return {
|
||||
sql: sql,
|
||||
output(resp) {
|
||||
const out = reduce(
|
||||
resp,
|
||||
function (columns, val) {
|
||||
columns[val.COLUMN_NAME] = {
|
||||
type: val.DATA_TYPE,
|
||||
defaultValue: val.DATA_DEFAULT,
|
||||
maxLength: val.CHAR_COL_DECL_LENGTH,
|
||||
nullable: val.NULLABLE === 'Y',
|
||||
};
|
||||
return columns;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return (column && out[column]) || out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
select() {
|
||||
let query = this.with();
|
||||
const statements = components.map((component) => {
|
||||
return this[component]();
|
||||
});
|
||||
query += compact(statements).join(' ');
|
||||
return this._surroundQueryWithLimitAndOffset(query);
|
||||
}
|
||||
|
||||
aggregate(stmt) {
|
||||
return this._aggregate(stmt, { aliasSeparator: ' ' });
|
||||
}
|
||||
|
||||
// for single commands only
|
||||
_addReturningToSqlAndConvert(sql, returning, tableName) {
|
||||
const res = {
|
||||
sql,
|
||||
};
|
||||
|
||||
if (!returning) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const returningValues = Array.isArray(returning) ? returning : [returning];
|
||||
const returningHelper = new ReturningHelper(returningValues.join(':'));
|
||||
res.sql =
|
||||
sql +
|
||||
' returning ROWID into ' +
|
||||
this.client.parameter(returningHelper, this.builder, this.bindingsHolder);
|
||||
res.returningSql = `select ${this.formatter.columnize(
|
||||
returning
|
||||
)} from ${tableName} where ROWID = :1`;
|
||||
res.outParams = [returningHelper];
|
||||
res.returning = returning;
|
||||
return res;
|
||||
}
|
||||
|
||||
_surroundQueryWithLimitAndOffset(query) {
|
||||
let { limit } = this.single;
|
||||
const { offset } = this.single;
|
||||
const hasLimit = limit || limit === 0 || limit === '0';
|
||||
limit = +limit;
|
||||
|
||||
if (!hasLimit && !offset) return query;
|
||||
query = query || '';
|
||||
|
||||
if (hasLimit && !offset) {
|
||||
return `select * from (${query}) where rownum <= ${this._getValueOrParameterFromAttribute(
|
||||
'limit',
|
||||
limit
|
||||
)}`;
|
||||
}
|
||||
|
||||
const endRow = +offset + (hasLimit ? limit : 10000000000000);
|
||||
|
||||
return (
|
||||
'select * from ' +
|
||||
'(select row_.*, ROWNUM rownum_ from (' +
|
||||
query +
|
||||
') row_ ' +
|
||||
'where rownum <= ' +
|
||||
(this.single.skipBinding['offset']
|
||||
? endRow
|
||||
: this.client.parameter(endRow, this.builder, this.bindingsHolder)) +
|
||||
') ' +
|
||||
'where rownum_ > ' +
|
||||
this._getValueOrParameterFromAttribute('offset', offset)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryCompiler_Oracle;
|
22
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js
generated
vendored
Normal file
22
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
const Trigger = require('./trigger');
|
||||
|
||||
// helper function for pushAdditional in increments() and bigincrements()
|
||||
function createAutoIncrementTriggerAndSequence(columnCompiler) {
|
||||
const trigger = new Trigger(columnCompiler.client.version);
|
||||
|
||||
// TODO Add warning that sequence etc is created
|
||||
columnCompiler.pushAdditional(function () {
|
||||
const tableName = this.tableCompiler.tableNameRaw;
|
||||
const schemaName = this.tableCompiler.schemaNameRaw;
|
||||
const createTriggerSQL = trigger.createAutoIncrementTrigger(
|
||||
this.client.logger,
|
||||
tableName,
|
||||
schemaName
|
||||
);
|
||||
this.pushQuery(createTriggerSQL);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createAutoIncrementTriggerAndSequence,
|
||||
};
|
155
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js
generated
vendored
Normal file
155
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
const { NameHelper } = require('../../utils');
|
||||
|
||||
class Trigger {
|
||||
constructor(oracleVersion) {
|
||||
this.nameHelper = new NameHelper(oracleVersion);
|
||||
}
|
||||
|
||||
renameColumnTrigger(logger, tableName, columnName, to) {
|
||||
const triggerName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'autoinc_trg',
|
||||
tableName
|
||||
);
|
||||
const sequenceName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'seq',
|
||||
tableName
|
||||
);
|
||||
return (
|
||||
`DECLARE ` +
|
||||
`PK_NAME VARCHAR(200); ` +
|
||||
`IS_AUTOINC NUMBER := 0; ` +
|
||||
`BEGIN` +
|
||||
` EXECUTE IMMEDIATE ('ALTER TABLE "${tableName}" RENAME COLUMN "${columnName}" TO "${to}"');` +
|
||||
` SELECT COUNT(*) INTO IS_AUTOINC from "USER_TRIGGERS" where trigger_name = '${triggerName}';` +
|
||||
` IF (IS_AUTOINC > 0) THEN` +
|
||||
` SELECT cols.column_name INTO PK_NAME` +
|
||||
` FROM all_constraints cons, all_cons_columns cols` +
|
||||
` WHERE cons.constraint_type = 'P'` +
|
||||
` AND cons.constraint_name = cols.constraint_name` +
|
||||
` AND cons.owner = cols.owner` +
|
||||
` AND cols.table_name = '${tableName}';` +
|
||||
` IF ('${to}' = PK_NAME) THEN` +
|
||||
` EXECUTE IMMEDIATE ('DROP TRIGGER "${triggerName}"');` +
|
||||
` EXECUTE IMMEDIATE ('create or replace trigger "${triggerName}"` +
|
||||
` BEFORE INSERT on "${tableName}" for each row` +
|
||||
` declare` +
|
||||
` checking number := 1;` +
|
||||
` begin` +
|
||||
` if (:new."${to}" is null) then` +
|
||||
` while checking >= 1 loop` +
|
||||
` select "${sequenceName}".nextval into :new."${to}" from dual;` +
|
||||
` select count("${to}") into checking from "${tableName}"` +
|
||||
` where "${to}" = :new."${to}";` +
|
||||
` end loop;` +
|
||||
` end if;` +
|
||||
` end;');` +
|
||||
` end if;` +
|
||||
` end if;` +
|
||||
`END;`
|
||||
);
|
||||
}
|
||||
|
||||
createAutoIncrementTrigger(logger, tableName, schemaName) {
|
||||
const tableQuoted = `"${tableName}"`;
|
||||
const tableUnquoted = tableName;
|
||||
const schemaQuoted = schemaName ? `"${schemaName}".` : '';
|
||||
const constraintOwner = schemaName ? `'${schemaName}'` : 'cols.owner';
|
||||
const triggerName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'autoinc_trg',
|
||||
tableName
|
||||
);
|
||||
const sequenceNameUnquoted = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'seq',
|
||||
tableName
|
||||
);
|
||||
const sequenceNameQuoted = `"${sequenceNameUnquoted}"`;
|
||||
return (
|
||||
`DECLARE ` +
|
||||
`PK_NAME VARCHAR(200); ` +
|
||||
`BEGIN` +
|
||||
` EXECUTE IMMEDIATE ('CREATE SEQUENCE ${schemaQuoted}${sequenceNameQuoted}');` +
|
||||
` SELECT cols.column_name INTO PK_NAME` + // TODO : support autoincrement on table with multiple primary keys
|
||||
` FROM all_constraints cons, all_cons_columns cols` +
|
||||
` WHERE cons.constraint_type = 'P'` +
|
||||
` AND cons.constraint_name = cols.constraint_name` +
|
||||
` AND cons.owner = ${constraintOwner}` +
|
||||
` AND cols.table_name = '${tableUnquoted}';` +
|
||||
` execute immediate ('create or replace trigger ${schemaQuoted}"${triggerName}"` +
|
||||
` BEFORE INSERT on ${schemaQuoted}${tableQuoted}` +
|
||||
` for each row` +
|
||||
` declare` +
|
||||
` checking number := 1;` +
|
||||
` begin` +
|
||||
` if (:new."' || PK_NAME || '" is null) then` +
|
||||
` while checking >= 1 loop` +
|
||||
` select ${schemaQuoted}${sequenceNameQuoted}.nextval into :new."' || PK_NAME || '" from dual;` +
|
||||
` select count("' || PK_NAME || '") into checking from ${schemaQuoted}${tableQuoted}` +
|
||||
` where "' || PK_NAME || '" = :new."' || PK_NAME || '";` +
|
||||
` end loop;` +
|
||||
` end if;` +
|
||||
` end;'); ` +
|
||||
`END;`
|
||||
);
|
||||
}
|
||||
|
||||
renameTableAndAutoIncrementTrigger(logger, tableName, to) {
|
||||
const triggerName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'autoinc_trg',
|
||||
tableName
|
||||
);
|
||||
const sequenceName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'seq',
|
||||
tableName
|
||||
);
|
||||
const toTriggerName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'autoinc_trg',
|
||||
to
|
||||
);
|
||||
const toSequenceName = this.nameHelper.generateCombinedName(
|
||||
logger,
|
||||
'seq',
|
||||
to
|
||||
);
|
||||
return (
|
||||
`DECLARE ` +
|
||||
`PK_NAME VARCHAR(200); ` +
|
||||
`IS_AUTOINC NUMBER := 0; ` +
|
||||
`BEGIN` +
|
||||
` EXECUTE IMMEDIATE ('RENAME "${tableName}" TO "${to}"');` +
|
||||
` SELECT COUNT(*) INTO IS_AUTOINC from "USER_TRIGGERS" where trigger_name = '${triggerName}';` +
|
||||
` IF (IS_AUTOINC > 0) THEN` +
|
||||
` EXECUTE IMMEDIATE ('DROP TRIGGER "${triggerName}"');` +
|
||||
` EXECUTE IMMEDIATE ('RENAME "${sequenceName}" TO "${toSequenceName}"');` +
|
||||
` SELECT cols.column_name INTO PK_NAME` +
|
||||
` FROM all_constraints cons, all_cons_columns cols` +
|
||||
` WHERE cons.constraint_type = 'P'` +
|
||||
` AND cons.constraint_name = cols.constraint_name` +
|
||||
` AND cons.owner = cols.owner` +
|
||||
` AND cols.table_name = '${to}';` +
|
||||
` EXECUTE IMMEDIATE ('create or replace trigger "${toTriggerName}"` +
|
||||
` BEFORE INSERT on "${to}" for each row` +
|
||||
` declare` +
|
||||
` checking number := 1;` +
|
||||
` begin` +
|
||||
` if (:new."' || PK_NAME || '" is null) then` +
|
||||
` while checking >= 1 loop` +
|
||||
` select "${toSequenceName}".nextval into :new."' || PK_NAME || '" from dual;` +
|
||||
` select count("' || PK_NAME || '") into checking from "${to}"` +
|
||||
` where "' || PK_NAME || '" = :new."' || PK_NAME || '";` +
|
||||
` end loop;` +
|
||||
` end if;` +
|
||||
` end;');` +
|
||||
` end if;` +
|
||||
`END;`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Trigger;
|
17
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js
generated
vendored
Normal file
17
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
const ColumnBuilder = require('../../../schema/columnbuilder');
|
||||
const toArray = require('lodash/toArray');
|
||||
|
||||
class ColumnBuilder_Oracle extends ColumnBuilder {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
// checkIn added to the builder to allow the column compiler to change the
|
||||
// order via the modifiers ("check" must be after "default")
|
||||
checkIn() {
|
||||
this._modifiers.checkIn = toArray(arguments);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ColumnBuilder_Oracle;
|
126
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js
generated
vendored
Normal file
126
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
const uniq = require('lodash/uniq');
|
||||
const Raw = require('../../../raw');
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
const {
|
||||
createAutoIncrementTriggerAndSequence,
|
||||
} = require('./internal/incrementUtils');
|
||||
const { toNumber } = require('../../../util/helpers');
|
||||
|
||||
// Column Compiler
|
||||
// -------
|
||||
|
||||
class ColumnCompiler_Oracle extends ColumnCompiler {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.modifiers = ['defaultTo', 'checkIn', 'nullable', 'comment'];
|
||||
}
|
||||
|
||||
increments(options = { primaryKey: true }) {
|
||||
createAutoIncrementTriggerAndSequence(this);
|
||||
return (
|
||||
'integer not null' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
|
||||
bigincrements(options = { primaryKey: true }) {
|
||||
createAutoIncrementTriggerAndSequence(this);
|
||||
return (
|
||||
'number(20, 0) not null' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
|
||||
floating(precision) {
|
||||
const parsedPrecision = toNumber(precision, 0);
|
||||
return `float${parsedPrecision ? `(${parsedPrecision})` : ''}`;
|
||||
}
|
||||
|
||||
double(precision, scale) {
|
||||
// if (!precision) return 'number'; // TODO: Check If default is ok
|
||||
return `number(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`;
|
||||
}
|
||||
|
||||
decimal(precision, scale) {
|
||||
if (precision === null) return 'decimal';
|
||||
return `decimal(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`;
|
||||
}
|
||||
|
||||
integer(length) {
|
||||
return length ? `number(${toNumber(length, 11)})` : 'integer';
|
||||
}
|
||||
|
||||
enu(allowed) {
|
||||
allowed = uniq(allowed);
|
||||
const maxLength = (allowed || []).reduce(
|
||||
(maxLength, name) => Math.max(maxLength, String(name).length),
|
||||
1
|
||||
);
|
||||
|
||||
// implicitly add the enum values as checked values
|
||||
this.columnBuilder._modifiers.checkIn = [allowed];
|
||||
|
||||
return `varchar2(${maxLength})`;
|
||||
}
|
||||
|
||||
datetime(without) {
|
||||
return without ? 'timestamp' : 'timestamp with time zone';
|
||||
}
|
||||
|
||||
timestamp(without) {
|
||||
return without ? 'timestamp' : 'timestamp with time zone';
|
||||
}
|
||||
|
||||
bool() {
|
||||
// implicitly add the check for 0 and 1
|
||||
this.columnBuilder._modifiers.checkIn = [[0, 1]];
|
||||
return 'number(1, 0)';
|
||||
}
|
||||
|
||||
varchar(length) {
|
||||
return `varchar2(${toNumber(length, 255)})`;
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
// ------
|
||||
|
||||
comment(comment) {
|
||||
const columnName = this.args[0] || this.defaults('columnName');
|
||||
|
||||
this.pushAdditional(function () {
|
||||
this.pushQuery(
|
||||
`comment on column ${this.tableCompiler.tableName()}.` +
|
||||
this.formatter.wrap(columnName) +
|
||||
" is '" +
|
||||
(comment || '') +
|
||||
"'"
|
||||
);
|
||||
}, comment);
|
||||
}
|
||||
|
||||
checkIn(value) {
|
||||
// TODO: Maybe accept arguments also as array
|
||||
// TODO: value(s) should be escaped properly
|
||||
if (value === undefined) {
|
||||
return '';
|
||||
} else if (value instanceof Raw) {
|
||||
value = value.toQuery();
|
||||
} else if (Array.isArray(value)) {
|
||||
value = value.map((v) => `'${v}'`).join(', ');
|
||||
} else {
|
||||
value = `'${value}'`;
|
||||
}
|
||||
return `check (${this.formatter.wrap(this.args[0])} in (${value}))`;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_Oracle.prototype.tinyint = 'smallint';
|
||||
ColumnCompiler_Oracle.prototype.smallint = 'smallint';
|
||||
ColumnCompiler_Oracle.prototype.mediumint = 'integer';
|
||||
ColumnCompiler_Oracle.prototype.biginteger = 'number(20, 0)';
|
||||
ColumnCompiler_Oracle.prototype.text = 'clob';
|
||||
ColumnCompiler_Oracle.prototype.time = 'timestamp with time zone';
|
||||
ColumnCompiler_Oracle.prototype.bit = 'clob';
|
||||
ColumnCompiler_Oracle.prototype.json = 'clob';
|
||||
|
||||
module.exports = ColumnCompiler_Oracle;
|
124
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js
generated
vendored
Normal file
124
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js
generated
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
// Oracle Schema Compiler
|
||||
// -------
|
||||
const SchemaCompiler = require('../../../schema/compiler');
|
||||
const utils = require('../utils');
|
||||
const Trigger = require('./internal/trigger');
|
||||
|
||||
class SchemaCompiler_Oracle extends SchemaCompiler {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
// Rename a table on the schema.
|
||||
renameTable(tableName, to) {
|
||||
const trigger = new Trigger(this.client.version);
|
||||
const renameTable = trigger.renameTableAndAutoIncrementTrigger(
|
||||
this.client.logger,
|
||||
tableName,
|
||||
to
|
||||
);
|
||||
this.pushQuery(renameTable);
|
||||
}
|
||||
|
||||
// Check whether a table exists on the query.
|
||||
hasTable(tableName) {
|
||||
this.pushQuery({
|
||||
sql:
|
||||
'select TABLE_NAME from USER_TABLES where TABLE_NAME = ' +
|
||||
this.client.parameter(tableName, this.builder, this.bindingsHolder),
|
||||
output(resp) {
|
||||
return resp.length > 0;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Check whether a column exists on the schema.
|
||||
hasColumn(tableName, column) {
|
||||
const sql =
|
||||
`select COLUMN_NAME from ALL_TAB_COLUMNS ` +
|
||||
`where TABLE_NAME = ${this.client.parameter(
|
||||
tableName,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)} ` +
|
||||
`and COLUMN_NAME = ${this.client.parameter(
|
||||
column,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}`;
|
||||
this.pushQuery({ sql, output: (resp) => resp.length > 0 });
|
||||
}
|
||||
|
||||
dropSequenceIfExists(sequenceName) {
|
||||
const prefix = this.schema ? `"${this.schema}".` : '';
|
||||
this.pushQuery(
|
||||
utils.wrapSqlWithCatch(
|
||||
`drop sequence ${prefix}${this.formatter.wrap(sequenceName)}`,
|
||||
-2289
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
_dropRelatedSequenceIfExists(tableName) {
|
||||
// removing the sequence that was possibly generated by increments() column
|
||||
const nameHelper = new utils.NameHelper(this.client.version);
|
||||
const sequenceName = nameHelper.generateCombinedName(
|
||||
this.client.logger,
|
||||
'seq',
|
||||
tableName
|
||||
);
|
||||
this.dropSequenceIfExists(sequenceName);
|
||||
}
|
||||
|
||||
dropTable(tableName) {
|
||||
const prefix = this.schema ? `"${this.schema}".` : '';
|
||||
this.pushQuery(`drop table ${prefix}${this.formatter.wrap(tableName)}`);
|
||||
|
||||
// removing the sequence that was possibly generated by increments() column
|
||||
this._dropRelatedSequenceIfExists(tableName);
|
||||
}
|
||||
|
||||
dropTableIfExists(tableName) {
|
||||
this.dropObject(tableName, 'table');
|
||||
}
|
||||
|
||||
dropViewIfExists(viewName) {
|
||||
this.dropObject(viewName, 'view');
|
||||
}
|
||||
|
||||
dropObject(objectName, type) {
|
||||
const prefix = this.schema ? `"${this.schema}".` : '';
|
||||
let errorCode = -942;
|
||||
if (type === 'materialized view') {
|
||||
// https://stackoverflow.com/a/1801453
|
||||
errorCode = -12003;
|
||||
}
|
||||
this.pushQuery(
|
||||
utils.wrapSqlWithCatch(
|
||||
`drop ${type} ${prefix}${this.formatter.wrap(objectName)}`,
|
||||
errorCode
|
||||
)
|
||||
);
|
||||
|
||||
// removing the sequence that was possibly generated by increments() column
|
||||
this._dropRelatedSequenceIfExists(objectName);
|
||||
}
|
||||
|
||||
refreshMaterializedView(viewName) {
|
||||
return this.pushQuery({
|
||||
sql: `BEGIN DBMS_MVIEW.REFRESH('${
|
||||
this.schemaNameRaw ? this.schemaNameRaw + '.' : ''
|
||||
}${viewName}'); END;`,
|
||||
});
|
||||
}
|
||||
|
||||
dropMaterializedView(viewName) {
|
||||
this._dropView(viewName, false, true);
|
||||
}
|
||||
|
||||
dropMaterializedViewIfExists(viewName) {
|
||||
this.dropObject(viewName, 'materialized view');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_Oracle;
|
197
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js
generated
vendored
Normal file
197
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/* eslint max-len:0 */
|
||||
|
||||
const utils = require('../utils');
|
||||
const TableCompiler = require('../../../schema/tablecompiler');
|
||||
const helpers = require('../../../util/helpers');
|
||||
const Trigger = require('./internal/trigger');
|
||||
const { isObject } = require('../../../util/is');
|
||||
|
||||
// Table Compiler
|
||||
// ------
|
||||
|
||||
class TableCompiler_Oracle extends TableCompiler {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
addColumns(columns, prefix) {
|
||||
if (columns.sql.length > 0) {
|
||||
prefix = prefix || this.addColumnsPrefix;
|
||||
|
||||
const columnSql = columns.sql;
|
||||
const alter = this.lowerCase ? 'alter table ' : 'ALTER TABLE ';
|
||||
|
||||
let sql = `${alter}${this.tableName()} ${prefix}`;
|
||||
if (columns.sql.length > 1) {
|
||||
sql += `(${columnSql.join(', ')})`;
|
||||
} else {
|
||||
sql += columnSql.join(', ');
|
||||
}
|
||||
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Compile a rename column command.
|
||||
renameColumn(from, to) {
|
||||
// Remove quotes around tableName
|
||||
const tableName = this.tableName().slice(1, -1);
|
||||
const trigger = new Trigger(this.client.version);
|
||||
return this.pushQuery(
|
||||
trigger.renameColumnTrigger(this.client.logger, tableName, from, to)
|
||||
);
|
||||
}
|
||||
|
||||
compileAdd(builder) {
|
||||
const table = this.formatter.wrap(builder);
|
||||
const columns = this.prefixArray('add column', this.getColumns(builder));
|
||||
return this.pushQuery({
|
||||
sql: `alter table ${table} ${columns.join(', ')}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Adds the "create" query to the query sequence.
|
||||
createQuery(columns, ifNot, like) {
|
||||
const columnsSql =
|
||||
like && this.tableNameLike()
|
||||
? ' as (select * from ' + this.tableNameLike() + ' where 0=1)'
|
||||
: ' (' + columns.sql.join(', ') + this._addChecks() + ')';
|
||||
const sql = `create table ${this.tableName()}${columnsSql}`;
|
||||
|
||||
this.pushQuery({
|
||||
// catch "name is already used by an existing object" for workaround for "if not exists"
|
||||
sql: ifNot ? utils.wrapSqlWithCatch(sql, -955) : sql,
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
if (this.single.comment) this.comment(this.single.comment);
|
||||
if (like) {
|
||||
this.addColumns(columns, this.addColumnsPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
// Compiles the comment on the table.
|
||||
comment(comment) {
|
||||
this.pushQuery(`comment on table ${this.tableName()} is '${comment}'`);
|
||||
}
|
||||
|
||||
dropColumn() {
|
||||
const columns = helpers.normalizeArr.apply(null, arguments);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop (${this.formatter.columnize(
|
||||
columns
|
||||
)})`
|
||||
);
|
||||
}
|
||||
|
||||
_indexCommand(type, tableName, columns) {
|
||||
const nameHelper = new utils.NameHelper(this.client.version);
|
||||
return this.formatter.wrap(
|
||||
nameHelper.generateCombinedName(
|
||||
this.client.logger,
|
||||
type,
|
||||
tableName,
|
||||
columns
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
primary(columns, constraintName) {
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
const primaryCols = columns;
|
||||
let incrementsCols = [];
|
||||
if (this.grouped.columns) {
|
||||
incrementsCols = this._getIncrementsColumnNames();
|
||||
if (incrementsCols) {
|
||||
incrementsCols.forEach((c) => {
|
||||
if (!primaryCols.includes(c)) {
|
||||
primaryCols.unshift(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize(
|
||||
primaryCols
|
||||
)})${deferrable}`
|
||||
);
|
||||
}
|
||||
|
||||
dropPrimary(constraintName) {
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(this.tableNameRaw + '_pkey');
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${constraintName}`
|
||||
);
|
||||
}
|
||||
|
||||
index(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`create index ${indexName} on ${this.tableName()}` +
|
||||
' (' +
|
||||
this.formatter.columnize(columns) +
|
||||
')'
|
||||
);
|
||||
}
|
||||
|
||||
dropIndex(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
this.pushQuery(`drop index ${indexName}`);
|
||||
}
|
||||
|
||||
unique(columns, indexName) {
|
||||
let deferrable;
|
||||
if (isObject(indexName)) {
|
||||
({ indexName, deferrable } = indexName);
|
||||
}
|
||||
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add constraint ${indexName}` +
|
||||
' unique (' +
|
||||
this.formatter.columnize(columns) +
|
||||
')' +
|
||||
deferrable
|
||||
);
|
||||
}
|
||||
|
||||
dropUnique(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${indexName}`
|
||||
);
|
||||
}
|
||||
|
||||
dropForeign(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('foreign', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${indexName}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TableCompiler_Oracle.prototype.addColumnsPrefix = 'add ';
|
||||
TableCompiler_Oracle.prototype.alterColumnsPrefix = 'modify ';
|
||||
|
||||
module.exports = TableCompiler_Oracle;
|
106
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/utils.js
generated
vendored
Normal file
106
backend/apis/nodejs/node_modules/knex/lib/dialects/oracle/utils.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
class NameHelper {
|
||||
constructor(oracleVersion) {
|
||||
this.oracleVersion = oracleVersion;
|
||||
|
||||
// In oracle versions prior to 12.2, the maximum length for a database
|
||||
// object name was 30 characters. 12.2 extended this to 128.
|
||||
const versionParts = oracleVersion
|
||||
.split('.')
|
||||
.map((versionPart) => parseInt(versionPart));
|
||||
if (
|
||||
versionParts[0] > 12 ||
|
||||
(versionParts[0] === 12 && versionParts[1] >= 2)
|
||||
) {
|
||||
this.limit = 128;
|
||||
} else {
|
||||
this.limit = 30;
|
||||
}
|
||||
}
|
||||
|
||||
generateCombinedName(logger, postfix, name, subNames) {
|
||||
const crypto = require('crypto');
|
||||
if (!Array.isArray(subNames)) subNames = subNames ? [subNames] : [];
|
||||
const table = name.replace(/\.|-/g, '_');
|
||||
const subNamesPart = subNames.join('_');
|
||||
let result = `${table}_${
|
||||
subNamesPart.length ? subNamesPart + '_' : ''
|
||||
}${postfix}`.toLowerCase();
|
||||
if (result.length > this.limit) {
|
||||
logger.warn(
|
||||
`Automatically generated name "${result}" exceeds ${this.limit} character ` +
|
||||
`limit for Oracle Database ${this.oracleVersion}. Using base64 encoded sha1 of that name instead.`
|
||||
);
|
||||
// generates the sha1 of the name and encode it with base64
|
||||
result = crypto
|
||||
.createHash('sha1')
|
||||
.update(result)
|
||||
.digest('base64')
|
||||
.replace('=', '');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function wrapSqlWithCatch(sql, errorNumberToCatch) {
|
||||
return (
|
||||
`begin execute immediate '${sql.replace(/'/g, "''")}'; ` +
|
||||
`exception when others then if sqlcode != ${errorNumberToCatch} then raise; ` +
|
||||
`end if; ` +
|
||||
`end;`
|
||||
);
|
||||
}
|
||||
|
||||
function ReturningHelper(columnName) {
|
||||
this.columnName = columnName;
|
||||
}
|
||||
|
||||
ReturningHelper.prototype.toString = function () {
|
||||
return `[object ReturningHelper:${this.columnName}]`;
|
||||
};
|
||||
|
||||
// If the error is any of these, we'll assume we need to
|
||||
// mark the connection as failed
|
||||
function isConnectionError(err) {
|
||||
return [
|
||||
'DPI-1010', // not connected
|
||||
'DPI-1080', // connection was closed by ORA-%d
|
||||
'ORA-03114', // not connected to ORACLE
|
||||
'ORA-03113', // end-of-file on communication channel
|
||||
'ORA-03135', // connection lost contact
|
||||
'ORA-12514', // listener does not currently know of service requested in connect descriptor
|
||||
'ORA-00022', // invalid session ID; access denied
|
||||
'ORA-00028', // your session has been killed
|
||||
'ORA-00031', // your session has been marked for kill
|
||||
'ORA-00045', // your session has been terminated with no replay
|
||||
'ORA-00378', // buffer pools cannot be created as specified
|
||||
'ORA-00602', // internal programming exception
|
||||
'ORA-00603', // ORACLE server session terminated by fatal error
|
||||
'ORA-00609', // could not attach to incoming connection
|
||||
'ORA-01012', // not logged on
|
||||
'ORA-01041', // internal error. hostdef extension doesn't exist
|
||||
'ORA-01043', // user side memory corruption
|
||||
'ORA-01089', // immediate shutdown or close in progress
|
||||
'ORA-01092', // ORACLE instance terminated. Disconnection forced
|
||||
'ORA-02396', // exceeded maximum idle time, please connect again
|
||||
'ORA-03122', // attempt to close ORACLE-side window on user side
|
||||
'ORA-12153', // TNS'not connected
|
||||
'ORA-12537', // TNS'connection closed
|
||||
'ORA-12547', // TNS'lost contact
|
||||
'ORA-12570', // TNS'packet reader failure
|
||||
'ORA-12583', // TNS'no reader
|
||||
'ORA-27146', // post/wait initialization failed
|
||||
'ORA-28511', // lost RPC connection
|
||||
'ORA-56600', // an illegal OCI function call was issued
|
||||
'NJS-024',
|
||||
'NJS-003',
|
||||
].some(function (prefix) {
|
||||
return err.message.indexOf(prefix) === 0;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
NameHelper,
|
||||
isConnectionError,
|
||||
wrapSqlWithCatch,
|
||||
ReturningHelper,
|
||||
};
|
381
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/index.js
generated
vendored
Normal file
381
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/index.js
generated
vendored
Normal file
@ -0,0 +1,381 @@
|
||||
// Oracledb Client
|
||||
// -------
|
||||
const each = require('lodash/each');
|
||||
const flatten = require('lodash/flatten');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const map = require('lodash/map');
|
||||
|
||||
const Formatter = require('../../formatter');
|
||||
const QueryCompiler = require('./query/oracledb-querycompiler');
|
||||
const TableCompiler = require('./schema/oracledb-tablecompiler');
|
||||
const ColumnCompiler = require('./schema/oracledb-columncompiler');
|
||||
const {
|
||||
BlobHelper,
|
||||
ReturningHelper,
|
||||
monkeyPatchConnection,
|
||||
} = require('./utils');
|
||||
const ViewCompiler = require('./schema/oracledb-viewcompiler');
|
||||
const ViewBuilder = require('./schema/oracledb-viewbuilder');
|
||||
const Transaction = require('./transaction');
|
||||
const Client_Oracle = require('../oracle');
|
||||
const { isString } = require('../../util/is');
|
||||
const { outputQuery, unwrapRaw } = require('../../formatter/wrappingFormatter');
|
||||
const { compileCallback } = require('../../formatter/formatterUtils');
|
||||
|
||||
class Client_Oracledb extends Client_Oracle {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
|
||||
if (this.version) {
|
||||
// Normalize version format; null bad format
|
||||
// to trigger fallback to auto-detect.
|
||||
this.version = parseVersion(this.version);
|
||||
}
|
||||
|
||||
if (this.driver) {
|
||||
process.env.UV_THREADPOOL_SIZE = process.env.UV_THREADPOOL_SIZE || 1;
|
||||
process.env.UV_THREADPOOL_SIZE =
|
||||
parseInt(process.env.UV_THREADPOOL_SIZE) + this.driver.poolMax;
|
||||
}
|
||||
}
|
||||
|
||||
_driver() {
|
||||
const client = this;
|
||||
const oracledb = require('oracledb');
|
||||
client.fetchAsString = [];
|
||||
if (this.config.fetchAsString && Array.isArray(this.config.fetchAsString)) {
|
||||
this.config.fetchAsString.forEach(function (type) {
|
||||
if (!isString(type)) return;
|
||||
type = type.toUpperCase();
|
||||
if (oracledb[type]) {
|
||||
if (
|
||||
type !== 'NUMBER' &&
|
||||
type !== 'DATE' &&
|
||||
type !== 'CLOB' &&
|
||||
type !== 'BUFFER'
|
||||
) {
|
||||
this.logger.warn(
|
||||
'Only "date", "number", "clob" and "buffer" are supported for fetchAsString'
|
||||
);
|
||||
}
|
||||
client.fetchAsString.push(oracledb[type]);
|
||||
}
|
||||
});
|
||||
}
|
||||
return oracledb;
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
formatter(builder) {
|
||||
return new Formatter(this, builder);
|
||||
}
|
||||
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
prepBindings(bindings) {
|
||||
return map(bindings, (value) => {
|
||||
if (value instanceof BlobHelper && this.driver) {
|
||||
return { type: this.driver.BLOB, dir: this.driver.BIND_OUT };
|
||||
// Returning helper always use ROWID as string
|
||||
} else if (value instanceof ReturningHelper && this.driver) {
|
||||
return { type: this.driver.STRING, dir: this.driver.BIND_OUT };
|
||||
} else if (typeof value === 'boolean') {
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
// Checks whether a value is a function... if it is, we compile it
|
||||
// otherwise we check whether it's a raw
|
||||
parameter(value, builder, formatter) {
|
||||
if (typeof value === 'function') {
|
||||
return outputQuery(
|
||||
compileCallback(value, undefined, this, formatter),
|
||||
true,
|
||||
builder,
|
||||
this
|
||||
);
|
||||
} else if (value instanceof BlobHelper) {
|
||||
formatter.bindings.push(value.value);
|
||||
return '?';
|
||||
}
|
||||
return unwrapRaw(value, true, builder, this, formatter) || '?';
|
||||
}
|
||||
|
||||
// Get a raw connection, called by the `pool` whenever a new
|
||||
// connection needs to be added to the pool.
|
||||
acquireRawConnection() {
|
||||
return new Promise((resolver, rejecter) => {
|
||||
// If external authentication don't have to worry about username/password and
|
||||
// if not need to set the username and password
|
||||
const oracleDbConfig = this.connectionSettings.externalAuth
|
||||
? { externalAuth: this.connectionSettings.externalAuth }
|
||||
: {
|
||||
user: this.connectionSettings.user,
|
||||
password: this.connectionSettings.password,
|
||||
};
|
||||
|
||||
// In the case of external authentication connection string will be given
|
||||
oracleDbConfig.connectString = resolveConnectString(
|
||||
this.connectionSettings
|
||||
);
|
||||
|
||||
if (this.connectionSettings.prefetchRowCount) {
|
||||
oracleDbConfig.prefetchRows = this.connectionSettings.prefetchRowCount;
|
||||
}
|
||||
|
||||
if (this.connectionSettings.stmtCacheSize !== undefined) {
|
||||
oracleDbConfig.stmtCacheSize = this.connectionSettings.stmtCacheSize;
|
||||
}
|
||||
|
||||
this.driver.fetchAsString = this.fetchAsString;
|
||||
|
||||
this.driver.getConnection(oracleDbConfig, (err, connection) => {
|
||||
if (err) {
|
||||
return rejecter(err);
|
||||
}
|
||||
monkeyPatchConnection(connection, this);
|
||||
|
||||
resolver(connection);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool
|
||||
// when a connection times out or the pool is shutdown.
|
||||
destroyRawConnection(connection) {
|
||||
return connection.release();
|
||||
}
|
||||
|
||||
// Handle oracle version resolution on acquiring connection from pool instead of connection creation.
|
||||
// Must do this here since only the client used to create a connection would be updated with version
|
||||
// information on creation. Poses a problem when knex instance is cloned since instances share the
|
||||
// connection pool while having their own client instances.
|
||||
async acquireConnection() {
|
||||
const connection = await super.acquireConnection();
|
||||
this.checkVersion(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
// In Oracle, we need to check the version to dynamically determine
|
||||
// certain limits. If user did not specify a version, get it from the connection.
|
||||
checkVersion(connection) {
|
||||
// Already determined version before?
|
||||
if (this.version) {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
const detectedVersion = parseVersion(connection.oracleServerVersionString);
|
||||
if (!detectedVersion) {
|
||||
// When original version is set to null, user-provided version was invalid and we fell-back to auto-detect.
|
||||
// Otherwise, we couldn't auto-detect at all. Set error message accordingly.
|
||||
throw new Error(
|
||||
this.version === null
|
||||
? 'Invalid Oracledb version number format passed to knex. Unable to successfully auto-detect as fallback. Please specify a valid oracledb version.'
|
||||
: 'Unable to detect Oracledb version number automatically. Please specify the version in knex configuration.'
|
||||
);
|
||||
}
|
||||
|
||||
this.version = detectedVersion;
|
||||
return detectedVersion;
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings
|
||||
// and any other necessary prep work.
|
||||
_query(connection, obj) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
const options = Object.assign({}, obj.options, { autoCommit: false });
|
||||
if (obj.method === 'select') {
|
||||
options.resultSet = true;
|
||||
}
|
||||
return connection
|
||||
.executeAsync(obj.sql, obj.bindings, options)
|
||||
.then(async function (response) {
|
||||
// Flatten outBinds
|
||||
let outBinds = flatten(response.outBinds);
|
||||
obj.response = response.rows || [];
|
||||
obj.rowsAffected = response.rows
|
||||
? response.rows.rowsAffected
|
||||
: response.rowsAffected;
|
||||
|
||||
//added for outBind parameter
|
||||
if (obj.method === 'raw' && outBinds.length > 0) {
|
||||
return {
|
||||
response: outBinds,
|
||||
};
|
||||
}
|
||||
|
||||
if (obj.method === 'update') {
|
||||
const modifiedRowsCount = obj.rowsAffected.length || obj.rowsAffected;
|
||||
const updatedObjOutBinding = [];
|
||||
const updatedOutBinds = [];
|
||||
const updateOutBinds = (i) =>
|
||||
function (value, index) {
|
||||
const OutBindsOffset = index * modifiedRowsCount;
|
||||
updatedOutBinds.push(outBinds[i + OutBindsOffset]);
|
||||
};
|
||||
|
||||
for (let i = 0; i < modifiedRowsCount; i++) {
|
||||
updatedObjOutBinding.push(obj.outBinding[0]);
|
||||
each(obj.outBinding[0], updateOutBinds(i));
|
||||
}
|
||||
outBinds = updatedOutBinds;
|
||||
obj.outBinding = updatedObjOutBinding;
|
||||
}
|
||||
|
||||
if (!obj.returning && outBinds.length === 0) {
|
||||
if (!connection.isTransaction) {
|
||||
await connection.commitAsync();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
const rowIds = [];
|
||||
let offset = 0;
|
||||
|
||||
for (let line = 0; line < obj.outBinding.length; line++) {
|
||||
const ret = obj.outBinding[line];
|
||||
|
||||
offset =
|
||||
offset +
|
||||
(obj.outBinding[line - 1] ? obj.outBinding[line - 1].length : 0);
|
||||
|
||||
for (let index = 0; index < ret.length; index++) {
|
||||
const out = ret[index];
|
||||
|
||||
await new Promise(function (bindResolver, bindRejecter) {
|
||||
if (out instanceof BlobHelper) {
|
||||
const blob = outBinds[index + offset];
|
||||
if (out.returning) {
|
||||
obj.response[line] = obj.response[line] || {};
|
||||
obj.response[line][out.columnName] = out.value;
|
||||
}
|
||||
blob.on('error', function (err) {
|
||||
bindRejecter(err);
|
||||
});
|
||||
blob.on('finish', function () {
|
||||
bindResolver();
|
||||
});
|
||||
blob.write(out.value);
|
||||
blob.end();
|
||||
} else if (obj.outBinding[line][index] === 'ROWID') {
|
||||
rowIds.push(outBinds[index + offset]);
|
||||
bindResolver();
|
||||
} else {
|
||||
obj.response[line] = obj.response[line] || {};
|
||||
obj.response[line][out] = outBinds[index + offset];
|
||||
bindResolver();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (obj.returningSql) {
|
||||
const response = await connection.executeAsync(
|
||||
obj.returningSql(),
|
||||
rowIds,
|
||||
{ resultSet: true }
|
||||
);
|
||||
obj.response = response.rows;
|
||||
}
|
||||
if (connection.isTransaction) {
|
||||
return obj;
|
||||
}
|
||||
await connection.commitAsync();
|
||||
return obj;
|
||||
});
|
||||
}
|
||||
|
||||
// Process the response as returned from the query.
|
||||
processResponse(obj, runner) {
|
||||
const { response } = obj;
|
||||
if (obj.output) {
|
||||
return obj.output.call(runner, response);
|
||||
}
|
||||
switch (obj.method) {
|
||||
case 'select':
|
||||
return response;
|
||||
case 'first':
|
||||
return response[0];
|
||||
case 'pluck':
|
||||
return map(response, obj.pluck);
|
||||
case 'insert':
|
||||
case 'del':
|
||||
case 'update':
|
||||
case 'counter':
|
||||
if ((obj.returning && !isEmpty(obj.returning)) || obj.returningSql) {
|
||||
return response;
|
||||
} else if (obj.rowsAffected !== undefined) {
|
||||
return obj.rowsAffected;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
processPassedConnection(connection) {
|
||||
this.checkVersion(connection);
|
||||
monkeyPatchConnection(connection, this);
|
||||
}
|
||||
}
|
||||
|
||||
Client_Oracledb.prototype.driverName = 'oracledb';
|
||||
|
||||
function parseVersion(versionString) {
|
||||
try {
|
||||
// We only care about first two version components at most
|
||||
const versionParts = versionString.split('.').slice(0, 2);
|
||||
// Strip off any character suffixes in version number (ex. 12c => 12, 12.2c => 12.2)
|
||||
versionParts.forEach((versionPart, idx) => {
|
||||
versionParts[idx] = versionPart.replace(/\D$/, '');
|
||||
});
|
||||
const version = versionParts.join('.');
|
||||
return version.match(/^\d+\.?\d*$/) ? version : null;
|
||||
} catch (err) {
|
||||
// Non-string versionString passed in.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveConnectString(connectionSettings) {
|
||||
if (connectionSettings.connectString) {
|
||||
return connectionSettings.connectString;
|
||||
}
|
||||
|
||||
if (!connectionSettings.port) {
|
||||
return connectionSettings.host + '/' + connectionSettings.database;
|
||||
}
|
||||
|
||||
return (
|
||||
connectionSettings.host +
|
||||
':' +
|
||||
connectionSettings.port +
|
||||
'/' +
|
||||
connectionSettings.database
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = Client_Oracledb;
|
481
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js
generated
vendored
Normal file
481
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,481 @@
|
||||
const clone = require('lodash/clone');
|
||||
const each = require('lodash/each');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const isPlainObject = require('lodash/isPlainObject');
|
||||
const Oracle_Compiler = require('../../oracle/query/oracle-querycompiler');
|
||||
const ReturningHelper = require('../utils').ReturningHelper;
|
||||
const BlobHelper = require('../utils').BlobHelper;
|
||||
const { isString } = require('../../../util/is');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class Oracledb_Compiler extends Oracle_Compiler {
|
||||
// Compiles an "insert" query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
const self = this;
|
||||
const outBindPrep = this._prepOutbindings(
|
||||
this.single.insert,
|
||||
this.single.returning
|
||||
);
|
||||
const outBinding = outBindPrep.outBinding;
|
||||
const returning = outBindPrep.returning;
|
||||
const insertValues = outBindPrep.values;
|
||||
|
||||
if (
|
||||
Array.isArray(insertValues) &&
|
||||
insertValues.length === 1 &&
|
||||
isEmpty(insertValues[0])
|
||||
) {
|
||||
const returningFragment = this.single.returning
|
||||
? ' (' + this.formatter.wrap(this.single.returning) + ')'
|
||||
: '';
|
||||
|
||||
return this._addReturningToSqlAndConvert(
|
||||
'insert into ' +
|
||||
this.tableName +
|
||||
returningFragment +
|
||||
' values (default)',
|
||||
outBinding[0],
|
||||
this.tableName,
|
||||
returning
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isEmpty(this.single.insert) &&
|
||||
typeof this.single.insert !== 'function'
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const insertData = this._prepInsert(insertValues);
|
||||
|
||||
const sql = {};
|
||||
|
||||
if (isString(insertData)) {
|
||||
return this._addReturningToSqlAndConvert(
|
||||
'insert into ' + this.tableName + ' ' + insertData,
|
||||
outBinding[0],
|
||||
this.tableName,
|
||||
returning
|
||||
);
|
||||
}
|
||||
|
||||
if (insertData.values.length === 1) {
|
||||
return this._addReturningToSqlAndConvert(
|
||||
'insert into ' +
|
||||
this.tableName +
|
||||
' (' +
|
||||
this.formatter.columnize(insertData.columns) +
|
||||
') values (' +
|
||||
this.client.parameterize(
|
||||
insertData.values[0],
|
||||
undefined,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
')',
|
||||
outBinding[0],
|
||||
this.tableName,
|
||||
returning
|
||||
);
|
||||
}
|
||||
|
||||
const insertDefaultsOnly = insertData.columns.length === 0;
|
||||
sql.returning = returning;
|
||||
sql.sql =
|
||||
'begin ' +
|
||||
insertData.values
|
||||
.map(function (value, index) {
|
||||
const parameterizedValues = !insertDefaultsOnly
|
||||
? self.client.parameterize(
|
||||
value,
|
||||
self.client.valueForUndefined,
|
||||
self.builder,
|
||||
self.bindingsHolder
|
||||
)
|
||||
: '';
|
||||
let subSql = 'insert into ' + self.tableName;
|
||||
|
||||
if (insertDefaultsOnly) {
|
||||
// No columns given so only the default value
|
||||
subSql +=
|
||||
' (' +
|
||||
self.formatter.wrap(self.single.returning) +
|
||||
') values (default)';
|
||||
} else {
|
||||
subSql +=
|
||||
' (' +
|
||||
self.formatter.columnize(insertData.columns) +
|
||||
') values (' +
|
||||
parameterizedValues +
|
||||
')';
|
||||
}
|
||||
|
||||
let returningClause = '';
|
||||
let intoClause = '';
|
||||
// ToDo review if this code is still needed or could be dropped
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let usingClause = '';
|
||||
let outClause = '';
|
||||
|
||||
each(value, function (val) {
|
||||
if (!(val instanceof BlobHelper)) {
|
||||
usingClause += ' ?,';
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
usingClause = usingClause.slice(0, -1);
|
||||
|
||||
// Build returning and into clauses
|
||||
outBinding[index].forEach(function (ret) {
|
||||
const columnName = ret.columnName || ret;
|
||||
returningClause += self.formatter.wrap(columnName) + ',';
|
||||
intoClause += ' ?,';
|
||||
outClause += ' out ?,';
|
||||
|
||||
// Add Helpers to bindings
|
||||
if (ret instanceof BlobHelper) {
|
||||
return self.formatter.bindings.push(ret);
|
||||
}
|
||||
self.formatter.bindings.push(new ReturningHelper(columnName));
|
||||
});
|
||||
|
||||
// Strip last comma
|
||||
returningClause = returningClause.slice(0, -1);
|
||||
intoClause = intoClause.slice(0, -1);
|
||||
outClause = outClause.slice(0, -1);
|
||||
|
||||
if (returningClause && intoClause) {
|
||||
subSql += ' returning ' + returningClause + ' into' + intoClause;
|
||||
}
|
||||
|
||||
// Pre bind position because subSql is an execute immediate parameter
|
||||
// later position binding will only convert the ? params
|
||||
subSql = self.formatter.client.positionBindings(subSql);
|
||||
const parameterizedValuesWithoutDefaultAndBlob = parameterizedValues
|
||||
.replace(/DEFAULT, /g, '')
|
||||
.replace(/, DEFAULT/g, '')
|
||||
.replace('EMPTY_BLOB(), ', '')
|
||||
.replace(', EMPTY_BLOB()', '');
|
||||
return (
|
||||
"execute immediate '" +
|
||||
subSql.replace(/'/g, "''") +
|
||||
(parameterizedValuesWithoutDefaultAndBlob || value
|
||||
? "' using "
|
||||
: '') +
|
||||
parameterizedValuesWithoutDefaultAndBlob +
|
||||
(parameterizedValuesWithoutDefaultAndBlob && outClause ? ',' : '') +
|
||||
outClause +
|
||||
';'
|
||||
);
|
||||
})
|
||||
.join(' ') +
|
||||
'end;';
|
||||
|
||||
sql.outBinding = outBinding;
|
||||
if (returning[0] === '*') {
|
||||
// Generate select statement with special order by
|
||||
// to keep the order because 'in (..)' may change the order
|
||||
sql.returningSql = function () {
|
||||
return (
|
||||
'select * from ' +
|
||||
self.tableName +
|
||||
' where ROWID in (' +
|
||||
this.outBinding
|
||||
.map(function (v, i) {
|
||||
return ':' + (i + 1);
|
||||
})
|
||||
.join(', ') +
|
||||
')' +
|
||||
' order by case ROWID ' +
|
||||
this.outBinding
|
||||
.map(function (v, i) {
|
||||
return 'when CHARTOROWID(:' + (i + 1) + ') then ' + i;
|
||||
})
|
||||
.join(' ') +
|
||||
' end'
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
with() {
|
||||
// WITH RECURSIVE is a syntax error in Oracle SQL.
|
||||
// So mark all statements as non-recursive, generate the SQL, then restore.
|
||||
// This approach ensures any changes in base class with() get propagated here.
|
||||
const undoList = [];
|
||||
if (this.grouped.with) {
|
||||
for (const stmt of this.grouped.with) {
|
||||
if (stmt.recursive) {
|
||||
undoList.push(stmt);
|
||||
stmt.recursive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = super.with();
|
||||
|
||||
// Restore the recursive markings, in case this same query gets cloned and passed to other drivers.
|
||||
for (const stmt of undoList) {
|
||||
stmt.recursive = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
_addReturningToSqlAndConvert(sql, outBinding, tableName, returning) {
|
||||
const self = this;
|
||||
const res = {
|
||||
sql: sql,
|
||||
};
|
||||
|
||||
if (!outBinding) {
|
||||
return res;
|
||||
}
|
||||
const returningValues = Array.isArray(outBinding)
|
||||
? outBinding
|
||||
: [outBinding];
|
||||
let returningClause = '';
|
||||
let intoClause = '';
|
||||
// Build returning and into clauses
|
||||
returningValues.forEach(function (ret) {
|
||||
const columnName = ret.columnName || ret;
|
||||
returningClause += self.formatter.wrap(columnName) + ',';
|
||||
intoClause += '?,';
|
||||
|
||||
// Add Helpers to bindings
|
||||
if (ret instanceof BlobHelper) {
|
||||
return self.formatter.bindings.push(ret);
|
||||
}
|
||||
self.formatter.bindings.push(new ReturningHelper(columnName));
|
||||
});
|
||||
res.sql = sql;
|
||||
|
||||
// Strip last comma
|
||||
returningClause = returningClause.slice(0, -1);
|
||||
intoClause = intoClause.slice(0, -1);
|
||||
if (returningClause && intoClause) {
|
||||
res.sql += ' returning ' + returningClause + ' into ' + intoClause;
|
||||
}
|
||||
res.outBinding = [outBinding];
|
||||
if (returning[0] === '*') {
|
||||
res.returningSql = function () {
|
||||
return 'select * from ' + self.tableName + ' where ROWID = :1';
|
||||
};
|
||||
}
|
||||
res.returning = returning;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
_prepOutbindings(paramValues, paramReturning) {
|
||||
const result = {};
|
||||
let params = paramValues || [];
|
||||
let returning = paramReturning || [];
|
||||
if (!Array.isArray(params) && isPlainObject(paramValues)) {
|
||||
params = [params];
|
||||
}
|
||||
// Always wrap returning argument in array
|
||||
if (returning && !Array.isArray(returning)) {
|
||||
returning = [returning];
|
||||
}
|
||||
|
||||
const outBinding = [];
|
||||
// Handle Buffer value as Blob
|
||||
each(params, function (values, index) {
|
||||
if (returning[0] === '*') {
|
||||
outBinding[index] = ['ROWID'];
|
||||
} else {
|
||||
outBinding[index] = clone(returning);
|
||||
}
|
||||
each(values, function (value, key) {
|
||||
if (value instanceof Buffer) {
|
||||
values[key] = new BlobHelper(key, value);
|
||||
|
||||
// Delete blob duplicate in returning
|
||||
const blobIndex = outBinding[index].indexOf(key);
|
||||
if (blobIndex >= 0) {
|
||||
outBinding[index].splice(blobIndex, 1);
|
||||
values[key].returning = true;
|
||||
}
|
||||
outBinding[index].push(values[key]);
|
||||
}
|
||||
if (value === undefined) {
|
||||
delete params[index][key];
|
||||
}
|
||||
});
|
||||
});
|
||||
result.returning = returning;
|
||||
result.outBinding = outBinding;
|
||||
result.values = params;
|
||||
return result;
|
||||
}
|
||||
|
||||
_groupOrder(item, type) {
|
||||
return super._groupOrderNulls(item, type);
|
||||
}
|
||||
|
||||
update() {
|
||||
const self = this;
|
||||
const sql = {};
|
||||
const outBindPrep = this._prepOutbindings(
|
||||
this.single.update || this.single.counter,
|
||||
this.single.returning
|
||||
);
|
||||
const outBinding = outBindPrep.outBinding;
|
||||
const returning = outBindPrep.returning;
|
||||
|
||||
const updates = this._prepUpdate(this.single.update);
|
||||
const where = this.where();
|
||||
|
||||
let returningClause = '';
|
||||
let intoClause = '';
|
||||
|
||||
if (isEmpty(updates) && typeof this.single.update !== 'function') {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Build returning and into clauses
|
||||
outBinding.forEach(function (out) {
|
||||
out.forEach(function (ret) {
|
||||
const columnName = ret.columnName || ret;
|
||||
returningClause += self.formatter.wrap(columnName) + ',';
|
||||
intoClause += ' ?,';
|
||||
|
||||
// Add Helpers to bindings
|
||||
if (ret instanceof BlobHelper) {
|
||||
return self.formatter.bindings.push(ret);
|
||||
}
|
||||
self.formatter.bindings.push(new ReturningHelper(columnName));
|
||||
});
|
||||
});
|
||||
// Strip last comma
|
||||
returningClause = returningClause.slice(0, -1);
|
||||
intoClause = intoClause.slice(0, -1);
|
||||
|
||||
sql.outBinding = outBinding;
|
||||
sql.returning = returning;
|
||||
sql.sql =
|
||||
'update ' +
|
||||
this.tableName +
|
||||
' set ' +
|
||||
updates.join(', ') +
|
||||
(where ? ' ' + where : '');
|
||||
if (outBinding.length && !isEmpty(outBinding[0])) {
|
||||
sql.sql += ' returning ' + returningClause + ' into' + intoClause;
|
||||
}
|
||||
if (returning[0] === '*') {
|
||||
sql.returningSql = function () {
|
||||
let sql = 'select * from ' + self.tableName;
|
||||
const modifiedRowsCount = this.rowsAffected.length || this.rowsAffected;
|
||||
let returningSqlIn = ' where ROWID in (';
|
||||
let returningSqlOrderBy = ') order by case ROWID ';
|
||||
|
||||
// Needs special order by because in(...) change result order
|
||||
for (let i = 0; i < modifiedRowsCount; i++) {
|
||||
if (this.returning[0] === '*') {
|
||||
returningSqlIn += ':' + (i + 1) + ', ';
|
||||
returningSqlOrderBy +=
|
||||
'when CHARTOROWID(:' + (i + 1) + ') then ' + i + ' ';
|
||||
}
|
||||
}
|
||||
if (this.returning[0] === '*') {
|
||||
this.returning = this.returning.slice(0, -1);
|
||||
returningSqlIn = returningSqlIn.slice(0, -2);
|
||||
returningSqlOrderBy = returningSqlOrderBy.slice(0, -1);
|
||||
}
|
||||
return (sql += returningSqlIn + returningSqlOrderBy + ' end');
|
||||
};
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_jsonPathWrap(extraction) {
|
||||
return `'${extraction.path || extraction[1]}'`;
|
||||
}
|
||||
|
||||
// Json functions
|
||||
jsonExtract(params) {
|
||||
return this._jsonExtract(
|
||||
params.singleValue ? 'json_value' : 'json_query',
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
return `json_transform(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)}, set ${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)} = ${this.client.parameter(
|
||||
params.value,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
return `json_transform(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)}, insert ${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)} = ${this.client.parameter(
|
||||
params.value,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
const jsonCol = `json_transform(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)}, remove ${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
return params.alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
||||
: jsonCol;
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
return this._whereJsonPath('json_value', statement);
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
throw new Error(
|
||||
'Json superset where clause not actually supported by Oracle'
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
throw new Error(
|
||||
'Json subset where clause not actually supported by Oracle'
|
||||
);
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('json_value', clause);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Oracledb_Compiler;
|
61
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js
generated
vendored
Normal file
61
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
const ColumnCompiler_Oracle = require('../../oracle/schema/oracle-columncompiler');
|
||||
const { isObject } = require('../../../util/is');
|
||||
|
||||
class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.modifiers = ['defaultTo', 'nullable', 'comment', 'checkJson'];
|
||||
this._addCheckModifiers();
|
||||
}
|
||||
|
||||
datetime(withoutTz) {
|
||||
let useTz;
|
||||
if (isObject(withoutTz)) {
|
||||
({ useTz } = withoutTz);
|
||||
} else {
|
||||
useTz = !withoutTz;
|
||||
}
|
||||
return useTz ? 'timestamp with local time zone' : 'timestamp';
|
||||
}
|
||||
|
||||
timestamp(withoutTz) {
|
||||
let useTz;
|
||||
if (isObject(withoutTz)) {
|
||||
({ useTz } = withoutTz);
|
||||
} else {
|
||||
useTz = !withoutTz;
|
||||
}
|
||||
return useTz ? 'timestamp with local time zone' : 'timestamp';
|
||||
}
|
||||
|
||||
checkRegex(regex, constraintName) {
|
||||
return this._check(
|
||||
`REGEXP_LIKE(${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)},${this.client._escapeBinding(regex)})`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
json() {
|
||||
// implicitly add the check for json
|
||||
this.columnBuilder._modifiers.checkJson = [
|
||||
this.formatter.columnize(this.getColumnName()),
|
||||
];
|
||||
return 'varchar2(4000)';
|
||||
}
|
||||
|
||||
jsonb() {
|
||||
return this.json();
|
||||
}
|
||||
|
||||
checkJson(column) {
|
||||
return `check (${column} is json)`;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_Oracledb.prototype.time = 'timestamp with local time zone';
|
||||
ColumnCompiler_Oracledb.prototype.uuid = ({ useBinaryUuid = false } = {}) =>
|
||||
useBinaryUuid ? 'raw(16)' : 'char(36)';
|
||||
|
||||
module.exports = ColumnCompiler_Oracledb;
|
19
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js
generated
vendored
Normal file
19
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
const TableCompiler_Oracle = require('../../oracle/schema/oracle-tablecompiler');
|
||||
|
||||
class TableCompiler_Oracledb extends TableCompiler_Oracle {
|
||||
constructor(client, tableBuilder) {
|
||||
super(client, tableBuilder);
|
||||
}
|
||||
|
||||
_setNullableState(column, isNullable) {
|
||||
const nullability = isNullable ? 'NULL' : 'NOT NULL';
|
||||
const sql = `alter table ${this.tableName()} modify (${this.formatter.wrap(
|
||||
column
|
||||
)} ${nullability})`;
|
||||
return this.pushQuery({
|
||||
sql: sql,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TableCompiler_Oracledb;
|
13
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js
generated
vendored
Normal file
13
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
const ViewBuilder = require('../../../schema/viewbuilder.js');
|
||||
|
||||
class ViewBuilder_Oracledb extends ViewBuilder {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
checkOption() {
|
||||
this._single.checkOption = 'default_option';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewBuilder_Oracledb;
|
19
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js
generated
vendored
Normal file
19
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
|
||||
class ViewCompiler_Oracledb extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
|
||||
createOrReplace() {
|
||||
this.createQuery(this.columns, this.selectQuery, false, true);
|
||||
}
|
||||
|
||||
createMaterializedView() {
|
||||
this.createQuery(this.columns, this.selectQuery, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_Oracledb;
|
98
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/transaction.js
generated
vendored
Normal file
98
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/transaction.js
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
const Transaction = require('../../execution/transaction');
|
||||
const { timeout, KnexTimeoutError } = require('../../util/timeout');
|
||||
const debugTx = require('debug')('knex:tx');
|
||||
|
||||
// There's also a "read only", but that's not really an "isolationLevel"
|
||||
const supportedIsolationLevels = ['read committed', 'serializable'];
|
||||
// Remove this if you make it work and set it to true
|
||||
const isIsolationLevelEnabled = false;
|
||||
|
||||
module.exports = class Oracle_Transaction extends Transaction {
|
||||
// disable autocommit to allow correct behavior (default is true)
|
||||
begin(conn) {
|
||||
if (this.isolationLevel) {
|
||||
if (isIsolationLevelEnabled) {
|
||||
if (!supportedIsolationLevels.includes(this.isolationLevel)) {
|
||||
this.client.logger.warn(
|
||||
'Oracle only supports read committed and serializable transactions, ignoring the isolation level param'
|
||||
);
|
||||
} else {
|
||||
// I tried this, but it didn't work
|
||||
// Doc here: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SET-TRANSACTION.html
|
||||
return this.query(conn, `SET TRANSACTION ${this.isolationLevel}`);
|
||||
}
|
||||
} else {
|
||||
this.client.logger.warn(
|
||||
'Transaction isolation is not currently supported for Oracle'
|
||||
);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
async commit(conn, value) {
|
||||
this._completed = true;
|
||||
try {
|
||||
await conn.commitAsync();
|
||||
this._resolver(value);
|
||||
} catch (err) {
|
||||
this._rejecter(err);
|
||||
}
|
||||
}
|
||||
|
||||
release(conn, value) {
|
||||
return this._resolver(value);
|
||||
}
|
||||
|
||||
rollback(conn, err) {
|
||||
this._completed = true;
|
||||
debugTx('%s: rolling back', this.txid);
|
||||
return timeout(conn.rollbackAsync(), 5000)
|
||||
.catch((e) => {
|
||||
if (!(e instanceof KnexTimeoutError)) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
this._rejecter(e);
|
||||
})
|
||||
.then(() => {
|
||||
if (err === undefined) {
|
||||
if (this.doNotRejectOnRollback) {
|
||||
this._resolver();
|
||||
return;
|
||||
}
|
||||
err = new Error(`Transaction rejected with non-error: ${err}`);
|
||||
}
|
||||
this._rejecter(err);
|
||||
});
|
||||
}
|
||||
|
||||
savepoint(conn) {
|
||||
return this.query(conn, `SAVEPOINT ${this.txid}`);
|
||||
}
|
||||
|
||||
async acquireConnection(config, cb) {
|
||||
const configConnection = config && config.connection;
|
||||
|
||||
const connection =
|
||||
configConnection || (await this.client.acquireConnection());
|
||||
try {
|
||||
connection.__knexTxId = this.txid;
|
||||
connection.isTransaction = true;
|
||||
return await cb(connection);
|
||||
} finally {
|
||||
debugTx('%s: releasing connection', this.txid);
|
||||
connection.isTransaction = false;
|
||||
try {
|
||||
await connection.commitAsync();
|
||||
} catch (err) {
|
||||
this._rejecter(err);
|
||||
} finally {
|
||||
if (!configConnection) {
|
||||
await this.client.releaseConnection(connection);
|
||||
} else {
|
||||
debugTx('%s: not releasing external connection', this.txid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
208
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/utils.js
generated
vendored
Normal file
208
backend/apis/nodejs/node_modules/knex/lib/dialects/oracledb/utils.js
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
const Utils = require('../oracle/utils');
|
||||
const { promisify } = require('util');
|
||||
const stream = require('stream');
|
||||
|
||||
function BlobHelper(columnName, value) {
|
||||
this.columnName = columnName;
|
||||
this.value = value;
|
||||
this.returning = false;
|
||||
}
|
||||
|
||||
BlobHelper.prototype.toString = function () {
|
||||
return '[object BlobHelper:' + this.columnName + ']';
|
||||
};
|
||||
|
||||
/**
|
||||
* @param stream
|
||||
* @param {'string' | 'buffer'} type
|
||||
*/
|
||||
function readStream(stream, type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = type === 'string' ? '' : Buffer.alloc(0);
|
||||
|
||||
stream.on('error', function (err) {
|
||||
reject(err);
|
||||
});
|
||||
stream.on('data', function (chunk) {
|
||||
if (type === 'string') {
|
||||
data += chunk;
|
||||
} else {
|
||||
data = Buffer.concat([data, chunk]);
|
||||
}
|
||||
});
|
||||
stream.on('end', function () {
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const lobProcessing = function (stream) {
|
||||
const oracledb = require('oracledb');
|
||||
|
||||
/**
|
||||
* @type 'string' | 'buffer'
|
||||
*/
|
||||
let type;
|
||||
|
||||
if (stream.type) {
|
||||
// v1.2-v4
|
||||
if (stream.type === oracledb.BLOB) {
|
||||
type = 'buffer';
|
||||
} else if (stream.type === oracledb.CLOB) {
|
||||
type = 'string';
|
||||
}
|
||||
} else if (stream.iLob) {
|
||||
// v1
|
||||
if (stream.iLob.type === oracledb.CLOB) {
|
||||
type = 'string';
|
||||
} else if (stream.iLob.type === oracledb.BLOB) {
|
||||
type = 'buffer';
|
||||
}
|
||||
} else {
|
||||
throw new Error('Unrecognized oracledb lob stream type');
|
||||
}
|
||||
if (type === 'string') {
|
||||
stream.setEncoding('utf-8');
|
||||
}
|
||||
return readStream(stream, type);
|
||||
};
|
||||
|
||||
function monkeyPatchConnection(connection, client) {
|
||||
// Connection is already monkey-patched
|
||||
if (connection.executeAsync) {
|
||||
return;
|
||||
}
|
||||
|
||||
connection.commitAsync = function () {
|
||||
return new Promise((commitResolve, commitReject) => {
|
||||
this.commit(function (err) {
|
||||
if (err) {
|
||||
return commitReject(err);
|
||||
}
|
||||
commitResolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
connection.rollbackAsync = function () {
|
||||
return new Promise((rollbackResolve, rollbackReject) => {
|
||||
this.rollback(function (err) {
|
||||
if (err) {
|
||||
return rollbackReject(err);
|
||||
}
|
||||
rollbackResolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
const fetchAsync = promisify(function (sql, bindParams, options, cb) {
|
||||
options = options || {};
|
||||
options.outFormat = client.driver.OUT_FORMAT_OBJECT || client.driver.OBJECT;
|
||||
if (!options.outFormat) {
|
||||
throw new Error('not found oracledb.outFormat constants');
|
||||
}
|
||||
if (options.resultSet) {
|
||||
connection.execute(
|
||||
sql,
|
||||
bindParams || [],
|
||||
options,
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
if (Utils.isConnectionError(err)) {
|
||||
connection.close().catch(function (err) {});
|
||||
connection.__knex__disposed = err;
|
||||
}
|
||||
return cb(err);
|
||||
}
|
||||
const fetchResult = { rows: [], resultSet: result.resultSet };
|
||||
const numRows = 100;
|
||||
const fetchRowsFromRS = function (connection, resultSet, numRows) {
|
||||
resultSet.getRows(numRows, function (err, rows) {
|
||||
if (err) {
|
||||
if (Utils.isConnectionError(err)) {
|
||||
connection.close().catch(function (err) {});
|
||||
connection.__knex__disposed = err;
|
||||
}
|
||||
resultSet.close(function () {
|
||||
return cb(err);
|
||||
});
|
||||
} else if (rows.length === 0) {
|
||||
return cb(null, fetchResult);
|
||||
} else if (rows.length > 0) {
|
||||
if (rows.length === numRows) {
|
||||
fetchResult.rows = fetchResult.rows.concat(rows);
|
||||
fetchRowsFromRS(connection, resultSet, numRows);
|
||||
} else {
|
||||
fetchResult.rows = fetchResult.rows.concat(rows);
|
||||
return cb(null, fetchResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
fetchRowsFromRS(connection, result.resultSet, numRows);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
connection.execute(
|
||||
sql,
|
||||
bindParams || [],
|
||||
options,
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
// dispose the connection on connection error
|
||||
if (Utils.isConnectionError(err)) {
|
||||
connection.close().catch(function (err) {});
|
||||
connection.__knex__disposed = err;
|
||||
}
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
return cb(null, result);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
connection.executeAsync = function (sql, bindParams, options) {
|
||||
// Read all lob
|
||||
return fetchAsync(sql, bindParams, options).then(async (results) => {
|
||||
const closeResultSet = () => {
|
||||
return results.resultSet
|
||||
? promisify(results.resultSet.close).call(results.resultSet)
|
||||
: Promise.resolve();
|
||||
};
|
||||
|
||||
// Collect LOBs to read
|
||||
const lobs = [];
|
||||
if (results.rows) {
|
||||
if (Array.isArray(results.rows)) {
|
||||
for (let i = 0; i < results.rows.length; i++) {
|
||||
// Iterate through the rows
|
||||
const row = results.rows[i];
|
||||
for (const column in row) {
|
||||
if (row[column] instanceof stream.Readable) {
|
||||
lobs.push({ index: i, key: column, stream: row[column] });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (const lob of lobs) {
|
||||
// todo should be fetchAsString/fetchAsBuffer polyfill only
|
||||
results.rows[lob.index][lob.key] = await lobProcessing(lob.stream);
|
||||
}
|
||||
} catch (e) {
|
||||
await closeResultSet().catch(() => {});
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
await closeResultSet();
|
||||
|
||||
return results;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
Utils.BlobHelper = BlobHelper;
|
||||
Utils.monkeyPatchConnection = monkeyPatchConnection;
|
||||
module.exports = Utils;
|
60
backend/apis/nodejs/node_modules/knex/lib/dialects/pgnative/index.js
generated
vendored
Normal file
60
backend/apis/nodejs/node_modules/knex/lib/dialects/pgnative/index.js
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
// PostgreSQL Native Driver (pg-native)
|
||||
// -------
|
||||
const Client_PG = require('../postgres');
|
||||
|
||||
class Client_PgNative extends Client_PG {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.driverName = 'pgnative';
|
||||
this.canCancelQuery = true;
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('pg').native;
|
||||
}
|
||||
|
||||
_stream(connection, obj, stream, options) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
const client = this;
|
||||
return new Promise((resolver, rejecter) => {
|
||||
stream.on('error', rejecter);
|
||||
stream.on('end', resolver);
|
||||
|
||||
return client
|
||||
._query(connection, obj)
|
||||
.then((obj) => obj.response)
|
||||
.then(({ rows }) => rows.forEach((row) => stream.write(row)))
|
||||
.catch(function (err) {
|
||||
stream.emit('error', err);
|
||||
})
|
||||
.then(function () {
|
||||
stream.end();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async cancelQuery(connectionToKill) {
|
||||
try {
|
||||
return await this._wrappedCancelQueryCall(null, connectionToKill);
|
||||
} catch (err) {
|
||||
this.logger.warn(`Connection Error: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
_wrappedCancelQueryCall(emptyConnection, connectionToKill) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
connectionToKill.native.cancel(function (err) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Client_PgNative;
|
19
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js
generated
vendored
Normal file
19
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
const Transaction = require('../../../execution/transaction');
|
||||
|
||||
class Transaction_PG extends Transaction {
|
||||
begin(conn) {
|
||||
const trxMode = [
|
||||
this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '',
|
||||
this.readOnly ? 'READ ONLY' : '',
|
||||
]
|
||||
.join(' ')
|
||||
.trim();
|
||||
|
||||
if (trxMode.length === 0) {
|
||||
return this.query(conn, 'BEGIN;');
|
||||
}
|
||||
return this.query(conn, `BEGIN TRANSACTION ${trxMode};`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction_PG;
|
361
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/index.js
generated
vendored
Normal file
361
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/index.js
generated
vendored
Normal file
@ -0,0 +1,361 @@
|
||||
// PostgreSQL
|
||||
// -------
|
||||
const extend = require('lodash/extend');
|
||||
const map = require('lodash/map');
|
||||
const { promisify } = require('util');
|
||||
const Client = require('../../client');
|
||||
|
||||
const Transaction = require('./execution/pg-transaction');
|
||||
const QueryCompiler = require('./query/pg-querycompiler');
|
||||
const QueryBuilder = require('./query/pg-querybuilder');
|
||||
const ColumnCompiler = require('./schema/pg-columncompiler');
|
||||
const TableCompiler = require('./schema/pg-tablecompiler');
|
||||
const ViewCompiler = require('./schema/pg-viewcompiler');
|
||||
const ViewBuilder = require('./schema/pg-viewbuilder');
|
||||
const SchemaCompiler = require('./schema/pg-compiler');
|
||||
const { makeEscape } = require('../../util/string');
|
||||
const { isString } = require('../../util/is');
|
||||
|
||||
class Client_PG extends Client {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
if (config.returning) {
|
||||
this.defaultReturning = config.returning;
|
||||
}
|
||||
|
||||
if (config.searchPath) {
|
||||
this.searchPath = config.searchPath;
|
||||
}
|
||||
}
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
queryBuilder() {
|
||||
return new QueryBuilder(this);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('pg');
|
||||
}
|
||||
|
||||
wrapIdentifierImpl(value) {
|
||||
if (value === '*') return value;
|
||||
|
||||
let arrayAccessor = '';
|
||||
const arrayAccessorMatch = value.match(/(.*?)(\[[0-9]+\])/);
|
||||
|
||||
if (arrayAccessorMatch) {
|
||||
value = arrayAccessorMatch[1];
|
||||
arrayAccessor = arrayAccessorMatch[2];
|
||||
}
|
||||
|
||||
return `"${value.replace(/"/g, '""')}"${arrayAccessor}`;
|
||||
}
|
||||
|
||||
_acquireOnlyConnection() {
|
||||
const connection = new this.driver.Client(this.connectionSettings);
|
||||
|
||||
connection.on('error', (err) => {
|
||||
connection.__knex__disposed = err;
|
||||
});
|
||||
|
||||
connection.on('end', (err) => {
|
||||
connection.__knex__disposed = err || 'Connection ended unexpectedly';
|
||||
});
|
||||
|
||||
return connection.connect().then(() => connection);
|
||||
}
|
||||
|
||||
// Get a raw connection, called by the `pool` whenever a new
|
||||
// connection needs to be added to the pool.
|
||||
acquireRawConnection() {
|
||||
const client = this;
|
||||
|
||||
return this._acquireOnlyConnection()
|
||||
.then(function (connection) {
|
||||
if (!client.version) {
|
||||
return client.checkVersion(connection).then(function (version) {
|
||||
client.version = version;
|
||||
return connection;
|
||||
});
|
||||
}
|
||||
|
||||
return connection;
|
||||
})
|
||||
.then(async function setSearchPath(connection) {
|
||||
await client.setSchemaSearchPath(connection);
|
||||
return connection;
|
||||
});
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool
|
||||
// when a connection times out or the pool is shutdown.
|
||||
async destroyRawConnection(connection) {
|
||||
const end = promisify((cb) => connection.end(cb));
|
||||
return end();
|
||||
}
|
||||
|
||||
// In PostgreSQL, we need to do a version check to do some feature
|
||||
// checking on the database.
|
||||
checkVersion(connection) {
|
||||
return new Promise((resolve, reject) => {
|
||||
connection.query('select version();', (err, resp) => {
|
||||
if (err) return reject(err);
|
||||
resolve(this._parseVersion(resp.rows[0].version));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_parseVersion(versionString) {
|
||||
return /^PostgreSQL (.*?)( |$)/.exec(versionString)[1];
|
||||
}
|
||||
|
||||
// Position the bindings for the query. The escape sequence for question mark
|
||||
// is \? (e.g. knex.raw("\\?") since javascript requires '\' to be escaped too...)
|
||||
positionBindings(sql) {
|
||||
let questionCount = 0;
|
||||
return sql.replace(/(\\*)(\?)/g, function (match, escapes) {
|
||||
if (escapes.length % 2) {
|
||||
return '?';
|
||||
} else {
|
||||
questionCount++;
|
||||
return `$${questionCount}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setSchemaSearchPath(connection, searchPath) {
|
||||
let path = searchPath || this.searchPath;
|
||||
|
||||
if (!path) return Promise.resolve(true);
|
||||
|
||||
if (!Array.isArray(path) && !isString(path)) {
|
||||
throw new TypeError(
|
||||
`knex: Expected searchPath to be Array/String, got: ${typeof path}`
|
||||
);
|
||||
}
|
||||
|
||||
if (isString(path)) {
|
||||
if (path.includes(',')) {
|
||||
const parts = path.split(',');
|
||||
const arraySyntax = `[${parts
|
||||
.map((searchPath) => `'${searchPath}'`)
|
||||
.join(', ')}]`;
|
||||
this.logger.warn(
|
||||
`Detected comma in searchPath "${path}".` +
|
||||
`If you are trying to specify multiple schemas, use Array syntax: ${arraySyntax}`
|
||||
);
|
||||
}
|
||||
path = [path];
|
||||
}
|
||||
|
||||
path = path.map((schemaName) => `"${schemaName}"`).join(',');
|
||||
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
connection.query(`set search_path to ${path}`, function (err) {
|
||||
if (err) return rejecter(err);
|
||||
resolver(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_stream(connection, obj, stream, options) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
const PGQueryStream = process.browser
|
||||
? undefined
|
||||
: require('pg-query-stream');
|
||||
const sql = obj.sql;
|
||||
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
const queryStream = connection.query(
|
||||
new PGQueryStream(sql, obj.bindings, options),
|
||||
(err) => {
|
||||
rejecter(err);
|
||||
}
|
||||
);
|
||||
|
||||
queryStream.on('error', function (error) {
|
||||
rejecter(error);
|
||||
stream.emit('error', error);
|
||||
});
|
||||
|
||||
// 'end' IS propagated by .pipe, by default
|
||||
stream.on('end', resolver);
|
||||
queryStream.pipe(stream);
|
||||
});
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings
|
||||
// and any other necessary prep work.
|
||||
_query(connection, obj) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
let queryConfig = {
|
||||
text: obj.sql,
|
||||
values: obj.bindings || [],
|
||||
};
|
||||
|
||||
if (obj.options) {
|
||||
queryConfig = extend(queryConfig, obj.options);
|
||||
}
|
||||
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
connection.query(queryConfig, function (err, response) {
|
||||
if (err) return rejecter(err);
|
||||
obj.response = response;
|
||||
resolver(obj);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Ensures the response is returned in the same format as other clients.
|
||||
processResponse(obj, runner) {
|
||||
const resp = obj.response;
|
||||
if (obj.output) return obj.output.call(runner, resp);
|
||||
if (obj.method === 'raw') return resp;
|
||||
const { returning } = obj;
|
||||
if (resp.command === 'SELECT') {
|
||||
if (obj.method === 'first') return resp.rows[0];
|
||||
if (obj.method === 'pluck') return map(resp.rows, obj.pluck);
|
||||
return resp.rows;
|
||||
}
|
||||
if (returning) {
|
||||
const returns = [];
|
||||
for (let i = 0, l = resp.rows.length; i < l; i++) {
|
||||
const row = resp.rows[i];
|
||||
returns[i] = row;
|
||||
}
|
||||
return returns;
|
||||
}
|
||||
if (resp.command === 'UPDATE' || resp.command === 'DELETE') {
|
||||
return resp.rowCount;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
async cancelQuery(connectionToKill) {
|
||||
const conn = await this.acquireRawConnection();
|
||||
|
||||
try {
|
||||
return await this._wrappedCancelQueryCall(conn, connectionToKill);
|
||||
} finally {
|
||||
await this.destroyRawConnection(conn).catch((err) => {
|
||||
this.logger.warn(`Connection Error: ${err}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
_wrappedCancelQueryCall(conn, connectionToKill) {
|
||||
return this._query(conn, {
|
||||
sql: 'SELECT pg_cancel_backend($1);',
|
||||
bindings: [connectionToKill.processID],
|
||||
options: {},
|
||||
});
|
||||
}
|
||||
|
||||
toPathForJson(jsonPath) {
|
||||
const PG_PATH_REGEX = /^{.*}$/;
|
||||
if (jsonPath.match(PG_PATH_REGEX)) {
|
||||
return jsonPath;
|
||||
}
|
||||
return (
|
||||
'{' +
|
||||
jsonPath
|
||||
.replace(/^(\$\.)/, '') // remove the first dollar
|
||||
.replace('.', ',')
|
||||
.replace(/\[([0-9]+)]/, ',$1') + // transform [number] to ,number
|
||||
'}'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_PG.prototype, {
|
||||
dialect: 'postgresql',
|
||||
|
||||
driverName: 'pg',
|
||||
canCancelQuery: true,
|
||||
|
||||
_escapeBinding: makeEscape({
|
||||
escapeArray(val, esc) {
|
||||
return esc(arrayString(val, esc));
|
||||
},
|
||||
escapeString(str) {
|
||||
let hasBackslash = false;
|
||||
let escaped = "'";
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const c = str[i];
|
||||
if (c === "'") {
|
||||
escaped += c + c;
|
||||
} else if (c === '\\') {
|
||||
escaped += c + c;
|
||||
hasBackslash = true;
|
||||
} else {
|
||||
escaped += c;
|
||||
}
|
||||
}
|
||||
escaped += "'";
|
||||
if (hasBackslash === true) {
|
||||
escaped = 'E' + escaped;
|
||||
}
|
||||
return escaped;
|
||||
},
|
||||
escapeObject(val, prepareValue, timezone, seen = []) {
|
||||
if (val && typeof val.toPostgres === 'function') {
|
||||
seen = seen || [];
|
||||
if (seen.indexOf(val) !== -1) {
|
||||
throw new Error(
|
||||
`circular reference detected while preparing "${val}" for query`
|
||||
);
|
||||
}
|
||||
seen.push(val);
|
||||
return prepareValue(val.toPostgres(prepareValue), seen);
|
||||
}
|
||||
return JSON.stringify(val);
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
function arrayString(arr, esc) {
|
||||
let result = '{';
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (i > 0) result += ',';
|
||||
const val = arr[i];
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
result += 'NULL';
|
||||
} else if (Array.isArray(val)) {
|
||||
result += arrayString(val, esc);
|
||||
} else if (typeof val === 'number') {
|
||||
result += val;
|
||||
} else {
|
||||
result += JSON.stringify(typeof val === 'string' ? val : esc(val));
|
||||
}
|
||||
}
|
||||
return result + '}';
|
||||
}
|
||||
|
||||
module.exports = Client_PG;
|
43
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js
generated
vendored
Normal file
43
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
const QueryBuilder = require('../../../query/querybuilder.js');
|
||||
|
||||
module.exports = class QueryBuilder_PostgreSQL extends QueryBuilder {
|
||||
updateFrom(name) {
|
||||
this._single.updateFrom = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
using(tables) {
|
||||
this._single.using = tables;
|
||||
return this;
|
||||
}
|
||||
|
||||
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
||||
this._validateWithArgs(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
'with'
|
||||
);
|
||||
return this.withWrapped(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
||||
this._validateWithArgs(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
'with'
|
||||
);
|
||||
return this.withWrapped(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
false
|
||||
);
|
||||
}
|
||||
};
|
400
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js
generated
vendored
Normal file
400
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
// PostgreSQL Query Builder & Compiler
|
||||
// ------
|
||||
const identity = require('lodash/identity');
|
||||
const reduce = require('lodash/reduce');
|
||||
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
const {
|
||||
wrapString,
|
||||
columnize: columnize_,
|
||||
operator: operator_,
|
||||
wrap: wrap_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class QueryCompiler_PG extends QueryCompiler {
|
||||
constructor(client, builder, formatter) {
|
||||
super(client, builder, formatter);
|
||||
this._defaultInsertValue = 'default';
|
||||
}
|
||||
|
||||
// Compiles a truncate query.
|
||||
truncate() {
|
||||
return `truncate ${this.tableName} restart identity`;
|
||||
}
|
||||
|
||||
// is used if the an array with multiple empty values supplied
|
||||
|
||||
// Compiles an `insert` query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
let sql = super.insert();
|
||||
if (sql === '') return sql;
|
||||
|
||||
const { returning, onConflict, ignore, merge, insert } = this.single;
|
||||
if (onConflict && ignore) sql += this._ignore(onConflict);
|
||||
if (onConflict && merge) {
|
||||
sql += this._merge(merge.updates, onConflict, insert);
|
||||
const wheres = this.where();
|
||||
if (wheres) sql += ` ${wheres}`;
|
||||
}
|
||||
if (returning) sql += this._returning(returning);
|
||||
|
||||
return {
|
||||
sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
// Compiles an `update` query, allowing for a return value.
|
||||
update() {
|
||||
const withSQL = this.with();
|
||||
const updateData = this._prepUpdate(this.single.update);
|
||||
const wheres = this.where();
|
||||
const { returning, updateFrom } = this.single;
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
`update ${this.single.only ? 'only ' : ''}${this.tableName} ` +
|
||||
`set ${updateData.join(', ')}` +
|
||||
this._updateFrom(updateFrom) +
|
||||
(wheres ? ` ${wheres}` : '') +
|
||||
this._returning(returning),
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
using() {
|
||||
const usingTables = this.single.using;
|
||||
if (!usingTables) return;
|
||||
let sql = 'using ';
|
||||
if (Array.isArray(usingTables)) {
|
||||
sql += usingTables
|
||||
.map((table) => {
|
||||
return this.formatter.wrap(table);
|
||||
})
|
||||
.join(',');
|
||||
} else {
|
||||
sql += this.formatter.wrap(usingTables);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
// Compiles an `delete` query, allowing for a return value.
|
||||
del() {
|
||||
// Make sure tableName is processed by the formatter first.
|
||||
const { tableName } = this;
|
||||
const withSQL = this.with();
|
||||
let wheres = this.where() || '';
|
||||
let using = this.using() || '';
|
||||
const joins = this.grouped.join;
|
||||
|
||||
const tableJoins = [];
|
||||
if (Array.isArray(joins)) {
|
||||
for (const join of joins) {
|
||||
tableJoins.push(
|
||||
wrap_(
|
||||
this._joinTable(join),
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)
|
||||
);
|
||||
|
||||
const joinWheres = [];
|
||||
for (const clause of join.clauses) {
|
||||
joinWheres.push(
|
||||
this.whereBasic({
|
||||
column: clause.column,
|
||||
operator: '=',
|
||||
value: clause.value,
|
||||
asColumn: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
if (joinWheres.length > 0) {
|
||||
wheres += (wheres ? ' and ' : 'where ') + joinWheres.join(' and ');
|
||||
}
|
||||
}
|
||||
if (tableJoins.length > 0) {
|
||||
using += (using ? ',' : 'using ') + tableJoins.join(',');
|
||||
}
|
||||
}
|
||||
|
||||
// With 'using' syntax, no tablename between DELETE and FROM.
|
||||
const sql =
|
||||
withSQL +
|
||||
`delete from ${this.single.only ? 'only ' : ''}${tableName}` +
|
||||
(using ? ` ${using}` : '') +
|
||||
(wheres ? ` ${wheres}` : '');
|
||||
const { returning } = this.single;
|
||||
return {
|
||||
sql: sql + this._returning(returning),
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
aggregate(stmt) {
|
||||
return this._aggregate(stmt, { distinctParentheses: true });
|
||||
}
|
||||
|
||||
_returning(value) {
|
||||
return value ? ` returning ${this.formatter.columnize(value)}` : '';
|
||||
}
|
||||
|
||||
_updateFrom(name) {
|
||||
return name ? ` from ${this.formatter.wrap(name)}` : '';
|
||||
}
|
||||
|
||||
_ignore(columns) {
|
||||
if (columns === true) {
|
||||
return ' on conflict do nothing';
|
||||
}
|
||||
return ` on conflict ${this._onConflictClause(columns)} do nothing`;
|
||||
}
|
||||
|
||||
_merge(updates, columns, insert) {
|
||||
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
|
||||
if (updates && Array.isArray(updates)) {
|
||||
sql += updates
|
||||
.map((column) =>
|
||||
wrapString(
|
||||
column.split('.').pop(),
|
||||
this.formatter.builder,
|
||||
this.client,
|
||||
this.formatter
|
||||
)
|
||||
)
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ');
|
||||
|
||||
return sql;
|
||||
} else if (updates && typeof updates === 'object') {
|
||||
const updateData = this._prepUpdate(updates);
|
||||
if (typeof updateData === 'string') {
|
||||
sql += updateData;
|
||||
} else {
|
||||
sql += updateData.join(',');
|
||||
}
|
||||
|
||||
return sql;
|
||||
} else {
|
||||
const insertData = this._prepInsert(insert);
|
||||
if (typeof insertData === 'string') {
|
||||
throw new Error(
|
||||
'If using merge with a raw insert query, then updates must be provided'
|
||||
);
|
||||
}
|
||||
|
||||
sql += insertData.columns
|
||||
.map((column) =>
|
||||
wrapString(column.split('.').pop(), this.builder, this.client)
|
||||
)
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ');
|
||||
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
// Join array of table names and apply default schema.
|
||||
_tableNames(tables) {
|
||||
const schemaName = this.single.schema;
|
||||
const sql = [];
|
||||
|
||||
for (let i = 0; i < tables.length; i++) {
|
||||
let tableName = tables[i];
|
||||
|
||||
if (tableName) {
|
||||
if (schemaName) {
|
||||
tableName = `${schemaName}.${tableName}`;
|
||||
}
|
||||
sql.push(this.formatter.wrap(tableName));
|
||||
}
|
||||
}
|
||||
|
||||
return sql.join(', ');
|
||||
}
|
||||
|
||||
_lockingClause(lockMode) {
|
||||
const tables = this.single.lockTables || [];
|
||||
|
||||
return lockMode + (tables.length ? ' of ' + this._tableNames(tables) : '');
|
||||
}
|
||||
|
||||
_groupOrder(item, type) {
|
||||
return super._groupOrderNulls(item, type);
|
||||
}
|
||||
|
||||
forUpdate() {
|
||||
return this._lockingClause('for update');
|
||||
}
|
||||
|
||||
forShare() {
|
||||
return this._lockingClause('for share');
|
||||
}
|
||||
|
||||
forNoKeyUpdate() {
|
||||
return this._lockingClause('for no key update');
|
||||
}
|
||||
|
||||
forKeyShare() {
|
||||
return this._lockingClause('for key share');
|
||||
}
|
||||
|
||||
skipLocked() {
|
||||
return 'skip locked';
|
||||
}
|
||||
|
||||
noWait() {
|
||||
return 'nowait';
|
||||
}
|
||||
|
||||
// Compiles a columnInfo query
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
let schema = this.single.schema;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
if (schema) {
|
||||
schema = this.client.customWrapIdentifier(schema, identity);
|
||||
}
|
||||
|
||||
const sql =
|
||||
'select * from information_schema.columns where table_name = ? and table_catalog = current_database()';
|
||||
const bindings = [table];
|
||||
|
||||
return this._buildColumnInfoQuery(schema, sql, bindings, column);
|
||||
}
|
||||
|
||||
_buildColumnInfoQuery(schema, sql, bindings, column) {
|
||||
if (schema) {
|
||||
sql += ' and table_schema = ?';
|
||||
bindings.push(schema);
|
||||
} else {
|
||||
sql += ' and table_schema = current_schema()';
|
||||
}
|
||||
|
||||
return {
|
||||
sql,
|
||||
bindings,
|
||||
output(resp) {
|
||||
const out = reduce(
|
||||
resp.rows,
|
||||
function (columns, val) {
|
||||
columns[val.column_name] = {
|
||||
type: val.data_type,
|
||||
maxLength: val.character_maximum_length,
|
||||
nullable: val.is_nullable === 'YES',
|
||||
defaultValue: val.column_default,
|
||||
};
|
||||
return columns;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return (column && out[column]) || out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
distinctOn(value) {
|
||||
return 'distinct on (' + this.formatter.columnize(value) + ') ';
|
||||
}
|
||||
|
||||
// Json functions
|
||||
jsonExtract(params) {
|
||||
return this._jsonExtract('jsonb_path_query', params);
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
return this._jsonSet(
|
||||
'jsonb_set',
|
||||
Object.assign({}, params, {
|
||||
path: this.client.toPathForJson(params.path),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
return this._jsonSet(
|
||||
'jsonb_insert',
|
||||
Object.assign({}, params, {
|
||||
path: this.client.toPathForJson(params.path),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
const jsonCol = `${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)} #- ${this.client.parameter(
|
||||
this.client.toPathForJson(params.path),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}`;
|
||||
return params.alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
||||
: jsonCol;
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
let castValue = '';
|
||||
if (!isNaN(statement.value) && parseInt(statement.value)) {
|
||||
castValue = '::int';
|
||||
} else if (!isNaN(statement.value) && parseFloat(statement.value)) {
|
||||
castValue = '::float';
|
||||
} else {
|
||||
castValue = " #>> '{}'";
|
||||
}
|
||||
return `jsonb_path_query_first(${this._columnClause(
|
||||
statement
|
||||
)}, ${this.client.parameter(
|
||||
statement.jsonPath,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})${castValue} ${operator_(
|
||||
statement.operator,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)} ${this._jsonValueClause(statement)}`;
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
return this._not(
|
||||
statement,
|
||||
`${wrap_(
|
||||
statement.column,
|
||||
undefined,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)} @> ${this._jsonValueClause(statement)}`
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
return this._not(
|
||||
statement,
|
||||
`${columnize_(
|
||||
statement.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)} <@ ${this._jsonValueClause(statement)}`
|
||||
);
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('jsonb_path_query_first', clause);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryCompiler_PG;
|
156
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js
generated
vendored
Normal file
156
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
// PostgreSQL Column Compiler
|
||||
// -------
|
||||
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
const { isObject } = require('../../../util/is');
|
||||
const { toNumber } = require('../../../util/helpers');
|
||||
const commentEscapeRegex = /(?<!')'(?!')/g;
|
||||
|
||||
class ColumnCompiler_PG extends ColumnCompiler {
|
||||
constructor(client, tableCompiler, columnBuilder) {
|
||||
super(client, tableCompiler, columnBuilder);
|
||||
this.modifiers = ['nullable', 'defaultTo', 'comment'];
|
||||
this._addCheckModifiers();
|
||||
}
|
||||
|
||||
// Types
|
||||
// ------
|
||||
|
||||
bit(column) {
|
||||
return column.length !== false ? `bit(${column.length})` : 'bit';
|
||||
}
|
||||
|
||||
// Create the column definition for an enum type.
|
||||
// Using method "2" here: http://stackoverflow.com/a/10984951/525714
|
||||
enu(allowed, options) {
|
||||
options = options || {};
|
||||
|
||||
const values =
|
||||
options.useNative && options.existingType
|
||||
? undefined
|
||||
: allowed.join("', '");
|
||||
|
||||
if (options.useNative) {
|
||||
let enumName = '';
|
||||
const schemaName = options.schemaName || this.tableCompiler.schemaNameRaw;
|
||||
|
||||
if (schemaName) {
|
||||
enumName += `"${schemaName}".`;
|
||||
}
|
||||
|
||||
enumName += `"${options.enumName}"`;
|
||||
|
||||
if (!options.existingType) {
|
||||
this.tableCompiler.unshiftQuery(
|
||||
`create type ${enumName} as enum ('${values}')`
|
||||
);
|
||||
}
|
||||
|
||||
return enumName;
|
||||
}
|
||||
return `text check (${this.formatter.wrap(this.args[0])} in ('${values}'))`;
|
||||
}
|
||||
|
||||
decimal(precision, scale) {
|
||||
if (precision === null) return 'decimal';
|
||||
return `decimal(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`;
|
||||
}
|
||||
|
||||
json(jsonb) {
|
||||
if (jsonb) this.client.logger.deprecate('json(true)', 'jsonb()');
|
||||
return jsonColumn(this.client, jsonb);
|
||||
}
|
||||
|
||||
jsonb() {
|
||||
return jsonColumn(this.client, true);
|
||||
}
|
||||
|
||||
checkRegex(regex, constraintName) {
|
||||
return this._check(
|
||||
`${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)} ~ ${this.client._escapeBinding(regex)}`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
|
||||
datetime(withoutTz = false, precision) {
|
||||
let useTz;
|
||||
if (isObject(withoutTz)) {
|
||||
({ useTz, precision } = withoutTz);
|
||||
} else {
|
||||
useTz = !withoutTz;
|
||||
}
|
||||
useTz = typeof useTz === 'boolean' ? useTz : true;
|
||||
precision =
|
||||
precision !== undefined && precision !== null
|
||||
? '(' + precision + ')'
|
||||
: '';
|
||||
|
||||
return `${useTz ? 'timestamptz' : 'timestamp'}${precision}`;
|
||||
}
|
||||
|
||||
timestamp(withoutTz = false, precision) {
|
||||
return this.datetime(withoutTz, precision);
|
||||
}
|
||||
|
||||
// Modifiers:
|
||||
// ------
|
||||
comment(comment) {
|
||||
const columnName = this.args[0] || this.defaults('columnName');
|
||||
const escapedComment = comment
|
||||
? `'${comment.replace(commentEscapeRegex, "''")}'`
|
||||
: 'NULL';
|
||||
|
||||
this.pushAdditional(function () {
|
||||
this.pushQuery(
|
||||
`comment on column ${this.tableCompiler.tableName()}.` +
|
||||
this.formatter.wrap(columnName) +
|
||||
` is ${escapedComment}`
|
||||
);
|
||||
}, comment);
|
||||
}
|
||||
|
||||
increments(options = { primaryKey: true }) {
|
||||
return (
|
||||
'serial' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
|
||||
bigincrements(options = { primaryKey: true }) {
|
||||
return (
|
||||
'bigserial' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
|
||||
uuid(options = { primaryKey: false }) {
|
||||
return (
|
||||
'uuid' +
|
||||
(this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_PG.prototype.bigint = 'bigint';
|
||||
ColumnCompiler_PG.prototype.binary = 'bytea';
|
||||
ColumnCompiler_PG.prototype.bool = 'boolean';
|
||||
ColumnCompiler_PG.prototype.double = 'double precision';
|
||||
ColumnCompiler_PG.prototype.floating = 'real';
|
||||
ColumnCompiler_PG.prototype.smallint = 'smallint';
|
||||
ColumnCompiler_PG.prototype.tinyint = 'smallint';
|
||||
|
||||
function jsonColumn(client, jsonb) {
|
||||
if (
|
||||
!client.version ||
|
||||
client.config.client === 'cockroachdb' ||
|
||||
client.config.jsonbSupport === true ||
|
||||
parseFloat(client.version) >= 9.2
|
||||
) {
|
||||
return jsonb ? 'jsonb' : 'json';
|
||||
}
|
||||
return 'text';
|
||||
}
|
||||
|
||||
module.exports = ColumnCompiler_PG;
|
138
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js
generated
vendored
Normal file
138
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
// PostgreSQL Schema Compiler
|
||||
// -------
|
||||
|
||||
const SchemaCompiler = require('../../../schema/compiler');
|
||||
|
||||
class SchemaCompiler_PG extends SchemaCompiler {
|
||||
constructor(client, builder) {
|
||||
super(client, builder);
|
||||
}
|
||||
|
||||
// Check whether the current table
|
||||
hasTable(tableName) {
|
||||
let sql = 'select * from information_schema.tables where table_name = ?';
|
||||
const bindings = [tableName];
|
||||
|
||||
if (this.schema) {
|
||||
sql += ' and table_schema = ?';
|
||||
bindings.push(this.schema);
|
||||
} else {
|
||||
sql += ' and table_schema = current_schema()';
|
||||
}
|
||||
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings,
|
||||
output(resp) {
|
||||
return resp.rows.length > 0;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Compile the query to determine if a column exists in a table.
|
||||
hasColumn(tableName, columnName) {
|
||||
let sql =
|
||||
'select * from information_schema.columns where table_name = ? and column_name = ?';
|
||||
const bindings = [tableName, columnName];
|
||||
|
||||
if (this.schema) {
|
||||
sql += ' and table_schema = ?';
|
||||
bindings.push(this.schema);
|
||||
} else {
|
||||
sql += ' and table_schema = current_schema()';
|
||||
}
|
||||
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings,
|
||||
output(resp) {
|
||||
return resp.rows.length > 0;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
qualifiedTableName(tableName) {
|
||||
const name = this.schema ? `${this.schema}.${tableName}` : tableName;
|
||||
return this.formatter.wrap(name);
|
||||
}
|
||||
|
||||
// Compile a rename table command.
|
||||
renameTable(from, to) {
|
||||
this.pushQuery(
|
||||
`alter table ${this.qualifiedTableName(
|
||||
from
|
||||
)} rename to ${this.formatter.wrap(to)}`
|
||||
);
|
||||
}
|
||||
|
||||
createSchema(schemaName) {
|
||||
this.pushQuery(`create schema ${this.formatter.wrap(schemaName)}`);
|
||||
}
|
||||
|
||||
createSchemaIfNotExists(schemaName) {
|
||||
this.pushQuery(
|
||||
`create schema if not exists ${this.formatter.wrap(schemaName)}`
|
||||
);
|
||||
}
|
||||
|
||||
dropSchema(schemaName, cascade = false) {
|
||||
this.pushQuery(
|
||||
`drop schema ${this.formatter.wrap(schemaName)}${
|
||||
cascade ? ' cascade' : ''
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
dropSchemaIfExists(schemaName, cascade = false) {
|
||||
this.pushQuery(
|
||||
`drop schema if exists ${this.formatter.wrap(schemaName)}${
|
||||
cascade ? ' cascade' : ''
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
dropExtension(extensionName) {
|
||||
this.pushQuery(`drop extension ${this.formatter.wrap(extensionName)}`);
|
||||
}
|
||||
|
||||
dropExtensionIfExists(extensionName) {
|
||||
this.pushQuery(
|
||||
`drop extension if exists ${this.formatter.wrap(extensionName)}`
|
||||
);
|
||||
}
|
||||
|
||||
createExtension(extensionName) {
|
||||
this.pushQuery(`create extension ${this.formatter.wrap(extensionName)}`);
|
||||
}
|
||||
|
||||
createExtensionIfNotExists(extensionName) {
|
||||
this.pushQuery(
|
||||
`create extension if not exists ${this.formatter.wrap(extensionName)}`
|
||||
);
|
||||
}
|
||||
|
||||
renameView(from, to) {
|
||||
this.pushQuery(
|
||||
this.alterViewPrefix +
|
||||
`${this.formatter.wrap(from)} rename to ${this.formatter.wrap(to)}`
|
||||
);
|
||||
}
|
||||
|
||||
refreshMaterializedView(viewName, concurrently = false) {
|
||||
this.pushQuery({
|
||||
sql: `refresh materialized view${
|
||||
concurrently ? ' concurrently' : ''
|
||||
} ${this.formatter.wrap(viewName)}`,
|
||||
});
|
||||
}
|
||||
|
||||
dropMaterializedView(viewName) {
|
||||
this._dropView(viewName, false, true);
|
||||
}
|
||||
|
||||
dropMaterializedViewIfExists(viewName) {
|
||||
this._dropView(viewName, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_PG;
|
304
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js
generated
vendored
Normal file
304
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
// PostgreSQL Table Builder & Compiler
|
||||
// -------
|
||||
|
||||
const has = require('lodash/has');
|
||||
const TableCompiler = require('../../../schema/tablecompiler');
|
||||
const { isObject, isString } = require('../../../util/is');
|
||||
|
||||
class TableCompiler_PG extends TableCompiler {
|
||||
constructor(client, tableBuilder) {
|
||||
super(client, tableBuilder);
|
||||
}
|
||||
|
||||
// Compile a rename column command.
|
||||
renameColumn(from, to) {
|
||||
return this.pushQuery({
|
||||
sql: `alter table ${this.tableName()} rename ${this.formatter.wrap(
|
||||
from
|
||||
)} to ${this.formatter.wrap(to)}`,
|
||||
});
|
||||
}
|
||||
|
||||
_setNullableState(column, isNullable) {
|
||||
const constraintAction = isNullable ? 'drop not null' : 'set not null';
|
||||
const sql = `alter table ${this.tableName()} alter column ${this.formatter.wrap(
|
||||
column
|
||||
)} ${constraintAction}`;
|
||||
return this.pushQuery({
|
||||
sql: sql,
|
||||
});
|
||||
}
|
||||
|
||||
compileAdd(builder) {
|
||||
const table = this.formatter.wrap(builder);
|
||||
const columns = this.prefixArray('add column', this.getColumns(builder));
|
||||
return this.pushQuery({
|
||||
sql: `alter table ${table} ${columns.join(', ')}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Adds the "create" query to the query sequence.
|
||||
createQuery(columns, ifNot, like) {
|
||||
const createStatement = ifNot
|
||||
? 'create table if not exists '
|
||||
: 'create table ';
|
||||
const columnsSql = ` (${columns.sql.join(', ')}${
|
||||
this.primaryKeys() || ''
|
||||
}${this._addChecks()})`;
|
||||
|
||||
let sql =
|
||||
createStatement +
|
||||
this.tableName() +
|
||||
(like && this.tableNameLike()
|
||||
? ' (like ' +
|
||||
this.tableNameLike() +
|
||||
' including all' +
|
||||
(columns.sql.length ? ', ' + columns.sql.join(', ') : '') +
|
||||
')'
|
||||
: columnsSql);
|
||||
if (this.single.inherits)
|
||||
sql += ` inherits (${this.formatter.wrap(this.single.inherits)})`;
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
const hasComment = has(this.single, 'comment');
|
||||
if (hasComment) this.comment(this.single.comment);
|
||||
}
|
||||
|
||||
primaryKeys() {
|
||||
const pks = (this.grouped.alterTable || []).filter(
|
||||
(k) => k.method === 'primary'
|
||||
);
|
||||
if (pks.length > 0 && pks[0].args.length > 0) {
|
||||
const columns = pks[0].args[0];
|
||||
let constraintName = pks[0].args[1] || '';
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
|
||||
return `, constraint ${constraintName} primary key (${this.formatter.columnize(
|
||||
columns
|
||||
)})${deferrable}`;
|
||||
}
|
||||
}
|
||||
|
||||
addColumns(columns, prefix, colCompilers) {
|
||||
if (prefix === this.alterColumnsPrefix) {
|
||||
// alter columns
|
||||
for (const col of colCompilers) {
|
||||
this._addColumn(col);
|
||||
}
|
||||
} else {
|
||||
// base class implementation for normal add
|
||||
super.addColumns(columns, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
_addColumn(col) {
|
||||
const quotedTableName = this.tableName();
|
||||
const type = col.getColumnType();
|
||||
// We'd prefer to call this.formatter.wrapAsIdentifier here instead, however the context passed to
|
||||
// `this` instance is not that of the column, but of the table. Thus, we unfortunately have to call
|
||||
// `wrapIdentifier` here as well (it is already called once on the initial column operation) to give
|
||||
// our `alter` operation the correct `queryContext`. Refer to issue #2606 and PR #2612.
|
||||
const colName = this.client.wrapIdentifier(
|
||||
col.getColumnName(),
|
||||
col.columnBuilder.queryContext()
|
||||
);
|
||||
|
||||
// To alter enum columns they must be cast to text first
|
||||
const isEnum = col.type === 'enu';
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} alter column ${colName} drop default`,
|
||||
bindings: [],
|
||||
});
|
||||
|
||||
const alterNullable = col.columnBuilder.alterNullable;
|
||||
if (alterNullable) {
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} alter column ${colName} drop not null`,
|
||||
bindings: [],
|
||||
});
|
||||
}
|
||||
|
||||
const alterType = col.columnBuilder.alterType;
|
||||
if (alterType) {
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${
|
||||
isEnum ? '::text::' : '::'
|
||||
}${type})`,
|
||||
bindings: [],
|
||||
});
|
||||
}
|
||||
|
||||
const defaultTo = col.modified['defaultTo'];
|
||||
if (defaultTo) {
|
||||
const modifier = col.defaultTo.apply(col, defaultTo);
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} alter column ${colName} set ${modifier}`,
|
||||
bindings: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (alterNullable) {
|
||||
const nullable = col.modified['nullable'];
|
||||
if (nullable && nullable[0] === false) {
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} alter column ${colName} set not null`,
|
||||
bindings: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compiles the comment on the table.
|
||||
comment(comment) {
|
||||
this.pushQuery(
|
||||
`comment on table ${this.tableName()} is '${this.single.comment}'`
|
||||
);
|
||||
}
|
||||
|
||||
// Indexes:
|
||||
// -------
|
||||
|
||||
primary(columns, constraintName) {
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
if (this.method !== 'create' && this.method !== 'createIfNot') {
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize(
|
||||
columns
|
||||
)})${deferrable}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unique(columns, indexName) {
|
||||
let deferrable;
|
||||
let useConstraint = true;
|
||||
let predicate;
|
||||
if (isObject(indexName)) {
|
||||
({ indexName, deferrable, useConstraint, predicate } = indexName);
|
||||
if (useConstraint === undefined) {
|
||||
useConstraint = !!deferrable || !predicate;
|
||||
}
|
||||
}
|
||||
if (!useConstraint && deferrable && deferrable !== 'not deferrable') {
|
||||
throw new Error('postgres cannot create deferrable index');
|
||||
}
|
||||
if (useConstraint && predicate) {
|
||||
throw new Error('postgres cannot create constraint with predicate');
|
||||
}
|
||||
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
|
||||
if (useConstraint) {
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} add constraint ${indexName}` +
|
||||
' unique (' +
|
||||
this.formatter.columnize(columns) +
|
||||
')' +
|
||||
deferrable
|
||||
);
|
||||
} else {
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: '';
|
||||
|
||||
this.pushQuery(
|
||||
`create unique index ${indexName} on ${this.tableName()} (${this.formatter.columnize(
|
||||
columns
|
||||
)})${predicateQuery}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
index(columns, indexName, options) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
|
||||
let predicate;
|
||||
let storageEngineIndexType;
|
||||
let indexType;
|
||||
|
||||
if (isString(options)) {
|
||||
storageEngineIndexType = options;
|
||||
} else if (isObject(options)) {
|
||||
({ indexType, storageEngineIndexType, predicate } = options);
|
||||
}
|
||||
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: '';
|
||||
|
||||
this.pushQuery(
|
||||
`create${
|
||||
typeof indexType === 'string' && indexType.toLowerCase() === 'unique'
|
||||
? ' unique'
|
||||
: ''
|
||||
} index ${indexName} on ${this.tableName()}${
|
||||
(storageEngineIndexType && ` using ${storageEngineIndexType}`) || ''
|
||||
}` +
|
||||
' (' +
|
||||
this.formatter.columnize(columns) +
|
||||
')' +
|
||||
`${predicateQuery}`
|
||||
);
|
||||
}
|
||||
|
||||
dropPrimary(constraintName) {
|
||||
constraintName = constraintName
|
||||
? this.formatter.wrap(constraintName)
|
||||
: this.formatter.wrap(this.tableNameRaw + '_pkey');
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${constraintName}`
|
||||
);
|
||||
}
|
||||
|
||||
dropIndex(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
indexName = this.schemaNameRaw
|
||||
? `${this.formatter.wrap(this.schemaNameRaw)}.${indexName}`
|
||||
: indexName;
|
||||
this.pushQuery(`drop index ${indexName}`);
|
||||
}
|
||||
|
||||
dropUnique(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${indexName}`
|
||||
);
|
||||
}
|
||||
|
||||
dropForeign(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('foreign', this.tableNameRaw, columns);
|
||||
this.pushQuery(
|
||||
`alter table ${this.tableName()} drop constraint ${indexName}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TableCompiler_PG;
|
21
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js
generated
vendored
Normal file
21
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
const ViewBuilder = require('../../../schema/viewbuilder.js');
|
||||
|
||||
class ViewBuilder_PG extends ViewBuilder {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
checkOption() {
|
||||
this._single.checkOption = 'default_option';
|
||||
}
|
||||
|
||||
localCheckOption() {
|
||||
this._single.checkOption = 'local';
|
||||
}
|
||||
|
||||
cascadedCheckOption() {
|
||||
this._single.checkOption = 'cascaded';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewBuilder_PG;
|
35
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js
generated
vendored
Normal file
35
backend/apis/nodejs/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
|
||||
class ViewCompiler_PG extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
|
||||
renameColumn(from, to) {
|
||||
return this.pushQuery({
|
||||
sql: `alter view ${this.viewName()} rename ${this.formatter.wrap(
|
||||
from
|
||||
)} to ${this.formatter.wrap(to)}`,
|
||||
});
|
||||
}
|
||||
|
||||
defaultTo(column, defaultValue) {
|
||||
return this.pushQuery({
|
||||
sql: `alter view ${this.viewName()} alter ${this.formatter.wrap(
|
||||
column
|
||||
)} set default ${defaultValue}`,
|
||||
});
|
||||
}
|
||||
|
||||
createOrReplace() {
|
||||
this.createQuery(this.columns, this.selectQuery, false, true);
|
||||
}
|
||||
|
||||
createMaterializedView() {
|
||||
this.createQuery(this.columns, this.selectQuery, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_PG;
|
86
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/index.js
generated
vendored
Normal file
86
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/index.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
// Redshift
|
||||
// -------
|
||||
const Client_PG = require('../postgres');
|
||||
const map = require('lodash/map');
|
||||
|
||||
const Transaction = require('./transaction');
|
||||
const QueryCompiler = require('./query/redshift-querycompiler');
|
||||
const ColumnBuilder = require('./schema/redshift-columnbuilder');
|
||||
const ColumnCompiler = require('./schema/redshift-columncompiler');
|
||||
const TableCompiler = require('./schema/redshift-tablecompiler');
|
||||
const SchemaCompiler = require('./schema/redshift-compiler');
|
||||
const ViewCompiler = require('./schema/redshift-viewcompiler');
|
||||
|
||||
class Client_Redshift extends Client_PG {
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new QueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
columnBuilder() {
|
||||
return new ColumnBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('pg');
|
||||
}
|
||||
|
||||
// Ensures the response is returned in the same format as other clients.
|
||||
processResponse(obj, runner) {
|
||||
const resp = obj.response;
|
||||
if (obj.output) return obj.output.call(runner, resp);
|
||||
if (obj.method === 'raw') return resp;
|
||||
if (resp.command === 'SELECT') {
|
||||
if (obj.method === 'first') return resp.rows[0];
|
||||
if (obj.method === 'pluck') return map(resp.rows, obj.pluck);
|
||||
return resp.rows;
|
||||
}
|
||||
if (
|
||||
resp.command === 'INSERT' ||
|
||||
resp.command === 'UPDATE' ||
|
||||
resp.command === 'DELETE'
|
||||
) {
|
||||
return resp.rowCount;
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
toPathForJson(jsonPath, builder, bindingsHolder) {
|
||||
return jsonPath
|
||||
.replace(/^(\$\.)/, '') // remove the first dollar
|
||||
.split('.')
|
||||
.map(
|
||||
function (v) {
|
||||
return this.parameter(v, builder, bindingsHolder);
|
||||
}.bind(this)
|
||||
)
|
||||
.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_Redshift.prototype, {
|
||||
dialect: 'redshift',
|
||||
|
||||
driverName: 'pg-redshift',
|
||||
});
|
||||
|
||||
module.exports = Client_Redshift;
|
163
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js
generated
vendored
Normal file
163
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
// Redshift Query Builder & Compiler
|
||||
// ------
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
const QueryCompiler_PG = require('../../postgres/query/pg-querycompiler');
|
||||
|
||||
const identity = require('lodash/identity');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class QueryCompiler_Redshift extends QueryCompiler_PG {
|
||||
truncate() {
|
||||
return `truncate ${this.tableName.toLowerCase()}`;
|
||||
}
|
||||
|
||||
// Compiles an `insert` query, allowing for multiple
|
||||
// inserts using a single query statement.
|
||||
insert() {
|
||||
const sql = QueryCompiler.prototype.insert.apply(this, arguments);
|
||||
if (sql === '') return sql;
|
||||
this._slightReturn();
|
||||
return {
|
||||
sql,
|
||||
};
|
||||
}
|
||||
|
||||
// Compiles an `update` query, warning on unsupported returning
|
||||
update() {
|
||||
const sql = QueryCompiler.prototype.update.apply(this, arguments);
|
||||
this._slightReturn();
|
||||
return {
|
||||
sql,
|
||||
};
|
||||
}
|
||||
|
||||
// Compiles an `delete` query, warning on unsupported returning
|
||||
del() {
|
||||
const sql = QueryCompiler.prototype.del.apply(this, arguments);
|
||||
this._slightReturn();
|
||||
return {
|
||||
sql,
|
||||
};
|
||||
}
|
||||
|
||||
// simple: if trying to return, warn
|
||||
_slightReturn() {
|
||||
if (this.single.isReturning) {
|
||||
this.client.logger.warn(
|
||||
'insert/update/delete returning is not supported by redshift dialect'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
forUpdate() {
|
||||
this.client.logger.warn('table lock is not supported by redshift dialect');
|
||||
return '';
|
||||
}
|
||||
|
||||
forShare() {
|
||||
this.client.logger.warn(
|
||||
'lock for share is not supported by redshift dialect'
|
||||
);
|
||||
return '';
|
||||
}
|
||||
|
||||
forNoKeyUpdate() {
|
||||
this.client.logger.warn('table lock is not supported by redshift dialect');
|
||||
return '';
|
||||
}
|
||||
|
||||
forKeyShare() {
|
||||
this.client.logger.warn(
|
||||
'lock for share is not supported by redshift dialect'
|
||||
);
|
||||
return '';
|
||||
}
|
||||
|
||||
// Compiles a columnInfo query
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
let schema = this.single.schema;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
if (schema) {
|
||||
schema = this.client.customWrapIdentifier(schema, identity);
|
||||
}
|
||||
|
||||
const sql =
|
||||
'select * from information_schema.columns where table_name = ? and table_catalog = ?';
|
||||
const bindings = [
|
||||
table.toLowerCase(),
|
||||
this.client.database().toLowerCase(),
|
||||
];
|
||||
|
||||
return this._buildColumnInfoQuery(schema, sql, bindings, column);
|
||||
}
|
||||
|
||||
jsonExtract(params) {
|
||||
let extractions;
|
||||
if (Array.isArray(params.column)) {
|
||||
extractions = params.column;
|
||||
} else {
|
||||
extractions = [params];
|
||||
}
|
||||
return extractions
|
||||
.map((extraction) => {
|
||||
const jsonCol = `json_extract_path_text(${columnize_(
|
||||
extraction.column || extraction[0],
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)}, ${this.client.toPathForJson(
|
||||
params.path || extraction[1],
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
const alias = extraction.alias || extraction[2];
|
||||
return alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(alias))
|
||||
: jsonCol;
|
||||
})
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
throw new Error('Json set is not supported by Redshift');
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
throw new Error('Json insert is not supported by Redshift');
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
throw new Error('Json remove is not supported by Redshift');
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
return this._whereJsonPath(
|
||||
'json_extract_path_text',
|
||||
Object.assign({}, statement, {
|
||||
path: this.client.toPathForJson(statement.path),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
throw new Error('Json superset is not supported by Redshift');
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
throw new Error('Json subset is not supported by Redshift');
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('json_extract_path_text', clause);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryCompiler_Redshift;
|
22
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js
generated
vendored
Normal file
22
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
const ColumnBuilder = require('../../../schema/columnbuilder');
|
||||
|
||||
class ColumnBuilder_Redshift extends ColumnBuilder {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
// primary needs to set not null on non-preexisting columns, or fail
|
||||
primary() {
|
||||
this.notNullable();
|
||||
return super.primary(...arguments);
|
||||
}
|
||||
|
||||
index() {
|
||||
this.client.logger.warn(
|
||||
'Redshift does not support the creation of indexes.'
|
||||
);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ColumnBuilder_Redshift;
|
67
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js
generated
vendored
Normal file
67
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// Redshift Column Compiler
|
||||
// -------
|
||||
|
||||
const ColumnCompiler_PG = require('../../postgres/schema/pg-columncompiler');
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
|
||||
class ColumnCompiler_Redshift extends ColumnCompiler_PG {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
// Types:
|
||||
// ------
|
||||
|
||||
bit(column) {
|
||||
return column.length !== false ? `char(${column.length})` : 'char(1)';
|
||||
}
|
||||
|
||||
datetime(without) {
|
||||
return without ? 'timestamp' : 'timestamptz';
|
||||
}
|
||||
|
||||
timestamp(without) {
|
||||
return without ? 'timestamp' : 'timestamptz';
|
||||
}
|
||||
|
||||
// Modifiers:
|
||||
// ------
|
||||
comment(comment) {
|
||||
this.pushAdditional(function () {
|
||||
this.pushQuery(
|
||||
`comment on column ${this.tableCompiler.tableName()}.` +
|
||||
this.formatter.wrap(this.args[0]) +
|
||||
' is ' +
|
||||
(comment ? `'${comment}'` : 'NULL')
|
||||
);
|
||||
}, comment);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_Redshift.prototype.increments = ({ primaryKey = true } = {}) =>
|
||||
'integer identity(1,1)' + (primaryKey ? ' primary key' : '') + ' not null';
|
||||
ColumnCompiler_Redshift.prototype.bigincrements = ({
|
||||
primaryKey = true,
|
||||
} = {}) =>
|
||||
'bigint identity(1,1)' + (primaryKey ? ' primary key' : '') + ' not null';
|
||||
ColumnCompiler_Redshift.prototype.binary = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.blob = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.enu = 'varchar(255)';
|
||||
ColumnCompiler_Redshift.prototype.enum = 'varchar(255)';
|
||||
ColumnCompiler_Redshift.prototype.json = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.jsonb = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.longblob = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.mediumblob = 'varchar(16777218)';
|
||||
ColumnCompiler_Redshift.prototype.set = 'text';
|
||||
ColumnCompiler_Redshift.prototype.text = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.tinyblob = 'varchar(256)';
|
||||
ColumnCompiler_Redshift.prototype.uuid = ColumnCompiler.prototype.uuid;
|
||||
ColumnCompiler_Redshift.prototype.varbinary = 'varchar(max)';
|
||||
ColumnCompiler_Redshift.prototype.bigint = 'bigint';
|
||||
ColumnCompiler_Redshift.prototype.bool = 'boolean';
|
||||
ColumnCompiler_Redshift.prototype.double = 'double precision';
|
||||
ColumnCompiler_Redshift.prototype.floating = 'real';
|
||||
ColumnCompiler_Redshift.prototype.smallint = 'smallint';
|
||||
ColumnCompiler_Redshift.prototype.tinyint = 'smallint';
|
||||
|
||||
module.exports = ColumnCompiler_Redshift;
|
14
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js
generated
vendored
Normal file
14
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
// Redshift Table Builder & Compiler
|
||||
// -------
|
||||
|
||||
const SchemaCompiler_PG = require('../../postgres/schema/pg-compiler');
|
||||
|
||||
class SchemaCompiler_Redshift extends SchemaCompiler_PG {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_Redshift;
|
122
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js
generated
vendored
Normal file
122
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
// Redshift Table Builder & Compiler
|
||||
// -------
|
||||
|
||||
const has = require('lodash/has');
|
||||
const TableCompiler_PG = require('../../postgres/schema/pg-tablecompiler');
|
||||
|
||||
class TableCompiler_Redshift extends TableCompiler_PG {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
index(columns, indexName, options) {
|
||||
this.client.logger.warn(
|
||||
'Redshift does not support the creation of indexes.'
|
||||
);
|
||||
}
|
||||
|
||||
dropIndex(columns, indexName) {
|
||||
this.client.logger.warn(
|
||||
'Redshift does not support the deletion of indexes.'
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: have to disable setting not null on columns that already exist...
|
||||
|
||||
// Adds the "create" query to the query sequence.
|
||||
createQuery(columns, ifNot, like) {
|
||||
const createStatement = ifNot
|
||||
? 'create table if not exists '
|
||||
: 'create table ';
|
||||
const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
|
||||
let sql =
|
||||
createStatement +
|
||||
this.tableName() +
|
||||
(like && this.tableNameLike()
|
||||
? ' (like ' + this.tableNameLike() + ')'
|
||||
: columnsSql);
|
||||
if (this.single.inherits)
|
||||
sql += ` like (${this.formatter.wrap(this.single.inherits)})`;
|
||||
this.pushQuery({
|
||||
sql,
|
||||
bindings: columns.bindings,
|
||||
});
|
||||
const hasComment = has(this.single, 'comment');
|
||||
if (hasComment) this.comment(this.single.comment);
|
||||
if (like) {
|
||||
this.addColumns(columns, this.addColumnsPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
primary(columns, constraintName) {
|
||||
const self = this;
|
||||
constraintName = constraintName
|
||||
? self.formatter.wrap(constraintName)
|
||||
: self.formatter.wrap(`${this.tableNameRaw}_pkey`);
|
||||
if (columns.constructor !== Array) {
|
||||
columns = [columns];
|
||||
}
|
||||
const thiscolumns = self.grouped.columns;
|
||||
|
||||
if (thiscolumns) {
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
let exists = thiscolumns.find(
|
||||
(tcb) =>
|
||||
tcb.grouping === 'columns' &&
|
||||
tcb.builder &&
|
||||
tcb.builder._method === 'add' &&
|
||||
tcb.builder._args &&
|
||||
tcb.builder._args.indexOf(columns[i]) > -1
|
||||
);
|
||||
if (exists) {
|
||||
exists = exists.builder;
|
||||
}
|
||||
const nullable = !(
|
||||
exists &&
|
||||
exists._modifiers &&
|
||||
exists._modifiers['nullable'] &&
|
||||
exists._modifiers['nullable'][0] === false
|
||||
);
|
||||
if (nullable) {
|
||||
if (exists) {
|
||||
return this.client.logger.warn(
|
||||
'Redshift does not allow primary keys to contain nullable columns.'
|
||||
);
|
||||
} else {
|
||||
return this.client.logger.warn(
|
||||
'Redshift does not allow primary keys to contain nonexistent columns.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.pushQuery(
|
||||
`alter table ${self.tableName()} add constraint ${constraintName} primary key (${self.formatter.columnize(
|
||||
columns
|
||||
)})`
|
||||
);
|
||||
}
|
||||
|
||||
// Compiles column add. Redshift can only add one column per ALTER TABLE, so core addColumns doesn't work. #2545
|
||||
addColumns(columns, prefix, colCompilers) {
|
||||
if (prefix === this.alterColumnsPrefix) {
|
||||
super.addColumns(columns, prefix, colCompilers);
|
||||
} else {
|
||||
prefix = prefix || this.addColumnsPrefix;
|
||||
colCompilers = colCompilers || this.getColumns();
|
||||
for (const col of colCompilers) {
|
||||
const quotedTableName = this.tableName();
|
||||
const colCompiled = col.compileColumn();
|
||||
|
||||
this.pushQuery({
|
||||
sql: `alter table ${quotedTableName} ${prefix}${colCompiled}`,
|
||||
bindings: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TableCompiler_Redshift;
|
11
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js
generated
vendored
Normal file
11
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler_PG = require('../../postgres/schema/pg-viewcompiler.js');
|
||||
|
||||
class ViewCompiler_Redshift extends ViewCompiler_PG {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_Redshift;
|
32
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/transaction.js
generated
vendored
Normal file
32
backend/apis/nodejs/node_modules/knex/lib/dialects/redshift/transaction.js
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
const Transaction = require('../../execution/transaction');
|
||||
|
||||
module.exports = class Redshift_Transaction extends Transaction {
|
||||
begin(conn) {
|
||||
const trxMode = [
|
||||
this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '',
|
||||
this.readOnly ? 'READ ONLY' : '',
|
||||
]
|
||||
.join(' ')
|
||||
.trim();
|
||||
|
||||
if (trxMode.length === 0) {
|
||||
return this.query(conn, 'BEGIN;');
|
||||
}
|
||||
return this.query(conn, `BEGIN ${trxMode};`);
|
||||
}
|
||||
|
||||
savepoint(conn) {
|
||||
this.trxClient.logger('Redshift does not support savepoints.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
release(conn, value) {
|
||||
this.trxClient.logger('Redshift does not support savepoints.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
rollbackTo(conn, error) {
|
||||
this.trxClient.logger('Redshift does not support savepoints.');
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
25
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js
generated
vendored
Normal file
25
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
const Transaction = require('../../../execution/transaction');
|
||||
|
||||
class Transaction_Sqlite extends Transaction {
|
||||
begin(conn) {
|
||||
// SQLite doesn't really support isolation levels, it is serializable by
|
||||
// default and so we override it to ignore isolation level.
|
||||
// There is a `PRAGMA read_uncommitted = true;`, but that's probably not
|
||||
// what the user wants
|
||||
if (this.isolationLevel) {
|
||||
this.client.logger.warn(
|
||||
'sqlite3 only supports serializable transactions, ignoring the isolation level param'
|
||||
);
|
||||
}
|
||||
// SQLite infers read vs write transactions from the statement operation
|
||||
// https://www.sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions
|
||||
if (this.readOnly) {
|
||||
this.client.logger.warn(
|
||||
'sqlite3 implicitly handles read vs write transactions'
|
||||
);
|
||||
}
|
||||
return this.query(conn, 'BEGIN;');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction_Sqlite;
|
250
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/index.js
generated
vendored
Normal file
250
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/index.js
generated
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
// SQLite3
|
||||
// -------
|
||||
const defaults = require('lodash/defaults');
|
||||
const map = require('lodash/map');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const Client = require('../../client');
|
||||
|
||||
const Raw = require('../../raw');
|
||||
const Transaction = require('./execution/sqlite-transaction');
|
||||
const SqliteQueryCompiler = require('./query/sqlite-querycompiler');
|
||||
const SchemaCompiler = require('./schema/sqlite-compiler');
|
||||
const ColumnCompiler = require('./schema/sqlite-columncompiler');
|
||||
const TableCompiler = require('./schema/sqlite-tablecompiler');
|
||||
const ViewCompiler = require('./schema/sqlite-viewcompiler');
|
||||
const SQLite3_DDL = require('./schema/ddl');
|
||||
const Formatter = require('../../formatter');
|
||||
const QueryBuilder = require('./query/sqlite-querybuilder');
|
||||
|
||||
class Client_SQLite3 extends Client {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
|
||||
if (config.connection && config.connection.filename === undefined) {
|
||||
this.logger.warn(
|
||||
'Could not find `connection.filename` in config. Please specify ' +
|
||||
'the database path and name to avoid errors. ' +
|
||||
'(see docs https://knexjs.org/guide/#configuration-options)'
|
||||
);
|
||||
}
|
||||
|
||||
if (config.useNullAsDefault === undefined) {
|
||||
this.logger.warn(
|
||||
'sqlite does not support inserting default values. Set the ' +
|
||||
'`useNullAsDefault` flag to hide this warning. ' +
|
||||
'(see docs https://knexjs.org/guide/query-builder.html#insert).'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('sqlite3');
|
||||
}
|
||||
|
||||
schemaCompiler() {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
transaction() {
|
||||
return new Transaction(this, ...arguments);
|
||||
}
|
||||
|
||||
queryCompiler(builder, formatter) {
|
||||
return new SqliteQueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
queryBuilder() {
|
||||
return new QueryBuilder(this);
|
||||
}
|
||||
|
||||
viewCompiler(builder, formatter) {
|
||||
return new ViewCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
tableCompiler() {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
ddl(compiler, pragma, connection) {
|
||||
return new SQLite3_DDL(this, compiler, pragma, connection);
|
||||
}
|
||||
|
||||
wrapIdentifierImpl(value) {
|
||||
return value !== '*' ? `\`${value.replace(/`/g, '``')}\`` : '*';
|
||||
}
|
||||
|
||||
// Get a raw connection from the database, returning a promise with the connection object.
|
||||
acquireRawConnection() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// the default mode for sqlite3
|
||||
let flags = this.driver.OPEN_READWRITE | this.driver.OPEN_CREATE;
|
||||
|
||||
if (this.connectionSettings.flags) {
|
||||
if (!Array.isArray(this.connectionSettings.flags)) {
|
||||
throw new Error(`flags must be an array of strings`);
|
||||
}
|
||||
this.connectionSettings.flags.forEach((_flag) => {
|
||||
if (!_flag.startsWith('OPEN_') || !this.driver[_flag]) {
|
||||
throw new Error(`flag ${_flag} not supported by node-sqlite3`);
|
||||
}
|
||||
flags = flags | this.driver[_flag];
|
||||
});
|
||||
}
|
||||
|
||||
const db = new this.driver.Database(
|
||||
this.connectionSettings.filename,
|
||||
flags,
|
||||
(err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(db);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Used to explicitly close a connection, called internally by the pool when
|
||||
// a connection times out or the pool is shutdown.
|
||||
async destroyRawConnection(connection) {
|
||||
const close = promisify((cb) => connection.close(cb));
|
||||
return close();
|
||||
}
|
||||
|
||||
// Runs the query on the specified connection, providing the bindings and any
|
||||
// other necessary prep work.
|
||||
_query(connection, obj) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
const { method } = obj;
|
||||
let callMethod;
|
||||
switch (method) {
|
||||
case 'insert':
|
||||
case 'update':
|
||||
callMethod = obj.returning ? 'all' : 'run';
|
||||
break;
|
||||
case 'counter':
|
||||
case 'del':
|
||||
callMethod = 'run';
|
||||
break;
|
||||
default:
|
||||
callMethod = 'all';
|
||||
}
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
if (!connection || !connection[callMethod]) {
|
||||
return rejecter(
|
||||
new Error(`Error calling ${callMethod} on connection.`)
|
||||
);
|
||||
}
|
||||
connection[callMethod](obj.sql, obj.bindings, function (err, response) {
|
||||
if (err) return rejecter(err);
|
||||
obj.response = response;
|
||||
|
||||
// We need the context here, as it contains
|
||||
// the "this.lastID" or "this.changes"
|
||||
obj.context = this;
|
||||
|
||||
return resolver(obj);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_stream(connection, obj, stream) {
|
||||
if (!obj.sql) throw new Error('The query is empty');
|
||||
|
||||
const client = this;
|
||||
return new Promise(function (resolver, rejecter) {
|
||||
stream.on('error', rejecter);
|
||||
stream.on('end', resolver);
|
||||
|
||||
return client
|
||||
._query(connection, obj)
|
||||
.then((obj) => obj.response)
|
||||
.then((rows) => rows.forEach((row) => stream.write(row)))
|
||||
.catch(function (err) {
|
||||
stream.emit('error', err);
|
||||
})
|
||||
.then(function () {
|
||||
stream.end();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Ensures the response is returned in the same format as other clients.
|
||||
processResponse(obj, runner) {
|
||||
const ctx = obj.context;
|
||||
const { response, returning } = obj;
|
||||
if (obj.output) return obj.output.call(runner, response);
|
||||
switch (obj.method) {
|
||||
case 'select':
|
||||
return response;
|
||||
case 'first':
|
||||
return response[0];
|
||||
case 'pluck':
|
||||
return map(response, obj.pluck);
|
||||
case 'insert': {
|
||||
if (returning) {
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
return [ctx.lastID];
|
||||
}
|
||||
case 'update': {
|
||||
if (returning) {
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
return ctx.changes;
|
||||
}
|
||||
case 'del':
|
||||
case 'counter':
|
||||
return ctx.changes;
|
||||
default: {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
poolDefaults() {
|
||||
return defaults({ min: 1, max: 1 }, super.poolDefaults());
|
||||
}
|
||||
|
||||
formatter(builder) {
|
||||
return new Formatter(this, builder);
|
||||
}
|
||||
|
||||
values(values, builder, formatter) {
|
||||
if (Array.isArray(values)) {
|
||||
if (Array.isArray(values[0])) {
|
||||
return `( values ${values
|
||||
.map(
|
||||
(value) =>
|
||||
`(${this.parameterize(value, undefined, builder, formatter)})`
|
||||
)
|
||||
.join(', ')})`;
|
||||
}
|
||||
return `(${this.parameterize(values, undefined, builder, formatter)})`;
|
||||
}
|
||||
|
||||
if (values instanceof Raw) {
|
||||
return `(${this.parameter(values, builder, formatter)})`;
|
||||
}
|
||||
|
||||
return this.parameter(values, builder, formatter);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(Client_SQLite3.prototype, {
|
||||
dialect: 'sqlite3',
|
||||
|
||||
driverName: 'sqlite3',
|
||||
});
|
||||
|
||||
module.exports = Client_SQLite3;
|
33
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js
generated
vendored
Normal file
33
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
const QueryBuilder = require('../../../query/querybuilder.js');
|
||||
|
||||
module.exports = class QueryBuilder_SQLite3 extends QueryBuilder {
|
||||
withMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
||||
this._validateWithArgs(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
'with'
|
||||
);
|
||||
return this.withWrapped(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) {
|
||||
this._validateWithArgs(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
'with'
|
||||
);
|
||||
return this.withWrapped(
|
||||
alias,
|
||||
statementOrColumnList,
|
||||
nothingOrStatement,
|
||||
false
|
||||
);
|
||||
}
|
||||
};
|
334
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js
generated
vendored
Normal file
334
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js
generated
vendored
Normal file
@ -0,0 +1,334 @@
|
||||
// SQLite3 Query Builder & Compiler
|
||||
|
||||
const constant = require('lodash/constant');
|
||||
const each = require('lodash/each');
|
||||
const identity = require('lodash/identity');
|
||||
const isEmpty = require('lodash/isEmpty');
|
||||
const reduce = require('lodash/reduce');
|
||||
|
||||
const QueryCompiler = require('../../../query/querycompiler');
|
||||
const noop = require('../../../util/noop');
|
||||
const { isString } = require('../../../util/is');
|
||||
const {
|
||||
wrapString,
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
const emptyStr = constant('');
|
||||
|
||||
class QueryCompiler_SQLite3 extends QueryCompiler {
|
||||
constructor(client, builder, formatter) {
|
||||
super(client, builder, formatter);
|
||||
|
||||
// The locks are not applicable in SQLite3
|
||||
this.forShare = emptyStr;
|
||||
this.forKeyShare = emptyStr;
|
||||
this.forUpdate = emptyStr;
|
||||
this.forNoKeyUpdate = emptyStr;
|
||||
}
|
||||
|
||||
// SQLite requires us to build the multi-row insert as a listing of select with
|
||||
// unions joining them together. So we'll build out this list of columns and
|
||||
// then join them all together with select unions to complete the queries.
|
||||
insert() {
|
||||
const insertValues = this.single.insert || [];
|
||||
let sql = this.with() + `insert into ${this.tableName} `;
|
||||
|
||||
if (Array.isArray(insertValues)) {
|
||||
if (insertValues.length === 0) {
|
||||
return '';
|
||||
} else if (
|
||||
insertValues.length === 1 &&
|
||||
insertValues[0] &&
|
||||
isEmpty(insertValues[0])
|
||||
) {
|
||||
return {
|
||||
sql: sql + this._emptyInsertValue,
|
||||
};
|
||||
}
|
||||
} else if (typeof insertValues === 'object' && isEmpty(insertValues)) {
|
||||
return {
|
||||
sql: sql + this._emptyInsertValue,
|
||||
};
|
||||
}
|
||||
|
||||
const insertData = this._prepInsert(insertValues);
|
||||
|
||||
if (isString(insertData)) {
|
||||
return {
|
||||
sql: sql + insertData,
|
||||
};
|
||||
}
|
||||
|
||||
if (insertData.columns.length === 0) {
|
||||
return {
|
||||
sql: '',
|
||||
};
|
||||
}
|
||||
|
||||
sql += `(${this.formatter.columnize(insertData.columns)})`;
|
||||
|
||||
// backwards compatible error
|
||||
if (this.client.valueForUndefined !== null) {
|
||||
insertData.values.forEach((bindings) => {
|
||||
each(bindings, (binding) => {
|
||||
if (binding === undefined)
|
||||
throw new TypeError(
|
||||
'`sqlite` does not support inserting default values. Specify ' +
|
||||
'values explicitly or use the `useNullAsDefault` config flag. ' +
|
||||
'(see docs https://knexjs.org/guide/query-builder.html#insert).'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (insertData.values.length === 1) {
|
||||
const parameters = this.client.parameterize(
|
||||
insertData.values[0],
|
||||
this.client.valueForUndefined,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
);
|
||||
sql += ` values (${parameters})`;
|
||||
|
||||
const { onConflict, ignore, merge } = this.single;
|
||||
if (onConflict && ignore) sql += this._ignore(onConflict);
|
||||
else if (onConflict && merge) {
|
||||
sql += this._merge(merge.updates, onConflict, insertValues);
|
||||
const wheres = this.where();
|
||||
if (wheres) sql += ` ${wheres}`;
|
||||
}
|
||||
|
||||
const { returning } = this.single;
|
||||
if (returning) {
|
||||
sql += this._returning(returning);
|
||||
}
|
||||
|
||||
return {
|
||||
sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
const blocks = [];
|
||||
let i = -1;
|
||||
while (++i < insertData.values.length) {
|
||||
let i2 = -1;
|
||||
const block = (blocks[i] = []);
|
||||
let current = insertData.values[i];
|
||||
current = current === undefined ? this.client.valueForUndefined : current;
|
||||
while (++i2 < insertData.columns.length) {
|
||||
block.push(
|
||||
this.client.alias(
|
||||
this.client.parameter(
|
||||
current[i2],
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
),
|
||||
this.formatter.wrap(insertData.columns[i2])
|
||||
)
|
||||
);
|
||||
}
|
||||
blocks[i] = block.join(', ');
|
||||
}
|
||||
sql += ' select ' + blocks.join(' union all select ');
|
||||
|
||||
const { onConflict, ignore, merge } = this.single;
|
||||
if (onConflict && ignore) sql += ' where true' + this._ignore(onConflict);
|
||||
else if (onConflict && merge) {
|
||||
sql +=
|
||||
' where true' + this._merge(merge.updates, onConflict, insertValues);
|
||||
}
|
||||
|
||||
const { returning } = this.single;
|
||||
if (returning) sql += this._returning(returning);
|
||||
|
||||
return {
|
||||
sql,
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
// Compiles an `update` query, allowing for a return value.
|
||||
update() {
|
||||
const withSQL = this.with();
|
||||
const updateData = this._prepUpdate(this.single.update);
|
||||
const wheres = this.where();
|
||||
const { returning } = this.single;
|
||||
return {
|
||||
sql:
|
||||
withSQL +
|
||||
`update ${this.single.only ? 'only ' : ''}${this.tableName} ` +
|
||||
`set ${updateData.join(', ')}` +
|
||||
(wheres ? ` ${wheres}` : '') +
|
||||
this._returning(returning),
|
||||
returning,
|
||||
};
|
||||
}
|
||||
|
||||
_ignore(columns) {
|
||||
if (columns === true) {
|
||||
return ' on conflict do nothing';
|
||||
}
|
||||
return ` on conflict ${this._onConflictClause(columns)} do nothing`;
|
||||
}
|
||||
|
||||
_merge(updates, columns, insert) {
|
||||
let sql = ` on conflict ${this._onConflictClause(columns)} do update set `;
|
||||
if (updates && Array.isArray(updates)) {
|
||||
sql += updates
|
||||
.map((column) =>
|
||||
wrapString(
|
||||
column.split('.').pop(),
|
||||
this.formatter.builder,
|
||||
this.client,
|
||||
this.formatter
|
||||
)
|
||||
)
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ');
|
||||
|
||||
return sql;
|
||||
} else if (updates && typeof updates === 'object') {
|
||||
const updateData = this._prepUpdate(updates);
|
||||
if (typeof updateData === 'string') {
|
||||
sql += updateData;
|
||||
} else {
|
||||
sql += updateData.join(',');
|
||||
}
|
||||
|
||||
return sql;
|
||||
} else {
|
||||
const insertData = this._prepInsert(insert);
|
||||
if (typeof insertData === 'string') {
|
||||
throw new Error(
|
||||
'If using merge with a raw insert query, then updates must be provided'
|
||||
);
|
||||
}
|
||||
|
||||
sql += insertData.columns
|
||||
.map((column) =>
|
||||
wrapString(column.split('.').pop(), this.builder, this.client)
|
||||
)
|
||||
.map((column) => `${column} = excluded.${column}`)
|
||||
.join(', ');
|
||||
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
_returning(value) {
|
||||
return value ? ` returning ${this.formatter.columnize(value)}` : '';
|
||||
}
|
||||
|
||||
// Compile a truncate table statement into SQL.
|
||||
truncate() {
|
||||
const { table } = this.single;
|
||||
return {
|
||||
sql: `delete from ${this.tableName}`,
|
||||
output() {
|
||||
return this.query({
|
||||
sql: `delete from sqlite_sequence where name = '${table}'`,
|
||||
}).catch(noop);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Compiles a `columnInfo` query
|
||||
columnInfo() {
|
||||
const column = this.single.columnInfo;
|
||||
|
||||
// The user may have specified a custom wrapIdentifier function in the config. We
|
||||
// need to run the identifiers through that function, but not format them as
|
||||
// identifiers otherwise.
|
||||
const table = this.client.customWrapIdentifier(this.single.table, identity);
|
||||
|
||||
return {
|
||||
sql: `PRAGMA table_info(\`${table}\`)`,
|
||||
output(resp) {
|
||||
const maxLengthRegex = /.*\((\d+)\)/;
|
||||
const out = reduce(
|
||||
resp,
|
||||
function (columns, val) {
|
||||
let { type } = val;
|
||||
let maxLength = type.match(maxLengthRegex);
|
||||
if (maxLength) {
|
||||
maxLength = maxLength[1];
|
||||
}
|
||||
type = maxLength ? type.split('(')[0] : type;
|
||||
columns[val.name] = {
|
||||
type: type.toLowerCase(),
|
||||
maxLength,
|
||||
nullable: !val.notnull,
|
||||
defaultValue: val.dflt_value,
|
||||
};
|
||||
return columns;
|
||||
},
|
||||
{}
|
||||
);
|
||||
return (column && out[column]) || out;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
limit() {
|
||||
const noLimit = !this.single.limit && this.single.limit !== 0;
|
||||
if (noLimit && !this.single.offset) return '';
|
||||
|
||||
// Workaround for offset only,
|
||||
// see http://stackoverflow.com/questions/10491492/sqllite-with-skip-offset-only-not-limit
|
||||
this.single.limit = noLimit ? -1 : this.single.limit;
|
||||
return `limit ${this._getValueOrParameterFromAttribute('limit')}`;
|
||||
}
|
||||
|
||||
// Json functions
|
||||
jsonExtract(params) {
|
||||
return this._jsonExtract('json_extract', params);
|
||||
}
|
||||
|
||||
jsonSet(params) {
|
||||
return this._jsonSet('json_set', params);
|
||||
}
|
||||
|
||||
jsonInsert(params) {
|
||||
return this._jsonSet('json_insert', params);
|
||||
}
|
||||
|
||||
jsonRemove(params) {
|
||||
const jsonCol = `json_remove(${columnize_(
|
||||
params.column,
|
||||
this.builder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
)},${this.client.parameter(
|
||||
params.path,
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)})`;
|
||||
return params.alias
|
||||
? this.client.alias(jsonCol, this.formatter.wrap(params.alias))
|
||||
: jsonCol;
|
||||
}
|
||||
|
||||
whereJsonPath(statement) {
|
||||
return this._whereJsonPath('json_extract', statement);
|
||||
}
|
||||
|
||||
whereJsonSupersetOf(statement) {
|
||||
throw new Error(
|
||||
'Json superset where clause not actually supported by SQLite'
|
||||
);
|
||||
}
|
||||
|
||||
whereJsonSubsetOf(statement) {
|
||||
throw new Error(
|
||||
'Json subset where clause not actually supported by SQLite'
|
||||
);
|
||||
}
|
||||
|
||||
onJsonPathEquals(clause) {
|
||||
return this._onJsonPathEquals('json_extract', clause);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = QueryCompiler_SQLite3;
|
400
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js
generated
vendored
Normal file
400
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js
generated
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
// SQLite3_DDL
|
||||
//
|
||||
// All of the SQLite3 specific DDL helpers for renaming/dropping
|
||||
// columns and changing datatypes.
|
||||
// -------
|
||||
|
||||
const identity = require('lodash/identity');
|
||||
const { nanonum } = require('../../../util/nanoid');
|
||||
const {
|
||||
copyData,
|
||||
dropOriginal,
|
||||
renameTable,
|
||||
getTableSql,
|
||||
isForeignCheckEnabled,
|
||||
setForeignCheck,
|
||||
executeForeignCheck,
|
||||
} = require('./internal/sqlite-ddl-operations');
|
||||
const { parseCreateTable, parseCreateIndex } = require('./internal/parser');
|
||||
const {
|
||||
compileCreateTable,
|
||||
compileCreateIndex,
|
||||
} = require('./internal/compiler');
|
||||
const { isEqualId, includesId } = require('./internal/utils');
|
||||
|
||||
// So altering the schema in SQLite3 is a major pain.
|
||||
// We have our own object to deal with the renaming and altering the types
|
||||
// for sqlite3 things.
|
||||
class SQLite3_DDL {
|
||||
constructor(client, tableCompiler, pragma, connection) {
|
||||
this.client = client;
|
||||
this.tableCompiler = tableCompiler;
|
||||
this.pragma = pragma;
|
||||
this.tableNameRaw = this.tableCompiler.tableNameRaw;
|
||||
this.alteredName = `_knex_temp_alter${nanonum(3)}`;
|
||||
this.connection = connection;
|
||||
this.formatter = (value) =>
|
||||
this.client.customWrapIdentifier(value, identity);
|
||||
this.wrap = (value) => this.client.wrapIdentifierImpl(value);
|
||||
}
|
||||
|
||||
tableName() {
|
||||
return this.formatter(this.tableNameRaw);
|
||||
}
|
||||
|
||||
getTableSql() {
|
||||
const tableName = this.tableName();
|
||||
|
||||
return this.client.transaction(
|
||||
async (trx) => {
|
||||
trx.disableProcessing();
|
||||
const result = await trx.raw(getTableSql(tableName));
|
||||
trx.enableProcessing();
|
||||
|
||||
return {
|
||||
createTable: result.filter((create) => create.type === 'table')[0]
|
||||
.sql,
|
||||
createIndices: result
|
||||
.filter((create) => create.type === 'index')
|
||||
.map((create) => create.sql),
|
||||
};
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
}
|
||||
|
||||
async isForeignCheckEnabled() {
|
||||
const result = await this.client
|
||||
.raw(isForeignCheckEnabled())
|
||||
.connection(this.connection);
|
||||
|
||||
return result[0].foreign_keys === 1;
|
||||
}
|
||||
|
||||
async setForeignCheck(enable) {
|
||||
await this.client.raw(setForeignCheck(enable)).connection(this.connection);
|
||||
}
|
||||
|
||||
renameTable(trx) {
|
||||
return trx.raw(renameTable(this.alteredName, this.tableName()));
|
||||
}
|
||||
|
||||
dropOriginal(trx) {
|
||||
return trx.raw(dropOriginal(this.tableName()));
|
||||
}
|
||||
|
||||
copyData(trx, columns) {
|
||||
return trx.raw(copyData(this.tableName(), this.alteredName, columns));
|
||||
}
|
||||
|
||||
async alterColumn(columns) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
parsedTable.columns = parsedTable.columns.map((column) => {
|
||||
const newColumnInfo = columns.find((c) => isEqualId(c.name, column.name));
|
||||
|
||||
if (newColumnInfo) {
|
||||
column.type = newColumnInfo.type;
|
||||
|
||||
column.constraints.default =
|
||||
newColumnInfo.defaultTo !== null
|
||||
? {
|
||||
name: null,
|
||||
value: newColumnInfo.defaultTo,
|
||||
expression: false,
|
||||
}
|
||||
: null;
|
||||
|
||||
column.constraints.notnull = newColumnInfo.notNull
|
||||
? { name: null, conflict: null }
|
||||
: null;
|
||||
|
||||
column.constraints.null = newColumnInfo.notNull
|
||||
? null
|
||||
: column.constraints.null;
|
||||
}
|
||||
|
||||
return column;
|
||||
});
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.generateAlterCommands(newTable, createIndices);
|
||||
}
|
||||
|
||||
async dropColumn(columns) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
parsedTable.columns = parsedTable.columns.filter(
|
||||
(parsedColumn) =>
|
||||
parsedColumn.expression || !includesId(columns, parsedColumn.name)
|
||||
);
|
||||
|
||||
if (parsedTable.columns.length === 0) {
|
||||
throw new Error('Unable to drop last column from table');
|
||||
}
|
||||
|
||||
parsedTable.constraints = parsedTable.constraints.filter((constraint) => {
|
||||
if (constraint.type === 'PRIMARY KEY' || constraint.type === 'UNIQUE') {
|
||||
return constraint.columns.every(
|
||||
(constraintColumn) =>
|
||||
constraintColumn.expression ||
|
||||
!includesId(columns, constraintColumn.name)
|
||||
);
|
||||
} else if (constraint.type === 'FOREIGN KEY') {
|
||||
return (
|
||||
constraint.columns.every(
|
||||
(constraintColumnName) => !includesId(columns, constraintColumnName)
|
||||
) &&
|
||||
(constraint.references.table !== parsedTable.table ||
|
||||
constraint.references.columns.every(
|
||||
(referenceColumnName) => !includesId(columns, referenceColumnName)
|
||||
))
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
const newColumns = parsedTable.columns.map((column) => column.name);
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
const newIndices = [];
|
||||
for (const createIndex of createIndices) {
|
||||
const parsedIndex = parseCreateIndex(createIndex);
|
||||
|
||||
parsedIndex.columns = parsedIndex.columns.filter(
|
||||
(parsedColumn) =>
|
||||
parsedColumn.expression || !includesId(columns, parsedColumn.name)
|
||||
);
|
||||
|
||||
if (parsedIndex.columns.length > 0) {
|
||||
newIndices.push(compileCreateIndex(parsedIndex, this.wrap));
|
||||
}
|
||||
}
|
||||
|
||||
return this.alter(newTable, newIndices, newColumns);
|
||||
}
|
||||
|
||||
async dropForeign(columns, foreignKeyName) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
if (!foreignKeyName) {
|
||||
parsedTable.columns = parsedTable.columns.map((column) => ({
|
||||
...column,
|
||||
references: includesId(columns, column.name) ? null : column.references,
|
||||
}));
|
||||
}
|
||||
|
||||
parsedTable.constraints = parsedTable.constraints.filter((constraint) => {
|
||||
if (constraint.type === 'FOREIGN KEY') {
|
||||
if (foreignKeyName) {
|
||||
return (
|
||||
!constraint.name || !isEqualId(constraint.name, foreignKeyName)
|
||||
);
|
||||
}
|
||||
|
||||
return constraint.columns.every(
|
||||
(constraintColumnName) => !includesId(columns, constraintColumnName)
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.alter(newTable, createIndices);
|
||||
}
|
||||
|
||||
async dropPrimary(constraintName) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
parsedTable.columns = parsedTable.columns.map((column) => ({
|
||||
...column,
|
||||
primary: null,
|
||||
}));
|
||||
|
||||
parsedTable.constraints = parsedTable.constraints.filter((constraint) => {
|
||||
if (constraint.type === 'PRIMARY KEY') {
|
||||
if (constraintName) {
|
||||
return (
|
||||
!constraint.name || !isEqualId(constraint.name, constraintName)
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.alter(newTable, createIndices);
|
||||
}
|
||||
|
||||
async primary(columns, constraintName) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
parsedTable.columns = parsedTable.columns.map((column) => ({
|
||||
...column,
|
||||
primary: null,
|
||||
}));
|
||||
|
||||
parsedTable.constraints = parsedTable.constraints.filter(
|
||||
(constraint) => constraint.type !== 'PRIMARY KEY'
|
||||
);
|
||||
|
||||
parsedTable.constraints.push({
|
||||
type: 'PRIMARY KEY',
|
||||
name: constraintName || null,
|
||||
columns: columns.map((column) => ({
|
||||
name: column,
|
||||
expression: false,
|
||||
collation: null,
|
||||
order: null,
|
||||
})),
|
||||
conflict: null,
|
||||
});
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.alter(newTable, createIndices);
|
||||
}
|
||||
|
||||
async foreign(foreignInfo) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
parsedTable.constraints.push({
|
||||
type: 'FOREIGN KEY',
|
||||
name: foreignInfo.keyName || null,
|
||||
columns: foreignInfo.column,
|
||||
references: {
|
||||
table: foreignInfo.inTable,
|
||||
columns: foreignInfo.references,
|
||||
delete: foreignInfo.onDelete || null,
|
||||
update: foreignInfo.onUpdate || null,
|
||||
match: null,
|
||||
deferrable: null,
|
||||
},
|
||||
});
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.generateAlterCommands(newTable, createIndices);
|
||||
}
|
||||
|
||||
async setNullable(column, isNullable) {
|
||||
const { createTable, createIndices } = await this.getTableSql();
|
||||
|
||||
const parsedTable = parseCreateTable(createTable);
|
||||
parsedTable.table = this.alteredName;
|
||||
|
||||
const parsedColumn = parsedTable.columns.find((c) =>
|
||||
isEqualId(column, c.name)
|
||||
);
|
||||
|
||||
if (!parsedColumn) {
|
||||
throw new Error(
|
||||
`.setNullable: Column ${column} does not exist in table ${this.tableName()}.`
|
||||
);
|
||||
}
|
||||
|
||||
parsedColumn.constraints.notnull = isNullable
|
||||
? null
|
||||
: { name: null, conflict: null };
|
||||
|
||||
parsedColumn.constraints.null = isNullable
|
||||
? parsedColumn.constraints.null
|
||||
: null;
|
||||
|
||||
const newTable = compileCreateTable(parsedTable, this.wrap);
|
||||
|
||||
return this.generateAlterCommands(newTable, createIndices);
|
||||
}
|
||||
|
||||
async alter(newSql, createIndices, columns) {
|
||||
const wasForeignCheckEnabled = await this.isForeignCheckEnabled();
|
||||
|
||||
if (wasForeignCheckEnabled) {
|
||||
await this.setForeignCheck(false);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.client.transaction(
|
||||
async (trx) => {
|
||||
await trx.raw(newSql);
|
||||
await this.copyData(trx, columns);
|
||||
await this.dropOriginal(trx);
|
||||
await this.renameTable(trx);
|
||||
|
||||
for (const createIndex of createIndices) {
|
||||
await trx.raw(createIndex);
|
||||
}
|
||||
|
||||
if (wasForeignCheckEnabled) {
|
||||
const foreignViolations = await trx.raw(executeForeignCheck());
|
||||
|
||||
if (foreignViolations.length > 0) {
|
||||
throw new Error('FOREIGN KEY constraint failed');
|
||||
}
|
||||
}
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
} finally {
|
||||
if (wasForeignCheckEnabled) {
|
||||
await this.setForeignCheck(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async generateAlterCommands(newSql, createIndices, columns) {
|
||||
const sql = [];
|
||||
const pre = [];
|
||||
const post = [];
|
||||
let check = null;
|
||||
|
||||
sql.push(newSql);
|
||||
sql.push(copyData(this.tableName(), this.alteredName, columns));
|
||||
sql.push(dropOriginal(this.tableName()));
|
||||
sql.push(renameTable(this.alteredName, this.tableName()));
|
||||
|
||||
for (const createIndex of createIndices) {
|
||||
sql.push(createIndex);
|
||||
}
|
||||
|
||||
const isForeignCheckEnabled = await this.isForeignCheckEnabled();
|
||||
|
||||
if (isForeignCheckEnabled) {
|
||||
pre.push(setForeignCheck(false));
|
||||
post.push(setForeignCheck(true));
|
||||
|
||||
check = executeForeignCheck();
|
||||
}
|
||||
|
||||
return { pre, sql, check, post };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SQLite3_DDL;
|
327
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js
generated
vendored
Normal file
327
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js
generated
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
function compileCreateTable(ast, wrap = (v) => v) {
|
||||
return createTable(ast, wrap);
|
||||
}
|
||||
|
||||
function compileCreateIndex(ast, wrap = (v) => v) {
|
||||
return createIndex(ast, wrap);
|
||||
}
|
||||
|
||||
function createTable(ast, wrap) {
|
||||
return `CREATE${temporary(ast, wrap)} TABLE${exists(ast, wrap)} ${schema(
|
||||
ast,
|
||||
wrap
|
||||
)}${table(ast, wrap)} (${columnDefinitionList(
|
||||
ast,
|
||||
wrap
|
||||
)}${tableConstraintList(ast, wrap)})${rowid(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function temporary(ast, wrap) {
|
||||
return ast.temporary ? ' TEMP' : '';
|
||||
}
|
||||
|
||||
function rowid(ast, wrap) {
|
||||
return ast.rowid ? ' WITHOUT ROWID' : '';
|
||||
}
|
||||
|
||||
function columnDefinitionList(ast, wrap) {
|
||||
return ast.columns.map((column) => columnDefinition(column, wrap)).join(', ');
|
||||
}
|
||||
|
||||
function columnDefinition(ast, wrap) {
|
||||
return `${identifier(ast.name, wrap)}${typeName(
|
||||
ast,
|
||||
wrap
|
||||
)}${columnConstraintList(ast.constraints, wrap)}`;
|
||||
}
|
||||
|
||||
function typeName(ast, wrap) {
|
||||
return ast.type !== null ? ` ${ast.type}` : '';
|
||||
}
|
||||
|
||||
function columnConstraintList(ast, wrap) {
|
||||
return `${primaryColumnConstraint(ast, wrap)}${notnullColumnConstraint(
|
||||
ast,
|
||||
wrap
|
||||
)}${nullColumnConstraint(ast, wrap)}${uniqueColumnConstraint(
|
||||
ast,
|
||||
wrap
|
||||
)}${checkColumnConstraint(ast, wrap)}${defaultColumnConstraint(
|
||||
ast,
|
||||
wrap
|
||||
)}${collateColumnConstraint(ast, wrap)}${referencesColumnConstraint(
|
||||
ast,
|
||||
wrap
|
||||
)}${asColumnConstraint(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function primaryColumnConstraint(ast, wrap) {
|
||||
return ast.primary !== null
|
||||
? ` ${constraintName(ast.primary, wrap)}PRIMARY KEY${order(
|
||||
ast.primary,
|
||||
wrap
|
||||
)}${conflictClause(ast.primary, wrap)}${autoincrement(ast.primary, wrap)}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function autoincrement(ast, wrap) {
|
||||
return ast.autoincrement ? ' AUTOINCREMENT' : '';
|
||||
}
|
||||
|
||||
function notnullColumnConstraint(ast, wrap) {
|
||||
return ast.notnull !== null
|
||||
? ` ${constraintName(ast.notnull, wrap)}NOT NULL${conflictClause(
|
||||
ast.notnull,
|
||||
wrap
|
||||
)}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function nullColumnConstraint(ast, wrap) {
|
||||
return ast.null !== null
|
||||
? ` ${constraintName(ast.null, wrap)}NULL${conflictClause(ast.null, wrap)}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function uniqueColumnConstraint(ast, wrap) {
|
||||
return ast.unique !== null
|
||||
? ` ${constraintName(ast.unique, wrap)}UNIQUE${conflictClause(
|
||||
ast.unique,
|
||||
wrap
|
||||
)}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function checkColumnConstraint(ast, wrap) {
|
||||
return ast.check !== null
|
||||
? ` ${constraintName(ast.check, wrap)}CHECK (${expression(
|
||||
ast.check.expression,
|
||||
wrap
|
||||
)})`
|
||||
: '';
|
||||
}
|
||||
|
||||
function defaultColumnConstraint(ast, wrap) {
|
||||
return ast.default !== null
|
||||
? ` ${constraintName(ast.default, wrap)}DEFAULT ${
|
||||
!ast.default.expression
|
||||
? ast.default.value
|
||||
: `(${expression(ast.default.value, wrap)})`
|
||||
}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function collateColumnConstraint(ast, wrap) {
|
||||
return ast.collate !== null
|
||||
? ` ${constraintName(ast.collate, wrap)}COLLATE ${ast.collate.collation}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function referencesColumnConstraint(ast, wrap) {
|
||||
return ast.references !== null
|
||||
? ` ${constraintName(ast.references, wrap)}${foreignKeyClause(
|
||||
ast.references,
|
||||
wrap
|
||||
)}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function asColumnConstraint(ast, wrap) {
|
||||
return ast.as !== null
|
||||
? ` ${constraintName(ast.as, wrap)}${
|
||||
ast.as.generated ? 'GENERATED ALWAYS ' : ''
|
||||
}AS (${expression(ast.as.expression, wrap)})${
|
||||
ast.as.mode !== null ? ` ${ast.as.mode}` : ''
|
||||
}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function tableConstraintList(ast, wrap) {
|
||||
return ast.constraints.reduce(
|
||||
(constraintList, constraint) =>
|
||||
`${constraintList}, ${tableConstraint(constraint, wrap)}`,
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
function tableConstraint(ast, wrap) {
|
||||
switch (ast.type) {
|
||||
case 'PRIMARY KEY':
|
||||
return primaryTableConstraint(ast, wrap);
|
||||
case 'UNIQUE':
|
||||
return uniqueTableConstraint(ast, wrap);
|
||||
case 'CHECK':
|
||||
return checkTableConstraint(ast, wrap);
|
||||
case 'FOREIGN KEY':
|
||||
return foreignTableConstraint(ast, wrap);
|
||||
}
|
||||
}
|
||||
|
||||
function primaryTableConstraint(ast, wrap) {
|
||||
return `${constraintName(ast, wrap)}PRIMARY KEY (${indexedColumnList(
|
||||
ast,
|
||||
wrap
|
||||
)})${conflictClause(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function uniqueTableConstraint(ast, wrap) {
|
||||
return `${constraintName(ast, wrap)}UNIQUE (${indexedColumnList(
|
||||
ast,
|
||||
wrap
|
||||
)})${conflictClause(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function conflictClause(ast, wrap) {
|
||||
return ast.conflict !== null ? ` ON CONFLICT ${ast.conflict}` : '';
|
||||
}
|
||||
|
||||
function checkTableConstraint(ast, wrap) {
|
||||
return `${constraintName(ast, wrap)}CHECK (${expression(
|
||||
ast.expression,
|
||||
wrap
|
||||
)})`;
|
||||
}
|
||||
|
||||
function foreignTableConstraint(ast, wrap) {
|
||||
return `${constraintName(ast, wrap)}FOREIGN KEY (${columnNameList(
|
||||
ast,
|
||||
wrap
|
||||
)}) ${foreignKeyClause(ast.references, wrap)}`;
|
||||
}
|
||||
|
||||
function foreignKeyClause(ast, wrap) {
|
||||
return `REFERENCES ${table(ast, wrap)}${columnNameListOptional(
|
||||
ast,
|
||||
wrap
|
||||
)}${deleteUpdateMatchList(ast, wrap)}${deferrable(ast.deferrable, wrap)}`;
|
||||
}
|
||||
|
||||
function columnNameListOptional(ast, wrap) {
|
||||
return ast.columns.length > 0 ? ` (${columnNameList(ast, wrap)})` : '';
|
||||
}
|
||||
|
||||
function columnNameList(ast, wrap) {
|
||||
return ast.columns.map((column) => identifier(column, wrap)).join(', ');
|
||||
}
|
||||
|
||||
function deleteUpdateMatchList(ast, wrap) {
|
||||
return `${deleteReference(ast, wrap)}${updateReference(
|
||||
ast,
|
||||
wrap
|
||||
)}${matchReference(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function deleteReference(ast, wrap) {
|
||||
return ast.delete !== null ? ` ON DELETE ${ast.delete}` : '';
|
||||
}
|
||||
|
||||
function updateReference(ast, wrap) {
|
||||
return ast.update !== null ? ` ON UPDATE ${ast.update}` : '';
|
||||
}
|
||||
|
||||
function matchReference(ast, wrap) {
|
||||
return ast.match !== null ? ` MATCH ${ast.match}` : '';
|
||||
}
|
||||
|
||||
function deferrable(ast, wrap) {
|
||||
return ast !== null
|
||||
? ` ${ast.not ? 'NOT ' : ''}DEFERRABLE${
|
||||
ast.initially !== null ? ` INITIALLY ${ast.initially}` : ''
|
||||
}`
|
||||
: '';
|
||||
}
|
||||
|
||||
function constraintName(ast, wrap) {
|
||||
return ast.name !== null ? `CONSTRAINT ${identifier(ast.name, wrap)} ` : '';
|
||||
}
|
||||
|
||||
function createIndex(ast, wrap) {
|
||||
return `CREATE${unique(ast, wrap)} INDEX${exists(ast, wrap)} ${schema(
|
||||
ast,
|
||||
wrap
|
||||
)}${index(ast, wrap)} on ${table(ast, wrap)} (${indexedColumnList(
|
||||
ast,
|
||||
wrap
|
||||
)})${where(ast, wrap)}`;
|
||||
}
|
||||
|
||||
function unique(ast, wrap) {
|
||||
return ast.unique ? ' UNIQUE' : '';
|
||||
}
|
||||
|
||||
function exists(ast, wrap) {
|
||||
return ast.exists ? ' IF NOT EXISTS' : '';
|
||||
}
|
||||
|
||||
function schema(ast, wrap) {
|
||||
return ast.schema !== null ? `${identifier(ast.schema, wrap)}.` : '';
|
||||
}
|
||||
|
||||
function index(ast, wrap) {
|
||||
return identifier(ast.index, wrap);
|
||||
}
|
||||
|
||||
function table(ast, wrap) {
|
||||
return identifier(ast.table, wrap);
|
||||
}
|
||||
|
||||
function where(ast, wrap) {
|
||||
return ast.where !== null ? ` where ${expression(ast.where)}` : '';
|
||||
}
|
||||
|
||||
function indexedColumnList(ast, wrap) {
|
||||
return ast.columns
|
||||
.map((column) =>
|
||||
!column.expression
|
||||
? indexedColumn(column, wrap)
|
||||
: indexedColumnExpression(column, wrap)
|
||||
)
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
function indexedColumn(ast, wrap) {
|
||||
return `${identifier(ast.name, wrap)}${collation(ast, wrap)}${order(
|
||||
ast,
|
||||
wrap
|
||||
)}`;
|
||||
}
|
||||
|
||||
function indexedColumnExpression(ast, wrap) {
|
||||
return `${indexedExpression(ast.name, wrap)}${collation(ast, wrap)}${order(
|
||||
ast,
|
||||
wrap
|
||||
)}`;
|
||||
}
|
||||
|
||||
function collation(ast, wrap) {
|
||||
return ast.collation !== null ? ` COLLATE ${ast.collation}` : '';
|
||||
}
|
||||
|
||||
function order(ast, wrap) {
|
||||
return ast.order !== null ? ` ${ast.order}` : '';
|
||||
}
|
||||
|
||||
function indexedExpression(ast, wrap) {
|
||||
return expression(ast, wrap);
|
||||
}
|
||||
|
||||
function expression(ast, wrap) {
|
||||
return ast.reduce(
|
||||
(expr, e) =>
|
||||
Array.isArray(e)
|
||||
? `${expr}(${expression(e)})`
|
||||
: !expr
|
||||
? e
|
||||
: `${expr} ${e}`,
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
function identifier(ast, wrap) {
|
||||
return wrap(ast);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compileCreateTable,
|
||||
compileCreateIndex,
|
||||
};
|
161
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js
generated
vendored
Normal file
161
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
// Sequence parser combinator
|
||||
function s(sequence, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
let position = index;
|
||||
const ast = [];
|
||||
|
||||
for (const parser of sequence) {
|
||||
const result = parser({ index: position, input });
|
||||
|
||||
if (result.success) {
|
||||
position = result.index;
|
||||
ast.push(result.ast);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true, ast: post(ast), index: position, input };
|
||||
};
|
||||
}
|
||||
|
||||
// Alternative parser combinator
|
||||
function a(alternative, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
for (const parser of alternative) {
|
||||
const result = parser({ index, input });
|
||||
|
||||
if (result.success) {
|
||||
return {
|
||||
success: true,
|
||||
ast: post(result.ast),
|
||||
index: result.index,
|
||||
input,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { success: false, ast: null, index, input };
|
||||
};
|
||||
}
|
||||
|
||||
// Many parser combinator
|
||||
function m(many, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
let result = {};
|
||||
let position = index;
|
||||
const ast = [];
|
||||
|
||||
do {
|
||||
result = many({ index: position, input });
|
||||
|
||||
if (result.success) {
|
||||
position = result.index;
|
||||
ast.push(result.ast);
|
||||
}
|
||||
} while (result.success);
|
||||
|
||||
if (ast.length > 0) {
|
||||
return { success: true, ast: post(ast), index: position, input };
|
||||
} else {
|
||||
return { success: false, ast: null, index: position, input };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Optional parser combinator
|
||||
function o(optional, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
const result = optional({ index, input });
|
||||
|
||||
if (result.success) {
|
||||
return {
|
||||
success: true,
|
||||
ast: post(result.ast),
|
||||
index: result.index,
|
||||
input,
|
||||
};
|
||||
} else {
|
||||
return { success: true, ast: post(null), index, input };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Lookahead parser combinator
|
||||
function l(lookahead, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
const result = lookahead.do({ index, input });
|
||||
|
||||
if (result.success) {
|
||||
const resultNext = lookahead.next({ index: result.index, input });
|
||||
|
||||
if (resultNext.success) {
|
||||
return {
|
||||
success: true,
|
||||
ast: post(result.ast),
|
||||
index: result.index,
|
||||
input,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { success: false, ast: null, index, input };
|
||||
};
|
||||
}
|
||||
|
||||
// Negative parser combinator
|
||||
function n(negative, post = (v) => v) {
|
||||
return function ({ index = 0, input }) {
|
||||
const result = negative.do({ index, input });
|
||||
|
||||
if (result.success) {
|
||||
const resultNot = negative.not({ index, input });
|
||||
|
||||
if (!resultNot.success) {
|
||||
return {
|
||||
success: true,
|
||||
ast: post(result.ast),
|
||||
index: result.index,
|
||||
input,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { success: false, ast: null, index, input };
|
||||
};
|
||||
}
|
||||
|
||||
// Token parser combinator
|
||||
function t(token, post = (v) => v.text) {
|
||||
return function ({ index = 0, input }) {
|
||||
const result = input[index];
|
||||
|
||||
if (
|
||||
result !== undefined &&
|
||||
(token.type === undefined || token.type === result.type) &&
|
||||
(token.text === undefined ||
|
||||
token.text.toUpperCase() === result.text.toUpperCase())
|
||||
) {
|
||||
return {
|
||||
success: true,
|
||||
ast: post(result),
|
||||
index: index + 1,
|
||||
input,
|
||||
};
|
||||
} else {
|
||||
return { success: false, ast: null, index, input };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Empty parser constant
|
||||
const e = function ({ index = 0, input }) {
|
||||
return { success: true, ast: null, index, input };
|
||||
};
|
||||
|
||||
// Finish parser constant
|
||||
const f = function ({ index = 0, input }) {
|
||||
return { success: index === input.length, ast: null, index, input };
|
||||
};
|
||||
|
||||
module.exports = { s, a, m, o, l, n, t, e, f };
|
638
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js
generated
vendored
Normal file
638
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js
generated
vendored
Normal file
@ -0,0 +1,638 @@
|
||||
const { tokenize } = require('./tokenizer');
|
||||
const { s, a, m, o, l, n, t, e, f } = require('./parser-combinator');
|
||||
|
||||
const TOKENS = {
|
||||
keyword:
|
||||
/(?:ABORT|ACTION|ADD|AFTER|ALL|ALTER|ALWAYS|ANALYZE|AND|AS|ASC|ATTACH|AUTOINCREMENT|BEFORE|BEGIN|BETWEEN|BY|CASCADE|CASE|CAST|CHECK|COLLATE|COLUMN|COMMIT|CONFLICT|CONSTRAINT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|DATABASE|DEFAULT|DEFERRED|DEFERRABLE|DELETE|DESC|DETACH|DISTINCT|DO|DROP|END|EACH|ELSE|ESCAPE|EXCEPT|EXCLUSIVE|EXCLUDE|EXISTS|EXPLAIN|FAIL|FILTER|FIRST|FOLLOWING|FOR|FOREIGN|FROM|FULL|GENERATED|GLOB|GROUP|GROUPS|HAVING|IF|IGNORE|IMMEDIATE|IN|INDEX|INDEXED|INITIALLY|INNER|INSERT|INSTEAD|INTERSECT|INTO|IS|ISNULL|JOIN|KEY|LAST|LEFT|LIKE|LIMIT|MATCH|MATERIALIZED|NATURAL|NO|NOT|NOTHING|NOTNULL|NULL|NULLS|OF|OFFSET|ON|OR|ORDER|OTHERS|OUTER|OVER|PARTITION|PLAN|PRAGMA|PRECEDING|PRIMARY|QUERY|RAISE|RANGE|RECURSIVE|REFERENCES|REGEXP|REINDEX|RELEASE|RENAME|REPLACE|RESTRICT|RETURNING|RIGHT|ROLLBACK|ROW|ROWS|SAVEPOINT|SELECT|SET|TABLE|TEMP|TEMPORARY|THEN|TIES|TO|TRANSACTION|TRIGGER|UNBOUNDED|UNION|UNIQUE|UPDATE|USING|VACUUM|VALUES|VIEW|VIRTUAL|WHEN|WHERE|WINDOW|WITH|WITHOUT)(?=\s+|-|\(|\)|;|\+|\*|\/|%|==|=|<=|<>|<<|<|>=|>>|>|!=|,|&|~|\|\||\||\.)/,
|
||||
id: /"[^"]*(?:""[^"]*)*"|`[^`]*(?:``[^`]*)*`|\[[^[\]]*\]|[a-z_][a-z0-9_$]*/,
|
||||
string: /'[^']*(?:''[^']*)*'/,
|
||||
blob: /x'(?:[0-9a-f][0-9a-f])+'/,
|
||||
numeric: /(?:\d+(?:\.\d*)?|\.\d+)(?:e(?:\+|-)?\d+)?|0x[0-9a-f]+/,
|
||||
variable: /\?\d*|[@$:][a-z0-9_$]+/,
|
||||
operator: /-|\(|\)|;|\+|\*|\/|%|==|=|<=|<>|<<|<|>=|>>|>|!=|,|&|~|\|\||\||\./,
|
||||
_ws: /\s+/,
|
||||
};
|
||||
|
||||
function parseCreateTable(sql) {
|
||||
const result = createTable({ input: tokenize(sql, TOKENS) });
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(
|
||||
`Parsing CREATE TABLE failed at [${result.input
|
||||
.slice(result.index)
|
||||
.map((t) => t.text)
|
||||
.join(' ')}] of "${sql}"`
|
||||
);
|
||||
}
|
||||
|
||||
return result.ast;
|
||||
}
|
||||
|
||||
function parseCreateIndex(sql) {
|
||||
const result = createIndex({ input: tokenize(sql, TOKENS) });
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(
|
||||
`Parsing CREATE INDEX failed at [${result.input
|
||||
.slice(result.index)
|
||||
.map((t) => t.text)
|
||||
.join(' ')}] of "${sql}"`
|
||||
);
|
||||
}
|
||||
|
||||
return result.ast;
|
||||
}
|
||||
|
||||
function createTable(ctx) {
|
||||
return s(
|
||||
[
|
||||
t({ text: 'CREATE' }, (v) => null),
|
||||
temporary,
|
||||
t({ text: 'TABLE' }, (v) => null),
|
||||
exists,
|
||||
schema,
|
||||
table,
|
||||
t({ text: '(' }, (v) => null),
|
||||
columnDefinitionList,
|
||||
tableConstraintList,
|
||||
t({ text: ')' }, (v) => null),
|
||||
rowid,
|
||||
f,
|
||||
],
|
||||
(v) => Object.assign({}, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function temporary(ctx) {
|
||||
return a([t({ text: 'TEMP' }), t({ text: 'TEMPORARY' }), e], (v) => ({
|
||||
temporary: v !== null,
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function rowid(ctx) {
|
||||
return o(s([t({ text: 'WITHOUT' }), t({ text: 'ROWID' })]), (v) => ({
|
||||
rowid: v !== null,
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function columnDefinitionList(ctx) {
|
||||
return a([
|
||||
s([columnDefinition, t({ text: ',' }), columnDefinitionList], (v) => ({
|
||||
columns: [v[0]].concat(v[2].columns),
|
||||
})),
|
||||
s([columnDefinition], (v) => ({ columns: [v[0]] })),
|
||||
])(ctx);
|
||||
}
|
||||
|
||||
function columnDefinition(ctx) {
|
||||
return s(
|
||||
[s([identifier], (v) => ({ name: v[0] })), typeName, columnConstraintList],
|
||||
(v) => Object.assign({}, ...v)
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function typeName(ctx) {
|
||||
return o(
|
||||
s(
|
||||
[
|
||||
m(t({ type: 'id' })),
|
||||
a([
|
||||
s(
|
||||
[
|
||||
t({ text: '(' }),
|
||||
signedNumber,
|
||||
t({ text: ',' }),
|
||||
signedNumber,
|
||||
t({ text: ')' }),
|
||||
],
|
||||
(v) => `(${v[1]}, ${v[3]})`
|
||||
),
|
||||
s(
|
||||
[t({ text: '(' }), signedNumber, t({ text: ')' })],
|
||||
(v) => `(${v[1]})`
|
||||
),
|
||||
e,
|
||||
]),
|
||||
],
|
||||
(v) => `${v[0].join(' ')}${v[1] || ''}`
|
||||
),
|
||||
(v) => ({ type: v })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function columnConstraintList(ctx) {
|
||||
return o(m(columnConstraint), (v) => ({
|
||||
constraints: Object.assign(
|
||||
{
|
||||
primary: null,
|
||||
notnull: null,
|
||||
null: null,
|
||||
unique: null,
|
||||
check: null,
|
||||
default: null,
|
||||
collate: null,
|
||||
references: null,
|
||||
as: null,
|
||||
},
|
||||
...(v || [])
|
||||
),
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function columnConstraint(ctx) {
|
||||
return a([
|
||||
primaryColumnConstraint,
|
||||
notnullColumnConstraint,
|
||||
nullColumnConstraint,
|
||||
uniqueColumnConstraint,
|
||||
checkColumnConstraint,
|
||||
defaultColumnConstraint,
|
||||
collateColumnConstraint,
|
||||
referencesColumnConstraint,
|
||||
asColumnConstraint,
|
||||
])(ctx);
|
||||
}
|
||||
|
||||
function primaryColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'PRIMARY' }, (v) => null),
|
||||
t({ text: 'KEY' }, (v) => null),
|
||||
order,
|
||||
conflictClause,
|
||||
autoincrement,
|
||||
],
|
||||
(v) => ({ primary: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function autoincrement(ctx) {
|
||||
return o(t({ text: 'AUTOINCREMENT' }), (v) => ({
|
||||
autoincrement: v !== null,
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function notnullColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'NOT' }, (v) => null),
|
||||
t({ text: 'NULL' }, (v) => null),
|
||||
conflictClause,
|
||||
],
|
||||
(v) => ({ notnull: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function nullColumnConstraint(ctx) {
|
||||
return s(
|
||||
[constraintName, t({ text: 'NULL' }, (v) => null), conflictClause],
|
||||
(v) => ({ null: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function uniqueColumnConstraint(ctx) {
|
||||
return s(
|
||||
[constraintName, t({ text: 'UNIQUE' }, (v) => null), conflictClause],
|
||||
(v) => ({ unique: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function checkColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'CHECK' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
s([expression], (v) => ({ expression: v[0] })),
|
||||
t({ text: ')' }, (v) => null),
|
||||
],
|
||||
(v) => ({ check: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function defaultColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'DEFAULT' }, (v) => null),
|
||||
a([
|
||||
s([t({ text: '(' }), expression, t({ text: ')' })], (v) => ({
|
||||
value: v[1],
|
||||
expression: true,
|
||||
})),
|
||||
s([literalValue], (v) => ({ value: v[0], expression: false })),
|
||||
s([signedNumber], (v) => ({ value: v[0], expression: false })),
|
||||
]),
|
||||
],
|
||||
(v) => ({ default: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function collateColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'COLLATE' }, (v) => null),
|
||||
t({ type: 'id' }, (v) => ({ collation: v.text })),
|
||||
],
|
||||
(v) => ({ collate: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function referencesColumnConstraint(ctx) {
|
||||
return s(
|
||||
[constraintName, s([foreignKeyClause], (v) => v[0].references)],
|
||||
(v) => ({
|
||||
references: Object.assign({}, ...v.filter((x) => x !== null)),
|
||||
})
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function asColumnConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
o(s([t({ text: 'GENERATED' }), t({ text: 'ALWAYS' })]), (v) => ({
|
||||
generated: v !== null,
|
||||
})),
|
||||
t({ text: 'AS' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
s([expression], (v) => ({ expression: v[0] })),
|
||||
t({ text: ')' }, (v) => null),
|
||||
a([t({ text: 'STORED' }), t({ text: 'VIRTUAL' }), e], (v) => ({
|
||||
mode: v ? v.toUpperCase() : null,
|
||||
})),
|
||||
],
|
||||
(v) => ({ as: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function tableConstraintList(ctx) {
|
||||
return o(m(s([t({ text: ',' }), tableConstraint], (v) => v[1])), (v) => ({
|
||||
constraints: v || [],
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function tableConstraint(ctx) {
|
||||
return a([
|
||||
primaryTableConstraint,
|
||||
uniqueTableConstraint,
|
||||
checkTableConstraint,
|
||||
foreignTableConstraint,
|
||||
])(ctx);
|
||||
}
|
||||
|
||||
function primaryTableConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'PRIMARY' }, (v) => null),
|
||||
t({ text: 'KEY' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
indexedColumnList,
|
||||
t({ text: ')' }, (v) => null),
|
||||
conflictClause,
|
||||
],
|
||||
(v) =>
|
||||
Object.assign({ type: 'PRIMARY KEY' }, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function uniqueTableConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'UNIQUE' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
indexedColumnList,
|
||||
t({ text: ')' }, (v) => null),
|
||||
conflictClause,
|
||||
],
|
||||
(v) => Object.assign({ type: 'UNIQUE' }, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function conflictClause(ctx) {
|
||||
return o(
|
||||
s(
|
||||
[
|
||||
t({ text: 'ON' }),
|
||||
t({ text: 'CONFLICT' }),
|
||||
a([
|
||||
t({ text: 'ROLLBACK' }),
|
||||
t({ text: 'ABORT' }),
|
||||
t({ text: 'FAIL' }),
|
||||
t({ text: 'IGNORE' }),
|
||||
t({ text: 'REPLACE' }),
|
||||
]),
|
||||
],
|
||||
(v) => v[2]
|
||||
),
|
||||
(v) => ({ conflict: v ? v.toUpperCase() : null })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function checkTableConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'CHECK' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
s([expression], (v) => ({ expression: v[0] })),
|
||||
t({ text: ')' }, (v) => null),
|
||||
],
|
||||
(v) => Object.assign({ type: 'CHECK' }, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function foreignTableConstraint(ctx) {
|
||||
return s(
|
||||
[
|
||||
constraintName,
|
||||
t({ text: 'FOREIGN' }, (v) => null),
|
||||
t({ text: 'KEY' }, (v) => null),
|
||||
t({ text: '(' }, (v) => null),
|
||||
columnNameList,
|
||||
t({ text: ')' }, (v) => null),
|
||||
foreignKeyClause,
|
||||
],
|
||||
(v) =>
|
||||
Object.assign({ type: 'FOREIGN KEY' }, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function foreignKeyClause(ctx) {
|
||||
return s(
|
||||
[
|
||||
t({ text: 'REFERENCES' }, (v) => null),
|
||||
table,
|
||||
columnNameListOptional,
|
||||
o(m(a([deleteReference, updateReference, matchReference])), (v) =>
|
||||
Object.assign({ delete: null, update: null, match: null }, ...(v || []))
|
||||
),
|
||||
deferrable,
|
||||
],
|
||||
(v) => ({ references: Object.assign({}, ...v.filter((x) => x !== null)) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function columnNameListOptional(ctx) {
|
||||
return o(
|
||||
s([t({ text: '(' }), columnNameList, t({ text: ')' })], (v) => v[1]),
|
||||
(v) => ({ columns: v ? v.columns : [] })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function columnNameList(ctx) {
|
||||
return s(
|
||||
[
|
||||
o(m(s([identifier, t({ text: ',' })], (v) => v[0])), (v) =>
|
||||
v !== null ? v : []
|
||||
),
|
||||
identifier,
|
||||
],
|
||||
(v) => ({ columns: v[0].concat([v[1]]) })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function deleteReference(ctx) {
|
||||
return s([t({ text: 'ON' }), t({ text: 'DELETE' }), onAction], (v) => ({
|
||||
delete: v[2],
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function updateReference(ctx) {
|
||||
return s([t({ text: 'ON' }), t({ text: 'UPDATE' }), onAction], (v) => ({
|
||||
update: v[2],
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function matchReference(ctx) {
|
||||
return s(
|
||||
[t({ text: 'MATCH' }), a([t({ type: 'keyword' }), t({ type: 'id' })])],
|
||||
(v) => ({ match: v[1] })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function deferrable(ctx) {
|
||||
return o(
|
||||
s([
|
||||
o(t({ text: 'NOT' })),
|
||||
t({ text: 'DEFERRABLE' }),
|
||||
o(
|
||||
s(
|
||||
[
|
||||
t({ text: 'INITIALLY' }),
|
||||
a([t({ text: 'DEFERRED' }), t({ text: 'IMMEDIATE' })]),
|
||||
],
|
||||
(v) => v[1].toUpperCase()
|
||||
)
|
||||
),
|
||||
]),
|
||||
(v) => ({ deferrable: v ? { not: v[0] !== null, initially: v[2] } : null })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function constraintName(ctx) {
|
||||
return o(
|
||||
s([t({ text: 'CONSTRAINT' }), identifier], (v) => v[1]),
|
||||
(v) => ({ name: v })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function createIndex(ctx) {
|
||||
return s(
|
||||
[
|
||||
t({ text: 'CREATE' }, (v) => null),
|
||||
unique,
|
||||
t({ text: 'INDEX' }, (v) => null),
|
||||
exists,
|
||||
schema,
|
||||
index,
|
||||
t({ text: 'ON' }, (v) => null),
|
||||
table,
|
||||
t({ text: '(' }, (v) => null),
|
||||
indexedColumnList,
|
||||
t({ text: ')' }, (v) => null),
|
||||
where,
|
||||
f,
|
||||
],
|
||||
(v) => Object.assign({}, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function unique(ctx) {
|
||||
return o(t({ text: 'UNIQUE' }), (v) => ({ unique: v !== null }))(ctx);
|
||||
}
|
||||
|
||||
function exists(ctx) {
|
||||
return o(
|
||||
s([t({ text: 'IF' }), t({ text: 'NOT' }), t({ text: 'EXISTS' })]),
|
||||
(v) => ({ exists: v !== null })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function schema(ctx) {
|
||||
return o(
|
||||
s([identifier, t({ text: '.' })], (v) => v[0]),
|
||||
(v) => ({ schema: v })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function index(ctx) {
|
||||
return s([identifier], (v) => ({ index: v[0] }))(ctx);
|
||||
}
|
||||
|
||||
function table(ctx) {
|
||||
return s([identifier], (v) => ({ table: v[0] }))(ctx);
|
||||
}
|
||||
|
||||
function where(ctx) {
|
||||
return o(
|
||||
s([t({ text: 'WHERE' }), expression], (v) => v[1]),
|
||||
(v) => ({ where: v })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function indexedColumnList(ctx) {
|
||||
return a([
|
||||
s([indexedColumn, t({ text: ',' }), indexedColumnList], (v) => ({
|
||||
columns: [v[0]].concat(v[2].columns),
|
||||
})),
|
||||
s([indexedColumnExpression, t({ text: ',' }), indexedColumnList], (v) => ({
|
||||
columns: [v[0]].concat(v[2].columns),
|
||||
})),
|
||||
l({ do: indexedColumn, next: t({ text: ')' }) }, (v) => ({
|
||||
columns: [v],
|
||||
})),
|
||||
l({ do: indexedColumnExpression, next: t({ text: ')' }) }, (v) => ({
|
||||
columns: [v],
|
||||
})),
|
||||
])(ctx);
|
||||
}
|
||||
|
||||
function indexedColumn(ctx) {
|
||||
return s(
|
||||
[
|
||||
s([identifier], (v) => ({ name: v[0], expression: false })),
|
||||
collation,
|
||||
order,
|
||||
],
|
||||
(v) => Object.assign({}, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function indexedColumnExpression(ctx) {
|
||||
return s(
|
||||
[
|
||||
s([indexedExpression], (v) => ({ name: v[0], expression: true })),
|
||||
collation,
|
||||
order,
|
||||
],
|
||||
(v) => Object.assign({}, ...v.filter((x) => x !== null))
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function collation(ctx) {
|
||||
return o(
|
||||
s([t({ text: 'COLLATE' }), t({ type: 'id' })], (v) => v[1]),
|
||||
(v) => ({ collation: v })
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function order(ctx) {
|
||||
return a([t({ text: 'ASC' }), t({ text: 'DESC' }), e], (v) => ({
|
||||
order: v ? v.toUpperCase() : null,
|
||||
}))(ctx);
|
||||
}
|
||||
|
||||
function indexedExpression(ctx) {
|
||||
return m(
|
||||
a([
|
||||
n({
|
||||
do: t({ type: 'keyword' }),
|
||||
not: a([
|
||||
t({ text: 'COLLATE' }),
|
||||
t({ text: 'ASC' }),
|
||||
t({ text: 'DESC' }),
|
||||
]),
|
||||
}),
|
||||
t({ type: 'id' }),
|
||||
t({ type: 'string' }),
|
||||
t({ type: 'blob' }),
|
||||
t({ type: 'numeric' }),
|
||||
t({ type: 'variable' }),
|
||||
n({
|
||||
do: t({ type: 'operator' }),
|
||||
not: a([t({ text: '(' }), t({ text: ')' }), t({ text: ',' })]),
|
||||
}),
|
||||
s([t({ text: '(' }), o(expression), t({ text: ')' })], (v) => v[1] || []),
|
||||
])
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function expression(ctx) {
|
||||
return m(
|
||||
a([
|
||||
t({ type: 'keyword' }),
|
||||
t({ type: 'id' }),
|
||||
t({ type: 'string' }),
|
||||
t({ type: 'blob' }),
|
||||
t({ type: 'numeric' }),
|
||||
t({ type: 'variable' }),
|
||||
n({
|
||||
do: t({ type: 'operator' }),
|
||||
not: a([t({ text: '(' }), t({ text: ')' })]),
|
||||
}),
|
||||
s([t({ text: '(' }), o(expression), t({ text: ')' })], (v) => v[1] || []),
|
||||
])
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function identifier(ctx) {
|
||||
return a([t({ type: 'id' }), t({ type: 'string' })], (v) =>
|
||||
/^["`['][^]*["`\]']$/.test(v) ? v.substring(1, v.length - 1) : v
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function onAction(ctx) {
|
||||
return a(
|
||||
[
|
||||
s([t({ text: 'SET' }), t({ text: 'NULL' })], (v) => `${v[0]} ${v[1]}`),
|
||||
s([t({ text: 'SET' }), t({ text: 'DEFAULT' })], (v) => `${v[0]} ${v[1]}`),
|
||||
t({ text: 'CASCADE' }),
|
||||
t({ text: 'RESTRICT' }),
|
||||
s([t({ text: 'NO' }), t({ text: 'ACTION' })], (v) => `${v[0]} ${v[1]}`),
|
||||
],
|
||||
(v) => v.toUpperCase()
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
function literalValue(ctx) {
|
||||
return a([
|
||||
t({ type: 'numeric' }),
|
||||
t({ type: 'string' }),
|
||||
t({ type: 'id' }),
|
||||
t({ type: 'blob' }),
|
||||
t({ text: 'NULL' }),
|
||||
t({ text: 'TRUE' }),
|
||||
t({ text: 'FALSE' }),
|
||||
t({ text: 'CURRENT_TIME' }),
|
||||
t({ text: 'CURRENT_DATE' }),
|
||||
t({ text: 'CURRENT_TIMESTAMP' }),
|
||||
])(ctx);
|
||||
}
|
||||
|
||||
function signedNumber(ctx) {
|
||||
return s(
|
||||
[a([t({ text: '+' }), t({ text: '-' }), e]), t({ type: 'numeric' })],
|
||||
(v) => `${v[0] || ''}${v[1]}`
|
||||
)(ctx);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseCreateTable,
|
||||
parseCreateIndex,
|
||||
};
|
41
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js
generated
vendored
Normal file
41
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
function copyData(sourceTable, targetTable, columns) {
|
||||
return `INSERT INTO "${targetTable}" SELECT ${
|
||||
columns === undefined
|
||||
? '*'
|
||||
: columns.map((column) => `"${column}"`).join(', ')
|
||||
} FROM "${sourceTable}";`;
|
||||
}
|
||||
|
||||
function dropOriginal(tableName) {
|
||||
return `DROP TABLE "${tableName}"`;
|
||||
}
|
||||
|
||||
function renameTable(tableName, alteredName) {
|
||||
return `ALTER TABLE "${tableName}" RENAME TO "${alteredName}"`;
|
||||
}
|
||||
|
||||
function getTableSql(tableName) {
|
||||
return `SELECT type, sql FROM sqlite_master WHERE (type='table' OR (type='index' AND sql IS NOT NULL)) AND lower(tbl_name)='${tableName.toLowerCase()}'`;
|
||||
}
|
||||
|
||||
function isForeignCheckEnabled() {
|
||||
return `PRAGMA foreign_keys`;
|
||||
}
|
||||
|
||||
function setForeignCheck(enable) {
|
||||
return `PRAGMA foreign_keys = ${enable ? 'ON' : 'OFF'}`;
|
||||
}
|
||||
|
||||
function executeForeignCheck() {
|
||||
return `PRAGMA foreign_key_check`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
copyData,
|
||||
dropOriginal,
|
||||
renameTable,
|
||||
getTableSql,
|
||||
isForeignCheckEnabled,
|
||||
setForeignCheck,
|
||||
executeForeignCheck,
|
||||
};
|
38
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js
generated
vendored
Normal file
38
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
function tokenize(text, tokens) {
|
||||
const compiledRegex = new RegExp(
|
||||
Object.entries(tokens)
|
||||
.map(([type, regex]) => `(?<${type}>${regex.source})`)
|
||||
.join('|'),
|
||||
'yi'
|
||||
);
|
||||
|
||||
let index = 0;
|
||||
const ast = [];
|
||||
|
||||
while (index < text.length) {
|
||||
compiledRegex.lastIndex = index;
|
||||
const result = text.match(compiledRegex);
|
||||
|
||||
if (result !== null) {
|
||||
const [type, text] = Object.entries(result.groups).find(
|
||||
([name, group]) => group !== undefined
|
||||
);
|
||||
|
||||
index += text.length;
|
||||
|
||||
if (!type.startsWith('_')) {
|
||||
ast.push({ type, text });
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`No matching tokenizer rule found at: [${text.substring(index)}]`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
tokenize,
|
||||
};
|
12
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js
generated
vendored
Normal file
12
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
function isEqualId(first, second) {
|
||||
return first.toLowerCase() === second.toLowerCase();
|
||||
}
|
||||
|
||||
function includesId(list, id) {
|
||||
return list.some((item) => isEqualId(item, id));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isEqualId,
|
||||
includesId,
|
||||
};
|
50
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js
generated
vendored
Normal file
50
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
const ColumnCompiler = require('../../../schema/columncompiler');
|
||||
|
||||
// Column Compiler
|
||||
// -------
|
||||
|
||||
class ColumnCompiler_SQLite3 extends ColumnCompiler {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.modifiers = ['nullable', 'defaultTo'];
|
||||
this._addCheckModifiers();
|
||||
}
|
||||
|
||||
// Types
|
||||
// -------
|
||||
|
||||
enu(allowed) {
|
||||
return `text check (${this.formatter.wrap(
|
||||
this.args[0]
|
||||
)} in ('${allowed.join("', '")}'))`;
|
||||
}
|
||||
|
||||
_pushAlterCheckQuery(checkPredicate, constraintName) {
|
||||
throw new Error(
|
||||
`Alter table with to add constraints is not permitted in SQLite`
|
||||
);
|
||||
}
|
||||
|
||||
checkRegex(regexes, constraintName) {
|
||||
return this._check(
|
||||
`${this.formatter.wrap(
|
||||
this.getColumnName()
|
||||
)} REGEXP ${this.client._escapeBinding(regexes)}`,
|
||||
constraintName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColumnCompiler_SQLite3.prototype.json = 'json';
|
||||
ColumnCompiler_SQLite3.prototype.jsonb = 'json';
|
||||
ColumnCompiler_SQLite3.prototype.double =
|
||||
ColumnCompiler_SQLite3.prototype.decimal =
|
||||
ColumnCompiler_SQLite3.prototype.floating =
|
||||
'float';
|
||||
ColumnCompiler_SQLite3.prototype.timestamp = 'datetime';
|
||||
// autoincrement without primary key is a syntax error in SQLite, so it's necessary
|
||||
ColumnCompiler_SQLite3.prototype.increments =
|
||||
ColumnCompiler_SQLite3.prototype.bigincrements =
|
||||
'integer not null primary key autoincrement';
|
||||
|
||||
module.exports = ColumnCompiler_SQLite3;
|
80
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js
generated
vendored
Normal file
80
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// SQLite3: Column Builder & Compiler
|
||||
// -------
|
||||
const SchemaCompiler = require('../../../schema/compiler');
|
||||
|
||||
const some = require('lodash/some');
|
||||
|
||||
// Schema Compiler
|
||||
// -------
|
||||
|
||||
class SchemaCompiler_SQLite3 extends SchemaCompiler {
|
||||
constructor(client, builder) {
|
||||
super(client, builder);
|
||||
}
|
||||
|
||||
// Compile the query to determine if a table exists.
|
||||
hasTable(tableName) {
|
||||
const sql =
|
||||
`select * from sqlite_master ` +
|
||||
`where type = 'table' and name = ${this.client.parameter(
|
||||
this.formatter.wrap(tableName).replace(/`/g, ''),
|
||||
this.builder,
|
||||
this.bindingsHolder
|
||||
)}`;
|
||||
this.pushQuery({ sql, output: (resp) => resp.length > 0 });
|
||||
}
|
||||
|
||||
// Compile the query to determine if a column exists.
|
||||
hasColumn(tableName, column) {
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.formatter.wrap(tableName)})`,
|
||||
output(resp) {
|
||||
return some(resp, (col) => {
|
||||
return (
|
||||
this.client.wrapIdentifier(col.name.toLowerCase()) ===
|
||||
this.client.wrapIdentifier(column.toLowerCase())
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Compile a rename table command.
|
||||
renameTable(from, to) {
|
||||
this.pushQuery(
|
||||
`alter table ${this.formatter.wrap(from)} rename to ${this.formatter.wrap(
|
||||
to
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
async generateDdlCommands() {
|
||||
const sequence = this.builder._sequence;
|
||||
for (let i = 0, l = sequence.length; i < l; i++) {
|
||||
const query = sequence[i];
|
||||
this[query.method].apply(this, query.args);
|
||||
}
|
||||
|
||||
const commandSources = this.sequence;
|
||||
|
||||
if (commandSources.length === 1 && commandSources[0].statementsProducer) {
|
||||
return commandSources[0].statementsProducer();
|
||||
} else {
|
||||
const result = [];
|
||||
|
||||
for (const commandSource of commandSources) {
|
||||
const command = commandSource.sql;
|
||||
|
||||
if (Array.isArray(command)) {
|
||||
result.push(...command);
|
||||
} else {
|
||||
result.push(command);
|
||||
}
|
||||
}
|
||||
|
||||
return { pre: [], sql: result, check: null, post: [] };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_SQLite3;
|
347
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js
generated
vendored
Normal file
347
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js
generated
vendored
Normal file
@ -0,0 +1,347 @@
|
||||
const filter = require('lodash/filter');
|
||||
const values = require('lodash/values');
|
||||
const identity = require('lodash/identity');
|
||||
const { isObject } = require('../../../util/is');
|
||||
|
||||
const TableCompiler = require('../../../schema/tablecompiler');
|
||||
const { formatDefault } = require('../../../formatter/formatterUtils');
|
||||
|
||||
class TableCompiler_SQLite3 extends TableCompiler {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
// Create a new table.
|
||||
createQuery(columns, ifNot, like) {
|
||||
const createStatement = ifNot
|
||||
? 'create table if not exists '
|
||||
: 'create table ';
|
||||
|
||||
let sql = createStatement + this.tableName();
|
||||
|
||||
if (like && this.tableNameLike()) {
|
||||
sql += ' as select * from ' + this.tableNameLike() + ' where 0=1';
|
||||
} else {
|
||||
// so we will need to check for a primary key commands and add the columns
|
||||
// to the table's declaration here so they can be created on the tables.
|
||||
sql += ' (' + columns.sql.join(', ');
|
||||
sql += this.foreignKeys() || '';
|
||||
sql += this.primaryKeys() || '';
|
||||
sql += this._addChecks();
|
||||
sql += ')';
|
||||
}
|
||||
this.pushQuery(sql);
|
||||
|
||||
if (like) {
|
||||
this.addColumns(columns, this.addColumnsPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
addColumns(columns, prefix, colCompilers) {
|
||||
if (prefix === this.alterColumnsPrefix) {
|
||||
const compiler = this;
|
||||
|
||||
const columnsInfo = colCompilers.map((col) => {
|
||||
const name = this.client.customWrapIdentifier(
|
||||
col.getColumnName(),
|
||||
identity,
|
||||
col.columnBuilder.queryContext()
|
||||
);
|
||||
|
||||
const type = col.getColumnType();
|
||||
|
||||
const defaultTo = col.modified['defaultTo']
|
||||
? formatDefault(col.modified['defaultTo'][0], col.type, this.client)
|
||||
: null;
|
||||
|
||||
const notNull =
|
||||
col.modified['nullable'] && col.modified['nullable'][0] === false;
|
||||
|
||||
return { name, type, defaultTo, notNull };
|
||||
});
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
statementsProducer(pragma, connection) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, connection)
|
||||
.alterColumn(columnsInfo);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
for (let i = 0, l = columns.sql.length; i < l; i++) {
|
||||
this.pushQuery({
|
||||
sql: `alter table ${this.tableName()} add column ${columns.sql[i]}`,
|
||||
bindings: columns.bindings[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compile a drop unique key command.
|
||||
dropUnique(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
this.pushQuery(`drop index ${indexName}`);
|
||||
}
|
||||
|
||||
// Compile a drop foreign key command.
|
||||
dropForeign(columns, indexName) {
|
||||
const compiler = this;
|
||||
|
||||
columns = Array.isArray(columns) ? columns : [columns];
|
||||
columns = columns.map((column) =>
|
||||
this.client.customWrapIdentifier(column, identity)
|
||||
);
|
||||
indexName = this.client.customWrapIdentifier(indexName, identity);
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
output(pragma) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, this.connection)
|
||||
.dropForeign(columns, indexName);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Compile a drop primary key command.
|
||||
dropPrimary(constraintName) {
|
||||
const compiler = this;
|
||||
|
||||
constraintName = this.client.customWrapIdentifier(constraintName, identity);
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
output(pragma) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, this.connection)
|
||||
.dropPrimary(constraintName);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
dropIndex(columns, indexName) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
this.pushQuery(`drop index ${indexName}`);
|
||||
}
|
||||
|
||||
// Compile a unique key command.
|
||||
unique(columns, indexName) {
|
||||
let deferrable;
|
||||
let predicate;
|
||||
if (isObject(indexName)) {
|
||||
({ indexName, deferrable, predicate } = indexName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`sqlite3: unique index \`${indexName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('unique', this.tableNameRaw, columns);
|
||||
columns = this.formatter.columnize(columns);
|
||||
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: '';
|
||||
|
||||
this.pushQuery(
|
||||
`create unique index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
|
||||
);
|
||||
}
|
||||
|
||||
// Compile a plain index key command.
|
||||
index(columns, indexName, options) {
|
||||
indexName = indexName
|
||||
? this.formatter.wrap(indexName)
|
||||
: this._indexCommand('index', this.tableNameRaw, columns);
|
||||
columns = this.formatter.columnize(columns);
|
||||
|
||||
let predicate;
|
||||
if (isObject(options)) {
|
||||
({ predicate } = options);
|
||||
}
|
||||
const predicateQuery = predicate
|
||||
? ' ' + this.client.queryCompiler(predicate).where()
|
||||
: '';
|
||||
this.pushQuery(
|
||||
`create index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a primary key to an existing table.
|
||||
*
|
||||
* @NOTE The `createQuery` method above handles table creation. Don't do anything regarding table
|
||||
* creation in this method
|
||||
*
|
||||
* @param {string | string[]} columns - Column name(s) to assign as primary keys
|
||||
* @param {string} [constraintName] - Custom name for the PK constraint
|
||||
*/
|
||||
primary(columns, constraintName) {
|
||||
const compiler = this;
|
||||
|
||||
columns = Array.isArray(columns) ? columns : [columns];
|
||||
columns = columns.map((column) =>
|
||||
this.client.customWrapIdentifier(column, identity)
|
||||
);
|
||||
|
||||
let deferrable;
|
||||
if (isObject(constraintName)) {
|
||||
({ constraintName, deferrable } = constraintName);
|
||||
}
|
||||
if (deferrable && deferrable !== 'not deferrable') {
|
||||
this.client.logger.warn(
|
||||
`sqlite3: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.`
|
||||
);
|
||||
}
|
||||
constraintName = this.client.customWrapIdentifier(constraintName, identity);
|
||||
|
||||
if (this.method !== 'create' && this.method !== 'createIfNot') {
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
output(pragma) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, this.connection)
|
||||
.primary(columns, constraintName);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a foreign key constraint to an existing table
|
||||
*
|
||||
* @NOTE The `createQuery` method above handles foreign key constraints on table creation. Don't do
|
||||
* anything regarding table creation in this method
|
||||
*
|
||||
* @param {object} foreignInfo - Information about the current column foreign setup
|
||||
* @param {string | string[]} [foreignInfo.column] - Column in the current constraint
|
||||
* @param {string | undefined} foreignInfo.keyName - Name of the foreign key constraint
|
||||
* @param {string | string[]} foreignInfo.references - What column it references in the other table
|
||||
* @param {string} foreignInfo.inTable - What table is referenced in this constraint
|
||||
* @param {string} [foreignInfo.onUpdate] - What to do on updates
|
||||
* @param {string} [foreignInfo.onDelete] - What to do on deletions
|
||||
*/
|
||||
foreign(foreignInfo) {
|
||||
const compiler = this;
|
||||
|
||||
if (this.method !== 'create' && this.method !== 'createIfNot') {
|
||||
foreignInfo.column = Array.isArray(foreignInfo.column)
|
||||
? foreignInfo.column
|
||||
: [foreignInfo.column];
|
||||
foreignInfo.column = foreignInfo.column.map((column) =>
|
||||
this.client.customWrapIdentifier(column, identity)
|
||||
);
|
||||
foreignInfo.inTable = this.client.customWrapIdentifier(
|
||||
foreignInfo.inTable,
|
||||
identity
|
||||
);
|
||||
foreignInfo.references = Array.isArray(foreignInfo.references)
|
||||
? foreignInfo.references
|
||||
: [foreignInfo.references];
|
||||
foreignInfo.references = foreignInfo.references.map((column) =>
|
||||
this.client.customWrapIdentifier(column, identity)
|
||||
);
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
statementsProducer(pragma, connection) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, connection)
|
||||
.foreign(foreignInfo);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
primaryKeys() {
|
||||
const pks = filter(this.grouped.alterTable || [], { method: 'primary' });
|
||||
if (pks.length > 0 && pks[0].args.length > 0) {
|
||||
const columns = pks[0].args[0];
|
||||
let constraintName = pks[0].args[1] || '';
|
||||
if (constraintName) {
|
||||
constraintName = ' constraint ' + this.formatter.wrap(constraintName);
|
||||
}
|
||||
const needUniqueCols =
|
||||
this.grouped.columns.filter((t) => t.builder._type === 'increments')
|
||||
.length > 0;
|
||||
// SQLite dont support autoincrement columns and composite primary keys (autoincrement is always primary key).
|
||||
// You need to add unique index instead when you have autoincrement columns (https://stackoverflow.com/a/6154876/1535159)
|
||||
return `,${constraintName} ${
|
||||
needUniqueCols ? 'unique' : 'primary key'
|
||||
} (${this.formatter.columnize(columns)})`;
|
||||
}
|
||||
}
|
||||
|
||||
foreignKeys() {
|
||||
let sql = '';
|
||||
const foreignKeys = filter(this.grouped.alterTable || [], {
|
||||
method: 'foreign',
|
||||
});
|
||||
for (let i = 0, l = foreignKeys.length; i < l; i++) {
|
||||
const foreign = foreignKeys[i].args[0];
|
||||
const column = this.formatter.columnize(foreign.column);
|
||||
const references = this.formatter.columnize(foreign.references);
|
||||
const foreignTable = this.formatter.wrap(foreign.inTable);
|
||||
let constraintName = foreign.keyName || '';
|
||||
if (constraintName) {
|
||||
constraintName = ' constraint ' + this.formatter.wrap(constraintName);
|
||||
}
|
||||
sql += `,${constraintName} foreign key(${column}) references ${foreignTable}(${references})`;
|
||||
if (foreign.onDelete) sql += ` on delete ${foreign.onDelete}`;
|
||||
if (foreign.onUpdate) sql += ` on update ${foreign.onUpdate}`;
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
createTableBlock() {
|
||||
return this.getColumns().concat().join(',');
|
||||
}
|
||||
|
||||
renameColumn(from, to) {
|
||||
this.pushQuery({
|
||||
sql: `alter table ${this.tableName()} rename ${this.formatter.wrap(
|
||||
from
|
||||
)} to ${this.formatter.wrap(to)}`,
|
||||
});
|
||||
}
|
||||
|
||||
_setNullableState(column, isNullable) {
|
||||
const compiler = this;
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
statementsProducer(pragma, connection) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, connection)
|
||||
.setNullable(column, isNullable);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
dropColumn() {
|
||||
const compiler = this;
|
||||
const columns = values(arguments);
|
||||
|
||||
const columnsWrapped = columns.map((column) =>
|
||||
this.client.customWrapIdentifier(column, identity)
|
||||
);
|
||||
|
||||
this.pushQuery({
|
||||
sql: `PRAGMA table_info(${this.tableName()})`,
|
||||
output(pragma) {
|
||||
return compiler.client
|
||||
.ddl(compiler, pragma, this.connection)
|
||||
.dropColumn(columnsWrapped);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TableCompiler_SQLite3;
|
40
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js
generated
vendored
Normal file
40
backend/apis/nodejs/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
const {
|
||||
columnize: columnize_,
|
||||
} = require('../../../formatter/wrappingFormatter');
|
||||
|
||||
class ViewCompiler_SQLite3 extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
createOrReplace() {
|
||||
const columns = this.columns;
|
||||
const selectQuery = this.selectQuery.toString();
|
||||
const viewName = this.viewName();
|
||||
|
||||
const columnList = columns
|
||||
? ' (' +
|
||||
columnize_(
|
||||
columns,
|
||||
this.viewBuilder,
|
||||
this.client,
|
||||
this.bindingsHolder
|
||||
) +
|
||||
')'
|
||||
: '';
|
||||
|
||||
const dropSql = `drop view if exists ${viewName}`;
|
||||
const createSql = `create view ${viewName}${columnList} as ${selectQuery}`;
|
||||
|
||||
this.pushQuery({
|
||||
sql: dropSql,
|
||||
});
|
||||
this.pushQuery({
|
||||
sql: createSql,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_SQLite3;
|
51
backend/apis/nodejs/node_modules/knex/lib/execution/batch-insert.js
generated
vendored
Normal file
51
backend/apis/nodejs/node_modules/knex/lib/execution/batch-insert.js
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
const chunk = require('lodash/chunk');
|
||||
const flatten = require('lodash/flatten');
|
||||
const delay = require('./internal/delay');
|
||||
const { isNumber } = require('../util/is');
|
||||
|
||||
function batchInsert(client, tableName, batch, chunkSize = 1000) {
|
||||
let returning = undefined;
|
||||
let transaction = null;
|
||||
if (!isNumber(chunkSize) || chunkSize < 1) {
|
||||
throw new TypeError(`Invalid chunkSize: ${chunkSize}`);
|
||||
}
|
||||
if (!Array.isArray(batch)) {
|
||||
throw new TypeError(`Invalid batch: Expected array, got ${typeof batch}`);
|
||||
}
|
||||
const chunks = chunk(batch, chunkSize);
|
||||
|
||||
const runInTransaction = (cb) => {
|
||||
if (transaction) {
|
||||
return cb(transaction);
|
||||
}
|
||||
return client.transaction(cb);
|
||||
};
|
||||
|
||||
return Object.assign(
|
||||
Promise.resolve().then(async () => {
|
||||
//Next tick to ensure wrapper functions are called if needed
|
||||
await delay(1);
|
||||
return runInTransaction(async (tr) => {
|
||||
const chunksResults = [];
|
||||
for (const items of chunks) {
|
||||
chunksResults.push(await tr(tableName).insert(items, returning));
|
||||
}
|
||||
return flatten(chunksResults);
|
||||
});
|
||||
}),
|
||||
{
|
||||
returning(columns) {
|
||||
returning = columns;
|
||||
|
||||
return this;
|
||||
},
|
||||
transacting(tr) {
|
||||
transaction = tr;
|
||||
|
||||
return this;
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = batchInsert;
|
6
backend/apis/nodejs/node_modules/knex/lib/execution/internal/delay.js
generated
vendored
Normal file
6
backend/apis/nodejs/node_modules/knex/lib/execution/internal/delay.js
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @param {number} delay
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
module.exports = (delay) =>
|
||||
new Promise((resolve) => setTimeout(resolve, delay));
|
41
backend/apis/nodejs/node_modules/knex/lib/execution/internal/ensure-connection-callback.js
generated
vendored
Normal file
41
backend/apis/nodejs/node_modules/knex/lib/execution/internal/ensure-connection-callback.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
function ensureConnectionCallback(runner) {
|
||||
runner.client.emit('start', runner.builder);
|
||||
runner.builder.emit('start', runner.builder);
|
||||
const sql = runner.builder.toSQL();
|
||||
|
||||
if (runner.builder._debug) {
|
||||
runner.client.logger.debug(sql);
|
||||
}
|
||||
|
||||
if (Array.isArray(sql)) {
|
||||
return runner.queryArray(sql);
|
||||
}
|
||||
return runner.query(sql);
|
||||
}
|
||||
|
||||
function ensureConnectionStreamCallback(runner, params) {
|
||||
try {
|
||||
const sql = runner.builder.toSQL();
|
||||
|
||||
if (Array.isArray(sql) && params.hasHandler) {
|
||||
throw new Error(
|
||||
'The stream may only be used with a single query statement.'
|
||||
);
|
||||
}
|
||||
|
||||
return runner.client.stream(
|
||||
runner.connection,
|
||||
sql,
|
||||
params.stream,
|
||||
params.options
|
||||
);
|
||||
} catch (e) {
|
||||
params.stream.emit('error', e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ensureConnectionCallback,
|
||||
ensureConnectionStreamCallback,
|
||||
};
|
62
backend/apis/nodejs/node_modules/knex/lib/execution/internal/query-executioner.js
generated
vendored
Normal file
62
backend/apis/nodejs/node_modules/knex/lib/execution/internal/query-executioner.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
const _debugQuery = require('debug')('knex:query');
|
||||
const debugBindings = require('debug')('knex:bindings');
|
||||
const debugQuery = (sql, txId) => _debugQuery(sql.replace(/%/g, '%%'), txId);
|
||||
const { isString } = require('../../util/is');
|
||||
|
||||
function formatQuery(sql, bindings, timeZone, client) {
|
||||
bindings = bindings == null ? [] : [].concat(bindings);
|
||||
let index = 0;
|
||||
return sql.replace(/\\?\?/g, (match) => {
|
||||
if (match === '\\?') {
|
||||
return '?';
|
||||
}
|
||||
if (index === bindings.length) {
|
||||
return match;
|
||||
}
|
||||
const value = bindings[index++];
|
||||
return client._escapeBinding(value, { timeZone });
|
||||
});
|
||||
}
|
||||
|
||||
function enrichQueryObject(connection, queryParam, client) {
|
||||
const queryObject = isString(queryParam) ? { sql: queryParam } : queryParam;
|
||||
|
||||
queryObject.bindings = client.prepBindings(queryObject.bindings);
|
||||
queryObject.sql = client.positionBindings(queryObject.sql);
|
||||
|
||||
const { __knexUid, __knexTxId } = connection;
|
||||
|
||||
client.emit('query', Object.assign({ __knexUid, __knexTxId }, queryObject));
|
||||
debugQuery(queryObject.sql, __knexTxId);
|
||||
debugBindings(queryObject.bindings, __knexTxId);
|
||||
|
||||
return queryObject;
|
||||
}
|
||||
|
||||
function executeQuery(connection, queryObject, client) {
|
||||
return client._query(connection, queryObject).catch((err) => {
|
||||
if (client.config && client.config.compileSqlOnError === false) {
|
||||
err.message = queryObject.sql + ' - ' + err.message;
|
||||
} else {
|
||||
err.message =
|
||||
formatQuery(queryObject.sql, queryObject.bindings, undefined, client) +
|
||||
' - ' +
|
||||
err.message;
|
||||
}
|
||||
client.emit(
|
||||
'query-error',
|
||||
err,
|
||||
Object.assign(
|
||||
{ __knexUid: connection.__knexUid, __knexTxId: connection.__knexUid },
|
||||
queryObject
|
||||
)
|
||||
);
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
enrichQueryObject,
|
||||
executeQuery,
|
||||
formatQuery,
|
||||
};
|
325
backend/apis/nodejs/node_modules/knex/lib/execution/runner.js
generated
vendored
Normal file
325
backend/apis/nodejs/node_modules/knex/lib/execution/runner.js
generated
vendored
Normal file
@ -0,0 +1,325 @@
|
||||
const { KnexTimeoutError } = require('../util/timeout');
|
||||
const { timeout } = require('../util/timeout');
|
||||
const {
|
||||
ensureConnectionCallback,
|
||||
ensureConnectionStreamCallback,
|
||||
} = require('./internal/ensure-connection-callback');
|
||||
|
||||
let Transform;
|
||||
|
||||
// The "Runner" constructor takes a "builder" (query, schema, or raw)
|
||||
// and runs through each of the query statements, calling any additional
|
||||
// "output" method provided alongside the query and bindings.
|
||||
class Runner {
|
||||
constructor(client, builder) {
|
||||
this.client = client;
|
||||
this.builder = builder;
|
||||
this.queries = [];
|
||||
|
||||
// The "connection" object is set on the runner when
|
||||
// "run" is called.
|
||||
this.connection = undefined;
|
||||
}
|
||||
|
||||
// "Run" the target, calling "toSQL" on the builder, returning
|
||||
// an object or array of queries to run, each of which are run on
|
||||
// a single connection.
|
||||
async run() {
|
||||
const runner = this;
|
||||
try {
|
||||
const res = await this.ensureConnection(ensureConnectionCallback);
|
||||
|
||||
// Fire a single "end" event on the builder when
|
||||
// all queries have successfully completed.
|
||||
runner.builder.emit('end');
|
||||
return res;
|
||||
|
||||
// If there are any "error" listeners, we fire an error event
|
||||
// and then re-throw the error to be eventually handled by
|
||||
// the promise chain. Useful if you're wrapping in a custom `Promise`.
|
||||
} catch (err) {
|
||||
if (runner.builder._events && runner.builder._events.error) {
|
||||
runner.builder.emit('error', err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Stream the result set, by passing through to the dialect's streaming
|
||||
// capabilities. If the options are
|
||||
stream(optionsOrHandler, handlerOrNil) {
|
||||
const firstOptionIsHandler =
|
||||
typeof optionsOrHandler === 'function' && arguments.length === 1;
|
||||
|
||||
const options = firstOptionIsHandler ? {} : optionsOrHandler;
|
||||
const handler = firstOptionIsHandler ? optionsOrHandler : handlerOrNil;
|
||||
|
||||
// Determines whether we emit an error or throw here.
|
||||
const hasHandler = typeof handler === 'function';
|
||||
|
||||
// Lazy-load the "Transform" dependency.
|
||||
Transform = Transform || require('stream').Transform;
|
||||
|
||||
const queryContext = this.builder.queryContext();
|
||||
|
||||
const stream = new Transform({
|
||||
objectMode: true,
|
||||
transform: (chunk, _, callback) => {
|
||||
callback(null, this.client.postProcessResponse(chunk, queryContext));
|
||||
},
|
||||
});
|
||||
stream.on('close', () => {
|
||||
this.client.releaseConnection(this.connection);
|
||||
});
|
||||
|
||||
// If the stream is manually destroyed, the close event is not
|
||||
// propagated to the top of the pipe chain. We need to manually verify
|
||||
// that the source stream is closed and if not, manually destroy it.
|
||||
stream.on('pipe', (sourceStream) => {
|
||||
const cleanSourceStream = () => {
|
||||
if (!sourceStream.closed) {
|
||||
sourceStream.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
// Stream already closed, cleanup immediately
|
||||
if (stream.closed) {
|
||||
cleanSourceStream();
|
||||
} else {
|
||||
stream.on('close', cleanSourceStream);
|
||||
}
|
||||
});
|
||||
|
||||
const connectionAcquirePromise = this.ensureConnection(
|
||||
ensureConnectionStreamCallback,
|
||||
{
|
||||
options,
|
||||
hasHandler,
|
||||
stream,
|
||||
}
|
||||
)
|
||||
// Emit errors on the stream if the error occurred before a connection
|
||||
// could be acquired.
|
||||
// If the connection was acquired, assume the error occurred in the client
|
||||
// code and has already been emitted on the stream. Don't emit it twice.
|
||||
.catch((err) => {
|
||||
if (!this.connection) {
|
||||
stream.emit('error', err);
|
||||
}
|
||||
});
|
||||
|
||||
// If a function is passed to handle the stream, send the stream
|
||||
// there and return the promise, otherwise just return the stream
|
||||
// and the promise will take care of itself.
|
||||
if (hasHandler) {
|
||||
handler(stream);
|
||||
return connectionAcquirePromise;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
// Allow you to pipe the stream to a writable stream.
|
||||
pipe(writable, options) {
|
||||
return this.stream(options).pipe(writable);
|
||||
}
|
||||
|
||||
// "Runs" a query, returning a promise. All queries specified by the builder are guaranteed
|
||||
// to run in sequence, and on the same connection, especially helpful when schema building
|
||||
// and dealing with foreign key constraints, etc.
|
||||
async query(obj) {
|
||||
const { __knexUid, __knexTxId } = this.connection;
|
||||
|
||||
this.builder.emit('query', Object.assign({ __knexUid, __knexTxId }, obj));
|
||||
|
||||
const runner = this;
|
||||
const queryContext = this.builder.queryContext();
|
||||
// query-error events are emitted before the queryPromise continuations.
|
||||
// pass queryContext into client.query so it can be raised properly.
|
||||
if (obj !== null && typeof obj === 'object') {
|
||||
obj.queryContext = queryContext;
|
||||
}
|
||||
let queryPromise = this.client.query(this.connection, obj);
|
||||
|
||||
if (obj.timeout) {
|
||||
queryPromise = timeout(queryPromise, obj.timeout);
|
||||
}
|
||||
|
||||
// Await the return value of client.processResponse; in the case of sqlite3's
|
||||
// dropColumn()/renameColumn(), it will be a Promise for the transaction
|
||||
// containing the complete rename procedure.
|
||||
return queryPromise
|
||||
.then((resp) => this.client.processResponse(resp, runner))
|
||||
.then((processedResponse) => {
|
||||
const postProcessedResponse = this.client.postProcessResponse(
|
||||
processedResponse,
|
||||
queryContext
|
||||
);
|
||||
|
||||
this.builder.emit(
|
||||
'query-response',
|
||||
postProcessedResponse,
|
||||
Object.assign({ __knexUid, __knexTxId }, obj),
|
||||
this.builder
|
||||
);
|
||||
|
||||
this.client.emit(
|
||||
'query-response',
|
||||
postProcessedResponse,
|
||||
Object.assign({ __knexUid, __knexTxId }, obj),
|
||||
this.builder
|
||||
);
|
||||
|
||||
return postProcessedResponse;
|
||||
})
|
||||
.catch((error) => {
|
||||
if (!(error instanceof KnexTimeoutError)) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const { timeout, sql, bindings } = obj;
|
||||
|
||||
let cancelQuery;
|
||||
if (obj.cancelOnTimeout) {
|
||||
cancelQuery = this.client.cancelQuery(this.connection);
|
||||
} else {
|
||||
// If we don't cancel the query, we need to mark the connection as disposed so that
|
||||
// it gets destroyed by the pool and is never used again. If we don't do this and
|
||||
// return the connection to the pool, it will be useless until the current operation
|
||||
// that timed out, finally finishes.
|
||||
this.connection.__knex__disposed = error;
|
||||
cancelQuery = Promise.resolve();
|
||||
}
|
||||
|
||||
return cancelQuery
|
||||
.catch((cancelError) => {
|
||||
// If the cancellation failed, we need to mark the connection as disposed so that
|
||||
// it gets destroyed by the pool and is never used again. If we don't do this and
|
||||
// return the connection to the pool, it will be useless until the current operation
|
||||
// that timed out, finally finishes.
|
||||
this.connection.__knex__disposed = error;
|
||||
|
||||
// cancellation failed
|
||||
throw Object.assign(cancelError, {
|
||||
message: `After query timeout of ${timeout}ms exceeded, cancelling of query failed.`,
|
||||
sql,
|
||||
bindings,
|
||||
timeout,
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// cancellation succeeded, rethrow timeout error
|
||||
throw Object.assign(error, {
|
||||
message: `Defined query timeout of ${timeout}ms exceeded when running query.`,
|
||||
sql,
|
||||
bindings,
|
||||
timeout,
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.builder.emit(
|
||||
'query-error',
|
||||
error,
|
||||
Object.assign({ __knexUid, __knexTxId, queryContext }, obj)
|
||||
);
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
// In the case of the "schema builder" we call `queryArray`, which runs each
|
||||
// of the queries in sequence.
|
||||
async queryArray(queries) {
|
||||
if (queries.length === 1) {
|
||||
const query = queries[0];
|
||||
|
||||
if (!query.statementsProducer) {
|
||||
return this.query(query);
|
||||
}
|
||||
|
||||
const statements = await query.statementsProducer(
|
||||
undefined,
|
||||
this.connection
|
||||
);
|
||||
|
||||
const sqlQueryObjects = statements.sql.map((statement) => ({
|
||||
sql: statement,
|
||||
bindings: query.bindings,
|
||||
}));
|
||||
const preQueryObjects = statements.pre.map((statement) => ({
|
||||
sql: statement,
|
||||
bindings: query.bindings,
|
||||
}));
|
||||
const postQueryObjects = statements.post.map((statement) => ({
|
||||
sql: statement,
|
||||
bindings: query.bindings,
|
||||
}));
|
||||
|
||||
let results = [];
|
||||
|
||||
await this.queryArray(preQueryObjects);
|
||||
|
||||
try {
|
||||
await this.client.transaction(
|
||||
async (trx) => {
|
||||
const transactionRunner = new Runner(trx.client, this.builder);
|
||||
transactionRunner.connection = this.connection;
|
||||
|
||||
results = await transactionRunner.queryArray(sqlQueryObjects);
|
||||
|
||||
if (statements.check) {
|
||||
const foreignViolations = await trx.raw(statements.check);
|
||||
|
||||
if (foreignViolations.length > 0) {
|
||||
throw new Error('FOREIGN KEY constraint failed');
|
||||
}
|
||||
}
|
||||
},
|
||||
{ connection: this.connection }
|
||||
);
|
||||
} finally {
|
||||
await this.queryArray(postQueryObjects);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
const results = [];
|
||||
for (const query of queries) {
|
||||
results.push(await this.queryArray([query]));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// Check whether there's a transaction flag, and that it has a connection.
|
||||
async ensureConnection(cb, cbParams) {
|
||||
// Use override from a builder if passed
|
||||
if (this.builder._connection) {
|
||||
this.connection = this.builder._connection;
|
||||
}
|
||||
|
||||
if (this.connection) {
|
||||
return cb(this, cbParams);
|
||||
}
|
||||
|
||||
let acquiredConnection;
|
||||
try {
|
||||
acquiredConnection = await this.client.acquireConnection();
|
||||
} catch (error) {
|
||||
if (!(error instanceof KnexTimeoutError)) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
if (this.builder) {
|
||||
error.sql = this.builder.sql;
|
||||
error.bindings = this.builder.bindings;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
try {
|
||||
this.connection = acquiredConnection;
|
||||
return await cb(this, cbParams);
|
||||
} finally {
|
||||
await this.client.releaseConnection(acquiredConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Runner;
|
413
backend/apis/nodejs/node_modules/knex/lib/execution/transaction.js
generated
vendored
Normal file
413
backend/apis/nodejs/node_modules/knex/lib/execution/transaction.js
generated
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
// Transaction
|
||||
// -------
|
||||
const { EventEmitter } = require('events');
|
||||
const Debug = require('debug');
|
||||
const uniqueId = require('lodash/uniqueId');
|
||||
const { callbackify } = require('util');
|
||||
|
||||
const makeKnex = require('../knex-builder/make-knex');
|
||||
const { timeout, KnexTimeoutError } = require('../util/timeout');
|
||||
const finallyMixin = require('../util/finally-mixin');
|
||||
|
||||
const debug = Debug('knex:tx');
|
||||
|
||||
// FYI: This is defined as a function instead of a constant so that
|
||||
// each Transactor can have its own copy of the default config.
|
||||
// This will minimize the impact of bugs that might be introduced
|
||||
// if a Transactor ever mutates its config.
|
||||
function DEFAULT_CONFIG() {
|
||||
return {
|
||||
userParams: {},
|
||||
doNotRejectOnRollback: true,
|
||||
};
|
||||
}
|
||||
// These aren't supported in sqlite3 which is serialized already so it's as
|
||||
// safe as reasonable, except for a special read_uncommitted pragma
|
||||
const validIsolationLevels = [
|
||||
// Doesn't really work in postgres, it treats it as read committed
|
||||
'read uncommitted',
|
||||
'read committed',
|
||||
'snapshot',
|
||||
// snapshot and repeatable read are basically the same, most "repeatable
|
||||
// read" implementations are actually "snapshot" also known as Multi Version
|
||||
// Concurrency Control (MVCC). Mssql's repeatable read doesn't stop
|
||||
// repeated reads for inserts as it uses a pessimistic locking system so
|
||||
// you should probably use 'snapshot' to stop read skew.
|
||||
'repeatable read',
|
||||
// mysql pretends to have serializable, but it is not
|
||||
'serializable',
|
||||
];
|
||||
|
||||
// Acts as a facade for a Promise, keeping the internal state
|
||||
// and managing any child transactions.
|
||||
class Transaction extends EventEmitter {
|
||||
constructor(client, container, config = DEFAULT_CONFIG(), outerTx = null) {
|
||||
super();
|
||||
this.userParams = config.userParams;
|
||||
this.doNotRejectOnRollback = config.doNotRejectOnRollback;
|
||||
|
||||
const txid = (this.txid = uniqueId('trx'));
|
||||
|
||||
this.client = client;
|
||||
this.logger = client.logger;
|
||||
this.outerTx = outerTx;
|
||||
this.trxClient = undefined;
|
||||
this._completed = false;
|
||||
this._debug = client.config && client.config.debug;
|
||||
|
||||
this.readOnly = config.readOnly;
|
||||
if (config.isolationLevel) {
|
||||
this.setIsolationLevel(config.isolationLevel);
|
||||
}
|
||||
|
||||
debug(
|
||||
'%s: Starting %s transaction',
|
||||
txid,
|
||||
outerTx ? 'nested' : 'top level'
|
||||
);
|
||||
|
||||
// `this` can potentially serve as an `outerTx` for another
|
||||
// Transaction. So, go ahead and establish `_lastChild` now.
|
||||
this._lastChild = Promise.resolve();
|
||||
|
||||
const _previousSibling = outerTx ? outerTx._lastChild : Promise.resolve();
|
||||
|
||||
// FYI: As you will see in a moment, this Promise will be used to construct
|
||||
// 2 separate Promise Chains. This ensures that each Promise Chain
|
||||
// can establish its error-handling semantics without interfering
|
||||
// with the other Promise Chain.
|
||||
const basePromise = _previousSibling.then(() =>
|
||||
this._evaluateContainer(config, container)
|
||||
);
|
||||
|
||||
// FYI: This is the Promise Chain for EXTERNAL use. It ensures that the
|
||||
// caller must handle any exceptions that result from `basePromise`.
|
||||
this._promise = basePromise.then((x) => x);
|
||||
|
||||
if (outerTx) {
|
||||
// FYI: This is the Promise Chain for INTERNAL use. It serves as a signal
|
||||
// for when the next sibling should begin its execution. Therefore,
|
||||
// exceptions are caught and ignored.
|
||||
outerTx._lastChild = basePromise.catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
isCompleted() {
|
||||
return (
|
||||
this._completed || (this.outerTx && this.outerTx.isCompleted()) || false
|
||||
);
|
||||
}
|
||||
|
||||
begin(conn) {
|
||||
const trxMode = [
|
||||
this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '',
|
||||
this.readOnly ? 'READ ONLY' : '',
|
||||
]
|
||||
.join(' ')
|
||||
.trim();
|
||||
|
||||
if (trxMode.length === 0) {
|
||||
return this.query(conn, 'BEGIN;');
|
||||
}
|
||||
|
||||
return this.query(conn, `SET TRANSACTION ${trxMode};`).then(() =>
|
||||
this.query(conn, 'BEGIN;')
|
||||
);
|
||||
}
|
||||
|
||||
savepoint(conn) {
|
||||
return this.query(conn, `SAVEPOINT ${this.txid};`);
|
||||
}
|
||||
|
||||
commit(conn, value) {
|
||||
return this.query(conn, 'COMMIT;', 1, value);
|
||||
}
|
||||
|
||||
release(conn, value) {
|
||||
return this.query(conn, `RELEASE SAVEPOINT ${this.txid};`, 1, value);
|
||||
}
|
||||
|
||||
setIsolationLevel(isolationLevel) {
|
||||
if (!validIsolationLevels.includes(isolationLevel)) {
|
||||
throw new Error(
|
||||
`Invalid isolationLevel, supported isolation levels are: ${JSON.stringify(
|
||||
validIsolationLevels
|
||||
)}`
|
||||
);
|
||||
}
|
||||
this.isolationLevel = isolationLevel;
|
||||
return this;
|
||||
}
|
||||
|
||||
rollback(conn, error) {
|
||||
return timeout(this.query(conn, 'ROLLBACK', 2, error), 5000).catch(
|
||||
(err) => {
|
||||
if (!(err instanceof KnexTimeoutError)) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
this._rejecter(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
rollbackTo(conn, error) {
|
||||
return timeout(
|
||||
this.query(conn, `ROLLBACK TO SAVEPOINT ${this.txid}`, 2, error),
|
||||
5000
|
||||
).catch((err) => {
|
||||
if (!(err instanceof KnexTimeoutError)) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
this._rejecter(error);
|
||||
});
|
||||
}
|
||||
|
||||
query(conn, sql, status, value) {
|
||||
const q = this.trxClient
|
||||
.query(conn, sql)
|
||||
.catch((err) => {
|
||||
status = 2;
|
||||
value = err;
|
||||
this._completed = true;
|
||||
debug('%s error running transaction query', this.txid);
|
||||
})
|
||||
.then((res) => {
|
||||
if (status === 1) {
|
||||
this._resolver(value);
|
||||
}
|
||||
if (status === 2) {
|
||||
if (value === undefined) {
|
||||
if (this.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) {
|
||||
this._resolver();
|
||||
return;
|
||||
}
|
||||
|
||||
value = new Error(`Transaction rejected with non-error: ${value}`);
|
||||
}
|
||||
this._rejecter(value);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
if (status === 1 || status === 2) {
|
||||
this._completed = true;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
debug(enabled) {
|
||||
this._debug = arguments.length ? enabled : true;
|
||||
return this;
|
||||
}
|
||||
|
||||
async _evaluateContainer(config, container) {
|
||||
return this.acquireConnection(config, (connection) => {
|
||||
const trxClient = (this.trxClient = makeTxClient(
|
||||
this,
|
||||
this.client,
|
||||
connection
|
||||
));
|
||||
const init = this.client.transacting
|
||||
? this.savepoint(connection)
|
||||
: this.begin(connection);
|
||||
const executionPromise = new Promise((resolver, rejecter) => {
|
||||
this._resolver = resolver;
|
||||
this._rejecter = rejecter;
|
||||
});
|
||||
|
||||
init
|
||||
.then(() => {
|
||||
return makeTransactor(this, connection, trxClient);
|
||||
})
|
||||
.then((transactor) => {
|
||||
this.transactor = transactor;
|
||||
if (this.outerTx) {
|
||||
transactor.parentTransaction = this.outerTx.transactor;
|
||||
}
|
||||
transactor.executionPromise = executionPromise;
|
||||
|
||||
// If we've returned a "thenable" from the transaction container, assume
|
||||
// the rollback and commit are chained to this object's success / failure.
|
||||
// Directly thrown errors are treated as automatic rollbacks.
|
||||
let result;
|
||||
try {
|
||||
result = container(transactor);
|
||||
} catch (err) {
|
||||
result = Promise.reject(err);
|
||||
}
|
||||
if (result && result.then && typeof result.then === 'function') {
|
||||
result
|
||||
.then((val) => {
|
||||
return transactor.commit(val);
|
||||
})
|
||||
.catch((err) => {
|
||||
return transactor.rollback(err);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.catch((e) => {
|
||||
return this._rejecter(e);
|
||||
});
|
||||
|
||||
return executionPromise;
|
||||
});
|
||||
}
|
||||
|
||||
// Acquire a connection and create a disposer - either using the one passed
|
||||
// via config or getting one off the client. The disposer will be called once
|
||||
// the original promise is marked completed.
|
||||
async acquireConnection(config, cb) {
|
||||
const configConnection = config && config.connection;
|
||||
const connection =
|
||||
configConnection || (await this.client.acquireConnection());
|
||||
|
||||
try {
|
||||
connection.__knexTxId = this.txid;
|
||||
return await cb(connection);
|
||||
} finally {
|
||||
if (!configConnection) {
|
||||
debug('%s: releasing connection', this.txid);
|
||||
this.client.releaseConnection(connection);
|
||||
} else {
|
||||
debug('%s: not releasing external connection', this.txid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
then(onResolve, onReject) {
|
||||
return this._promise.then(onResolve, onReject);
|
||||
}
|
||||
|
||||
catch(...args) {
|
||||
return this._promise.catch(...args);
|
||||
}
|
||||
|
||||
asCallback(cb) {
|
||||
callbackify(() => this._promise)(cb);
|
||||
return this._promise;
|
||||
}
|
||||
}
|
||||
finallyMixin(Transaction.prototype);
|
||||
|
||||
// The transactor is a full featured knex object, with a "commit", a "rollback"
|
||||
// and a "savepoint" function. The "savepoint" is just sugar for creating a new
|
||||
// transaction. If the rollback is run inside a savepoint, it rolls back to the
|
||||
// last savepoint - otherwise it rolls back the transaction.
|
||||
function makeTransactor(trx, connection, trxClient) {
|
||||
const transactor = makeKnex(trxClient);
|
||||
|
||||
transactor.context.withUserParams = () => {
|
||||
throw new Error(
|
||||
'Cannot set user params on a transaction - it can only inherit params from main knex instance'
|
||||
);
|
||||
};
|
||||
|
||||
transactor.isTransaction = true;
|
||||
transactor.userParams = trx.userParams || {};
|
||||
|
||||
transactor.context.transaction = function (container, options) {
|
||||
if (!options) {
|
||||
options = { doNotRejectOnRollback: true };
|
||||
} else if (options.doNotRejectOnRollback === undefined) {
|
||||
options.doNotRejectOnRollback = true;
|
||||
}
|
||||
|
||||
return this._transaction(container, options, trx);
|
||||
};
|
||||
|
||||
transactor.savepoint = function (container, options) {
|
||||
return transactor.transaction(container, options);
|
||||
};
|
||||
|
||||
if (trx.client.transacting) {
|
||||
transactor.commit = (value) => trx.release(connection, value);
|
||||
transactor.rollback = (error) => trx.rollbackTo(connection, error);
|
||||
} else {
|
||||
transactor.commit = (value) => trx.commit(connection, value);
|
||||
transactor.rollback = (error) => trx.rollback(connection, error);
|
||||
}
|
||||
|
||||
transactor.isCompleted = () => trx.isCompleted();
|
||||
|
||||
return transactor;
|
||||
}
|
||||
|
||||
// We need to make a client object which always acquires the same
|
||||
// connection and does not release back into the pool.
|
||||
function makeTxClient(trx, client, connection) {
|
||||
const trxClient = Object.create(client.constructor.prototype);
|
||||
trxClient.version = client.version;
|
||||
trxClient.config = client.config;
|
||||
trxClient.driver = client.driver;
|
||||
trxClient.connectionSettings = client.connectionSettings;
|
||||
trxClient.transacting = true;
|
||||
trxClient.valueForUndefined = client.valueForUndefined;
|
||||
trxClient.logger = client.logger;
|
||||
|
||||
trxClient.on('start', function (arg) {
|
||||
trx.emit('start', arg);
|
||||
client.emit('start', arg);
|
||||
});
|
||||
|
||||
trxClient.on('query', function (arg) {
|
||||
trx.emit('query', arg);
|
||||
client.emit('query', arg);
|
||||
});
|
||||
|
||||
trxClient.on('query-error', function (err, obj) {
|
||||
trx.emit('query-error', err, obj);
|
||||
client.emit('query-error', err, obj);
|
||||
});
|
||||
|
||||
trxClient.on('query-response', function (response, obj, builder) {
|
||||
trx.emit('query-response', response, obj, builder);
|
||||
client.emit('query-response', response, obj, builder);
|
||||
});
|
||||
|
||||
const _query = trxClient.query;
|
||||
trxClient.query = function (conn, obj) {
|
||||
const completed = trx.isCompleted();
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
if (conn !== connection)
|
||||
throw new Error('Invalid connection for transaction query.');
|
||||
if (completed) completedError(trx, obj);
|
||||
resolve(_query.call(trxClient, conn, obj));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
const _stream = trxClient.stream;
|
||||
trxClient.stream = function (conn, obj, stream, options) {
|
||||
const completed = trx.isCompleted();
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
if (conn !== connection)
|
||||
throw new Error('Invalid connection for transaction query.');
|
||||
if (completed) completedError(trx, obj);
|
||||
resolve(_stream.call(trxClient, conn, obj, stream, options));
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
trxClient.acquireConnection = function () {
|
||||
return Promise.resolve(connection);
|
||||
};
|
||||
trxClient.releaseConnection = function () {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
return trxClient;
|
||||
}
|
||||
|
||||
function completedError(trx, obj) {
|
||||
const sql = typeof obj === 'string' ? obj : obj && obj.sql;
|
||||
debug('%s: Transaction completed: %s', trx.txid, sql);
|
||||
throw new Error(
|
||||
'Transaction query already complete, run with DEBUG=knex:tx for more info'
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = Transaction;
|
25
backend/apis/nodejs/node_modules/knex/lib/formatter.js
generated
vendored
Normal file
25
backend/apis/nodejs/node_modules/knex/lib/formatter.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
const {
|
||||
columnize: columnize_,
|
||||
wrap: wrap_,
|
||||
} = require('./formatter/wrappingFormatter');
|
||||
|
||||
class Formatter {
|
||||
constructor(client, builder) {
|
||||
this.client = client;
|
||||
this.builder = builder;
|
||||
this.bindings = [];
|
||||
}
|
||||
|
||||
// Accepts a string or array of columns to wrap as appropriate.
|
||||
columnize(target) {
|
||||
return columnize_(target, this.builder, this.client, this);
|
||||
}
|
||||
|
||||
// Puts the appropriate wrapper around a value depending on the database
|
||||
// engine, unless it's a knex.raw value, in which case it's left alone.
|
||||
wrap(value, isParameter) {
|
||||
return wrap_(value, isParameter, this.builder, this.client, this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Formatter;
|
42
backend/apis/nodejs/node_modules/knex/lib/formatter/formatterUtils.js
generated
vendored
Normal file
42
backend/apis/nodejs/node_modules/knex/lib/formatter/formatterUtils.js
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
const { isObject } = require('../util/is');
|
||||
|
||||
// Compiles a callback using the query builder.
|
||||
function compileCallback(callback, method, client, bindingsHolder) {
|
||||
// Build the callback
|
||||
const builder = client.queryBuilder();
|
||||
callback.call(builder, builder);
|
||||
|
||||
// Compile the callback, using the current formatter (to track all bindings).
|
||||
const compiler = client.queryCompiler(builder, bindingsHolder.bindings);
|
||||
|
||||
// Return the compiled & parameterized sql.
|
||||
return compiler.toSQL(method || builder._method || 'select');
|
||||
}
|
||||
|
||||
function wrapAsIdentifier(value, builder, client) {
|
||||
const queryContext = builder.queryContext();
|
||||
return client.wrapIdentifier((value || '').trim(), queryContext);
|
||||
}
|
||||
|
||||
function formatDefault(value, type, client) {
|
||||
if (value === void 0) {
|
||||
return '';
|
||||
} else if (value === null) {
|
||||
return 'null';
|
||||
} else if (value && value.isRawInstance) {
|
||||
return value.toQuery();
|
||||
} else if (type === 'bool') {
|
||||
if (value === 'false') value = 0;
|
||||
return `'${value ? 1 : 0}'`;
|
||||
} else if ((type === 'json' || type === 'jsonb') && isObject(value)) {
|
||||
return `'${JSON.stringify(value)}'`;
|
||||
} else {
|
||||
return client._escapeBinding(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compileCallback,
|
||||
wrapAsIdentifier,
|
||||
formatDefault,
|
||||
};
|
84
backend/apis/nodejs/node_modules/knex/lib/formatter/rawFormatter.js
generated
vendored
Normal file
84
backend/apis/nodejs/node_modules/knex/lib/formatter/rawFormatter.js
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
const { columnize } = require('./wrappingFormatter');
|
||||
|
||||
function replaceRawArrBindings(raw, client) {
|
||||
const bindingsHolder = {
|
||||
bindings: [],
|
||||
};
|
||||
const builder = raw;
|
||||
|
||||
const expectedBindings = raw.bindings.length;
|
||||
const values = raw.bindings;
|
||||
let index = 0;
|
||||
|
||||
const sql = raw.sql.replace(/\\?\?\??/g, function (match) {
|
||||
if (match === '\\?') {
|
||||
return match;
|
||||
}
|
||||
|
||||
const value = values[index++];
|
||||
|
||||
if (match === '??') {
|
||||
return columnize(value, builder, client, bindingsHolder);
|
||||
}
|
||||
return client.parameter(value, builder, bindingsHolder);
|
||||
});
|
||||
|
||||
if (expectedBindings !== index) {
|
||||
throw new Error(`Expected ${expectedBindings} bindings, saw ${index}`);
|
||||
}
|
||||
|
||||
return {
|
||||
method: 'raw',
|
||||
sql,
|
||||
bindings: bindingsHolder.bindings,
|
||||
};
|
||||
}
|
||||
|
||||
function replaceKeyBindings(raw, client) {
|
||||
const bindingsHolder = {
|
||||
bindings: [],
|
||||
};
|
||||
const builder = raw;
|
||||
|
||||
const values = raw.bindings;
|
||||
const regex = /\\?(:(\w+):(?=::)|:(\w+):(?!:)|:(\w+))/g;
|
||||
|
||||
const sql = raw.sql.replace(regex, function (match, p1, p2, p3, p4) {
|
||||
if (match !== p1) {
|
||||
return p1;
|
||||
}
|
||||
|
||||
const part = p2 || p3 || p4;
|
||||
const key = match.trim();
|
||||
const isIdentifier = key[key.length - 1] === ':';
|
||||
const value = values[part];
|
||||
|
||||
if (value === undefined) {
|
||||
if (Object.prototype.hasOwnProperty.call(values, part)) {
|
||||
bindingsHolder.bindings.push(value);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
if (isIdentifier) {
|
||||
return match.replace(
|
||||
p1,
|
||||
columnize(value, builder, client, bindingsHolder)
|
||||
);
|
||||
}
|
||||
|
||||
return match.replace(p1, client.parameter(value, builder, bindingsHolder));
|
||||
});
|
||||
|
||||
return {
|
||||
method: 'raw',
|
||||
sql,
|
||||
bindings: bindingsHolder.bindings,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
replaceKeyBindings,
|
||||
replaceRawArrBindings,
|
||||
};
|
250
backend/apis/nodejs/node_modules/knex/lib/formatter/wrappingFormatter.js
generated
vendored
Normal file
250
backend/apis/nodejs/node_modules/knex/lib/formatter/wrappingFormatter.js
generated
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
const transform = require('lodash/transform');
|
||||
const QueryBuilder = require('../query/querybuilder');
|
||||
const { compileCallback, wrapAsIdentifier } = require('./formatterUtils');
|
||||
|
||||
// Valid values for the `order by` clause generation.
|
||||
const orderBys = ['asc', 'desc'];
|
||||
|
||||
// Turn this into a lookup map
|
||||
const operators = transform(
|
||||
[
|
||||
'=',
|
||||
'<',
|
||||
'>',
|
||||
'<=',
|
||||
'>=',
|
||||
'<>',
|
||||
'!=',
|
||||
'like',
|
||||
'not like',
|
||||
'between',
|
||||
'not between',
|
||||
'ilike',
|
||||
'not ilike',
|
||||
'exists',
|
||||
'not exist',
|
||||
'rlike',
|
||||
'not rlike',
|
||||
'regexp',
|
||||
'not regexp',
|
||||
'match',
|
||||
'&',
|
||||
'|',
|
||||
'^',
|
||||
'<<',
|
||||
'>>',
|
||||
'~',
|
||||
'~=',
|
||||
'~*',
|
||||
'!~',
|
||||
'!~*',
|
||||
'#',
|
||||
'&&',
|
||||
'@>',
|
||||
'<@',
|
||||
'||',
|
||||
'&<',
|
||||
'&>',
|
||||
'-|-',
|
||||
'@@',
|
||||
'!!',
|
||||
['?', '\\?'],
|
||||
['?|', '\\?|'],
|
||||
['?&', '\\?&'],
|
||||
],
|
||||
(result, key) => {
|
||||
if (Array.isArray(key)) {
|
||||
result[key[0]] = key[1];
|
||||
} else {
|
||||
result[key] = key;
|
||||
}
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
// Accepts a string or array of columns to wrap as appropriate. Column can be raw
|
||||
function columnize(target, builder, client, bindingHolder) {
|
||||
const columns = Array.isArray(target) ? target : [target];
|
||||
let str = '',
|
||||
i = -1;
|
||||
while (++i < columns.length) {
|
||||
if (i > 0) str += ', ';
|
||||
str += wrap(columns[i], undefined, builder, client, bindingHolder);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// Puts the appropriate wrapper around a value depending on the database
|
||||
// engine, unless it's a knex.raw value, in which case it's left alone.
|
||||
function wrap(value, isParameter, builder, client, bindingHolder) {
|
||||
const raw = unwrapRaw(value, isParameter, builder, client, bindingHolder);
|
||||
if (raw) return raw;
|
||||
switch (typeof value) {
|
||||
case 'function':
|
||||
return outputQuery(
|
||||
compileCallback(value, undefined, client, bindingHolder),
|
||||
true,
|
||||
builder,
|
||||
client
|
||||
);
|
||||
case 'object':
|
||||
return parseObject(value, builder, client, bindingHolder);
|
||||
case 'number':
|
||||
return value;
|
||||
default:
|
||||
return wrapString(value + '', builder, client);
|
||||
}
|
||||
}
|
||||
|
||||
function unwrapRaw(value, isParameter, builder, client, bindingsHolder) {
|
||||
let query;
|
||||
if (value instanceof QueryBuilder) {
|
||||
query = client.queryCompiler(value).toSQL();
|
||||
if (query.bindings) {
|
||||
bindingsHolder.bindings.push(...query.bindings);
|
||||
}
|
||||
return outputQuery(query, isParameter, builder, client);
|
||||
}
|
||||
if (value && value.isRawInstance) {
|
||||
value.client = client;
|
||||
if (builder._queryContext) {
|
||||
value.queryContext = () => {
|
||||
return builder._queryContext;
|
||||
};
|
||||
}
|
||||
|
||||
query = value.toSQL();
|
||||
if (query.bindings) {
|
||||
bindingsHolder.bindings.push(...query.bindings);
|
||||
}
|
||||
return query.sql;
|
||||
}
|
||||
if (isParameter) {
|
||||
bindingsHolder.bindings.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
function operator(value, builder, client, bindingsHolder) {
|
||||
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
||||
if (raw) return raw;
|
||||
const operator = operators[(value || '').toLowerCase()];
|
||||
if (!operator) {
|
||||
throw new TypeError(`The operator "${value}" is not permitted`);
|
||||
}
|
||||
return operator;
|
||||
}
|
||||
|
||||
// Coerce to string to prevent strange errors when it's not a string.
|
||||
function wrapString(value, builder, client) {
|
||||
const asIndex = value.toLowerCase().indexOf(' as ');
|
||||
if (asIndex !== -1) {
|
||||
const first = value.slice(0, asIndex);
|
||||
const second = value.slice(asIndex + 4);
|
||||
return client.alias(
|
||||
wrapString(first, builder, client),
|
||||
wrapAsIdentifier(second, builder, client)
|
||||
);
|
||||
}
|
||||
const wrapped = [];
|
||||
let i = -1;
|
||||
const segments = value.split('.');
|
||||
while (++i < segments.length) {
|
||||
value = segments[i];
|
||||
if (i === 0 && segments.length > 1) {
|
||||
wrapped.push(wrapString((value || '').trim(), builder, client));
|
||||
} else {
|
||||
wrapped.push(wrapAsIdentifier(value, builder, client));
|
||||
}
|
||||
}
|
||||
return wrapped.join('.');
|
||||
}
|
||||
|
||||
// Key-value notation for alias
|
||||
function parseObject(obj, builder, client, formatter) {
|
||||
const ret = [];
|
||||
for (const alias in obj) {
|
||||
const queryOrIdentifier = obj[alias];
|
||||
// Avoids double aliasing for subqueries
|
||||
if (typeof queryOrIdentifier === 'function') {
|
||||
const compiled = compileCallback(
|
||||
queryOrIdentifier,
|
||||
undefined,
|
||||
client,
|
||||
formatter
|
||||
);
|
||||
compiled.as = alias; // enforces the object's alias
|
||||
ret.push(outputQuery(compiled, true, builder, client));
|
||||
} else if (queryOrIdentifier instanceof QueryBuilder) {
|
||||
ret.push(
|
||||
client.alias(
|
||||
`(${wrap(queryOrIdentifier, undefined, builder, client, formatter)})`,
|
||||
wrapAsIdentifier(alias, builder, client)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
ret.push(
|
||||
client.alias(
|
||||
wrap(queryOrIdentifier, undefined, builder, client, formatter),
|
||||
wrapAsIdentifier(alias, builder, client)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return ret.join(', ');
|
||||
}
|
||||
|
||||
// Ensures the query is aliased if necessary.
|
||||
function outputQuery(compiled, isParameter, builder, client) {
|
||||
let sql = compiled.sql || '';
|
||||
if (sql) {
|
||||
if (
|
||||
(compiled.method === 'select' || compiled.method === 'first') &&
|
||||
(isParameter || compiled.as)
|
||||
) {
|
||||
sql = `(${sql})`;
|
||||
if (compiled.as)
|
||||
return client.alias(sql, wrapString(compiled.as, builder, client));
|
||||
}
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates SQL for a parameter, which might be passed to where() or .with() or
|
||||
* pretty much anywhere in API.
|
||||
*
|
||||
* @param value
|
||||
* @param method Optional at least 'select' or 'update' are valid
|
||||
* @param builder
|
||||
* @param client
|
||||
* @param bindingHolder
|
||||
*/
|
||||
function rawOrFn(value, method, builder, client, bindingHolder) {
|
||||
if (typeof value === 'function') {
|
||||
return outputQuery(
|
||||
compileCallback(value, method, client, bindingHolder),
|
||||
undefined,
|
||||
builder,
|
||||
client
|
||||
);
|
||||
}
|
||||
return unwrapRaw(value, undefined, builder, client, bindingHolder) || '';
|
||||
}
|
||||
|
||||
// Specify the direction of the ordering.
|
||||
function direction(value, builder, client, bindingsHolder) {
|
||||
const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder);
|
||||
if (raw) return raw;
|
||||
return orderBys.indexOf((value || '').toLowerCase()) !== -1 ? value : 'asc';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
columnize,
|
||||
direction,
|
||||
operator,
|
||||
outputQuery,
|
||||
rawOrFn,
|
||||
unwrapRaw,
|
||||
wrap,
|
||||
wrapString,
|
||||
};
|
3
backend/apis/nodejs/node_modules/knex/lib/index.js
generated
vendored
Normal file
3
backend/apis/nodejs/node_modules/knex/lib/index.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const Knex = require('./knex-builder/Knex');
|
||||
|
||||
module.exports = Knex;
|
80
backend/apis/nodejs/node_modules/knex/lib/knex-builder/FunctionHelper.js
generated
vendored
Normal file
80
backend/apis/nodejs/node_modules/knex/lib/knex-builder/FunctionHelper.js
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// FunctionHelper
|
||||
// -------
|
||||
// Used for adding functions from the builder
|
||||
// Example usage: table.dateTime('datetime_to_date').notNull().defaultTo(knex.fn.now());
|
||||
class FunctionHelper {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
now(precision) {
|
||||
if (typeof precision === 'number') {
|
||||
return this.client.raw(`CURRENT_TIMESTAMP(${precision})`);
|
||||
}
|
||||
return this.client.raw('CURRENT_TIMESTAMP');
|
||||
}
|
||||
|
||||
uuid() {
|
||||
switch (this.client.driverName) {
|
||||
case 'sqlite3':
|
||||
case 'better-sqlite3':
|
||||
return this.client.raw(
|
||||
"(lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6))))"
|
||||
);
|
||||
case 'mssql':
|
||||
return this.client.raw('(NEWID())');
|
||||
case 'pg':
|
||||
case 'pgnative':
|
||||
case 'cockroachdb':
|
||||
return this.client.raw('(gen_random_uuid())');
|
||||
case 'oracle':
|
||||
case 'oracledb':
|
||||
return this.client.raw('(random_uuid())');
|
||||
case 'mysql':
|
||||
case 'mysql2':
|
||||
return this.client.raw('(UUID())');
|
||||
default:
|
||||
throw new Error(
|
||||
`${this.client.driverName} does not have a uuid function`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
uuidToBin(uuid, ordered = true) {
|
||||
const buf = Buffer.from(uuid.replace(/-/g, ''), 'hex');
|
||||
return ordered
|
||||
? Buffer.concat([
|
||||
buf.slice(6, 8),
|
||||
buf.slice(4, 6),
|
||||
buf.slice(0, 4),
|
||||
buf.slice(8, 16),
|
||||
])
|
||||
: Buffer.concat([
|
||||
buf.slice(0, 4),
|
||||
buf.slice(4, 6),
|
||||
buf.slice(6, 8),
|
||||
buf.slice(8, 16),
|
||||
]);
|
||||
}
|
||||
|
||||
binToUuid(bin, ordered = true) {
|
||||
const buf = Buffer.from(bin, 'hex');
|
||||
return ordered
|
||||
? [
|
||||
buf.toString('hex', 4, 8),
|
||||
buf.toString('hex', 2, 4),
|
||||
buf.toString('hex', 0, 2),
|
||||
buf.toString('hex', 8, 10),
|
||||
buf.toString('hex', 10, 16),
|
||||
].join('-')
|
||||
: [
|
||||
buf.toString('hex', 0, 4),
|
||||
buf.toString('hex', 4, 6),
|
||||
buf.toString('hex', 6, 8),
|
||||
buf.toString('hex', 8, 10),
|
||||
buf.toString('hex', 10, 16),
|
||||
].join('-');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FunctionHelper;
|
59
backend/apis/nodejs/node_modules/knex/lib/knex-builder/Knex.js
generated
vendored
Normal file
59
backend/apis/nodejs/node_modules/knex/lib/knex-builder/Knex.js
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
const Client = require('../client');
|
||||
const QueryBuilder = require('../query/querybuilder');
|
||||
const QueryInterface = require('../query/method-constants');
|
||||
|
||||
const makeKnex = require('./make-knex');
|
||||
const { KnexTimeoutError } = require('../util/timeout');
|
||||
const { resolveConfig } = require('./internal/config-resolver');
|
||||
const SchemaBuilder = require('../schema/builder');
|
||||
const ViewBuilder = require('../schema/viewbuilder');
|
||||
const ColumnBuilder = require('../schema/columnbuilder');
|
||||
const TableBuilder = require('../schema/tablebuilder');
|
||||
|
||||
function knex(config) {
|
||||
const { resolvedConfig, Dialect } = resolveConfig(...arguments);
|
||||
|
||||
const newKnex = makeKnex(new Dialect(resolvedConfig));
|
||||
if (resolvedConfig.userParams) {
|
||||
newKnex.userParams = resolvedConfig.userParams;
|
||||
}
|
||||
return newKnex;
|
||||
}
|
||||
|
||||
// Expose Client on the main Knex namespace.
|
||||
knex.Client = Client;
|
||||
|
||||
knex.KnexTimeoutError = KnexTimeoutError;
|
||||
|
||||
knex.QueryBuilder = {
|
||||
extend: function (methodName, fn) {
|
||||
QueryBuilder.extend(methodName, fn);
|
||||
QueryInterface.push(methodName);
|
||||
},
|
||||
};
|
||||
|
||||
knex.SchemaBuilder = {
|
||||
extend: function (methodName, fn) {
|
||||
SchemaBuilder.extend(methodName, fn);
|
||||
},
|
||||
};
|
||||
|
||||
knex.ViewBuilder = {
|
||||
extend: function (methodName, fn) {
|
||||
ViewBuilder.extend(methodName, fn);
|
||||
},
|
||||
};
|
||||
|
||||
knex.ColumnBuilder = {
|
||||
extend: function (methodName, fn) {
|
||||
ColumnBuilder.extend(methodName, fn);
|
||||
},
|
||||
};
|
||||
|
||||
knex.TableBuilder = {
|
||||
extend: function (methodName, fn) {
|
||||
TableBuilder.extend(methodName, fn);
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = knex;
|
57
backend/apis/nodejs/node_modules/knex/lib/knex-builder/internal/config-resolver.js
generated
vendored
Normal file
57
backend/apis/nodejs/node_modules/knex/lib/knex-builder/internal/config-resolver.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
const Client = require('../../client');
|
||||
const { SUPPORTED_CLIENTS } = require('../../constants');
|
||||
|
||||
const parseConnection = require('./parse-connection');
|
||||
const { getDialectByNameOrAlias } = require('../../dialects');
|
||||
|
||||
function resolveConfig(config) {
|
||||
let Dialect;
|
||||
let resolvedConfig;
|
||||
|
||||
// If config is a string, try to parse it
|
||||
const parsedConfig =
|
||||
typeof config === 'string'
|
||||
? Object.assign(parseConnection(config), arguments[2])
|
||||
: config;
|
||||
|
||||
// If user provided no relevant parameters, use generic client
|
||||
if (
|
||||
arguments.length === 0 ||
|
||||
(!parsedConfig.client && !parsedConfig.dialect)
|
||||
) {
|
||||
Dialect = Client;
|
||||
}
|
||||
// If user provided Client constructor as a parameter, use it
|
||||
else if (typeof parsedConfig.client === 'function') {
|
||||
Dialect = parsedConfig.client;
|
||||
}
|
||||
// If neither applies, let's assume user specified name of a client or dialect as a string
|
||||
else {
|
||||
const clientName = parsedConfig.client || parsedConfig.dialect;
|
||||
if (!SUPPORTED_CLIENTS.includes(clientName)) {
|
||||
throw new Error(
|
||||
`knex: Unknown configuration option 'client' value ${clientName}. Note that it is case-sensitive, check documentation for supported values.`
|
||||
);
|
||||
}
|
||||
|
||||
Dialect = getDialectByNameOrAlias(clientName);
|
||||
}
|
||||
|
||||
// If config connection parameter is passed as string, try to parse it
|
||||
if (typeof parsedConfig.connection === 'string') {
|
||||
resolvedConfig = Object.assign({}, parsedConfig, {
|
||||
connection: parseConnection(parsedConfig.connection).connection,
|
||||
});
|
||||
} else {
|
||||
resolvedConfig = Object.assign({}, parsedConfig);
|
||||
}
|
||||
|
||||
return {
|
||||
resolvedConfig,
|
||||
Dialect,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveConfig,
|
||||
};
|
87
backend/apis/nodejs/node_modules/knex/lib/knex-builder/internal/parse-connection.js
generated
vendored
Normal file
87
backend/apis/nodejs/node_modules/knex/lib/knex-builder/internal/parse-connection.js
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
const { parse } = require('pg-connection-string');
|
||||
const parsePG = parse;
|
||||
const isWindows = process && process.platform && process.platform === 'win32';
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* @returns {URL}
|
||||
*/
|
||||
function tryParse(str) {
|
||||
try {
|
||||
return new URL(str);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function parseConnectionString(str) {
|
||||
const parsed = tryParse(str);
|
||||
const isDriveLetter = isWindows && parsed && parsed.protocol.length === 2;
|
||||
if (!parsed || isDriveLetter) {
|
||||
return {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: str,
|
||||
},
|
||||
};
|
||||
}
|
||||
let { protocol } = parsed;
|
||||
if (protocol.slice(-1) === ':') {
|
||||
protocol = protocol.slice(0, -1);
|
||||
}
|
||||
|
||||
const isPG = ['postgresql', 'postgres'].includes(protocol);
|
||||
|
||||
return {
|
||||
client: protocol,
|
||||
connection: isPG ? parsePG(str) : connectionObject(parsed),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {URL} parsed
|
||||
* @returns {{}}
|
||||
*/
|
||||
function connectionObject(parsed) {
|
||||
const connection = {};
|
||||
let db = parsed.pathname;
|
||||
if (db[0] === '/') {
|
||||
db = db.slice(1);
|
||||
}
|
||||
|
||||
connection.database = db;
|
||||
|
||||
if (parsed.hostname) {
|
||||
if (parsed.protocol.indexOf('mssql') === 0) {
|
||||
connection.server = parsed.hostname;
|
||||
} else {
|
||||
connection.host = parsed.hostname;
|
||||
}
|
||||
}
|
||||
if (parsed.port) {
|
||||
connection.port = parsed.port;
|
||||
}
|
||||
if (parsed.username || parsed.password) {
|
||||
connection.user = decodeURIComponent(parsed.username);
|
||||
}
|
||||
if (parsed.password) {
|
||||
connection.password = decodeURIComponent(parsed.password);
|
||||
}
|
||||
if (parsed.searchParams) {
|
||||
for (const [key, value] of parsed.searchParams.entries()) {
|
||||
const isNestedConfigSupported = ['mysql:', 'mariadb:', 'mssql:'].includes(
|
||||
parsed.protocol
|
||||
);
|
||||
if (isNestedConfigSupported) {
|
||||
try {
|
||||
connection[key] = JSON.parse(value);
|
||||
} catch (err) {
|
||||
connection[key] = value;
|
||||
}
|
||||
} else {
|
||||
connection[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
}
|
345
backend/apis/nodejs/node_modules/knex/lib/knex-builder/make-knex.js
generated
vendored
Normal file
345
backend/apis/nodejs/node_modules/knex/lib/knex-builder/make-knex.js
generated
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
const { EventEmitter } = require('events');
|
||||
|
||||
const { Migrator } = require('../migrations/migrate/Migrator');
|
||||
const Seeder = require('../migrations/seed/Seeder');
|
||||
const FunctionHelper = require('./FunctionHelper');
|
||||
const QueryInterface = require('../query/method-constants');
|
||||
const merge = require('lodash/merge');
|
||||
const batchInsert = require('../execution/batch-insert');
|
||||
const { isObject } = require('../util/is');
|
||||
const { setHiddenProperty } = require('../util/security');
|
||||
|
||||
// Javascript does not officially support "callable objects". Instead,
|
||||
// you must create a regular Function and inject properties/methods
|
||||
// into it. In other words: you can't leverage Prototype Inheritance
|
||||
// to share the property/method definitions.
|
||||
//
|
||||
// To work around this, we're creating an Object Property Definition.
|
||||
// This allow us to quickly inject everything into the `knex` function
|
||||
// via the `Object.defineProperties(..)` function. More importantly,
|
||||
// it allows the same definitions to be shared across `knex` instances.
|
||||
const KNEX_PROPERTY_DEFINITIONS = {
|
||||
client: {
|
||||
get() {
|
||||
return this.context.client;
|
||||
},
|
||||
set(client) {
|
||||
this.context.client = client;
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
|
||||
userParams: {
|
||||
get() {
|
||||
return this.context.userParams;
|
||||
},
|
||||
set(userParams) {
|
||||
this.context.userParams = userParams;
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
|
||||
schema: {
|
||||
get() {
|
||||
return this.client.schemaBuilder();
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
|
||||
migrate: {
|
||||
get() {
|
||||
return new Migrator(this);
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
|
||||
seed: {
|
||||
get() {
|
||||
return new Seeder(this);
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
|
||||
fn: {
|
||||
get() {
|
||||
return new FunctionHelper(this.client);
|
||||
},
|
||||
configurable: true,
|
||||
},
|
||||
};
|
||||
|
||||
// `knex` instances serve as proxies around `context` objects. So, calling
|
||||
// any of these methods on the `knex` instance will forward the call to
|
||||
// the `knex.context` object. This ensures that `this` will correctly refer
|
||||
// to `context` within each of these methods.
|
||||
const CONTEXT_METHODS = [
|
||||
'raw',
|
||||
'batchInsert',
|
||||
'transaction',
|
||||
'transactionProvider',
|
||||
'initialize',
|
||||
'destroy',
|
||||
'ref',
|
||||
'withUserParams',
|
||||
'queryBuilder',
|
||||
'disableProcessing',
|
||||
'enableProcessing',
|
||||
];
|
||||
|
||||
for (const m of CONTEXT_METHODS) {
|
||||
KNEX_PROPERTY_DEFINITIONS[m] = {
|
||||
value: function (...args) {
|
||||
return this.context[m](...args);
|
||||
},
|
||||
configurable: true,
|
||||
};
|
||||
}
|
||||
|
||||
function makeKnex(client) {
|
||||
// The object we're potentially using to kick off an initial chain.
|
||||
function knex(tableName, options) {
|
||||
return createQueryBuilder(knex.context, tableName, options);
|
||||
}
|
||||
|
||||
redefineProperties(knex, client);
|
||||
return knex;
|
||||
}
|
||||
|
||||
function initContext(knexFn) {
|
||||
const knexContext = knexFn.context || {};
|
||||
Object.assign(knexContext, {
|
||||
queryBuilder() {
|
||||
return this.client.queryBuilder();
|
||||
},
|
||||
|
||||
raw() {
|
||||
return this.client.raw.apply(this.client, arguments);
|
||||
},
|
||||
|
||||
batchInsert(table, batch, chunkSize = 1000) {
|
||||
return batchInsert(this, table, batch, chunkSize);
|
||||
},
|
||||
|
||||
// Creates a new transaction.
|
||||
// If container is provided, returns a promise for when the transaction is resolved.
|
||||
// If container is not provided, returns a promise with a transaction that is resolved
|
||||
// when transaction is ready to be used.
|
||||
transaction(container, _config) {
|
||||
// Overload support of `transaction(config)`
|
||||
if (!_config && isObject(container)) {
|
||||
_config = container;
|
||||
container = null;
|
||||
}
|
||||
|
||||
const config = Object.assign({}, _config);
|
||||
config.userParams = this.userParams || {};
|
||||
if (config.doNotRejectOnRollback === undefined) {
|
||||
config.doNotRejectOnRollback = true;
|
||||
}
|
||||
|
||||
return this._transaction(container, config);
|
||||
},
|
||||
|
||||
// Internal method that actually establishes the Transaction. It makes no assumptions
|
||||
// about the `config` or `outerTx`, and expects the caller to handle these details.
|
||||
_transaction(container, config, outerTx = null) {
|
||||
if (container) {
|
||||
const trx = this.client.transaction(container, config, outerTx);
|
||||
return trx;
|
||||
} else {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.transaction(resolve, config, outerTx).catch(reject);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
transactionProvider(config) {
|
||||
let trx;
|
||||
return () => {
|
||||
if (!trx) {
|
||||
trx = this.transaction(undefined, config);
|
||||
}
|
||||
return trx;
|
||||
};
|
||||
},
|
||||
|
||||
// Typically never needed, initializes the pool for a knex client.
|
||||
initialize(config) {
|
||||
return this.client.initializePool(config);
|
||||
},
|
||||
|
||||
// Convenience method for tearing down the pool.
|
||||
destroy(callback) {
|
||||
return this.client.destroy(callback);
|
||||
},
|
||||
|
||||
ref(ref) {
|
||||
return this.client.ref(ref);
|
||||
},
|
||||
|
||||
// Do not document this as public API until naming and API is improved for general consumption
|
||||
// This method exists to disable processing of internal queries in migrations
|
||||
disableProcessing() {
|
||||
if (this.userParams.isProcessingDisabled) {
|
||||
return;
|
||||
}
|
||||
this.userParams.wrapIdentifier = this.client.config.wrapIdentifier;
|
||||
this.userParams.postProcessResponse =
|
||||
this.client.config.postProcessResponse;
|
||||
this.client.config.wrapIdentifier = null;
|
||||
this.client.config.postProcessResponse = null;
|
||||
this.userParams.isProcessingDisabled = true;
|
||||
},
|
||||
|
||||
// Do not document this as public API until naming and API is improved for general consumption
|
||||
// This method exists to enable execution of non-internal queries with consistent identifier naming in migrations
|
||||
enableProcessing() {
|
||||
if (!this.userParams.isProcessingDisabled) {
|
||||
return;
|
||||
}
|
||||
this.client.config.wrapIdentifier = this.userParams.wrapIdentifier;
|
||||
this.client.config.postProcessResponse =
|
||||
this.userParams.postProcessResponse;
|
||||
this.userParams.isProcessingDisabled = false;
|
||||
},
|
||||
|
||||
withUserParams(params) {
|
||||
const knexClone = shallowCloneFunction(knexFn); // We need to include getters in our clone
|
||||
if (this.client) {
|
||||
knexClone.client = Object.create(this.client.constructor.prototype); // Clone client to avoid leaking listeners that are set on it
|
||||
merge(knexClone.client, this.client);
|
||||
knexClone.client.config = Object.assign({}, this.client.config); // Clone client config to make sure they can be modified independently
|
||||
|
||||
if (this.client.config.password) {
|
||||
setHiddenProperty(knexClone.client.config, this.client.config);
|
||||
}
|
||||
}
|
||||
|
||||
redefineProperties(knexClone, knexClone.client);
|
||||
_copyEventListeners('query', knexFn, knexClone);
|
||||
_copyEventListeners('query-error', knexFn, knexClone);
|
||||
_copyEventListeners('query-response', knexFn, knexClone);
|
||||
_copyEventListeners('start', knexFn, knexClone);
|
||||
knexClone.userParams = params;
|
||||
return knexClone;
|
||||
},
|
||||
});
|
||||
|
||||
if (!knexFn.context) {
|
||||
knexFn.context = knexContext;
|
||||
}
|
||||
}
|
||||
|
||||
function _copyEventListeners(eventName, sourceKnex, targetKnex) {
|
||||
const listeners = sourceKnex.listeners(eventName);
|
||||
listeners.forEach((listener) => {
|
||||
targetKnex.on(eventName, listener);
|
||||
});
|
||||
}
|
||||
|
||||
function redefineProperties(knex, client) {
|
||||
// Allow chaining methods from the root object, before
|
||||
// any other information is specified.
|
||||
//
|
||||
// TODO: `QueryBuilder.extend(..)` allows new QueryBuilder
|
||||
// methods to be introduced via external components.
|
||||
// As a side-effect, it also pushes the new method names
|
||||
// into the `QueryInterface` array.
|
||||
//
|
||||
// The Problem: due to the way the code is currently
|
||||
// structured, these new methods cannot be retroactively
|
||||
// injected into existing `knex` instances! As a result,
|
||||
// some `knex` instances will support the methods, and
|
||||
// others will not.
|
||||
//
|
||||
// We should revisit this once we figure out the desired
|
||||
// behavior / usage. For instance: do we really want to
|
||||
// allow external components to directly manipulate `knex`
|
||||
// data structures? Or, should we come up w/ a different
|
||||
// approach that avoids side-effects / mutation?
|
||||
//
|
||||
// (FYI: I noticed this issue because I attempted to integrate
|
||||
// this logic directly into the `KNEX_PROPERTY_DEFINITIONS`
|
||||
// construction. However, `KNEX_PROPERTY_DEFINITIONS` is
|
||||
// constructed before any `knex` instances are created.
|
||||
// As a result, the method extensions were missing from all
|
||||
// `knex` instances.)
|
||||
for (let i = 0; i < QueryInterface.length; i++) {
|
||||
const method = QueryInterface[i];
|
||||
knex[method] = function () {
|
||||
const builder = this.queryBuilder();
|
||||
return builder[method].apply(builder, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
Object.defineProperties(knex, KNEX_PROPERTY_DEFINITIONS);
|
||||
|
||||
initContext(knex);
|
||||
knex.client = client;
|
||||
knex.userParams = {};
|
||||
|
||||
// Hook up the "knex" object as an EventEmitter.
|
||||
const ee = new EventEmitter();
|
||||
for (const key in ee) {
|
||||
knex[key] = ee[key];
|
||||
}
|
||||
|
||||
// Unfortunately, something seems to be broken in Node 6 and removing events from a clone also mutates original Knex,
|
||||
// which is highly undesirable
|
||||
if (knex._internalListeners) {
|
||||
knex._internalListeners.forEach(({ eventName, listener }) => {
|
||||
knex.client.removeListener(eventName, listener); // Remove duplicates for copies
|
||||
});
|
||||
}
|
||||
knex._internalListeners = [];
|
||||
|
||||
// Passthrough all "start" and "query" events to the knex object.
|
||||
_addInternalListener(knex, 'start', (obj) => {
|
||||
knex.emit('start', obj);
|
||||
});
|
||||
_addInternalListener(knex, 'query', (obj) => {
|
||||
knex.emit('query', obj);
|
||||
});
|
||||
_addInternalListener(knex, 'query-error', (err, obj) => {
|
||||
knex.emit('query-error', err, obj);
|
||||
});
|
||||
_addInternalListener(knex, 'query-response', (response, obj, builder) => {
|
||||
knex.emit('query-response', response, obj, builder);
|
||||
});
|
||||
}
|
||||
|
||||
function _addInternalListener(knex, eventName, listener) {
|
||||
knex.client.on(eventName, listener);
|
||||
knex._internalListeners.push({
|
||||
eventName,
|
||||
listener,
|
||||
});
|
||||
}
|
||||
|
||||
function createQueryBuilder(knexContext, tableName, options) {
|
||||
const qb = knexContext.queryBuilder();
|
||||
if (!tableName)
|
||||
knexContext.client.logger.warn(
|
||||
'calling knex without a tableName is deprecated. Use knex.queryBuilder() instead.'
|
||||
);
|
||||
return tableName ? qb.table(tableName, options) : qb;
|
||||
}
|
||||
|
||||
function shallowCloneFunction(originalFunction) {
|
||||
const fnContext = Object.create(
|
||||
Object.getPrototypeOf(originalFunction),
|
||||
Object.getOwnPropertyDescriptors(originalFunction)
|
||||
);
|
||||
|
||||
const knexContext = {};
|
||||
const knexFnWrapper = (tableName, options) => {
|
||||
return createQueryBuilder(knexContext, tableName, options);
|
||||
};
|
||||
|
||||
const clonedFunction = knexFnWrapper.bind(fnContext);
|
||||
Object.assign(clonedFunction, originalFunction);
|
||||
clonedFunction.context = knexContext;
|
||||
return clonedFunction;
|
||||
}
|
||||
|
||||
module.exports = makeKnex;
|
76
backend/apis/nodejs/node_modules/knex/lib/logger.js
generated
vendored
Normal file
76
backend/apis/nodejs/node_modules/knex/lib/logger.js
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
const color = require('colorette');
|
||||
const { inspect } = require('util');
|
||||
const { isString, isFunction } = require('./util/is');
|
||||
|
||||
class Logger {
|
||||
constructor(config = {}) {
|
||||
const {
|
||||
log: {
|
||||
debug,
|
||||
warn,
|
||||
error,
|
||||
deprecate,
|
||||
inspectionDepth,
|
||||
enableColors,
|
||||
} = {},
|
||||
} = config;
|
||||
this._inspectionDepth = inspectionDepth || 5;
|
||||
this._enableColors = resolveIsEnabledColors(enableColors);
|
||||
this._debug = debug;
|
||||
this._warn = warn;
|
||||
this._error = error;
|
||||
this._deprecate = deprecate;
|
||||
}
|
||||
|
||||
_log(message, userFn, colorFn) {
|
||||
if (userFn != null && !isFunction(userFn)) {
|
||||
throw new TypeError('Extensions to knex logger must be functions!');
|
||||
}
|
||||
|
||||
if (isFunction(userFn)) {
|
||||
userFn(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isString(message)) {
|
||||
message = inspect(message, {
|
||||
depth: this._inspectionDepth,
|
||||
colors: this._enableColors,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(colorFn ? colorFn(message) : message);
|
||||
}
|
||||
|
||||
debug(message) {
|
||||
this._log(message, this._debug);
|
||||
}
|
||||
|
||||
warn(message) {
|
||||
this._log(message, this._warn, color.yellow);
|
||||
}
|
||||
|
||||
error(message) {
|
||||
this._log(message, this._error, color.red);
|
||||
}
|
||||
|
||||
deprecate(method, alternative) {
|
||||
const message = `${method} is deprecated, please use ${alternative}`;
|
||||
|
||||
this._log(message, this._deprecate, color.yellow);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveIsEnabledColors(enableColorsParam) {
|
||||
if (enableColorsParam != null) {
|
||||
return enableColorsParam;
|
||||
}
|
||||
|
||||
if (process && process.stdout) {
|
||||
return process.stdout.isTTY;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = Logger;
|
36
backend/apis/nodejs/node_modules/knex/lib/migrations/common/MigrationsLoader.js
generated
vendored
Normal file
36
backend/apis/nodejs/node_modules/knex/lib/migrations/common/MigrationsLoader.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
const path = require('path');
|
||||
const DEFAULT_LOAD_EXTENSIONS = Object.freeze([
|
||||
'.co',
|
||||
'.coffee',
|
||||
'.eg',
|
||||
'.iced',
|
||||
'.js',
|
||||
'.cjs',
|
||||
'.litcoffee',
|
||||
'.ls',
|
||||
'.ts',
|
||||
]);
|
||||
|
||||
class AbstractMigrationsLoader {
|
||||
constructor(migrationDirectories, sortDirsSeparately, loadExtensions) {
|
||||
this.sortDirsSeparately = sortDirsSeparately;
|
||||
|
||||
if (!Array.isArray(migrationDirectories)) {
|
||||
migrationDirectories = [migrationDirectories];
|
||||
}
|
||||
this.migrationsPaths = migrationDirectories;
|
||||
this.loadExtensions = loadExtensions || DEFAULT_LOAD_EXTENSIONS;
|
||||
}
|
||||
|
||||
getFile(migrationsInfo) {
|
||||
const absoluteDir = path.resolve(process.cwd(), migrationsInfo.directory);
|
||||
const _path = path.join(absoluteDir, migrationsInfo.file);
|
||||
const importFile = require('../util/import-file'); // late import
|
||||
return importFile(_path);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_LOAD_EXTENSIONS,
|
||||
AbstractMigrationsLoader,
|
||||
};
|
84
backend/apis/nodejs/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js
generated
vendored
Normal file
84
backend/apis/nodejs/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
const path = require('path');
|
||||
const { writeJsFileUsingTemplate } = require('../util/template');
|
||||
const { getMergedConfig } = require('./migrator-configuration-merger');
|
||||
const { ensureDirectoryExists } = require('../util/fs');
|
||||
const { yyyymmddhhmmss } = require('../util/timestamp');
|
||||
|
||||
class MigrationGenerator {
|
||||
constructor(migrationConfig, logger) {
|
||||
this.config = getMergedConfig(migrationConfig, undefined, logger);
|
||||
}
|
||||
|
||||
// Creates a new migration, with a given name.
|
||||
async make(name, config, logger) {
|
||||
this.config = getMergedConfig(config, this.config, logger);
|
||||
if (!name) {
|
||||
return Promise.reject(
|
||||
new Error('A name must be specified for the generated migration')
|
||||
);
|
||||
}
|
||||
await this._ensureFolder();
|
||||
const createdMigrationFilePath = await this._writeNewMigration(name);
|
||||
return createdMigrationFilePath;
|
||||
}
|
||||
|
||||
// Ensures a folder for the migrations exist, dependent on the migration
|
||||
// config settings.
|
||||
_ensureFolder() {
|
||||
const dirs = this._absoluteConfigDirs();
|
||||
|
||||
const promises = dirs.map(ensureDirectoryExists);
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
_getStubPath() {
|
||||
return (
|
||||
this.config.stub ||
|
||||
path.join(__dirname, 'stub', this.config.extension + '.stub')
|
||||
);
|
||||
}
|
||||
|
||||
_getNewMigrationName(name) {
|
||||
if (name[0] === '-') name = name.slice(1);
|
||||
return (
|
||||
yyyymmddhhmmss() + '_' + name + '.' + this.config.extension.split('-')[0]
|
||||
);
|
||||
}
|
||||
|
||||
_getNewMigrationPath(name) {
|
||||
const fileName = this._getNewMigrationName(name);
|
||||
const dirs = this._absoluteConfigDirs();
|
||||
const dir = dirs.slice(-1)[0]; // Get last specified directory
|
||||
return path.join(dir, fileName);
|
||||
}
|
||||
|
||||
// Write a new migration to disk, using the config and generated filename,
|
||||
// passing any `variables` given in the config to the template.
|
||||
async _writeNewMigration(name) {
|
||||
const migrationPath = this._getNewMigrationPath(name);
|
||||
await writeJsFileUsingTemplate(
|
||||
migrationPath,
|
||||
this._getStubPath(),
|
||||
{ variable: 'd' },
|
||||
this.config.variables || {}
|
||||
);
|
||||
return migrationPath;
|
||||
}
|
||||
|
||||
_absoluteConfigDirs() {
|
||||
const directories = Array.isArray(this.config.directory)
|
||||
? this.config.directory
|
||||
: [this.config.directory];
|
||||
return directories.map((directory) => {
|
||||
if (!directory) {
|
||||
console.warn(
|
||||
'Failed to resolve config file, knex cannot determine where to generate migrations'
|
||||
);
|
||||
}
|
||||
return path.resolve(process.cwd(), directory);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MigrationGenerator;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user