sequelize / sequelize/sequelize
BelongsToMany Instance.add{$plural} sourceKey get() used, but set() on join table not
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 30.4k
- Forks
- 4.3k
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 68
Description
BelongsToMany association doesn't use custom set on sourceKey field.
I have custom set() and get() on my primary key on a message model. I'm using ulid on a BINARY(16) field. In my API I'm using the canonical form, e.g. '01DNBHWZZ9CMW7MW5Z9NHFNTNF'.
This works fine in and of itself, but as soon as I begin creating associations, the get is fired to get the association key, but the set is not when saving into the association table, or into a foreignKey field, etc.
getUlid and setUlid are functions for converting between binary and hex, and vice versa (UlidMonotonic is imported from npm package id128).
function getUlid( this: any ) {
// outcoming Buffer -> canonical
let ulidMonotonic = UlidMonotonic.construct( this.getDataValue('ulid') )
return ulidMonotonic.toCanonical()
}
function setUlid( this: any, value: Buffer ) {
//incoming canonical --> Buffer
let ulidBuffer = UlidMonotonic.fromCanonical( value )
this.setDataValue('ulid', Buffer.from(ulidBuffer.bytes))
}
Message table:
Message.init({
ulid: {
type: 'BINARY(16)'
, primaryKey: true
, get: getUlid
, set: setUlid
}
, message: {
type: DataTypes.STRING(191).BINARY
, allowNull: false
}
}
, {
sequelize
, tableName
}
)
Message.belongsToMany(User, { as: "receivers", through: "messageReceivers" })
Association table:
MessageReceiver.init({
ulid: {
type: 'BINARY(16)'
, primaryKey: true
}
, messageUlid: {
type: 'BINARY(16)'
, references: {
model: Message
, key: 'ulid'
}
, get: getUlid
, set: setUlid
}
, userUlid: {
type: 'BINARY(16)'
, references: {
model: User
, key: 'ulid'
}
}
}
, {
sequelize
, tableName
}
)
Cut down version of User:
User.init(
{
ulid: {
type: 'BINARY(16)'
, primaryKey: true
}
, firstName: { type: new DataTypes.STRING(32).BINARY, allowNull: false }
, lastName: { type: new DataTypes.STRING(32).BINARY, allowNull: false }
, role: { type: new DataTypes.STRING(32).BINARY, allowNull: false }
}
, {
sequelize
, tableName
}
)
I expect that .addReceivers([user1, user2]) should use the defined set() method on the messageUlid field to store the ulid in binary form on the association table.
Instead, this error occurs because it's trying to insert a 26 character string into a 16 byte binary field.
sqlMessage: "Data too long for column 'MessageUlid' at row 1",
sql: "INSERT INTO 'messageReceivers' ('createdAt','updatedAt','MessageUlid','UserUlid') VALUES ('2019-09-22 03:58:28','2019-09-22 03:58:28','01DNBHWZZ9CMW7MW5Z9 NHFNTNF',X'016d571e7fe96548b85ff5c30820765d'),('2019-09-22 03:58:28','2019-09-22 03:58:28','01DNBHWZZ9CMW7MW5Z9NHFNTNF',X'016d571e7fe96545959960e350c63e05');"
Environment
- Sequelize version: 5.15.0
- Node.js version: v12.6.0
- Operating System: Archlinux
Issue Template Checklist
How does this problem relate to dialects?
- I think this problem happens regardless of the dialect.
- I think this problem happens only for the following dialect(s):
- I don't know, I was using
mariadb, with connector library version XXX and database version XXX
Would you be 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the BelongsToMany instance add{$plural} path exercised by .addReceivers([user1, user2]) and trace how sourceKey values are written to the association table. Reproduce the binary(16) ULID case with the shown custom getUlid and setUlid methods; done means the association insert invokes the setter and stores the binary value rather than the 26-character string.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- mariadb, node.js, typescript
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100