Reputation: 229
I have a custom type in Postgres that I want to use in Sequelize. I've written code based on the example in the Sequelize docs, except for call to a function ("inherits") which I can't find in Sequelize or elsewhere. However, using sequelize.define to create a model with an attribute of this custom type throws an exception inside Sequelize. Is there an error in my code that stands out? Or is there another good example or tutorial for implementing a custom datatype? Also, what's up with the "inherits" function shown in the doc example -- are the docs leaving out an import/requires, or is that call erroneous?
Docs I'm following are here: http://docs.sequelizejs.com/manual/data-types.html#extending-datatypes
The type as defined in Postgres:
CREATE TYPE public.measurement AS
(
unit text,
value double precision
);
My test code in NodeJS:
const Sequelize = require('sequelize');
let dataTypes = Sequelize.DataTypes;
// Create class for custom datatype
class MEASUREMENT extends dataTypes.ABSTRACT {
toSql() {
console.log('MEASUREMENT toSql');
return 'MEASUREMENT';
}
static parse(value) {
console.log('MEASUREMENT parse value=', value);
return value;
}
};
// Set key
MEASUREMENT.prototype.key = 'MEASUREMENT';
MEASUREMENT.key = MEASUREMENT.prototype.key;
// Add to DataTypes
dataTypes.MEASUREMENT = MEASUREMENT;
// Add to Sequelize
Sequelize.MEASUREMENT = Sequelize.Utils.classToInvokable(MEASUREMENT);
let pgTypes = dataTypes.postgres;
// Map dialects
dataTypes.MEASUREMENT.types.postgres = ['MEASUREMENT']
pgTypes.MEASUREMENT = function MEASUREMENT() {
if (!(this instanceof pgTypes.MEASUREMENT)) return new pgTypes.MEASUREMENT();
DataTypes.MEASUREMENT.apply(this, arguments);
}
// inherits(pgTypes.MEASUREMENT, dataTypes.MEASUREMENT);
// Node throws a parse error. This is in the example in the Sequelize docs, however.
pgTypes.MEASUREMENT.parse = dataTypes.MEASUREMENT.parse;
// ------------------------------
const sequelize = new Sequelize('test', 'test', 'test', {
host: 'localhost',
dialect: 'postgres'
});
const Thing = sequelize.define('thing', {
name: Sequelize.STRING,
weight: Sequelize.MEASUREMENT
});
Call stack when run:
C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:48
if (dataType.types[this.dialectName]) {
^
TypeError: Cannot read property 'postgres' of undefined
at _.each.dataType (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:48:27)
at C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:4911:15
at baseForOwn (C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:2996:24)
at C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:4880:18
at Function.forEach (C:\Workspaces\nebula\server\node_modules\lodash\lodash.js:9344:14)
at ConnectionManager.refreshTypeParser (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\abstract\connection-manager.js:46:7)
at new ConnectionManager (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\postgres\connection-manager.js:23:10)
at new PostgresDialect (C:\Workspaces\nebula\server\node_modules\sequelize\lib\dialects\postgres\index.js:14:30)
at new Sequelize (C:\Workspaces\nebula\server\node_modules\sequelize\lib\sequelize.js:320:20)
at Object.<anonymous> (C:\Workspaces\nebula\server\testsequelizecustom.js:58:19)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
at startup (internal/bootstrap/node.js:279:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:752:3)
Upvotes: 8
Views: 1271
Reputation: 1111
To fix the error, we need to cause the property postgres
on the object dataType.types
to be defined.
Just under the line you already have:
pgTypes.MEASUREMENT.parse = dataTypes.MEASUREMENT.parse;
Add the following line, and the error should go away:
pgTypes.MEASUREMENT.types = {postgres:[‘MEASUREMENT’]};
You'll probably also need to add this line, to handle a related error (see below).
dataTypes.postgres.MEASUREMENT.key = ‘MEASUREMENT’;
The related error:
[...]/node_modules/sequelize/lib/dialects/postgres/connection-manager.js:36
if (dataType.key.toLowerCase() === 'range') {
^
TypeError: Cannot read property 'toLowerCase' of undefined
Upvotes: 5