Skip to content

Commit

Permalink
feat: Add ability to alter columns
Browse files Browse the repository at this point in the history
Change type and nullability. More complex changes might still fail, but the it's a step in the right
direction.
  • Loading branch information
jezhiggins committed Dec 5, 2018
1 parent 0cd5f5d commit 6836d86
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 15 deletions.
63 changes: 49 additions & 14 deletions lib/statement-generators/column/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ const ejs = require('ejs')
const isDifferent = require('../is-different')
const missingTemplateString = fs.readFileSync(path.resolve(__dirname, './missing-template.ejs')).toString()
const missingTemplate = ejs.compile(missingTemplateString, {})
const differentTemplateString = fs.readFileSync(path.resolve(__dirname, './different-template.ejs')).toString()
const differentTemplate = ejs.compile(differentTemplateString, {})
const typeTemplateString = fs.readFileSync(path.resolve(__dirname, './type-template.ejs')).toString()
const typeTemplate = ejs.compile(typeTemplateString, {})
const nullableTemplateString = fs.readFileSync(path.resolve(__dirname, './nullable-template.ejs')).toString()
const nullableTemplate = ejs.compile(nullableTemplateString, {})

function buildConstraint (target) {
let constraint = target.dataType
Expand All @@ -28,30 +30,63 @@ function buildConstraint (target) {
return constraint
}

function buildType (target, columnName) {
let type = target.dataType

if (_.isNumber(target.numericScale) && target.numericScale > 0) {
type += `(${(target.numericPrecision || 9) + target.numericScale}, ${target.numericScale})`
}

if (target.array) {
type += '[]'
}

if (target.dataType === 'jsonb') {
type += ` USING ${columnName}::jsonb`
}

return type
}

function buildNullable (target) {
return `${target.isNullable === 'NO' ? 'SET' : 'DROP'} NOT NULL`
}

module.exports = function columnStatementGenerator (columnId, column, statements) {
const parts = columnId.split('.')
const columnName = parts[2]

const ctx = {
columnName: columnName,
tableId: parts[0] + '.' + parts[1],
constraint: buildConstraint(column.target)
constraint: buildConstraint(column.target),
type: buildType(column.target, columnName),
nullable: buildNullable(column.target)
}

if (_.isUndefined(column.base)) {
statements.push(
missingTemplate(ctx)
)
} else {
if (
isDifferent(column.target.array, column.base.array) ||
isDifferent(column.target.dataType, column.base.dataType) ||
isDifferent(column.target.columnDefault, column.base.columnDefault) ||
isDifferent(column.target.isNullable, column.base.isNullable) ||
isDifferent(column.target.characterMaximumLength, column.base.characterMaximumLength) ||
isDifferent(column.target.numericScale, column.base.numericScale)
) {
differentTemplate(ctx)
}
return
}

if (
isDifferent(column.target.array, column.base.array) ||
isDifferent(column.target.dataType, column.base.dataType) ||
isDifferent(column.target.columnDefault, column.base.columnDefault) ||
isDifferent(column.target.characterMaximumLength, column.base.characterMaximumLength) ||
isDifferent(column.target.numericScale, column.base.numericScale)
) {
statements.push(
typeTemplate(ctx)
)
}
if (
isDifferent(column.target.isNullable, column.base.isNullable)
) {
statements.push(
nullableTemplate(ctx)
)
}
}
1 change: 1 addition & 0 deletions lib/statement-generators/column/nullable-template.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE <%- tableId %> ALTER COLUMN <%- columnName %> <%- nullable %>;
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ALTER TABLE <%- tableId %> ALTER COLUMN <%- columnName %> TYPE <%- constraint %>;
ALTER TABLE <%- tableId %> ALTER COLUMN <%- columnName %> TYPE <%- type %>;
55 changes: 55 additions & 0 deletions test/column-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-env mocha */

const executionWithJson = require('./fixtures/execution-with-json.json')
const executionWithString = require('./fixtures/execution-with-string.json')
const executionWithAdditionalColumn = require('./fixtures/execution-with-additional-column.json')

const pgDiffSync = require('./../lib')
const expect = require('chai').expect

describe('columns', () => {
it('add a column', () => {
const statements = pgDiffSync(executionWithJson, executionWithAdditionalColumn)
expect(statements).to.eql(
[
'ALTER TABLE pg_diff_sync_test.execution ADD COLUMN additional text NOT NULL;'
]
)
})

it('remove a column', () => {
const statements = pgDiffSync(executionWithAdditionalColumn, executionWithJson)
expect(statements).to.eql(
[
// We don't actually remove it
]
)
})

it('change column types', () => {
const statements = pgDiffSync(executionWithJson, executionWithString)
expect(statements).to.eql(
[
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN ctx TYPE text;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN ctx DROP NOT NULL;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN executionOptions TYPE text;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN executionOptions DROP NOT NULL;'
]
)
})

it('change column type, add another column', () => {
const statements = pgDiffSync(executionWithString, executionWithAdditionalColumn)
expect(statements).to.eql(
[
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN ctx TYPE jsonb USING ctx::jsonb;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN ctx SET NOT NULL;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN executionOptions TYPE jsonb USING executionOptions::jsonb;',
'ALTER TABLE pg_diff_sync_test.execution ALTER COLUMN executionOptions SET NOT NULL;',
'ALTER TABLE pg_diff_sync_test.execution ADD COLUMN additional text NOT NULL;'
]
)

})

})
64 changes: 64 additions & 0 deletions test/fixtures/execution-with-additional-column.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"generated": "2017-05-22T16:06:17.034Z",
"schemas": {
"pg_diff_sync_test": {
"schemaExistsInDatabase": true,
"comment": "Schema auto-generated by Relationize.js!",
"tables": {
"execution": {
"comment": "Statebox executions instances",
"pkColumnNames": [
"execution_name"
],
"columns": {
"executionName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"ctx": {
"array": false,
"dataType": "jsonb",
"isNullable": "NO"
},
"currentStateName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"currentResource": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"stateMachineName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"status": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"executionOptions": {
"array": false,
"dataType": "jsonb",
"isNullable": "NO"
},
"additional": {
"array": false,
"dataType": "text",
"isNullable": "NO"
}
},
"indexes": {},
"fkConstraints":{}
}
}
}
},
"expectedDbSchemaNames": [
"pg_diff_sync_test"
]
}
59 changes: 59 additions & 0 deletions test/fixtures/execution-with-json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"generated": "2017-05-22T16:06:17.034Z",
"schemas": {
"pg_diff_sync_test": {
"schemaExistsInDatabase": true,
"comment": "Schema auto-generated by Relationize.js!",
"tables": {
"execution": {
"comment": "Statebox executions instances",
"pkColumnNames": [
"execution_name"
],
"columns": {
"executionName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"ctx": {
"array": false,
"dataType": "jsonb",
"isNullable": "NO"
},
"currentStateName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"currentResource": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"stateMachineName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"status": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"executionOptions": {
"array": false,
"dataType": "jsonb",
"isNullable": "NO"
}
},
"indexes": {},
"fkConstraints":{}
}
}
}
},
"expectedDbSchemaNames": [
"pg_diff_sync_test"
]
}
59 changes: 59 additions & 0 deletions test/fixtures/execution-with-string.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"generated": "2017-05-22T16:06:17.034Z",
"schemas": {
"pg_diff_sync_test": {
"schemaExistsInDatabase": true,
"comment": "Schema auto-generated by Relationize.js!",
"tables": {
"execution": {
"comment": "Statebox executions instances",
"pkColumnNames": [
"execution_name"
],
"columns": {
"executionName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"ctx": {
"array": false,
"dataType": "text",
"isNullable": "YES"
},
"currentStateName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"currentResource": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"stateMachineName": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"status": {
"array": false,
"dataType": "text",
"isNullable": "NO"
},
"executionOptions": {
"array": false,
"dataType": "text",
"isNullable": "YES"
}
},
"indexes": {},
"fkConstraints":{}
}
}
}
},
"expectedDbSchemaNames": [
"pg_diff_sync_test"
]
}

0 comments on commit 6836d86

Please sign in to comment.