Skip to content

Commit

Permalink
fix: resolves Postgres sequence identifier length error (#7115)
Browse files Browse the repository at this point in the history
Changes the sequence name generator to handle cases where PostgreSQL auto-generated sequence name differed from TypeORM generated sequence name.

Closes: #7106
  • Loading branch information
matthewberryman committed Jan 12, 2021
1 parent bcd998b commit 568ef35
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/driver/postgres/PostgresQueryRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,11 +2075,14 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
tableName = table.name.split(".")[1];
}

let seqName = `${tableName}_${columnName}_seq`;
if (seqName.length > this.connection.driver.maxAliasLength!) // note doesn't yet handle corner cases where .length differs from number of UTF-8 bytes
seqName=`${tableName.substring(0,29)}_${columnName.substring(0,Math.max(29,63-tableName.length-5))}_seq`;

if (schema && schema !== currentSchema && !skipSchema) {
return disableEscape ? `${schema}.${tableName}_${columnName}_seq` : `"${schema}"."${tableName}_${columnName}_seq"`;

return disableEscape ? `${schema}.${seqName}` : `"${schema}"."${seqName}"`;
} else {
return disableEscape ? `${tableName}_${columnName}_seq` : `"${tableName}_${columnName}_seq"`;
return disableEscape ? `${seqName}` : `"${seqName}"`;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {Column, Entity, Generated } from "../../../../src";

@Entity()
export class ReallyReallyVeryVeryVeryLongTableName {
@PrimaryGeneratedColumn() // typeORM requires a pkey
PrimaryGeneratedColumnIDBlahBlahBlahThisIsReallyLong: number;

@Column()
Name: string;

@Column() @Generated("increment")
MyNumber: number;


}

15 changes: 15 additions & 0 deletions test/github-issues/7106/entity/ShortTableName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {Column, Entity } from "../../../../src";

@Entity()
export class ShortTableName {
@PrimaryGeneratedColumn() // typeORM requires a pkey
PrimaryGeneratedColumnIDBlahBlahBlahThisIsReallyLong: number;

@Column()
Name: string;

@Column()
Value: number;
}

41 changes: 41 additions & 0 deletions test/github-issues/7106/issue-7106.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import "reflect-metadata";
import {expect} from "chai";
import {Connection} from "../../../src/connection/Connection";
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
import { ShortTableName } from "./entity/ShortTableName";
import { ReallyReallyVeryVeryVeryLongTableName } from "./entity/ReallyReallyVeryVeryVeryLongTableName";
import { QueryFailedError } from "../../../src/error/QueryFailedError";


/**
* @see https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
* "The system uses no more than NAMEDATALEN-1 bytes of an identifier; longer names can be
* written in commands, but they will be truncated. By default, NAMEDATALEN is 64 so the
* maximum identifier length is 63 bytes. If this limit is problematic, it can be raised
* by changing the NAMEDATALEN constant in src/include/pg_config_manual.h."
*/
describe("github issues > #7106 shorten sequence names (for RDBMS with a limit) when they are longer than 63 characters", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["postgres"]
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));

it("should be able to work with long sequence name with short table name", () => Promise.all(connections.map(async (connection) => {
const short = new ShortTableName();
short.Name = "Dharawal";
short.Value = 2500;
await connection.getRepository(ShortTableName).save(short);
return expect(connection.synchronize()).to.not.be.rejectedWith(QueryFailedError);
})));

it("should be able to work with long sequence name with long table name", () => Promise.all(connections.map(async (connection) => {
const long = new ReallyReallyVeryVeryVeryLongTableName();
long.Name = "Eora";
await connection.getRepository(ReallyReallyVeryVeryVeryLongTableName).save(long);
return expect(connection.synchronize()).to.not.be.rejectedWith(QueryFailedError);
})));

});

0 comments on commit 568ef35

Please sign in to comment.