diff --git a/LICENSE b/LICENSE index 87fd0340..6e651527 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,7 @@ The MIT License (MIT) +Copyright (c) 2016 Jan Dolezel <dolezel.jan@gmail.com> + Copyright (c) 2014 Theo Ephraim Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index b2c4458e..6d03d92a 100644 --- a/README.md +++ b/README.md @@ -352,6 +352,75 @@ This is required for some SQL operations that cannot be run within a transaction ----------------------------------------------------- +#### `pgm.renameType( type_name, new_type_name )` + +> Rename a data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type to rename +- `new_type_name` _[string]_ - name of the new type + +----------------------------------------------------- + +#### `pgm.addTypeAttribute( type_name, attribute_name, attribute_type )` + +> Add attribute to an existing data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type +- `attribute_name` _[string]_ - name of the attribute to add +- `attribute_type` _[string]_ - type of the attribute to add + +----------------------------------------------------- + +#### `pgm.dropTypeAttribute( type_name, attribute_name, options )` + +> Drop attribute from a data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type +- `attribute_name` _[string]_ - name of the attribute to drop +- `options` _[object]_ - options: + - `ifExists` _[boolean]_ - default false + +----------------------------------------------------- + +#### `pgm.setTypeAttribute( type_name, attribute_name, attribute_type )` + +> Set data type of an existing attribute of data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type +- `attribute_name` _[string]_ - name of the attribute +- `attribute_type` _[string]_ - new type of the attribute + +----------------------------------------------------- + +#### `pgm.addTypeValue( type_name, value, options )` + +> Add value to a list of enum data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type +- `value` _[string]_ - value to add to list +- `options` _[object]_ - options: + - `ifNotExists` _[boolean]_ - default false + - `before` _[string]_ - value before which the new value should be add + - `after` _[string]_ - value after which the new value should be add + +----------------------------------------------------- + +#### `pgm.renameTypeAttribute( type_name, attribute_name, new_attribute_name )` + +> Rename an attribute of data type - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertype.html) + +**Arguments:** +- `type_name` _[string]_ - name of the type +- `attribute_name` _[string]_ - name of the attribute to rename +- `new_attribute_name` _[string]_ - new name of the attribute + +----------------------------------------------------- + ### Role Operations #### `pgm.createRole( role_name, role_options )` @@ -391,7 +460,7 @@ This is required for some SQL operations that cannot be run within a transaction #### `pgm.alterRole( role_name, role_options )` -> Alters a role - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterrole.html) +> Alter a role - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterrole.html) **Arguments:** - `role_name` _[string]_ - name of the new role @@ -401,7 +470,7 @@ This is required for some SQL operations that cannot be run within a transaction #### `pgm.renameRole( old_role_name, new_role_name )` -> Renames a role - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterrole.html) +> Rename a role - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterrole.html) **Arguments:** - `old_role_name` _[string]_ - old name of the role @@ -455,7 +524,7 @@ This is required for some SQL operations that cannot be run within a transaction #### `pgm.renameFunction( old_function_name, function_params, new_function_name )` -> Renames a function - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterfunction.html) +> Rename a function - [postgres docs](http://www.postgresql.org/docs/current/static/sql-alterfunction.html) **Arguments:** - `old_function_name` _[string]_ - old name of the function @@ -503,7 +572,7 @@ This is required for some SQL operations that cannot be run within a transaction #### `pgm.renameTrigger( table_name, old_trigger_name, new_trigger_name )` -> Renames a trigger - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertrigger.html) +> Rename a trigger - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altertrigger.html) **Arguments:** - `table_name` _[string]_ - name of the table where the trigger lives diff --git a/bin/pg-migrate b/bin/pg-migrate index 64e7731c..e8e6b613 100755 --- a/bin/pg-migrate +++ b/bin/pg-migrate @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable strict */ +/* eslint-disable strict,prefer-destructuring */ 'use strict'; diff --git a/lib/migration-builder.js b/lib/migration-builder.js index e91445f9..4c840549 100644 --- a/lib/migration-builder.js +++ b/lib/migration-builder.js @@ -64,8 +64,13 @@ export default class MigrationBuilder { this.createType = wrap(types.create(options.typeShorthands)); this.dropType = wrap(types.drop); - this.alterType = wrap(types.alter); this.addType = this.createType; + this.renameType = wrap(types.rename); + this.renameTypeAttribute = wrap(types.renameTypeAttribute); + this.addTypeAttribute = wrap(types.addTypeAttribute(options.typeShorthands)); + this.dropTypeAttribute = wrap(types.dropTypeAttribute); + this.setTypeAttribute = wrap(types.setTypeAttribute(options.typeShorthands)); + this.addTypeValue = wrap(types.addTypeValue); this.createIndex = wrap(indexes.create); this.dropIndex = wrap(indexes.drop); diff --git a/lib/operations/types.js b/lib/operations/types.js index 1162ce29..74820681 100644 --- a/lib/operations/types.js +++ b/lib/operations/types.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { template, applyType } from '../utils'; +import { template, applyType, escapeValue } from '../utils'; export const drop = type_name => template`DROP TYPE "${type_name}";`; @@ -7,15 +7,59 @@ export const drop = type_name => export const create = (type_shorthands) => { const _create = (type_name, options) => { if (_.isArray(options)) { - return template`CREATE TYPE "${type_name}" AS ENUM ('${options.join('\', \'')}');`; + return template`CREATE TYPE "${type_name}" AS ENUM (${options.map(escapeValue).join(', ')});`; } - const columns = _.map(options, (column, column_name) => - template`"${column_name}" ${applyType(column, type_shorthands).type}` + const attributes = _.map(options, (attribute, attribute_name) => + template`"${attribute_name}" ${applyType(attribute, type_shorthands).type}` ).join(',\n'); - return template`CREATE TYPE "${type_name}" AS (\n${columns}\n);`; + return template`CREATE TYPE "${type_name}" AS (\n${attributes}\n);`; }; _create.reverse = drop; return _create; }; -export const alter = () => null; +export const dropTypeAttribute = (type_name, attribute_name, { ifExists } = {}) => + template`ALTER TYPE "${type_name}" DROP ATTRIBUTE "${attribute_name}"${ifExists ? ' IF EXISTS' : ''};`; + +export const addTypeAttribute = (type_shorthands) => { + const _alterAttributeAdd = (type_name, attribute_name, attribute_type) => + template`ALTER TYPE "${type_name}" ADD ATTRIBUTE "${attribute_name}" ${applyType(attribute_type, type_shorthands).type};`; + _alterAttributeAdd.reverse = dropTypeAttribute; + return _alterAttributeAdd; +}; + +export const setTypeAttribute = type_shorthands => + (type_name, attribute_name, attribute_type) => + template`ALTER TYPE "${type_name}" ALTER ATTRIBUTE "${attribute_name}" SET DATA TYPE ${applyType(attribute_type, type_shorthands).type};`; + +export const addTypeValue = (type_name, value, options = {}) => { + const { + ifNotExists, + before, + after, + } = options; + + if (before && after) { + throw new Error('"before" and "after" can\'t be specified together'); + } + const beforeClause = before ? ` BEFORE ${before}` : ''; + const afterClause = after ? ` BEFORE ${after}` : ''; + + return template`ALTER TYPE "${type_name}" ADD VALUE${ifNotExists ? ' IF NOT EXISTS' : ''} ${escapeValue(value)}${beforeClause}${afterClause};`; +}; + +// RENAME +export const rename = (type_name, new_type_name) => + template`ALTER TYPE "${type_name}" RENAME TO "${new_type_name}";`; + +export const undoRename = (type_name, new_type_name) => + rename(new_type_name, type_name); + +export const renameTypeAttribute = (type_name, attribute_name, new_attribute_name) => + template`ALTER TYPE "${type_name}" RENAME ATTRIBUTE "${attribute_name}" TO "${new_attribute_name}";`; + +export const undoRenameTypeAttribute = (type_name, attribute_name, new_attribute_name) => + renameTypeAttribute(type_name, new_attribute_name, attribute_name); + +rename.reverse = undoRename; +renameTypeAttribute.reverse = undoRenameTypeAttribute;