Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequences operations #157

Merged
merged 1 commit into from
Jan 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,71 @@ This is required for some SQL operations that cannot be run within a transaction

-----------------------------------------------------

### Sequence Operations

#### `pgm.createSequence( sequence_name, type, options )`

> Create a new sequence - [postgres docs](https://www.postgresql.org/docs/current/static/sql-createsequence.html)
**Arguments:**
- `sequence_name` _[string]_ - name of the new sequence
- `options` _[object]_ - options:
- `temporary` _[boolean]_ - adds `TEMPORARY` clause
- `ifNotExists` _[boolean]_ - adds `IF NOT EXISTS` clause
- `type` _[string]_ - type of the sequence
- `increment` _[number]_ - sets first value of sequence
- `minvalue` _[number or boolean]_ - sets minimum value of sequence or `NO MINVALUE` (on false or null value)
- `maxvalue` _[number or boolean]_ - sets maximum value of sequencee or `NO MAXVALUE` (on false or null value)
- `start` _[number]_ - sets first value of sequence
- `cache` _[number]_ - sets how many sequence numbers should be preallocated
- `cycle` _[boolean]_ - adds `CYCLE` or `NO CYCLE` clause if option is present
- `owner` _[string or boolean]_ - sets owner of sequence or no owner (on false or null value)

**Reverse Operation:** `dropSequence`

-----------------------------------------------------

#### `pgm.dropSequence( sequence_name, drop_options )`

> Drop a sequence - [postgres docs](http://www.postgresql.org/docs/current/static/sql-dropsequence.html)
**Arguments:**
- `sequence_name` _[string]_ - name of the the sequence to drop
- `drop_options` _[object]_ - options:
- `ifExists` _[boolean]_ - drops sequence only if it exists
- `cascade` _[boolean]_ - drops also dependent objects

-----------------------------------------------------

#### `pgm.alterSequence( sequence_name, options )`

> Alter a sequence - [postgres docs](https://www.postgresql.org/docs/current/static/sql-altersequence.html)
**Arguments:**
- `sequence_name` _[string]_ - name of the new sequence
- `options` _[object]_ - options:
- `type` _[string]_ - type of the sequence
- `increment` _[number]_ - sets first value of sequence
- `minvalue` _[number or boolean]_ - sets minimum value of sequence or `NO MINVALUE` (on false or null value)
- `maxvalue` _[number or boolean]_ - sets maximum value of sequencee or `NO MAXVALUE` (on false or null value)
- `start` _[number]_ - sets first value of sequence (no effect until restart)
- `restart` _[number or boolean]_ - sets first value of sequence or using `start` value (on true value)
- `cache` _[number]_ - sets how many sequence numbers should be preallocated
- `cycle` _[boolean]_ - adds `CYCLE` or `NO CYCLE` clause if option is present
- `owner` _[string or boolean]_ - sets owner of sequence or no owner (on false or null value)

-----------------------------------------------------

#### `pgm.renameSequence( old_sequence_name, new_sequence_name )`

> Rename a sequence - [postgres docs](http://www.postgresql.org/docs/current/static/sql-altersequence.html)
**Arguments:**
- `old_sequence_name` _[string]_ - old name of the sequence
- `new_sequence_name` _[string]_ - new name of the sequence

-----------------------------------------------------

### Miscellaneous Operations

#### `pgm.sql( sql )`
Expand Down
69 changes: 54 additions & 15 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Definitions by: Jan Doležel <https://github.com/dolezel>

interface ValueArray extends Array<Value> {}

export type Value = null | boolean | string | number | PgLiteral | ValueArray

export type Name = string | { schema?: string, name: string }
Expand Down Expand Up @@ -153,18 +154,23 @@ export interface RoleOptions {
admin?: string | string[]
}

export interface DropOptions {
export interface IfExistsOption {
ifExists?: boolean
}

export interface CascadeOption {
cascade?: boolean
}

export interface DropIndexOptions {
export type DropOptions = IfExistsOption & CascadeOption

interface DropIndexOptionsEn {
name?: string
concurrently?: boolean
ifExists?: boolean
cascade?: boolean
}

export type DropIndexOptions = DropIndexOptionsEn & DropOptions

export interface FunctionParamType {
mode: 'IN' | 'OUT' | 'INOUT' | 'VARIADIC'
name: string
Expand All @@ -184,7 +190,7 @@ export interface FunctionOptions {
parallel?: 'UNSAFE' | 'RESTRICTED' | 'SAFE'
}

export interface TriggerOptionsEn {
interface TriggerOptionsEn {
when: 'BEFORE' | 'AFTER' | 'INSTEAD OF'
operation: string | string[]
constraint: boolean
Expand All @@ -195,23 +201,50 @@ export interface TriggerOptionsEn {
deferred: boolean
}

export interface DomainOptionsCreate {
export type TriggerOptions = TriggerOptionsEn & FunctionOptions

interface DomainOptions {
default?: Value
collation?: string
notNull?: boolean
check?: string
constraintName?: string
}

export interface DomainOptionsAlter {
default?: Value
notNull?: boolean
interface DomainOptionsCreateEn {
collation?: string
}

interface DomainOptionsAlterEn {
allowNull?: boolean
check?: string
constraintName?: string
}

export type TriggerOptions = TriggerOptionsEn & FunctionOptions
export type DomainOptionsCreate = DomainOptionsCreateEn & DomainOptions

export type DomainOptionsAlter = DomainOptionsAlterEn & DomainOptions

interface SequenceOptions {
type?: string
increment?: number
minvalue?: number | null | false
maxvalue?: number | null | false
start?: number
cache?: number
cycle?: boolean
owner?: string | null | false
}

interface SequenceOptionsCreateEn {
temporary?: boolean
ifNotExists?: boolean
}

interface SequenceOptionsAlterEn {
restart?: number | true
}

export type SequenceOptionsCreate = SequenceOptionsCreateEn & SequenceOptions

export type SequenceOptionsAlter = SequenceOptionsAlterEn & SequenceOptions

export interface MigrationBuilder {
// Tables
Expand Down Expand Up @@ -249,14 +282,14 @@ export interface MigrationBuilder {
dropType(type_name: Name, drop_options: DropOptions): void
renameType(type_name: Name, new_type_name: Name): void
addTypeAttribute(type_name: Name, attribute_name: string, attribute_type: Type): void
dropTypeAttribute(type_name: Name, attribute_name: string, options: { ifExists?: boolean }): void
dropTypeAttribute(type_name: Name, attribute_name: string, options: IfExistsOption): void
setTypeAttribute(type_name: Name, attribute_name: string, attribute_type: Type): void
addTypeValue(type_name: Name, value: Value, options: { ifNotExists?: boolean, before?: string, after?: string }): void
renameTypeAttribute(type_name: Name, attribute_name: string, new_attribute_name: string): void

// Roles
createRole(role_name: Name, role_options: RoleOptions): void
dropRole(role_name: Name, options: { ifExists?: boolean }): void
dropRole(role_name: Name, options: IfExistsOption): void
alterRole(role_name: Name, role_options: RoleOptions): void
renameRole(old_role_name: Name, new_role_name: Name): void

Expand All @@ -281,6 +314,12 @@ export interface MigrationBuilder {
alterDomain(domain_name: Name, domain_options: DomainOptionsAlter): void
renameDomain(old_domain_name: Name, new_domain_name: Name): void

// Domains
createSequence(sequence_name: Name, sequence_options: SequenceOptionsCreate): void
dropSequence(sequence_name: Name, drop_options: DropOptions): void
alterSequence(sequence_name: Name, sequence_options: SequenceOptionsAlter): void
renameSequence(old_sequence_name: Name, new_sequence_name: Name): void

sql(sql: string, args?: object): void
func(sql: string): PgLiteral
noTransaction(): void
Expand Down
6 changes: 6 additions & 0 deletions lib/migration-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as functions from './operations/functions';
import * as triggers from './operations/triggers';
import * as schemas from './operations/schemas';
import * as domains from './operations/domains';
import * as sequences from './operations/sequences';
import * as other from './operations/other';

export default class MigrationBuilder {
Expand Down Expand Up @@ -101,6 +102,11 @@ export default class MigrationBuilder {
this.alterDomain = wrap(domains.alter);
this.renameDomain = wrap(domains.rename);

this.createSequence = wrap(sequences.create(options.typeShorthands));
this.dropSequence = wrap(sequences.drop);
this.alterSequence = wrap(sequences.alter(options.typeShorthands));
this.renameSequence = wrap(sequences.rename);

this.sql = wrap(other.sql);

// Other utilities which may be useful
Expand Down
91 changes: 91 additions & 0 deletions lib/operations/sequences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { template, applyType } from '../utils';

const parseOptions = (type_shorthands, options) => {
const {
type,
increment,
minvalue,
maxvalue,
start,
cache,
cycle,
owner,
} = options;
const clauses = [];
if (type) {
clauses.push(`AS ${applyType(type, type_shorthands).type}`);
}
if (increment) {
clauses.push(`INCREMENT BY ${increment}`);
}
if (minvalue) {
clauses.push(`MINVALUE ${minvalue}`);
} else if (minvalue === null || minvalue === false) {
clauses.push('NO MINVALUE');
}
if (maxvalue) {
clauses.push(`MAXVALUE ${maxvalue}`);
} else if (maxvalue === null || maxvalue === false) {
clauses.push('NO MAXVALUE');
}
if (start) {
clauses.push(`START WITH ${start}`);
}
if (cache) {
clauses.push(`CACHE ${cache}`);
}
if (cycle) {
clauses.push('CYCLE');
} else if (cycle === false) {
clauses.push('NO CYCLE');
}
if (owner) {
clauses.push(`OWNED BY ${owner}`);
} else if (owner === null || owner === false) {
clauses.push('OWNED BY NONE');
}
return clauses;
};

export const drop = (sequence_name, { ifExists, cascade } = {}) =>
template`DROP SEQUENCE${ifExists ? ' IF EXISTS' : ''} "${sequence_name}"${cascade ? ' CASCADE' : ''};`;

export const create = (type_shorthands) => {
const _create = (sequence_name, options) => {
const {
temporary,
ifNotExists,
} = options;
const clauses = parseOptions(type_shorthands, options);
return template`CREATE${temporary ? ' TEMPORARY' : ''} SEQUENCE${ifNotExists ? ' IF NOT EXISTS' : ''} "${sequence_name}"
${clauses.join('\n ')};`;
};
_create.reverse = drop;
return _create;
};

export const alter = type_shorthands =>
(sequence_name, options) => {
const {
restart,
} = options;
const clauses = parseOptions(type_shorthands, options);
if (restart) {
if (restart === true) {
clauses.push('RESTART');
} else {
clauses.push(`RESTART WITH ${restart}`);
}
}
return template`ALTER SEQUENCE "${sequence_name}"
${clauses.join('\n ')};`;
};

// RENAME
export const rename = (sequence_name, new_sequence_name) =>
template`ALTER SEQUENCE "${sequence_name}" RENAME TO "${new_sequence_name}";`;

export const undoRename = (sequence_name, new_sequence_name) =>
rename(new_sequence_name, sequence_name);

rename.reverse = undoRename;