node-pg-migrate icon indicating copy to clipboard operation
node-pg-migrate copied to clipboard

Feature: Support plain json objects for jsonb defaults.

Open rijnhard opened this issue 4 years ago • 1 comments

it should be possible to specify a jsonb fields default value as a plain js object.

Error

CREATE TABLE "my_table" (
  "id" serial PRIMARY KEY,
  "my_column" jsonb DEFAULT  NOT NULL
                             ^^^^
);

Migrations failed error: syntax error at or near "NOT"
    at Parser.parseErrorMessage (/Data/Projects/Infrastructure/azure-archiver/node_modules/pg-protocol/src/parser.ts:357:11)
    at Parser.handlePacket (/Data/Projects/Infrastructure/azure-archiver/node_modules/pg-protocol/src/parser.ts:186:21)
    at Parser.parse (/Data/Projects/Infrastructure/azure-archiver/node_modules/pg-protocol/src/parser.ts:101:30)
    at Socket.<anonymous> (/Data/Projects/Infrastructure/azure-archiver/node_modules/pg-protocol/src/index.ts:7:48)

Code

// this is ideal
pgm.addColumn('my_table', 'my_column', {
    type: 'jsonb',
    notNull: true,
    default: { attempts: 0, uploads: 0 }
});

// this is whats required:
pgm.addColumn('my_table', 'my_column', {
    type: 'jsonb',
    notNull: true,
    default: pgm.func(`'{ "attempts": 0, "uploads": 0 }'::jsonb`)
});

Suggestion

a naive psuedo-implementation

const JSON_FIELDS = ['json', 'jsonb];

if (column.notNull
    && column.default != null
    && JSON_FIELDS.includes(column.type)
) {
    if (!lodash.isplainobject(column.default)) {
        throw new Error(`${column.type} defaults can only be plain objects`);
    }

    const defaultStatement = `'${JSON.serialize(column.default)}'::${column.type}`
}

rijnhard avatar Feb 24 '21 22:02 rijnhard

Hello Rijnhard,

Thank you for your suggestion. We will consider adding this feature to one of the next releases.

However please note that there is a quite comfortable workaround as you yourself wrote, so this feature will probably not be the top-priority.

goce-cz avatar Mar 02 '21 07:03 goce-cz