typeorm: @Column({ type: "uuid" }) should be varchar(36) on MySQL instead of varchar(255)

Feature Description

In MySQL, we use varchar(36) by default for UUID primary key columns (see here: https://github.com/typeorm/typeorm/blob/c5143aab08a04e96aebb55996ed7683d48542bbd/src/driver/mysql/MysqlDriver.ts#L631).

The Problem

When I create a uuid column with @Column({ type: "uuid" }) it’s using varchar(255)

The Solution

I’ve dealt with this for now by using @Column({ type: "uuid", length: 36 }) but it seems like a simple change to make 36 the default length for uuid columns. If I threw up a PR for that, would anybody object?

Relevant Database Driver(s)

  • aurora-data-api
  • aurora-data-api-pg
  • better-sqlite3
  • cockroachdb
  • cordova
  • expo
  • mongodb
  • mysql
  • nativescript
  • oracle
  • postgres
  • react-native
  • sap
  • sqlite
  • sqlite-abstract
  • sqljs
  • sqlserver

Are you willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time, and I know how to start.
  • Yes, I have the time, but I don’t know how to start. I would need guidance.
  • No, I don’t have the time, although I believe I could do it if I had the time…
  • No, I don’t have the time and I wouldn’t even know how to start.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Comments: 21 (4 by maintainers)

Most upvoted comments

What are we to do if we have a production workload using uuid as char(36)? Would you accept a PR for uuid-char? Migrating to varchar doesn’t make sense to us and we want to benefit from the latest fixes.

Here’s a workaround to bring back char, for the brave among us. Don’t use this outside of migration code.

export default config.then((c) => {
  const dataSource = new DataSource(c);
  const driver = dataSource.driver as unknown as
    | typeof dataSource.driver
    & { oldNormalizeType: typeof dataSource.driver.normalizeType };
  driver.oldNormalizeType = driver.normalizeType;
  driver.normalizeType = (column: {
    type: ColumnType;
    length?: number | string;
    precision?: number | null;
    scale?: number;
  }): string => {
    if (column.type === 'uuid') {
      column.length = 36;
      return 'char';
    }
    return driver.oldNormalizeType(column);
  };

  return dataSource;
});

I have the same as @ArielPrevu3D, maybe an idea to change this behavior in typeorm config?

this is serious breaking change, it directly affects our production database after syncing. Previously default for uuid is varchar(36) now you changed to char(36) without any backward compatibility, we synced, and all the columns with uuid are cleared

Yeah, an alter column would have been a preferable and less destructive change.

Still, it’s also a lot of noise during each migration generation, particularly if one were to want to leave the varchar(32) and not change the column type. Seems like both changes would be good to have. If you are amenable to a flag to allow varchar (old behavior), I can help with a PR. The advantage here is that even if folks are only using schema generation for something like testing, they can get still things to match up without having to migrate to the new column types. This is nice for folks that are trying to make minimal changes in production setups.

Migrating all primary keys in tables between types

This doesn’t affect primary keys. Just UUIDs.

My suggestion would be to write a migration that you would prefer instead of using the automatically generated one. The automatically generated ones err on the side of EXACTNESS which may or may not be correct.

Please feel free to open another issue if you believe something needs to be done differently.

What about char(36)? varchar means variable lenth character.