Skip to content

Commit

Permalink
feat: integer types (mostly mysql specific) (#281)
Browse files Browse the repository at this point in the history
  • Loading branch information
cyjake authored Feb 24, 2022
1 parent cb308ae commit 478462d
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 10 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const connect = async function connect(opts) {
return realm;
};

Object.assign(Realm.prototype, migrations, { DataTypes });
Object.assign(Realm.prototype, migrations);
Object.assign(Realm, {
connect,
Bone,
Expand Down
64 changes: 61 additions & 3 deletions src/data_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ const Raw = require('./raw');

class DataType {
static findType(columnType) {
const { STRING, TEXT, DATE, DATEONLY, INTEGER, BIGINT, BOOLEAN, BINARY, VARBINARY, BLOB } = this;
const {
STRING, TEXT,
DATE, DATEONLY,
TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT,
BOOLEAN,
BINARY, VARBINARY, BLOB,
} = this;
const [ , dataType, appendix ] = columnType.match(/(\w+)(?:\((\d+)\))?/);
const length = appendix && parseInt(appendix, 10);

Expand All @@ -39,10 +45,13 @@ class DataType {
case 'int':
case 'integer':
case 'numeric':
return new INTEGER(length);
case 'mediumint':
return new MEDIUMINT(length);
case 'smallint':
return new SMALLINT(length);
case 'tinyint':
return new INTEGER(length);
return new TINYINT(length);
case 'bigint':
return new BIGINT(length);
case 'boolean':
Expand Down Expand Up @@ -203,12 +212,58 @@ class INTEGER extends DataType {
}
}

/**
* 8 bit integer
* @example
* TINYINT
* TINYINT.UNSIGNED
* TINYINT(1)
* @param {number} length
*/
class TINYINT extends INTEGER {
constructor(length) {
super(length);
this.dataType = 'tinyint';
}
}

/**
* 16 bit integer
* @example
* SMALLINT
* SMALLINT.UNSIGNED
* SMALLINT(2)
* @param {number} length
*/
class SMALLINT extends INTEGER {
constructor(length) {
super(length);
this.dataType = 'smallint';
}
}

/**
* 24 bit integer
* @example
* MEDIUMINT
* MEDIUMINT.UNSIGNED
* MEDIUMINT(3)
* @param {number} length
*/
class MEDIUMINT extends INTEGER {
constructor(length) {
super(length);
this.dataType = 'mediumint';
}
}


/**
* 64 bit integer
* @example
* BIGINT
* BIGINT.UNSIGNED
* BIGINT(10)
* BIGINT(8)
* @param {number} length
*/
class BIGINT extends INTEGER {
Expand Down Expand Up @@ -422,6 +477,9 @@ class JSONB extends JSON {

const DataTypes = {
STRING,
TINYINT,
SMALLINT,
MEDIUMINT,
INTEGER,
BIGINT,
DATE,
Expand Down
8 changes: 8 additions & 0 deletions src/drivers/abstract/attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ function createType(DataTypes, params) {
switch (type.constructor.name) {
case 'DATE':
return new DataType(type.precision, type.timezone);
case 'TINYINT':
case 'SMALLINT':
case 'MEDIUMINT':
case 'INTEGER':
case 'BIGINT':
case 'BINARY':
case 'VARBINARY':
return new DataType(type.length);
default:
return new DataType();
}
Expand Down
10 changes: 10 additions & 0 deletions src/drivers/postgres/data_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,22 @@ class Postgres_BIGINT extends Postgres_INTEGER {
}
}

class Postgres_SMALLINT extends Postgres_INTEGER {
constructor() {
super();
this.dataType = 'smallint';
}
}

class Postgres_DataTypes extends DataTypes {
static DATE = Postgres_DATE;
static JSONB = Postgres_JSONB;
static BINARY = Postgres_BINARY;
static VARBINARY = Postgres_BINARY;
static BLOB = Postgres_BINARY;
static TINYINT = Postgres_SMALLINT;
static SMALLINT = Postgres_SMALLINT;
static MEDIUMINT = Postgres_INTEGER;
static INTEGER = Postgres_INTEGER;
static BIGINT = Postgres_BIGINT;
}
Expand Down
5 changes: 5 additions & 0 deletions src/realm.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ class Realm {
this.options = Spine.options = options;
}

get DataTypes() {
if (!this.driver) throw new Error('database not connected yet');
return this.driver.DataTypes;
}

define(name, attributes, opts = {}, descriptors = {}) {
const Model = class extends this.Bone {
static name = name;
Expand Down
22 changes: 21 additions & 1 deletion test/unit/bone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ const assert = require('assert').strict;
const { Bone, DataTypes, connect } = require('../..');
const expect = require('expect.js');

const { BIGINT, STRING, DATE } = DataTypes;
const {
TINYINT, MEDIUMINT, BIGINT,
STRING,
DATE,
} = DataTypes;

describe('=> Bone', function() {
before(async function() {
Expand Down Expand Up @@ -312,4 +316,20 @@ describe('=> Bone', function() {
expect(note.updatedAt).to.be.a(Date);
});
});

describe('=> Bone.sync()', function() {
it('should allow specific types such as TINYINT', async function() {
class Note extends Bone {
static attributes = {
isPrivate: TINYINT(1),
wordCount: MEDIUMINT,
}
}
await Note.sync({ force: true });
const result = await Note.describe();
assert.equal(result.is_private.columnType, 'tinyint(1)');
// MySQL 5.x returns column type with length regardless specified or not
assert.ok(result.word_count.columnType.startsWith('mediumint'));
});
});
});
41 changes: 37 additions & 4 deletions test/unit/data_types.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ const Raw = require('../../src/raw');
const Postgres_DataTypes = require('../../src/drivers/postgres/data_types');
const SQLite_DataTypes = require('../../src/drivers/sqlite/data_types');



describe('=> Data Types', () => {
const {
STRING, BOOLEAN, DATE, DATEONLY, INTEGER, BIGINT, TEXT, JSON, JSONB, BLOB, BINARY, VARBINARY,
STRING, TEXT,
BOOLEAN,
DATE, DATEONLY,
TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT,
JSON, JSONB,
BLOB, BINARY, VARBINARY,
} = DataTypes;

it('STRING', () => {
Expand Down Expand Up @@ -41,6 +44,27 @@ describe('=> Data Types', () => {
assert.equal(new DATEONLY().toSqlString(), 'DATE');
});

it('TINYINT', () => {
assert.equal(new TINYINT().dataType, 'tinyint');
assert.equal(new TINYINT(1).toSqlString(), 'TINYINT(1)');
assert.equal(new TINYINT().UNSIGNED.toSqlString(), 'TINYINT UNSIGNED');
assert.equal(new TINYINT().UNSIGNED.ZEROFILL.toSqlString(), 'TINYINT UNSIGNED ZEROFILL');
});

it('SMALLINT', () => {
assert.equal(new SMALLINT().dataType, 'smallint');
assert.equal(new SMALLINT(1).toSqlString(), 'SMALLINT(1)');
assert.equal(new SMALLINT().UNSIGNED.toSqlString(), 'SMALLINT UNSIGNED');
assert.equal(new SMALLINT().UNSIGNED.ZEROFILL.toSqlString(), 'SMALLINT UNSIGNED ZEROFILL');
});

it('MEDIUMINT', () => {
assert.equal(new MEDIUMINT().dataType, 'mediumint');
assert.equal(new MEDIUMINT(1).toSqlString(), 'MEDIUMINT(1)');
assert.equal(new MEDIUMINT().UNSIGNED.toSqlString(), 'MEDIUMINT UNSIGNED');
assert.equal(new MEDIUMINT().UNSIGNED.ZEROFILL.toSqlString(), 'MEDIUMINT UNSIGNED ZEROFILL');
});

it('INTEGER', () => {
assert.equal(new INTEGER().dataType, 'integer');
assert.equal(new INTEGER(10).toSqlString(), 'INTEGER(10)');
Expand Down Expand Up @@ -103,7 +127,7 @@ describe('=> DataTypes type casting', function() {
await assert.rejects(async () => {
new INTEGER().uncast('yes?');
}, /Error: invalid integer: yes?/);

assert.equal(new INTEGER().uncast('yes?', false), 'yes?');

});
Expand Down Expand Up @@ -240,6 +264,15 @@ describe('=> DataTypes.findType()', () => {
assert.equal(DataTypes.findType('mediumblob').toSqlString(), 'MEDIUMBLOB');
});

it('integer => INTEGER', () => {
const { TINYINT, SMALLINT, MEDIUMINT, INTEGER } = DataTypes;
assert.ok(DataTypes.findType('tinyint') instanceof TINYINT);
assert.ok(DataTypes.findType('smallint') instanceof SMALLINT);
assert.ok(DataTypes.findType('mediumint') instanceof MEDIUMINT);
assert.ok(DataTypes.findType('integer') instanceof INTEGER);
assert.equal(DataTypes.findType('bigint').toSqlString(), 'BIGINT');
});

it('unknown type', async () => {
await assert.rejects(async () => DataTypes.findType('error'), /Unexpected data type error/);
});
Expand Down
13 changes: 12 additions & 1 deletion test/unit/drivers/postgres/data_types.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ const DataTypes = require('../../../../src/drivers/postgres/data_types');

describe('=> Data Types', () => {
const {
STRING, DATE, JSONB, VARBINARY, BINARY, BLOB
STRING,
DATE,
JSONB,
VARBINARY, BINARY, BLOB,
TINYINT, SMALLINT, MEDIUMINT, INTEGER,
} = DataTypes;

it('STRING', () => {
Expand Down Expand Up @@ -35,5 +39,12 @@ describe('=> Data Types', () => {
assert.equal(new JSONB().dataType, 'jsonb');
assert.equal(new JSONB().toSqlString(), 'JSONB');
});

it('INTEGER', () => {
assert.equal(new TINYINT().toSqlString(), 'SMALLINT');
assert.equal(new SMALLINT().toSqlString(), 'SMALLINT');
assert.equal(new MEDIUMINT().toSqlString(), 'INTEGER');
assert.equal(new INTEGER().toSqlString(), 'INTEGER');
});
});

0 comments on commit 478462d

Please sign in to comment.