2016-05-17 01:01:34 +10:00
/* eslint max-len:0 */
2016-03-02 17:07:05 +01:00
// MSSQL Table Builder & Compiler
// -------
2016-05-17 01:01:34 +10:00
import inherits from 'inherits' ;
import TableCompiler from '../../../schema/tablecompiler' ;
import * as helpers from '../../../helpers' ;
2016-08-09 17:23:07 -04:00
import Promise from 'bluebird' ;
2016-03-02 17:07:05 +01:00
2016-05-18 20:22:50 +10:00
import { assign } from 'lodash'
2016-03-02 17:07:05 +01:00
// Table Compiler
// ------
function TableCompiler _MSSQL ( ) {
TableCompiler . apply ( this , arguments ) ;
}
inherits ( TableCompiler _MSSQL , TableCompiler ) ;
assign ( TableCompiler _MSSQL . prototype , {
2018-06-29 10:47:06 +03:00
createAlterTableMethods : [ 'foreign' , 'primary' ] ,
2016-05-17 01:01:34 +10:00
createQuery ( columns , ifNot ) {
const createStatement = ifNot ? ` if object_id(' ${ this . tableName ( ) } ', 'U') is null CREATE TABLE ` : 'CREATE TABLE ' ;
const sql = createStatement + this . tableName ( ) + ( this . _formatting ? ' (\n ' : ' (' ) + columns . sql . join ( this . _formatting ? ',\n ' : ', ' ) + ')' ;
2016-03-02 17:07:05 +01:00
if ( this . single . comment ) {
2017-10-31 23:22:07 +01:00
const { comment } = this . single ;
2018-05-29 17:42:03 +02:00
if ( comment . length > 60 ) this . client . logger . warn ( 'The max length for a table comment is 60 characters' ) ;
2016-03-02 17:07:05 +01:00
}
this . pushQuery ( sql ) ;
} ,
lowerCase : false ,
addColumnsPrefix : 'ADD ' ,
dropColumnPrefix : 'DROP COLUMN ' ,
2017-02-16 20:34:59 +02:00
alterColumnPrefix : 'ALTER COLUMN ' ,
2016-05-12 10:24:29 +01:00
// Compiles column add. Multiple columns need only one ADD clause (not one ADD per column) so core addColumns doesn't work. #1348
2017-02-16 20:34:59 +02:00
addColumns ( columns , prefix ) {
prefix = prefix || this . addColumnsPrefix ;
2016-05-12 10:24:29 +01:00
if ( columns . sql . length > 0 ) {
this . pushQuery ( {
2017-02-16 20:34:59 +02:00
sql : ( this . lowerCase ? 'alter table ' : 'ALTER TABLE ' ) + this . tableName ( ) + ' ' + prefix + columns . sql . join ( ', ' ) ,
2016-05-12 10:24:29 +01:00
bindings : columns . bindings
} ) ;
}
} ,
// Compiles column drop. Multiple columns need only one DROP clause (not one DROP per column) so core dropColumn doesn't work. #1348
2016-05-17 01:01:34 +10:00
dropColumn ( ) {
const _this2 = this ;
const columns = helpers . normalizeArr . apply ( null , arguments ) ;
2016-05-12 10:24:29 +01:00
2016-05-17 01:01:34 +10:00
const drops = ( Array . isArray ( columns ) ? columns : [ columns ] ) . map ( column => _this2 . formatter . wrap ( column ) ) ;
2016-05-12 10:24:29 +01:00
this . pushQuery ( ( this . lowerCase ? 'alter table ' : 'ALTER TABLE ' ) + this . tableName ( ) + ' ' + this . dropColumnPrefix + drops . join ( ', ' ) ) ;
} ,
2016-03-02 17:07:05 +01:00
// Compiles the comment on the table.
2016-05-17 01:01:34 +10:00
comment ( ) {
2016-03-02 17:07:05 +01:00
} ,
2016-05-17 01:01:34 +10:00
changeType ( ) {
2016-03-02 17:07:05 +01:00
} ,
// Renames a column on the table.
2016-05-17 01:01:34 +10:00
renameColumn ( from , to ) {
this . pushQuery ( ` exec sp_rename ${ this . formatter . parameter ( this . tableName ( ) + '.' + from ) } , ${ this . formatter . parameter ( to ) } , 'COLUMN' ` ) ;
2016-03-02 17:07:05 +01:00
} ,
2016-05-17 01:01:34 +10:00
dropFKRefs ( runner , refs ) {
2018-02-01 23:41:01 +01:00
const formatter = this . client . formatter ( this . tableBuilder ) ;
2016-03-02 17:07:05 +01:00
return Promise . all ( refs . map ( function ( ref ) {
2016-05-17 01:01:34 +10:00
const constraintName = formatter . wrap ( ref . CONSTRAINT _NAME ) ;
const tableName = formatter . wrap ( ref . TABLE _NAME ) ;
2016-03-02 17:07:05 +01:00
return runner . query ( {
2016-05-17 01:01:34 +10:00
sql : ` ALTER TABLE ${ tableName } DROP CONSTRAINT ${ constraintName } `
2016-03-02 17:07:05 +01:00
} ) ;
} ) ) ;
} ,
2016-05-17 01:01:34 +10:00
createFKRefs ( runner , refs ) {
2018-02-01 23:41:01 +01:00
const formatter = this . client . formatter ( this . tableBuilder ) ;
2016-03-02 17:07:05 +01:00
return Promise . all ( refs . map ( function ( ref ) {
2016-05-17 01:01:34 +10:00
const tableName = formatter . wrap ( ref . TABLE _NAME ) ;
const keyName = formatter . wrap ( ref . CONSTRAINT _NAME ) ;
const column = formatter . columnize ( ref . COLUMN _NAME ) ;
const references = formatter . columnize ( ref . REFERENCED _COLUMN _NAME ) ;
const inTable = formatter . wrap ( ref . REFERENCED _TABLE _NAME ) ;
const onUpdate = ` ON UPDATE ${ ref . UPDATE _RULE } ` ;
const onDelete = ` ON DELETE ${ ref . DELETE _RULE } ` ;
2016-03-02 17:07:05 +01:00
return runner . query ( {
2016-05-17 01:01:34 +10:00
sql : ` ALTER TABLE ${ tableName } ADD CONSTRAINT ${ keyName } ` +
2016-03-02 17:07:05 +01:00
' FOREIGN KEY (' + column + ') REFERENCES ' + inTable + ' (' + references + ')' + onUpdate + onDelete
} ) ;
} ) ) ;
} ,
2016-05-17 01:01:34 +10:00
index ( columns , indexName ) {
2015-07-15 23:16:30 -03:00
indexName = indexName ? this . formatter . wrap ( indexName ) : this . _indexCommand ( 'index' , this . tableNameRaw , columns ) ;
2016-05-17 01:01:34 +10:00
this . pushQuery ( ` CREATE INDEX ${ indexName } ON ${ this . tableName ( ) } ( ${ this . formatter . columnize ( columns ) } ) ` ) ;
2016-03-02 17:07:05 +01:00
} ,
2016-05-19 21:30:17 +02:00
primary ( columns , constraintName ) {
2016-07-20 04:22:17 +03:00
constraintName = constraintName ? this . formatter . wrap ( constraintName ) : this . formatter . wrap ( ` ${ this . tableNameRaw } _pkey ` ) ;
2016-03-02 17:07:05 +01:00
if ( ! this . forCreate ) {
2016-05-19 21:30:17 +02:00
this . pushQuery ( ` ALTER TABLE ${ this . tableName ( ) } ADD CONSTRAINT ${ constraintName } PRIMARY KEY ( ${ this . formatter . columnize ( columns ) } ) ` ) ;
2016-03-02 17:07:05 +01:00
} else {
2016-05-19 21:30:17 +02:00
this . pushQuery ( ` CONSTRAINT ${ constraintName } PRIMARY KEY ( ${ this . formatter . columnize ( columns ) } ) ` ) ;
2016-03-02 17:07:05 +01:00
}
} ,
2016-05-17 01:01:34 +10:00
unique ( columns , indexName ) {
2015-07-15 23:16:30 -03:00
indexName = indexName ? this . formatter . wrap ( indexName ) : this . _indexCommand ( 'unique' , this . tableNameRaw , columns ) ;
2018-06-29 10:47:06 +03:00
if ( ! Array . isArray ( columns ) ) {
columns = [ columns ] ;
2016-03-02 17:07:05 +01:00
}
2018-06-29 10:47:06 +03:00
const whereAllTheColumnsAreNotNull = columns . map ( column => this . formatter . columnize ( column ) + ' IS NOT NULL' ) . join ( ' AND ' ) ;
// make unique constraint that allows null https://stackoverflow.com/a/767702/360060
// to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed)
this . pushQuery ( ` CREATE UNIQUE INDEX ${ indexName } ON ${ this . tableName ( ) } ( ${ this . formatter . columnize ( columns ) } ) WHERE ${ whereAllTheColumnsAreNotNull } ` ) ;
2016-03-02 17:07:05 +01:00
} ,
// Compile a drop index command.
2016-05-17 01:01:34 +10:00
dropIndex ( columns , indexName ) {
2015-07-15 23:16:30 -03:00
indexName = indexName ? this . formatter . wrap ( indexName ) : this . _indexCommand ( 'index' , this . tableNameRaw , columns ) ;
2016-05-17 01:01:34 +10:00
this . pushQuery ( ` DROP INDEX ${ indexName } ON ${ this . tableName ( ) } ` ) ;
2016-03-02 17:07:05 +01:00
} ,
// Compile a drop foreign key command.
2016-05-17 01:01:34 +10:00
dropForeign ( columns , indexName ) {
2015-07-15 23:16:30 -03:00
indexName = indexName ? this . formatter . wrap ( indexName ) : this . _indexCommand ( 'foreign' , this . tableNameRaw , columns ) ;
2016-05-17 01:01:34 +10:00
this . pushQuery ( ` ALTER TABLE ${ this . tableName ( ) } DROP CONSTRAINT ${ indexName } ` ) ;
2016-03-02 17:07:05 +01:00
} ,
// Compile a drop primary key command.
2016-07-20 04:22:17 +03:00
dropPrimary ( constraintName ) {
constraintName = constraintName ? this . formatter . wrap ( constraintName ) : this . formatter . wrap ( ` ${ this . tableNameRaw } _pkey ` ) ;
this . pushQuery ( ` ALTER TABLE ${ this . tableName ( ) } DROP CONSTRAINT ${ constraintName } ` ) ;
2016-03-02 17:07:05 +01:00
} ,
// Compile a drop unique key command.
2016-05-17 01:01:34 +10:00
dropUnique ( column , indexName ) {
2015-07-15 23:16:30 -03:00
indexName = indexName ? this . formatter . wrap ( indexName ) : this . _indexCommand ( 'unique' , this . tableNameRaw , column ) ;
2018-06-29 10:47:06 +03:00
this . pushQuery ( ` DROP INDEX ${ indexName } ON ${ this . tableName ( ) } ` ) ;
2016-03-02 17:07:05 +01:00
}
} )
2016-05-17 01:01:34 +10:00
export default TableCompiler _MSSQL ;