データ型の拡張
実装しようとしている型は、ほとんどの場合、DataTypes に含まれています。もし新しいデータ型が含まれていない場合は、このマニュアルで自分で作成する方法を説明します。
Sequelizeはデータベースに新しいデータ型を作成しません。このチュートリアルでは、Sequelizeに新しいデータ型を認識させる方法を説明し、それらの新しいデータ型がすでにデータベースに作成されていることを前提としています。
Sequelizeのデータ型を拡張するには、Sequelizeインスタンスを作成する前に行ってください。
例
この例では、組み込みのデータ型 DataTypes.INTEGER(11).ZEROFILL.UNSIGNED
を複製する SOMETYPE
という型を作成します。
const { Sequelize, DataTypes, Utils } = require('Sequelize');
createTheNewDataType();
const sequelize = new Sequelize('sqlite::memory:');
function createTheNewDataType() {
class SOMETYPE extends DataTypes.ABSTRACT {
// Mandatory: complete definition of the new type in the database
toSql() {
return 'INTEGER(11) UNSIGNED ZEROFILL';
}
// Optional: validator function
validate(value, options) {
return typeof value === 'number' && !Number.isNaN(value);
}
// Optional: sanitizer
_sanitize(value) {
// Force all numbers to be positive
return value < 0 ? 0 : Math.round(value);
}
// Optional: value stringifier before sending to database
_stringify(value) {
return value.toString();
}
// Optional: parser for values received from the database
static parse(value) {
return Number.parseInt(value);
}
}
// Mandatory: set the type key
SOMETYPE.prototype.key = SOMETYPE.key = 'SOMETYPE';
// Mandatory: add the new type to DataTypes. Optionally wrap it on `Utils.classToInvokable` to
// be able to use this datatype directly without having to call `new` on it.
DataTypes.SOMETYPE = Utils.classToInvokable(SOMETYPE);
// Optional: disable escaping after stringifier. Do this at your own risk, since this opens opportunity for SQL injections.
// DataTypes.SOMETYPE.escape = false;
}
この新しいデータ型を作成したら、各データベースダイアレクトでこのデータ型をマッピングし、いくつかの調整を行う必要があります。
PostgreSQL
新しいデータ型の名前がPostgresデータベースで pg_new_type
であると仮定しましょう。その名前は DataTypes.SOMETYPE
にマッピングする必要があります。さらに、Postgres固有の子データ型を作成する必要があります。
function createTheNewDataType() {
// [...]
const PgTypes = DataTypes.postgres;
// Mandatory: map postgres datatype name
DataTypes.SOMETYPE.types.postgres = ['pg_new_type'];
// Mandatory: create a postgres-specific child datatype with its own parse
// method. The parser will be dynamically mapped to the OID of pg_new_type.
PgTypes.SOMETYPE = function SOMETYPE() {
if (!(this instanceof PgTypes.SOMETYPE)) {
return new PgTypes.SOMETYPE();
}
DataTypes.SOMETYPE.apply(this, arguments);
}
const util = require('util'); // Built-in Node package
util.inherits(PgTypes.SOMETYPE, DataTypes.SOMETYPE);
// Mandatory: create, override or reassign a postgres-specific parser
// PgTypes.SOMETYPE.parse = value => value;
PgTypes.SOMETYPE.parse = DataTypes.SOMETYPE.parse || x => x;
// Optional: add or override methods of the postgres-specific datatype
// like toSql, escape, validate, _stringify, _sanitize...
}
範囲型
新しい範囲型がPostgresで定義された後、それをSequelizeに追加するのは簡単です。
この例では、Postgresの範囲型の名前は SOMETYPE_range
で、Postgresの基礎となるデータ型の名前は pg_new_type
です。 subtypes
と castTypes
のキーは、Sequelizeのデータ型 DataTypes.SOMETYPE.key
のキー(小文字)です。
function createTheNewDataType() {
// [...]
// Add postgresql range, SOMETYPE comes from DataType.SOMETYPE.key in lower case
DataTypes.RANGE.types.postgres.subtypes.SOMETYPE = 'SOMETYPE_range';
DataTypes.RANGE.types.postgres.castTypes.SOMETYPE = 'pg_new_type';
}
新しい範囲型は、モデル定義で DataTypes.RANGE(DataTypes.SOMETYPE)
または DataTypes.RANGE(DataTypes.SOMETYPE)
として使用できます。