sequelize: Custom datatype not working
What are you doing?
// Custom Type File
import Big from "big.js";
export default function sequelizeAdditions(Sequelize) {
const DataTypes = Sequelize.DataTypes;
/*
* Create new types
*/
class BIGJS extends DataTypes.DECIMAL {
public static parse(value) {
return new Big(value);
}
private _precision: number;
private _scale: number;
constructor(precision: number, scale: number) {
super();
this._precision = precision;
this._scale = scale;
}
public toSql() {
if (this._precision || this._scale) {
return `DECIMAL(${[this._precision, this._scale].filter(this.identity).join(",")})`;
}
return "DECIMAL";
}
// Optional, validator function
public validate(value, options) {
if (value instanceof Big) {
return true;
} else {
return false;
}
}
}
DataTypes.BIGJS = BIGJS;
// Mandatory, set key
DataTypes.BIGJS.prototype.key = DataTypes.BIGJS.key = "BIGJS";
// For convenience
// `classToInvokable` allows you to use the datatype without `new`
Sequelize.BIGJS = Sequelize.Utils.classToInvokable(DataTypes.BIGJS);
}
// Connection File
import { Sequelize } from "sequelize";
import BigJsCol from "./types/BigJsColumn";
BigJsCol(Sequelize);
const sequelize = new Sequelize(...);
// Model File
MyModel.init({
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
amount: new DataTypes.BIGJS(13, 4)
}, {
sequelize: Connection,
tableName: "MyModel",
});
// Simple Query
await MyModel.findAll();
To Reproduce Steps to reproduce the behavior:
- Defined models, and get everything wired up
- Run simple query
- Result for the field amount is not wrapped in a BigJs object
What do you expect to happen?
I would like the result coming back from the database to be wrapped
What is actually happening?
It is just returning a number đŚ
Environment
Dialect:
- mysql
- postgres
- sqlite
- mssql
- any Dialect mysql2 version: 1.6.5 Database version: 5.7.26 Sequelize version: 5.9.3 Node Version: 12.x OS: Mac OS 10.14.5 If TypeScript related: TypeScript version: 3.5.3 Tested with latest release:
- No
- Yes, specify that version:
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 5
- Comments: 32 (18 by maintainers)
The issue lays with
classToInvokable
, which doesnât allow access to the actual constructor. The following code shows how we worked around that:This issue has been automatically marked as stale because it has been open for 14 days without activity. It will be closed if no further activity occurs within the next 14 days. If this is still an issue, just leave a comment or remove the âstaleâ label. đ
This is a snippet of code that shows how I was able to add the ltree extension as a custom datatype using the workaround of @mcuelenaere
`
So could anyone please update the documentations to reflect the correct way to implement custom datatypes?
I will try to figure this out đ
I seem to be stuck on creating custom DataTypes in v5 as well. It never seems to call the
toSql()
when actually running queries. So instead of trying to execute (CREATE TABLE
)'id' BIGINT(20) UNSIGNED NOT NULL auto_increment
itâs trying to do'id' OBFUSCATEDID NOT NULL auto_increment
which obviously doesnât work.This works perfect for me, Thank you soo much
@sm2017 as mentioned by @ktret overriding the
key
propperty seems to work at least for the created sql statements, I implemented it like this:but as he mentioned it is not a solid workaround, since it fails for
instanceof
checks. Other overrides like_stringify()
andparse()
are also never called, so it seems like this feature is completely screwed right now.RE: It never seems to call the toSql() when actually running queries.
More-so it seems to call ABSTRACTâs toSql. My new data type extends ABSTRACT, and ABSTRACTâs toSql is
return this.key
so if when I manage to set key to the postgres type, it creates the column in the database fine. But an instancex
of said type for a field does not passx instanceof NEWTYPE
check. Sorry, probably not making much sense, and no time to provide code right now.Anyway, if you can make your key be âBIGINT(20) UNSIGNEDâ or whatever you want the database to get, it might create the column fine, but you may still have issues if you check instanceof and such.
@papb Oh nice, Iâll take a look at those then. If I can get something working, maybe it can serve as a good example.
@moberegger It should be, I believe, although the docs really need fixing. I will hopefully be able to take a look soon. If you could dig a bit and find out how to do it, that would be awesome⌠But if you donât have the time, I shall do it in the near future.
Taking a peak at your reproduction, I think the steps from https://sequelize.org/master/manual/data-types.html#postgresql are missing, where it says:
It is hard to make sense of that example, though. The example given is for Postgres, so itâs not clear what is required for other dialects (they all seem to have types assigned slightly differently in the source). Furthermore, it uses an
inherits
API which isnât available anywhere (I think it used to be part ofutils
in V4).Another issue (https://github.com/sequelize/sequelize/issues/10964) was posted where the author was having the same problem.
Is this feature fully supported?
I added a little sample project in this repo: https://github.com/Bene-Graham/SequelizeCustomColumnTypeBug
Couple of things I have noticed:
.sync()
does not work with custom types it puts the wrong DB type in the create table statementEdit: To switch between dialects just comment / uncomment the import in connectionToggle.ts