mirror of
https://github.com/knex/knex.git
synced 2025-11-30 00:46:20 +00:00
parent
2f85fde189
commit
60db2d25a2
@ -28,6 +28,8 @@ 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 debug = require('debug')('knex:client');
|
||||
|
||||
@ -102,10 +104,18 @@ class Client extends EventEmitter {
|
||||
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);
|
||||
}
|
||||
|
||||
15
lib/dialects/cockroachdb/crdb-viewcompiler.js
Normal file
15
lib/dialects/cockroachdb/crdb-viewcompiler.js
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;
|
||||
@ -4,6 +4,7 @@ const Client_PostgreSQL = require('../postgres');
|
||||
const Transaction = require('../postgres/execution/pg-transaction');
|
||||
const QueryCompiler = require('./crdb-querycompiler');
|
||||
const TableCompiler = require('./crdb-tablecompiler');
|
||||
const ViewCompiler = require('./crdb-viewcompiler');
|
||||
|
||||
// Always initialize with the "QueryBuilder" and "QueryCompiler"
|
||||
// objects, which extend the base 'lib/query/builder' and
|
||||
@ -21,6 +22,10 @@ class Client_CockroachDB extends Client_PostgreSQL {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
_parseVersion(versionString) {
|
||||
return versionString.split(' ')[2];
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ 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');
|
||||
|
||||
@ -112,6 +113,9 @@ class Client_MSSQL extends Client {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
queryBuilder() {
|
||||
const b = new QueryBuilder(this);
|
||||
return b;
|
||||
|
||||
@ -14,6 +14,13 @@ class SchemaCompiler_MSSQL extends SchemaCompiler {
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
@ -25,6 +32,16 @@ class SchemaCompiler_MSSQL extends SchemaCompiler {
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
|
||||
41
lib/dialects/mssql/schema/mssql-viewcompiler.js
Normal file
41
lib/dialects/mssql/schema/mssql-viewcompiler.js
Normal file
@ -0,0 +1,41 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
|
||||
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();
|
||||
|
||||
sql += ' (' + columns.join(', ') + ')';
|
||||
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;
|
||||
@ -12,6 +12,8 @@ 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
|
||||
@ -33,6 +35,14 @@ class Client_MySQL extends Client {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
@ -16,6 +16,10 @@ class SchemaCompiler_MySQL extends SchemaCompiler {
|
||||
);
|
||||
}
|
||||
|
||||
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 = ?';
|
||||
|
||||
21
lib/dialects/mysql/schema/mysql-viewbuilder.js
Normal file
21
lib/dialects/mysql/schema/mysql-viewbuilder.js
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
lib/dialects/mysql/schema/mysql-viewcompiler.js
Normal file
15
lib/dialects/mysql/schema/mysql-viewcompiler.js
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;
|
||||
@ -77,16 +77,45 @@ class SchemaCompiler_Oracle extends SchemaCompiler {
|
||||
}
|
||||
|
||||
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 table ${prefix}${this.formatter.wrap(tableName)}`,
|
||||
-942
|
||||
`drop ${type} ${prefix}${this.formatter.wrap(objectName)}`,
|
||||
errorCode
|
||||
)
|
||||
);
|
||||
|
||||
// removing the sequence that was possibly generated by increments() column
|
||||
this._dropRelatedSequenceIfExists(tableName);
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@ const Formatter = require('../../formatter');
|
||||
const QueryCompiler = require('./query/oracledb-querycompiler');
|
||||
const TableCompiler = require('./schema/oracledb-tablecompiler');
|
||||
const ColumnCompiler = require('./schema/oracledb-columncompiler');
|
||||
const ViewCompiler = require('./schema/oracledb-viewcompiler');
|
||||
const ViewBuilder = require('./schema/oracledb-viewbuilder');
|
||||
const { BlobHelper, ReturningHelper, isConnectionError } = require('./utils');
|
||||
const Transaction = require('./transaction');
|
||||
const Client_Oracle = require('../oracle');
|
||||
@ -67,6 +69,14 @@ class Client_Oracledb extends Client_Oracle {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
formatter(builder) {
|
||||
return new Formatter(this, builder);
|
||||
}
|
||||
|
||||
13
lib/dialects/oracledb/schema/oracledb-viewbuilder.js
Normal file
13
lib/dialects/oracledb/schema/oracledb-viewbuilder.js
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
lib/dialects/oracledb/schema/oracledb-viewcompiler.js
Normal file
19
lib/dialects/oracledb/schema/oracledb-viewcompiler.js
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;
|
||||
@ -9,6 +9,8 @@ const Transaction = require('./execution/pg-transaction');
|
||||
const QueryCompiler = require('./query/pg-querycompiler');
|
||||
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');
|
||||
@ -44,6 +46,14 @@ class Client_PG extends Client {
|
||||
return new TableCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewBuilder() {
|
||||
return new ViewBuilder(this, ...arguments);
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('pg');
|
||||
}
|
||||
|
||||
@ -110,6 +110,27 @@ class SchemaCompiler_PG extends SchemaCompiler {
|
||||
`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) {
|
||||
this.pushQuery({
|
||||
sql: `refresh materialized view ${this.formatter.wrap(viewName)}`,
|
||||
});
|
||||
}
|
||||
|
||||
dropMaterializedView(viewName) {
|
||||
this._dropView(viewName, false, true);
|
||||
}
|
||||
|
||||
dropMaterializedViewIfExists(viewName) {
|
||||
this._dropView(viewName, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SchemaCompiler_PG;
|
||||
|
||||
21
lib/dialects/postgres/schema/pg-viewbuilder.js
Normal file
21
lib/dialects/postgres/schema/pg-viewbuilder.js
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
lib/dialects/postgres/schema/pg-viewcompiler.js
Normal file
35
lib/dialects/postgres/schema/pg-viewcompiler.js
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;
|
||||
@ -9,6 +9,7 @@ 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() {
|
||||
@ -35,6 +36,10 @@ class Client_Redshift extends Client_PG {
|
||||
return new SchemaCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
viewCompiler() {
|
||||
return new ViewCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
_driver() {
|
||||
return require('pg');
|
||||
}
|
||||
|
||||
11
lib/dialects/redshift/schema/redshift-viewcompiler.js
Normal file
11
lib/dialects/redshift/schema/redshift-viewcompiler.js
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;
|
||||
@ -12,6 +12,7 @@ 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');
|
||||
|
||||
@ -43,6 +44,10 @@ class Client_SQLite3 extends Client {
|
||||
return new SqliteQueryCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
viewCompiler(builder, formatter) {
|
||||
return new ViewCompiler(this, builder, formatter);
|
||||
}
|
||||
|
||||
columnCompiler() {
|
||||
return new ColumnCompiler(this, ...arguments);
|
||||
}
|
||||
|
||||
11
lib/dialects/sqlite3/schema/sqlite-viewcompiler.js
Normal file
11
lib/dialects/sqlite3/schema/sqlite-viewcompiler.js
Normal file
@ -0,0 +1,11 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
const ViewCompiler = require('../../../schema/viewcompiler.js');
|
||||
|
||||
class ViewCompiler_PG extends ViewCompiler {
|
||||
constructor(client, viewCompiler) {
|
||||
super(client, viewCompiler);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ViewCompiler_PG;
|
||||
@ -46,6 +46,14 @@ class SchemaBuilder extends EventEmitter {
|
||||
'createTable',
|
||||
'createTableIfNotExists',
|
||||
'createTableLike',
|
||||
'createView',
|
||||
'createViewOrReplace',
|
||||
'createMaterializedView',
|
||||
'refreshMaterializedView',
|
||||
'dropView',
|
||||
'dropViewIfExists',
|
||||
'dropMaterializedView',
|
||||
'dropMaterializedViewIfExists',
|
||||
'createSchema',
|
||||
'createSchemaIfNotExists',
|
||||
'dropSchema',
|
||||
@ -56,10 +64,13 @@ class SchemaBuilder extends EventEmitter {
|
||||
'dropExtensionIfExists',
|
||||
'table',
|
||||
'alterTable',
|
||||
'view',
|
||||
'alterView',
|
||||
'hasTable',
|
||||
'hasColumn',
|
||||
'dropTable',
|
||||
'renameTable',
|
||||
'renameView',
|
||||
'dropTableIfExists',
|
||||
'raw',
|
||||
].forEach(function (method) {
|
||||
@ -76,6 +87,7 @@ class SchemaBuilder extends EventEmitter {
|
||||
);
|
||||
}
|
||||
if (method === 'table') method = 'alterTable';
|
||||
if (method === 'view') method = 'alterView';
|
||||
this._sequence.push({
|
||||
method,
|
||||
args: toArray(arguments),
|
||||
|
||||
@ -52,6 +52,40 @@ class SchemaCompiler {
|
||||
);
|
||||
}
|
||||
|
||||
dropView(viewName) {
|
||||
this._dropView(viewName, false, false);
|
||||
}
|
||||
|
||||
dropViewIfExists(viewName) {
|
||||
this._dropView(viewName, true, false);
|
||||
}
|
||||
|
||||
dropMaterializedView(viewName) {
|
||||
throw new Error('materialized views are not supported by this dialect.');
|
||||
}
|
||||
|
||||
dropMaterializedViewIfExists(viewName) {
|
||||
throw new Error('materialized views are not supported by this dialect.');
|
||||
}
|
||||
|
||||
renameView(from, to) {
|
||||
throw new Error(
|
||||
'rename view is not supported by this dialect (instead drop then create another view).'
|
||||
);
|
||||
}
|
||||
|
||||
refreshMaterializedView() {
|
||||
throw new Error('materialized views are not supported by this dialect.');
|
||||
}
|
||||
|
||||
_dropView(viewName, ifExists, materialized) {
|
||||
this.pushQuery(
|
||||
(materialized ? this.dropMaterializedViewPrefix : this.dropViewPrefix) +
|
||||
(ifExists ? 'if exists ' : '') +
|
||||
this.formatter.wrap(prefixedTableName(this.schema, viewName))
|
||||
);
|
||||
}
|
||||
|
||||
raw(sql, bindings) {
|
||||
this.sequence.push(this.client.raw(sql, bindings).toSQL());
|
||||
}
|
||||
@ -78,32 +112,42 @@ class SchemaCompiler {
|
||||
}
|
||||
|
||||
SchemaCompiler.prototype.dropTablePrefix = 'drop table ';
|
||||
SchemaCompiler.prototype.dropViewPrefix = 'drop view ';
|
||||
SchemaCompiler.prototype.dropMaterializedViewPrefix = 'drop materialized view ';
|
||||
SchemaCompiler.prototype.alterViewPrefix = 'alter view ';
|
||||
|
||||
SchemaCompiler.prototype.alterTable = buildTable('alter');
|
||||
SchemaCompiler.prototype.createTable = buildTable('create');
|
||||
SchemaCompiler.prototype.createTableIfNotExists = buildTable('createIfNot');
|
||||
SchemaCompiler.prototype.createTableLike = buildTable('createLike');
|
||||
|
||||
SchemaCompiler.prototype.createView = buildView('create');
|
||||
SchemaCompiler.prototype.createViewOrReplace = buildView('createOrReplace');
|
||||
SchemaCompiler.prototype.createMaterializedView = buildView(
|
||||
'createMaterializedView'
|
||||
);
|
||||
SchemaCompiler.prototype.alterView = buildView('alter');
|
||||
|
||||
SchemaCompiler.prototype.pushQuery = pushQuery;
|
||||
SchemaCompiler.prototype.pushAdditional = pushAdditional;
|
||||
SchemaCompiler.prototype.unshiftQuery = unshiftQuery;
|
||||
|
||||
function buildTable(type) {
|
||||
function build(builder) {
|
||||
// pass queryContext down to tableBuilder but do not overwrite it if already set
|
||||
const queryContext = this.builder.queryContext();
|
||||
if (queryContext !== undefined && builder.queryContext() === undefined) {
|
||||
builder.queryContext(queryContext);
|
||||
}
|
||||
|
||||
builder.setSchema(this.schema);
|
||||
const sql = builder.toSQL();
|
||||
|
||||
for (let i = 0, l = sql.length; i < l; i++) {
|
||||
this.sequence.push(sql[i]);
|
||||
}
|
||||
function build(builder) {
|
||||
// pass queryContext down to tableBuilder but do not overwrite it if already set
|
||||
const queryContext = this.builder.queryContext();
|
||||
if (queryContext !== undefined && builder.queryContext() === undefined) {
|
||||
builder.queryContext(queryContext);
|
||||
}
|
||||
|
||||
builder.setSchema(this.schema);
|
||||
const sql = builder.toSQL();
|
||||
|
||||
for (let i = 0, l = sql.length; i < l; i++) {
|
||||
this.sequence.push(sql[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function buildTable(type) {
|
||||
if (type === 'createLike') {
|
||||
return function (tableName, tableNameLike, fn) {
|
||||
const builder = this.client.tableBuilder(
|
||||
@ -122,6 +166,13 @@ function buildTable(type) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildView(type) {
|
||||
return function (viewName, fn) {
|
||||
const builder = this.client.viewBuilder(type, viewName, fn);
|
||||
build.call(this, builder);
|
||||
};
|
||||
}
|
||||
|
||||
function prefixedTableName(prefix, table) {
|
||||
return prefix ? `${prefix}.${table}` : table;
|
||||
}
|
||||
|
||||
81
lib/schema/viewbuilder.js
Normal file
81
lib/schema/viewbuilder.js
Normal file
@ -0,0 +1,81 @@
|
||||
const helpers = require('../util/helpers');
|
||||
const extend = require('lodash/extend');
|
||||
|
||||
class ViewBuilder {
|
||||
constructor(client, method, viewName, fn) {
|
||||
this.client = client;
|
||||
this._method = method;
|
||||
this._schemaName = undefined;
|
||||
this._columns = undefined;
|
||||
this._fn = fn;
|
||||
this._viewName = viewName;
|
||||
this._statements = [];
|
||||
this._single = {};
|
||||
}
|
||||
|
||||
setSchema(schemaName) {
|
||||
this._schemaName = schemaName;
|
||||
}
|
||||
|
||||
columns(columns) {
|
||||
this._columns = columns;
|
||||
}
|
||||
|
||||
as(selectQuery) {
|
||||
this._selectQuery = selectQuery;
|
||||
}
|
||||
|
||||
checkOption() {
|
||||
throw new Error(
|
||||
'check option definition is not supported by this dialect.'
|
||||
);
|
||||
}
|
||||
|
||||
localCheckOption() {
|
||||
throw new Error(
|
||||
'check option definition is not supported by this dialect.'
|
||||
);
|
||||
}
|
||||
|
||||
cascadedCheckOption() {
|
||||
throw new Error(
|
||||
'check option definition is not supported by this dialect.'
|
||||
);
|
||||
}
|
||||
|
||||
toSQL() {
|
||||
if (this._method === 'alter') {
|
||||
extend(this, AlterMethods);
|
||||
}
|
||||
this._fn.call(this, this);
|
||||
return this.client.viewCompiler(this).toSQL();
|
||||
}
|
||||
}
|
||||
|
||||
const AlterMethods = {
|
||||
column(column) {
|
||||
const self = this;
|
||||
return {
|
||||
rename: function (newName) {
|
||||
self._statements.push({
|
||||
grouping: 'alterView',
|
||||
method: 'renameColumn',
|
||||
args: [column, newName],
|
||||
});
|
||||
return this;
|
||||
},
|
||||
defaultTo: function (defaultValue) {
|
||||
self._statements.push({
|
||||
grouping: 'alterView',
|
||||
method: 'defaultTo',
|
||||
args: [column, defaultValue],
|
||||
});
|
||||
return this;
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
helpers.addQueryContext(ViewBuilder);
|
||||
|
||||
module.exports = ViewBuilder;
|
||||
135
lib/schema/viewcompiler.js
Normal file
135
lib/schema/viewcompiler.js
Normal file
@ -0,0 +1,135 @@
|
||||
/* eslint max-len:0 */
|
||||
|
||||
// View Compiler
|
||||
// -------
|
||||
const { pushQuery } = require('./internal/helpers');
|
||||
const groupBy = require('lodash/groupBy');
|
||||
const { columnize: columnize_ } = require('../formatter/wrappingFormatter');
|
||||
|
||||
class ViewCompiler {
|
||||
constructor(client, viewBuilder) {
|
||||
this.client = client;
|
||||
this.viewBuilder = viewBuilder;
|
||||
this._commonBuilder = this.viewBuilder;
|
||||
this.method = viewBuilder._method;
|
||||
this.schemaNameRaw = viewBuilder._schemaName;
|
||||
this.viewNameRaw = viewBuilder._viewName;
|
||||
this.single = viewBuilder._single;
|
||||
this.selectQuery = viewBuilder._selectQuery;
|
||||
this.columns = viewBuilder._columns;
|
||||
this.grouped = groupBy(viewBuilder._statements, 'grouping');
|
||||
|
||||
this.formatter = client.formatter(viewBuilder);
|
||||
this.bindings = [];
|
||||
this.formatter.bindings = this.bindings;
|
||||
this.bindingsHolder = this;
|
||||
|
||||
this.sequence = [];
|
||||
}
|
||||
|
||||
// Convert the tableCompiler toSQL
|
||||
toSQL() {
|
||||
this[this.method]();
|
||||
return this.sequence;
|
||||
}
|
||||
|
||||
// Column Compilation
|
||||
// -------
|
||||
|
||||
create() {
|
||||
this.createQuery(this.columns, this.selectQuery);
|
||||
}
|
||||
|
||||
createOrReplace() {
|
||||
throw new Error('replace views is not supported by this dialect.');
|
||||
}
|
||||
|
||||
createMaterializedView() {
|
||||
throw new Error('materialized views are not supported by this dialect.');
|
||||
}
|
||||
|
||||
createQuery(columns, selectQuery, materialized, replace) {
|
||||
const createStatement =
|
||||
'create ' +
|
||||
(materialized ? 'materialized ' : '') +
|
||||
'view ' +
|
||||
(replace ? 'or replace ' : '');
|
||||
const formatColumns = [];
|
||||
for (const c of columns) {
|
||||
formatColumns.push(
|
||||
columnize_(c, this.viewBuilder, this.client, this.bindingsHolder)
|
||||
);
|
||||
}
|
||||
let sql =
|
||||
createStatement + this.viewName() + ' (' + formatColumns.join(', ') + ')';
|
||||
sql += ' as ';
|
||||
sql += selectQuery.toString();
|
||||
switch (this.single.checkOption) {
|
||||
case 'default_option':
|
||||
sql += ' with check option';
|
||||
break;
|
||||
case 'local':
|
||||
sql += ' with local check option';
|
||||
break;
|
||||
case 'cascaded':
|
||||
sql += ' with cascaded check option';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.pushQuery({
|
||||
sql,
|
||||
});
|
||||
}
|
||||
|
||||
renameView(from, to) {
|
||||
throw new Error(
|
||||
'rename view is not supported by this dialect (instead drop, then create another view).'
|
||||
);
|
||||
}
|
||||
|
||||
refreshMaterializedView() {
|
||||
throw new Error('materialized views are not supported by this dialect.');
|
||||
}
|
||||
|
||||
alter() {
|
||||
this.alterView();
|
||||
}
|
||||
|
||||
alterView() {
|
||||
const alterView = this.grouped.alterView || [];
|
||||
for (let i = 0, l = alterView.length; i < l; i++) {
|
||||
const statement = alterView[i];
|
||||
if (this[statement.method]) {
|
||||
this[statement.method].apply(this, statement.args);
|
||||
} else {
|
||||
this.client.logger.error(`Debug: ${statement.method} does not exist`);
|
||||
}
|
||||
}
|
||||
for (const item in this.single) {
|
||||
if (typeof this[item] === 'function') this[item](this.single[item]);
|
||||
}
|
||||
}
|
||||
|
||||
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.'
|
||||
);
|
||||
}
|
||||
|
||||
viewName() {
|
||||
const name = this.schemaNameRaw
|
||||
? `${this.schemaNameRaw}.${this.viewNameRaw}`
|
||||
: this.viewNameRaw;
|
||||
|
||||
return this.formatter.wrap(name);
|
||||
}
|
||||
}
|
||||
|
||||
ViewCompiler.prototype.pushQuery = pushQuery;
|
||||
|
||||
module.exports = ViewCompiler;
|
||||
275
test/integration2/schema/views.spec.js
Normal file
275
test/integration2/schema/views.spec.js
Normal file
@ -0,0 +1,275 @@
|
||||
'use strict';
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
require('lodash');
|
||||
|
||||
const { isOracle, isSQLite, isMssql } = require('../../util/db-helpers');
|
||||
const { getAllDbs, getKnexForDb } = require('../util/knex-instance-provider');
|
||||
const logger = require('../../integration/logger');
|
||||
const { isMysql, isCockroachDB } = require('../../util/db-helpers.js');
|
||||
const { assertNumber } = require('../../util/assertHelper');
|
||||
|
||||
describe('Views', () => {
|
||||
getAllDbs().forEach((db) => {
|
||||
describe(db, () => {
|
||||
let knex;
|
||||
|
||||
before(async () => {
|
||||
knex = logger(getKnexForDb(db));
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
return knex.destroy();
|
||||
});
|
||||
|
||||
describe('view', () => {
|
||||
beforeEach(async () => {
|
||||
await knex.schema.dropViewIfExists('view_test');
|
||||
await knex.schema.dropTableIfExists('table_view');
|
||||
await knex.schema.createTable('table_view', (t) => {
|
||||
t.string('a');
|
||||
t.integer('b');
|
||||
});
|
||||
await knex('table_view').insert([
|
||||
{ a: 'test', b: 5 },
|
||||
{ a: 'test2', b: 12 },
|
||||
{ a: 'test3', b: 45 },
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await knex.schema.dropViewIfExists('view_test');
|
||||
await knex.schema.dropViewIfExists('new_view');
|
||||
if (!isMssql(knex) && !isSQLite(knex) && !isMysql(knex)) {
|
||||
await knex.schema.dropMaterializedViewIfExists('mat_view');
|
||||
}
|
||||
await knex.schema.dropTableIfExists('table_view');
|
||||
});
|
||||
|
||||
it('create view', async () => {
|
||||
await knex.schema
|
||||
.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(
|
||||
knex('table_view').select('a', 'b').where('b', '>', '10')
|
||||
);
|
||||
})
|
||||
.testSql((tester) => {
|
||||
tester(
|
||||
['pg', 'pg-redshift', 'cockroachdb', 'oracledb'],
|
||||
[
|
||||
'create view "view_test" ("a", "b") as select "a", "b" from "table_view" where "b" > \'10\'',
|
||||
]
|
||||
);
|
||||
tester(
|
||||
['sqlite3', 'mysql'],
|
||||
[
|
||||
"create view `view_test` (`a`, `b`) as select `a`, `b` from `table_view` where `b` > '10'",
|
||||
]
|
||||
);
|
||||
tester('mssql', [
|
||||
"CREATE VIEW [view_test] (a, b) AS select [a], [b] from [table_view] where [b] > '10'",
|
||||
]);
|
||||
});
|
||||
|
||||
// We test if the select on the view work and if results are good
|
||||
await knex
|
||||
.select(['a', 'b'])
|
||||
.from('view_test')
|
||||
.then(function (results) {
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
expect(results[0].a).to.be.equal('test2');
|
||||
expect(results[1].a).to.be.equal('test3');
|
||||
});
|
||||
});
|
||||
|
||||
it('create materialized view', async function () {
|
||||
if (isMssql(knex) || isSQLite(knex) || isMysql(knex)) {
|
||||
return this.skip();
|
||||
}
|
||||
await knex.schema
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(
|
||||
knex('table_view').select('a', 'b').where('b', '>', '10')
|
||||
);
|
||||
})
|
||||
.testSql((tester) => {
|
||||
tester(
|
||||
['pg', 'cockroachdb', 'pg-redshift', 'oracledb'],
|
||||
[
|
||||
'create materialized view "mat_view" ("a", "b") as select "a", "b" from "table_view" where "b" > \'10\'',
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
await knex
|
||||
.select(['a', 'b'])
|
||||
.from('mat_view')
|
||||
.then(function (results) {
|
||||
expect(results[0].a).to.be.equal('test2');
|
||||
expect(results[1].a).to.be.equal('test3');
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
});
|
||||
|
||||
await knex('table_view').insert([{ a: 'test', b: 32 }]);
|
||||
|
||||
// We test we have same values, because the view is not refreshed
|
||||
await knex
|
||||
.select(['a', 'b'])
|
||||
.from('mat_view')
|
||||
.then(function (results) {
|
||||
expect(results[0].a).to.be.equal('test2');
|
||||
expect(results[1].a).to.be.equal('test3');
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
});
|
||||
|
||||
await knex.schema.refreshMaterializedView('mat_view');
|
||||
|
||||
// Materialized view is refreshed
|
||||
await knex
|
||||
.select(['a', 'b'])
|
||||
.from('mat_view')
|
||||
.then(function (results) {
|
||||
expect(results[0].a).to.be.equal('test2');
|
||||
expect(results[1].a).to.be.equal('test3');
|
||||
expect(results[2].a).to.be.equal('test');
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
assertNumber(knex, results[2].b, 32);
|
||||
});
|
||||
await knex.schema.dropMaterializedView('mat_view');
|
||||
});
|
||||
|
||||
it('alter column view', async function () {
|
||||
if (
|
||||
isOracle(knex) ||
|
||||
isSQLite(knex) ||
|
||||
isMysql(knex) ||
|
||||
isCockroachDB(knex)
|
||||
) {
|
||||
return this.skip();
|
||||
}
|
||||
await knex.schema.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(knex('table_view').select('a', 'b').where('b', '>', '10'));
|
||||
});
|
||||
|
||||
await knex.schema.alterView('view_test', function (view) {
|
||||
view.column('a').rename('new_a');
|
||||
});
|
||||
|
||||
await knex
|
||||
.select(['new_a', 'b'])
|
||||
.from('view_test')
|
||||
.then(function (results) {
|
||||
expect(results[0].new_a).to.be.equal('test2');
|
||||
expect(results[1].new_a).to.be.equal('test3');
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
});
|
||||
});
|
||||
|
||||
it('alter view rename', async function () {
|
||||
if (isOracle(knex) || isSQLite(knex)) {
|
||||
return this.skip();
|
||||
}
|
||||
await knex.schema.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(knex('table_view').select('a', 'b').where('b', '>', '10'));
|
||||
});
|
||||
|
||||
await knex.schema.renameView('view_test', 'new_view');
|
||||
|
||||
await knex
|
||||
.select(['a', 'b'])
|
||||
.from('new_view')
|
||||
.then(function (results) {
|
||||
expect(results[0].a).to.be.equal('test2');
|
||||
expect(results[1].a).to.be.equal('test3');
|
||||
assertNumber(knex, results[0].b, 12);
|
||||
assertNumber(knex, results[1].b, 45);
|
||||
});
|
||||
await knex.schema.dropView('new_view');
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
if (isMssql(knex) || isCockroachDB(knex) || isSQLite(knex)) {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
await knex.schema
|
||||
.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(
|
||||
knex('table_view').select('a', 'b').where('b', '>', '10')
|
||||
);
|
||||
view.checkOption();
|
||||
})
|
||||
.testSql((tester) => {
|
||||
tester(
|
||||
['oracledb'],
|
||||
[
|
||||
'create view "view_test" ("a", "b") as select "a", "b" from "table_view" where "b" > \'10\' with check option',
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
if (isOracle(knex)) {
|
||||
return this.skip();
|
||||
}
|
||||
await knex.schema.dropView('view_test');
|
||||
await knex.schema
|
||||
.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(
|
||||
knex('table_view').select('a', 'b').where('b', '>', '10')
|
||||
);
|
||||
view.localCheckOption();
|
||||
})
|
||||
.testSql((tester) => {
|
||||
tester(
|
||||
['pg', 'cockroachdb', 'pg-redshift'],
|
||||
[
|
||||
'create view "view_test" ("a", "b") as select "a", "b" from "table_view" where "b" > \'10\' with local check option',
|
||||
]
|
||||
);
|
||||
tester(
|
||||
['mysql'],
|
||||
[
|
||||
"create view `view_test` (`a`, `b`) as select `a`, `b` from `table_view` where `b` > '10' with local check option",
|
||||
]
|
||||
);
|
||||
});
|
||||
await knex.schema.dropView('view_test');
|
||||
await knex.schema
|
||||
.createView('view_test', function (view) {
|
||||
view.columns(['a', 'b']);
|
||||
view.as(
|
||||
knex('table_view').select('a', 'b').where('b', '>', '10')
|
||||
);
|
||||
view.cascadedCheckOption();
|
||||
})
|
||||
.testSql((tester) => {
|
||||
tester(
|
||||
['pg', 'cockroachdb', 'pg-redshift'],
|
||||
[
|
||||
'create view "view_test" ("a", "b") as select "a", "b" from "table_view" where "b" > \'10\' with cascaded check option',
|
||||
]
|
||||
);
|
||||
tester(
|
||||
['mysql'],
|
||||
[
|
||||
"create view `view_test` (`a`, `b`) as select `a`, `b` from `table_view` where `b` > '10' with cascaded check option",
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -3,6 +3,7 @@
|
||||
const expect = require('chai').expect;
|
||||
const sinon = require('sinon');
|
||||
const MSSQL_Client = require('../../../lib/dialects/mssql');
|
||||
const knex = require('../../../knex');
|
||||
const client = new MSSQL_Client({ client: 'mssql' });
|
||||
|
||||
describe('MSSQL SchemaBuilder', function () {
|
||||
@ -49,6 +50,119 @@ describe('MSSQL SchemaBuilder', function () {
|
||||
);
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexMssql;
|
||||
|
||||
before(function () {
|
||||
knexMssql = knex({
|
||||
client: 'mssql',
|
||||
connection: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMssql('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
"CREATE VIEW [adults] (name) AS select [name] from [users] where [age] > '18'"
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createViewOrReplace('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMssql('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
"CREATE OR ALTER VIEW [adults] (name) AS select [name] from [users] where [age] > '18'"
|
||||
);
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
expect(() => {
|
||||
client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMssql('users').select('name').where('age', '>', '18'));
|
||||
view.localCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('check option definition is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view [users]');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view [myschema].[users]');
|
||||
});
|
||||
|
||||
it('rename column of view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName');
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal("exec sp_rename ?, ?, 'COLUMN'");
|
||||
expect(tableSql[0].bindings[0]).to.equal('[users].oldName');
|
||||
expect(tableSql[0].bindings[1]).to.equal('newName');
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('exec sp_rename ?, ?');
|
||||
expect(tableSql[0].bindings[0]).to.equal('old_view');
|
||||
expect(tableSql[0].bindings[1]).to.equal('new_view');
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMssql('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
});
|
||||
|
||||
it('test basic create table with incrementing without primary key', function () {
|
||||
tableSql = client.schemaBuilder().createTable('users', function (table) {
|
||||
table.increments('id', { primaryKey: false });
|
||||
|
||||
@ -3,6 +3,7 @@ const { expect } = require('chai');
|
||||
const sinon = require('sinon');
|
||||
const MySQL_Client = require('../../../lib/dialects/mysql');
|
||||
const MySQL2_Client = require('../../../lib/dialects/mysql2');
|
||||
const knex = require('../../../knex');
|
||||
|
||||
module.exports = function (dialect) {
|
||||
describe(dialect + ' SchemaBuilder', function () {
|
||||
@ -92,6 +93,134 @@ module.exports = function (dialect) {
|
||||
);
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexMysql;
|
||||
|
||||
before(function () {
|
||||
knexMysql = knex({
|
||||
client: 'mysql2',
|
||||
connection: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMysql('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
"create view `adults` (`name`) as select `name` from `users` where `age` > '18'"
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createViewOrReplace('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMysql('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
"create view or replace `adults` (`name`) as select `name` from `users` where `age` > '18'"
|
||||
);
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
const viewSqlLocalCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMysql('users').select('name').where('age', '>', '18'));
|
||||
view.localCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlLocalCheck.length);
|
||||
expect(viewSqlLocalCheck[0].sql).to.equal(
|
||||
"create view `adults` (`name`) as select `name` from `users` where `age` > '18' with local check option"
|
||||
);
|
||||
|
||||
const viewSqlCascadedCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexMysql('users').select('name').where('age', '>', '18'));
|
||||
view.cascadedCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlCascadedCheck.length);
|
||||
expect(viewSqlCascadedCheck[0].sql).to.equal(
|
||||
"create view `adults` (`name`) as select `name` from `users` where `age` > '18' with cascaded check option"
|
||||
);
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view `users`');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view `myschema`.`users`');
|
||||
});
|
||||
|
||||
it('rename and change default of column of view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('rename column of views is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'rename table `old_view` to `new_view`'
|
||||
);
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(
|
||||
knexMysql('users').select('name').where('age', '>', '18')
|
||||
);
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
});
|
||||
|
||||
it('adding json', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
|
||||
@ -4,6 +4,7 @@ const { expect } = require('chai');
|
||||
|
||||
const sinon = require('sinon');
|
||||
const Oracle_Client = require('../../../lib/dialects/oracledb');
|
||||
const knex = require('../../../knex');
|
||||
const client = new Oracle_Client({ client: 'oracledb' });
|
||||
|
||||
describe('OracleDb SchemaBuilder', function () {
|
||||
@ -34,6 +35,136 @@ describe('OracleDb SchemaBuilder', function () {
|
||||
);
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexOracleDb;
|
||||
|
||||
before(function () {
|
||||
knexOracleDb = knex({
|
||||
client: 'oracledb',
|
||||
connection: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexOracleDb('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createViewOrReplace('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexOracleDb('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view or replace "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexOracleDb('users').select('name').where('age', '>', '18'));
|
||||
view.checkOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\' with check option'
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(
|
||||
knexOracleDb('users').select('name').where('age', '>', '18')
|
||||
);
|
||||
view.cascadedCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('check option definition is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "users"');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "myschema"."users"');
|
||||
});
|
||||
|
||||
it('rename and change default of column of view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('rename column of views is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
}).to.throw(
|
||||
'rename view is not supported by this dialect (instead drop then create another view).'
|
||||
);
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexOracleDb('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'create materialized view "mat_view" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
"BEGIN DBMS_MVIEW.REFRESH('view_to_refresh'); END;"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('test basic create table if not exists', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
|
||||
@ -193,6 +193,144 @@ describe('PostgreSQL SchemaBuilder', function () {
|
||||
expect(tableSql[0].sql).to.equal('drop table "users"');
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexPg;
|
||||
|
||||
before(function () {
|
||||
knexPg = knex({
|
||||
client: 'postgresql',
|
||||
version: '10.5',
|
||||
connection: {
|
||||
pool: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexPg('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createViewOrReplace('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexPg('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view or replace "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
const viewSqlLocalCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexPg('users').select('name').where('age', '>', '18'));
|
||||
view.localCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlLocalCheck.length);
|
||||
expect(viewSqlLocalCheck[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\' with local check option'
|
||||
);
|
||||
|
||||
const viewSqlCascadedCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexPg('users').select('name').where('age', '>', '18'));
|
||||
view.cascadedCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlCascadedCheck.length);
|
||||
expect(viewSqlCascadedCheck[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\' with cascaded check option'
|
||||
);
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "users"');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "myschema"."users"');
|
||||
});
|
||||
|
||||
it('rename and change default of column of view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
equal(2, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'alter view "users" rename "oldName" to "newName"'
|
||||
);
|
||||
expect(tableSql[1].sql).to.equal(
|
||||
'alter view "users" alter "oldName" set default 10'
|
||||
);
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'alter view "old_view" rename to "new_view"'
|
||||
);
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexPg('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'create materialized view "mat_view" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'refresh materialized view "view_to_refresh"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('drop table with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
|
||||
@ -6,6 +6,7 @@ const { expect } = require('chai');
|
||||
let tableSql;
|
||||
|
||||
const Redshift_Client = require('../../../lib/dialects/redshift');
|
||||
const knex = require('../../../knex');
|
||||
const client = new Redshift_Client({ client: 'redshift' });
|
||||
|
||||
const equal = require('assert').equal;
|
||||
@ -54,6 +55,141 @@ describe('Redshift SchemaBuilder', function () {
|
||||
);
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexRedShift;
|
||||
|
||||
before(function () {
|
||||
knexRedShift = knex({
|
||||
client: 'redshift',
|
||||
connection: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexRedShift('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createViewOrReplace('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexRedShift('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
'create view or replace "adults" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
const viewSqlLocalCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexRedShift('users').select('name').where('age', '>', '18'));
|
||||
view.localCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlLocalCheck.length);
|
||||
expect(viewSqlLocalCheck[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\' with local check option'
|
||||
);
|
||||
|
||||
const viewSqlCascadedCheck = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexRedShift('users').select('name').where('age', '>', '18'));
|
||||
view.cascadedCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSqlCascadedCheck.length);
|
||||
expect(viewSqlCascadedCheck[0].sql).to.equal(
|
||||
'create view "adults" ("name") as select "name" from "users" where "age" > \'18\' with cascaded check option'
|
||||
);
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "users"');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view "myschema"."users"');
|
||||
});
|
||||
|
||||
it('rename and change default of column of view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
equal(2, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'alter view "users" rename "oldName" to "newName"'
|
||||
);
|
||||
expect(tableSql[1].sql).to.equal(
|
||||
'alter view "users" alter "oldName" set default 10'
|
||||
);
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'alter view "old_view" rename to "new_view"'
|
||||
);
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexRedShift('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'create materialized view "mat_view" ("name") as select "name" from "users" where "age" > \'18\''
|
||||
);
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal(
|
||||
'refresh materialized view "view_to_refresh"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('alter table with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
|
||||
@ -18,6 +18,7 @@ const {
|
||||
|
||||
const _ = require('lodash');
|
||||
const { equal, deepEqual } = require('assert');
|
||||
const knex = require('../../../knex');
|
||||
|
||||
describe('SQLite SchemaBuilder', function () {
|
||||
it('basic create table', function () {
|
||||
@ -49,6 +50,120 @@ describe('SQLite SchemaBuilder', function () {
|
||||
);
|
||||
});
|
||||
|
||||
describe('views', function () {
|
||||
let knexSqlite3;
|
||||
|
||||
before(function () {
|
||||
knexSqlite3 = knex({
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: '',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('basic create view', async function () {
|
||||
const viewSql = client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(knexSqlite3('users').select('name').where('age', '>', '18'));
|
||||
})
|
||||
.toSQL();
|
||||
equal(1, viewSql.length);
|
||||
expect(viewSql[0].sql).to.equal(
|
||||
"create view `adults` (`name`) as select `name` from `users` where `age` > '18'"
|
||||
);
|
||||
});
|
||||
|
||||
it('create view or replace', async function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('rename column of views is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('create view with check options', async function () {
|
||||
expect(() => {
|
||||
client
|
||||
.schemaBuilder()
|
||||
.createView('adults', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(
|
||||
knexSqlite3('users').select('name').where('age', '>', '18')
|
||||
);
|
||||
view.localCheckOption();
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('check option definition is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('drop view', function () {
|
||||
tableSql = client.schemaBuilder().dropView('users').toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view `users`');
|
||||
});
|
||||
|
||||
it('drop view with schema', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.withSchema('myschema')
|
||||
.dropView('users')
|
||||
.toSQL();
|
||||
equal(1, tableSql.length);
|
||||
expect(tableSql[0].sql).to.equal('drop view `myschema`.`users`');
|
||||
});
|
||||
|
||||
it('rename and change default of column of view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.view('users', function (view) {
|
||||
view.column('oldName').rename('newName').defaultTo('10');
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('rename column of views is not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('rename view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.renameView('old_view', 'new_view')
|
||||
.toSQL();
|
||||
}).to.throw(
|
||||
'rename view is not supported by this dialect (instead drop then create another view).'
|
||||
);
|
||||
});
|
||||
|
||||
it('create materialized view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.createMaterializedView('mat_view', function (view) {
|
||||
view.columns(['name']);
|
||||
view.as(
|
||||
knexSqlite3('users').select('name').where('age', '>', '18')
|
||||
);
|
||||
})
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
|
||||
it('refresh view', function () {
|
||||
expect(() => {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
.refreshMaterializedView('view_to_refresh')
|
||||
.toSQL();
|
||||
}).to.throw('materialized views are not supported by this dialect.');
|
||||
});
|
||||
});
|
||||
|
||||
it('create json table', function () {
|
||||
tableSql = client
|
||||
.schemaBuilder()
|
||||
|
||||
60
types/index.d.ts
vendored
60
types/index.d.ts
vendored
@ -1833,6 +1833,35 @@ export declare namespace Knex {
|
||||
//
|
||||
|
||||
interface SchemaBuilder extends ChainableInterface<void> {
|
||||
// Views
|
||||
createView(
|
||||
viewName: string,
|
||||
callback: (viewBuilder: ViewBuilder) => any
|
||||
): SchemaBuilder;
|
||||
createViewOrReplace(
|
||||
viewName: string,
|
||||
callback: (viewBuilder: ViewBuilder) => any
|
||||
): SchemaBuilder;
|
||||
createMaterializedView(
|
||||
viewName: string,
|
||||
callback: (viewBuilder: ViewBuilder) => any
|
||||
): SchemaBuilder;
|
||||
refreshMaterializedView(viewName: string): SchemaBuilder;
|
||||
dropView(viewName: string): SchemaBuilder;
|
||||
dropViewIfExists(viewName: string): SchemaBuilder;
|
||||
dropMaterializedView(viewName: string): SchemaBuilder;
|
||||
dropMaterializedViewIfExists(viewName: string): SchemaBuilder;
|
||||
renameView(oldViewName: string, newViewName: string): Promise<void>;
|
||||
view(
|
||||
viewName: string,
|
||||
callback: (viewBuilder: AlterViewBuilder) => any
|
||||
): Promise<void>;
|
||||
alterView(
|
||||
viewName: string,
|
||||
callback: (tableBuilder: AlterViewBuilder) => any
|
||||
): SchemaBuilder;
|
||||
|
||||
// Tables
|
||||
createTable(
|
||||
tableName: string,
|
||||
callback: (tableBuilder: CreateTableBuilder) => any
|
||||
@ -1846,8 +1875,6 @@ export declare namespace Knex {
|
||||
tableNameLike: string,
|
||||
callback: (tableBuilder: CreateTableBuilder) => any
|
||||
): SchemaBuilder;
|
||||
createSchema(schemaName: string): SchemaBuilder;
|
||||
createSchemaIfNotExists(schemaName: string): SchemaBuilder;
|
||||
alterTable(
|
||||
tableName: string,
|
||||
callback: (tableBuilder: CreateTableBuilder) => any
|
||||
@ -1855,16 +1882,22 @@ export declare namespace Knex {
|
||||
renameTable(oldTableName: string, newTableName: string): Promise<void>;
|
||||
dropTable(tableName: string): SchemaBuilder;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
hasColumn(tableName: string, columnName: string): Promise<boolean>;
|
||||
table(
|
||||
tableName: string,
|
||||
callback: (tableBuilder: AlterTableBuilder) => any
|
||||
): Promise<void>;
|
||||
dropTableIfExists(tableName: string): SchemaBuilder;
|
||||
|
||||
// Schema
|
||||
createSchema(schemaName: string): SchemaBuilder;
|
||||
createSchemaIfNotExists(schemaName: string): SchemaBuilder;
|
||||
dropSchema(schemaName: string, cascade?: boolean): SchemaBuilder;
|
||||
dropSchemaIfExists(schemaName: string, cascade?: boolean): SchemaBuilder;
|
||||
raw(statement: string): SchemaBuilder;
|
||||
withSchema(schemaName: string): SchemaBuilder;
|
||||
|
||||
// Others
|
||||
hasColumn(tableName: string, columnName: string): Promise<boolean>;
|
||||
raw(statement: string): SchemaBuilder;
|
||||
queryContext(context: any): SchemaBuilder;
|
||||
toString(): string;
|
||||
toSQL(): Sql;
|
||||
@ -1956,6 +1989,15 @@ export declare namespace Knex {
|
||||
queryContext(context: any): TableBuilder;
|
||||
}
|
||||
|
||||
interface ViewBuilder<TRecord extends {} = any, TResult = any> {
|
||||
columns(columns: any): ViewBuilder;
|
||||
as(selectQuery: QueryBuilder): ViewBuilder;
|
||||
checkOption(): Promise<void>;
|
||||
localCheckOption(): Promise<void>;
|
||||
cascadedCheckOption(): Promise<void>;
|
||||
queryContext(context: any): ViewBuilder;
|
||||
}
|
||||
|
||||
interface CreateTableBuilder extends TableBuilder {
|
||||
engine(val: string): CreateTableBuilder;
|
||||
charset(val: string): CreateTableBuilder;
|
||||
@ -1964,6 +2006,16 @@ export declare namespace Knex {
|
||||
}
|
||||
|
||||
interface AlterTableBuilder extends TableBuilder {}
|
||||
|
||||
interface AlterColumnView extends ViewBuilder {
|
||||
rename(newName: string): AlterColumnView;
|
||||
defaultTo(defaultValue: string): AlterColumnView;
|
||||
}
|
||||
|
||||
interface AlterViewBuilder extends ViewBuilder {
|
||||
column(column: string): AlterColumnView;
|
||||
}
|
||||
|
||||
type deferrableType = 'not deferrable' | 'immediate' | 'deferred';
|
||||
interface ColumnBuilder {
|
||||
index(indexName?: string): ColumnBuilder;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user