feat: inline primary key creation for postgres flavours (#5233)

This commit is contained in:
Lucas Bickel 2022-06-30 15:09:25 +02:00 committed by GitHub
parent d371c0424a
commit 8b0dd49700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 157 additions and 27 deletions

View File

@ -44,7 +44,10 @@ class TableCompiler_PG extends TableCompiler {
const createStatement = ifNot
? 'create table if not exists '
: 'create table ';
const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')';
const columnsSql = ` (${columns.sql.join(', ')}${
this.primaryKeys() || ''
}${this._addChecks()})`;
let sql =
createStatement +
this.tableName() +
@ -65,6 +68,28 @@ class TableCompiler_PG extends TableCompiler {
if (hasComment) this.comment(this.single.comment);
}
primaryKeys() {
const pks = (this.grouped.alterTable || []).filter(
(k) => k.method === 'primary'
);
if (pks.length > 0 && pks[0].args.length > 0) {
const columns = pks[0].args[0];
let constraintName = pks[0].args[1] || '';
let deferrable;
if (isObject(constraintName)) {
({ constraintName, deferrable } = constraintName);
}
deferrable = deferrable ? ` deferrable initially ${deferrable}` : '';
constraintName = constraintName
? this.formatter.wrap(constraintName)
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
return `, constraint ${constraintName} primary key (${this.formatter.columnize(
columns
)})${deferrable}`;
}
}
addColumns(columns, prefix, colCompilers) {
if (prefix === this.alterColumnsPrefix) {
// alter columns
@ -153,11 +178,13 @@ class TableCompiler_PG extends TableCompiler {
constraintName = constraintName
? this.formatter.wrap(constraintName)
: this.formatter.wrap(`${this.tableNameRaw}_pkey`);
this.pushQuery(
`alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize(
columns
)})${deferrable}`
);
if (this.method !== 'create' && this.method !== 'createIfNot') {
this.pushQuery(
`alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize(
columns
)})${deferrable}`
);
}
}
unique(columns, indexName) {

View File

@ -483,25 +483,54 @@ describe('Schema (misc)', () => {
});
describe('uuid types - postgres', () => {
before(async () => {
await knex.schema.createTable('uuid_column_test', (table) => {
table.uuid('id', { primaryKey: true });
});
after(async () => {
if (isPgBased(knex)) {
await knex.schema.dropTable('uuid_column_test');
}
});
after(async () => {
await knex.schema.dropTable('uuid_column_test');
it('creates a uuid column as primary using fluid syntax', async function () {
if (!isPgBased(knex)) {
return this.skip();
}
const table_name = 'uuid_column_test';
const expected_column = 'id';
const expected_type = 'uuid';
await knex.schema.dropTableIfExists(table_name);
await knex.schema.createTable(table_name, (table) => {
table.uuid('id').primary();
});
const cols = await knex.raw(
`select c.column_name, c.data_type
from INFORMATION_SCHEMA.COLUMNS c
join INFORMATION_SCHEMA.KEY_COLUMN_USAGE cu
on (c.table_name = cu.table_name and c.column_name = cu.column_name)
where c.table_name = ?
and (cu.constraint_name like '%_pkey' or cu.constraint_name = 'primary')`,
table_name
);
const column_name = cols.rows[0].column_name;
const column_type = cols.rows[0].data_type;
expect(column_name).to.equal(expected_column);
expect(column_type).to.equal(expected_type);
});
it('#5211 - creates an uuid column as primary key', async function () {
if (!isPgBased(knex)) {
return this.skip();
}
const table_name = 'uuid_column_test';
const expected_column = 'id';
const expected_type = 'uuid';
await knex.schema.dropTableIfExists(table_name);
await knex.schema.createTable(table_name, (table) => {
table.uuid('id', { primaryKey: true });
});
const cols = await knex.raw(
`select c.column_name, c.data_type
from INFORMATION_SCHEMA.COLUMNS c
@ -862,8 +891,7 @@ describe('Schema (misc)', () => {
tester(
['pg', 'cockroachdb'],
[
'create table "test_table_three" ("main" integer not null, "paragraph" text default \'Lorem ipsum Qui quis qui in.\', "metadata" json default \'{"a":10}\', "details" jsonb default \'{"b":{"d":20}}\')',
'alter table "test_table_three" add constraint "test_table_three_pkey" primary key ("main")',
'create table "test_table_three" ("main" integer not null, "paragraph" text default \'Lorem ipsum Qui quis qui in.\', "metadata" json default \'{"a":10}\', "details" jsonb default \'{"b":{"d":20}}\', constraint "test_table_three_pkey" primary key ("main"))',
]
);
tester('pg-redshift', [

View File

@ -150,6 +150,20 @@ describe('PostgreSQL SchemaBuilder', function () {
);
});
it('should create a table with inline uuid primary key creation', function () {
tableSql = client
.schemaBuilder()
.createTable('uuids', function (table) {
table.uuid('id').primary();
})
.toSQL();
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'create table "uuids" ("id" uuid, constraint "uuids_pkey" primary key ("id"))'
);
});
it('basic alter table', function () {
tableSql = client
.schemaBuilder()
@ -547,6 +561,19 @@ describe('PostgreSQL SchemaBuilder', function () {
);
});
it('drop primary takes constraint name', function () {
tableSql = client
.schemaBuilder()
.table('users', function (table) {
table.dropPrimary('testconstraintname');
})
.toSQL();
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'alter table "users" drop constraint "testconstraintname"'
);
});
it('drop unique', function () {
tableSql = client
.schemaBuilder()
@ -688,9 +715,9 @@ describe('PostgreSQL SchemaBuilder', function () {
});
})
.toSQL();
equal(2, tableSql.length);
expect(tableSql[1].sql).to.equal(
'alter table "person" add constraint "user_id_primary" primary key ("user_id") deferrable initially immediate'
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'create table "person" ("user_id" integer, constraint "user_id_primary" primary key ("user_id") deferrable initially immediate)'
);
});
@ -733,12 +760,9 @@ describe('PostgreSQL SchemaBuilder', function () {
table.string('name').primary();
})
.toSQL();
equal(2, tableSql.length);
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'create table "users" ("name" varchar(255))'
);
expect(tableSql[1].sql).to.equal(
'alter table "users" add constraint "users_pkey" primary key ("name")'
'create table "users" ("name" varchar(255), constraint "users_pkey" primary key ("name"))'
);
});
@ -1992,12 +2016,15 @@ describe('PostgreSQL SchemaBuilder', function () {
it('#1430 - .primary & .dropPrimary takes columns and constraintName', function () {
tableSql = client
.schemaBuilder()
.table('users', function (t) {
.createTable('users', function (t) {
t.string('test1');
t.string('test2');
t.primary(['test1', 'test2'], 'testconstraintname');
})
.toSQL();
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'alter table "users" add constraint "testconstraintname" primary key ("test1", "test2")'
'create table "users" ("test1" varchar(255), "test2" varchar(255), constraint "testconstraintname" primary key ("test1", "test2"))'
);
tableSql = client
@ -2007,11 +2034,59 @@ describe('PostgreSQL SchemaBuilder', function () {
})
.toSQL();
expect(tableSql[1].sql).to.equal(
'alter table "users" add constraint "testconstraintname" primary key ("test")'
expect(tableSql[0].sql).to.equal(
'create table "users" ("test" varchar(255), constraint "testconstraintname" primary key ("test"))'
);
});
describe('alter with primary', function () {
it('liquid argument', function () {
tableSql = client
.schemaBuilder()
.alterTable('users', function (t) {
t.string('test').primary();
})
.toSQL();
equal(2, tableSql.length);
expect(tableSql[0].sql).to.equal(
'alter table "users" add column "test" varchar(255)'
);
expect(tableSql[1].sql).to.equal(
'alter table "users" add constraint "users_pkey" primary key ("test")'
);
});
it('liquid argument with name', function () {
tableSql = client
.schemaBuilder()
.alterTable('users', function (t) {
t.string('test').primary('testname');
})
.toSQL();
equal(2, tableSql.length);
expect(tableSql[0].sql).to.equal(
'alter table "users" add column "test" varchar(255)'
);
expect(tableSql[1].sql).to.equal(
'alter table "users" add constraint "testname" primary key ("test")'
);
});
it('call on table with columns and name', function () {
tableSql = client
.schemaBuilder()
.alterTable('users', function (t) {
t.primary(['test1', 'test2'], 'testconstraintname');
})
.toSQL();
equal(1, tableSql.length);
expect(tableSql[0].sql).to.equal(
'alter table "users" add constraint "testconstraintname" primary key ("test1", "test2")'
);
});
});
describe('queryContext', function () {
let spy;
let originalWrapIdentifier;