Skip to content

Commit

Permalink
Sequences operations (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
dolezel authored Jan 23, 2018
1 parent 0887f22 commit a9dd40a
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 15 deletions.
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;

0 comments on commit a9dd40a

Please sign in to comment.