sequelize: defaultValue: Sequelize.UUIDV4 is not setting a default value on column in postgres
What you are doing?
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Test", {
id: {
allowNull: false,
autoIncrement: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
},
name: {
type: Sequelize.TEXT,
defaultValue: "123",
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Test");
},
};
Checking the default column value with:
SELECT column_name, column_default
FROM information_schema.columns
WHERE (table_schema, table_name) = ('public', 'Currencies')
ORDER BY ordinal_position;
Gives me:
column_name | column_default |
---|---|
id | (NULL) |
name | ‘123’::text |
What do you expect to happen?
default to be uuid_generate_v4()
or gen_random_uuid()
What is actually happening?
default is (NULL)
Dialect: postgres Database version: 13.2 Sequelize CLI version: 6.2.0 Sequelize version: 6.2.2
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 20 (7 by maintainers)
Summary of the solution here, to bump it up in search results for using an auto-generated UUID as a primary key in Postgres. For example, for an entity called Product, create your migration like this:
Then, create your model like this:
now when you create a new instance of Product, you only need the
productName
field. The UUID is auto-generated by the Sequelize model.The id field in the model will trace the defaultValue setting back to the https://www.npmjs.com/package/uuid package that Sequelize relies on. As @Spekpannenkoek and @ephys have pointed out, Sequelize relies on that package to auto-generate the UUID as part of the model operation, not as part of native Postgres.
The other option in the case of Postgres specifically, would be to use its native uuid_generate_v4() function. The only issue there is, that function is not part of core Postgres, and thus is not loaded automatically in a default install of Postgres. You’d need to run this on your PostgreSQL instance first:
This may or may not be possible, depending on what level of access you have to your DB. Thus, IMHO it’s best to keep the NPM uuid dependency, even if the native Postgres UUID option gets added. Maybe a config like this could be added?
@SimonHausdorf I was facing same issue and tried this in a migration file
queryInterface.createTable(‘users’, { id: { type: Sequelize.UUID, defaultValue: Sequelize.literal(‘gen_random_uuid()’), // postgres will generate UUID by default I’m using version 15.1 primaryKey: true, }, });
I still want to add
DataTypes.UUIDV4.NATIVE
but in the meantime I’ve documented how to useuuid_generate_v4
in the new documentation (not yet released):Of the three types of
defaultValues
(“A literal default value, a JavaScript function, or an SQL function”), in this case you’re passing a JavaScript function. Short of implementing PLv8, Sequelize has to generate the default value on the client side (your app) rather than in the database.You ought to still get a default value when you insert a new record, just not one generated by your database & its definition would not be visible in the db schema.
While I haven’t tried it, I think you should be able to achieve what you want by setting a SQL function:
defaultValue: sequelize.fn('uuid_generate_v4')
.I don’t think that there is an implementation for the migration to set UUID as default in the database? I could not find anything about
uuid_generate_v4()
orgen_random_uuid()
in the code? As it looks like, it can only be used in the model which then is generating a UUID.defaultValue: DataTypes.UUIDV4
ordefaultValue: Sequelize.UUIDV4
does not work for migrations. I think it should be possible to set the default type inside the migration as well?@SimonHausdorf I’ve found the same issue but checking the source code I’ve found that perhaps the docs are incorrect. Instead of
Sequelize.UUIDV4
, it should beDataTypes.UUIDV4
. Moreover, checking from the Typescript declaration files, it’s also pointing toDataTypes.UUIDV4
. All of them bring me to the conclusion that the documentation is misled.Refs: https://github.com/sequelize/sequelize/blob/9f950cbcbdd659d559496b77c40e0f827b108561/test/unit/utils.test.js#L45 https://github.com/sequelize/sequelize/blob/9f950cbcbdd659d559496b77c40e0f827b108561/test/integration/instance/increment.test.js#L27 https://github.com/sequelize/sequelize/blob/9f950cbcbdd659d559496b77c40e0f827b108561/types/lib/data-types.d.ts#L451
Not sure I can add anything more. If you want to use a defaultValue for UUID in migrations, you need to use the native SQL function (shown how above and here), otherwise you’ll need to manually set a value in JS
Well, probably not the best implementation, but i kinda solved this problem using
beforeCreate
hook in my sequelize model and getting UUID with crypto, like this:In Sequelize 7, you can now use
sql.uuidV1
andsql.uuidV4
. They set the default value on the database when possible, and fallback to JavaScript the rest of the time:https://sequelize.org/docs/v7/models/data-types/#built-in-default-values-for-uuid
Hi 👋 I solved the same problem with Sequelize v16.9.1 and PostgreSQL v12 using the
uuid-ossp
extension and set theuuid_generate_v4
function as default value in the migration file and in the model withSequelize.literal
Ex:
DBeaver screenshots:
only on migration file you need not using (all the 3 options not working):
you need to remove this defaultValue from migration file only and if you are create rows on migration file then manually determine uuid value. for example:
import {v1 as uuidv1} from ‘uuid’; await query.bulkInsert({ tableName: ‘user’, schema }, [ {id: uuidv1(), name: “tom” }, {id: uuidv1(), name: “gil” }, ]);
This issue has been automatically marked as stale because it has been open for 7 days without activity. It will be closed if no further activity occurs. If this is still an issue, just leave a comment or remove the “stale” label. 🙂