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:
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;
|
Reference in New Issue
Block a user