Skip to content

Commit

Permalink
fix: DataType.invokable.INTEGER.toString() = "INTEGER(1)" and type de…
Browse files Browse the repository at this point in the history
…finitions
  • Loading branch information
JimmyDaddy committed Apr 26, 2022
1 parent 8672e90 commit efd1eb0
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 48 deletions.
30 changes: 15 additions & 15 deletions src/data_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,20 @@ class DataType {
* STRING
* STRING(127)
* STRING.BINARY
* @param {number} length
* @param {number} dataLength
*/
class STRING extends DataType {
constructor(length = 255) {
super();
this.dataType = 'varchar';
this.length = length;
this.dataLength = length;
}

toSqlString() {
const { length } = this;
const { dataLength } = this;
const dataType = this.dataType.toUpperCase();
const chunks = [];
chunks.push(length > 0 ? `${dataType}(${length})` : dataType);
chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType);
return chunks.join(' ');
}

Expand All @@ -136,15 +136,15 @@ class STRING extends DataType {
class BINARY extends DataType {
constructor(length = 255) {
super();
this.length = length;
this.dataLength = length;
this.dataType = 'binary';
}

toSqlString() {
const { length } = this;
const { dataLength } = this;
const dataType = this.dataType.toUpperCase();
const chunks = [];
chunks.push(length > 0 ? `${dataType}(${length})` : dataType);
chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType);
return chunks.join(' ');
}

Expand All @@ -170,12 +170,12 @@ class VARBINARY extends BINARY {
* INTEGER.UNSIGNED
* INTEGER.UNSIGNED.ZEROFILL
* INTEGER(10)
* @param {number} length
* @param {number} dataLength
*/
class INTEGER extends DataType {
constructor(length) {
super();
this.length = length;
this.dataLength = length;
this.dataType = 'integer';
}

Expand All @@ -190,10 +190,10 @@ class INTEGER extends DataType {
}

toSqlString() {
const { length, unsigned, zerofill } = this;
const { dataLength, unsigned, zerofill } = this;
const dataType = this.dataType.toUpperCase();
const chunks = [];
chunks.push(length > 0 ? `${dataType}(${length})` : dataType);
chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType);
if (unsigned) chunks.push('UNSIGNED');
if (zerofill) chunks.push('ZEROFILL');
return chunks.join(' ');
Expand Down Expand Up @@ -442,11 +442,11 @@ class TEXT extends DataType {
}
super();
this.dataType = 'text';
this.length = length;
this.dataLength = length;
}

toSqlString() {
return [ this.length, this.dataType ].join('').toUpperCase();
return [ this.dataLength, this.dataType ].join('').toUpperCase();
}
}

Expand All @@ -457,11 +457,11 @@ class BLOB extends DataType {
}
super();
this.dataType = 'blob';
this.length = length;
this.dataLength = length;
}

toSqlString() {
return [ this.length, this.dataType ].join('').toUpperCase();
return [ this.dataLength, this.dataType ].join('').toUpperCase();
}

cast(value) {
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/abstract/attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function createType(DataTypes, params) {
case 'VARBINARY':
case 'CHAR':
case 'VARCHAR':
return new DataType(type.length);
return new DataType(type.dataLength);
default:
return new DataType();
}
Expand Down
3 changes: 3 additions & 0 deletions src/utils/invokable.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ function invokable(DataType) {

// INTEGER.UNSIGNED
get(target, p) {
// ref: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length
// Function.length = Function.arguments.length
// invokable INTEGER.toSqlString() will default to return "INTEGER(1)"
return target.hasOwnProperty(p) ? target[p] : new target()[p];
}
});
Expand Down
16 changes: 10 additions & 6 deletions test/types/custom_driver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,21 @@ describe('=> Realm (TypeScript)', function () {
});
});

afterEach(async () => {
await realm?.driver?.dropTable('test_user');
});

describe('realm.define(name, attributes, options, descriptors)', async function() {
it('options and descriptors should be optional', async function() {
assert.doesNotThrow(function() {
const { STRING } = realm.DataTypes;
realm.define('User', { name: STRING });
realm.define('TestUser', { name: STRING });
});
});

it('can customize attributes with descriptors', async function() {
const { STRING } = realm.DataTypes;
const User = realm.define('User', { name: STRING }, {}, {
const User = realm.define('TestUser', { name: STRING }, {}, {
get name() {
return this.attribute('name').replace(/^([a-z])/, function(m, chr) {
return chr.toUpperCase();
Expand All @@ -216,31 +220,31 @@ describe('=> Realm (TypeScript)', function () {
it('options should be optional', async function() {
assert.doesNotThrow(async () => {
const { STRING } = realm.DataTypes;
realm.define('User', { name: STRING });
realm.define('TestUser', { name: STRING });
await realm.sync();
});
});

it('`force` can be passed individually', async function() {
assert.doesNotThrow(async () => {
const { STRING } = realm.DataTypes;
realm.define('User', { name: STRING });
realm.define('TestUser', { name: STRING });
await realm.sync({ force: true });
});
});

it('`alter` can be passed individually', async function() {
assert.doesNotThrow(async () => {
const { STRING } = realm.DataTypes;
realm.define('User', { name: STRING });
realm.define('TestUser', { name: STRING });
await realm.sync({ alter: true });
});
});

it('`force` and `alter` can be passed together', async function() {
assert.doesNotThrow(async () => {
const { STRING } = realm.DataTypes;
realm.define('User', { name: STRING });
realm.define('TestUser', { name: STRING });
await realm.sync({ force: true, alter: true });
});
});
Expand Down
74 changes: 69 additions & 5 deletions test/types/data_types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { strict as assert } from 'assert';
import Realm, { Bone, DataTypes } from '../..';

describe('=> Data types (TypeScript)', function() {
const { STRING, TEXT, BLOB } = DataTypes;

it('Bone.DataTypes', async function() {
assert.equal(Bone.DataTypes, DataTypes);
});
const { STRING, TEXT, BLOB, INTEGER, BIGINT, DATE, BOOLEAN, BINARY, VARBINARY, VIRTUAL, JSON, JSONB } = DataTypes;

it('realm.Bone.DataTypes', async function() {
const realm = new Realm({
Expand All @@ -19,13 +15,81 @@ describe('=> Data types (TypeScript)', function() {

it('STRING', async function() {
assert.equal(STRING(255).toSqlString(), 'VARCHAR(255)');
// default 255
assert.equal(STRING.toSqlString(), 'VARCHAR(255)');
});

it('INTEGER', async function() {
assert.equal(INTEGER(255).toSqlString(), 'INTEGER(255)');
assert.equal(INTEGER(255).UNSIGNED.toSqlString(), 'INTEGER(255) UNSIGNED');
assert.equal(INTEGER(255).ZEROFILL.toSqlString(), 'INTEGER(255) ZEROFILL');

assert.equal(INTEGER.toSqlString(), 'INTEGER');
assert.equal(INTEGER.UNSIGNED.toSqlString(), 'INTEGER UNSIGNED');
assert.equal(INTEGER.ZEROFILL.toSqlString(), 'INTEGER ZEROFILL');

assert.equal(INTEGER(255).toSqlString(), 'INTEGER(255)');
assert.equal(INTEGER(255).UNSIGNED.toSqlString(), 'INTEGER(255) UNSIGNED');
assert.equal(INTEGER(255).ZEROFILL.toSqlString(), 'INTEGER(255) ZEROFILL');
});

it('BIGINT', async function() {
assert.equal(BIGINT(255).toSqlString(), 'BIGINT(255)');
assert.equal(BIGINT(255).UNSIGNED.toSqlString(), 'BIGINT(255) UNSIGNED');
assert.equal(BIGINT(255).ZEROFILL.toSqlString(), 'BIGINT(255) ZEROFILL');

assert.equal(BIGINT.toSqlString(), 'BIGINT');
assert.equal(BIGINT.UNSIGNED.toSqlString(), 'BIGINT UNSIGNED');

assert.equal(BIGINT.ZEROFILL.toSqlString(), 'BIGINT ZEROFILL');
assert.equal(BIGINT(255).toSqlString(), 'BIGINT(255)');
assert.equal(BIGINT(255).UNSIGNED.toSqlString(), 'BIGINT(255) UNSIGNED');
assert.equal(BIGINT(255).ZEROFILL.toSqlString(), 'BIGINT(255) ZEROFILL');
});

it('TEXT', async function() {
assert.equal(TEXT('long').toSqlString(), 'LONGTEXT');
assert.equal(TEXT.toSqlString(), 'TEXT');
});

it('BLOB', async function() {
assert.equal(BLOB('medium').toSqlString(), 'MEDIUMBLOB');
assert.equal(BLOB.toSqlString(), 'BLOB');
});

it('DATE', () => {
assert.equal(DATE.toSqlString(), 'DATETIME');
assert.equal(DATE(3).toSqlString(), 'DATETIME(3)');
});

it('BOOLEAN', () => {
assert.equal(BOOLEAN.toSqlString(), 'BOOLEAN');
})

it('BINARY', () => {
// default 255
assert.equal(BINARY.toSqlString(), 'BINARY(255)');
assert.equal(BINARY(3).toSqlString(), 'BINARY(3)');
});

it('VARBINARY', () => {
// default 255
assert.equal(VARBINARY.toSqlString(), 'VARBINARY(255)');
assert.equal(VARBINARY(3).toSqlString(), 'VARBINARY(3)');
});

it('VIRTUAL', () => {
// default 255
assert.equal(VIRTUAL.toSqlString(), 'VIRTUAL');
});

it('JSON', () => {
// default 255
assert.equal(JSON.toSqlString(), 'TEXT');
});

it('JSONB', () => {
// default 255
assert.equal(JSONB.toSqlString(), 'JSON');
});
});
30 changes: 29 additions & 1 deletion test/unit/data_types.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,37 @@ describe('=> DataTypes.findType()', () => {
});

describe('=> DataTypes.invokable', function() {
const { STRING } = DataTypes.invokable;
const { STRING, INTEGER, TEXT, BLOB, BIGINT } = DataTypes.invokable;

it('should wrap data types to support flexible invoking', async function() {
assert.equal(STRING(255).toSqlString(), 'VARCHAR(255)');
assert.equal(STRING.toSqlString(), 'VARCHAR(255)');

// NOT "INTEGER(1)"
// ref: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length
// Function.length = Function.arguments.length
assert.equal(INTEGER.toSqlString(), 'INTEGER');
assert.equal(INTEGER.UNSIGNED.toSqlString(), 'INTEGER UNSIGNED');
assert.equal(INTEGER.ZEROFILL.toSqlString(), 'INTEGER ZEROFILL');

assert.equal(INTEGER(10).UNSIGNED.toSqlString(), 'INTEGER(10) UNSIGNED');
assert.equal(INTEGER(10).ZEROFILL.toSqlString(), 'INTEGER(10) ZEROFILL');
assert.equal(INTEGER(10).toSqlString(), 'INTEGER(10)');

assert.equal(BIGINT.toSqlString(), 'BIGINT');
assert.equal(BIGINT.UNSIGNED.toSqlString(), 'BIGINT UNSIGNED');
assert.equal(BIGINT.ZEROFILL.toSqlString(), 'BIGINT ZEROFILL');

assert.equal(BIGINT(10).UNSIGNED.toSqlString(), 'BIGINT(10) UNSIGNED');
assert.equal(BIGINT(10).ZEROFILL.toSqlString(), 'BIGINT(10) ZEROFILL');
assert.equal(BIGINT(10).toSqlString(), 'BIGINT(10)');

// NOT "0TEXT"
assert.equal(TEXT.toSqlString(), 'TEXT');
assert.equal(TEXT('tiny').toSqlString(), 'TINYTEXT');

assert.equal(BLOB.toSqlString(), 'BLOB');
assert.equal(BLOB('tiny').toSqlString(), 'TINYBLOB');

});
});
41 changes: 21 additions & 20 deletions types/data_types.d.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
type LENGTH_VARIANTS = 'tiny' | '' | 'medium' | 'long';

interface INVOKABLE<T> {
(length: LENGTH_VARIANTS): T;
(length: number): T;
interface INVOKABLE<T> extends DataType {
(length?: LENGTH_VARIANTS): T;
(length?: number): T;
}

export default class DataType {
toSqlString(): string;

static STRING: typeof STRING & INVOKABLE<STRING>;
static INTEGER: typeof INTEGER & INVOKABLE<INTEGER>;
static BIGINT: typeof BIGINT & INVOKABLE<BIGINT>;
static DECIMAL: typeof DECIMAL & INVOKABLE<DECIMAL>;
static TEXT: typeof TEXT & INVOKABLE<TEXT>;
static BLOB: typeof BLOB & INVOKABLE<BLOB>;
static JSON: typeof JSON & INVOKABLE<JSON>;
static JSONB: typeof JSONB & INVOKABLE<JSONB>;
static BINARY: typeof BINARY & INVOKABLE<BINARY>;
static VARBINARY: typeof VARBINARY & INVOKABLE<VARBINARY>;
static DATE: typeof DATE & INVOKABLE<DATE>;
static DATEONLY: typeof DATEONLY & INVOKABLE<DATEONLY>;
static BOOLEAN: typeof BOOLEAN & INVOKABLE<BOOLEAN>;
static VIRTUAL: typeof VIRTUAL & INVOKABLE<VIRTUAL>;
static STRING: INVOKABLE<STRING>;
static INTEGER: INTEGER & INVOKABLE<INTEGER>;
static BIGINT: BIGINT & INVOKABLE<BIGINT>;
static DECIMAL: DECIMAL & INVOKABLE<DECIMAL>;
static TEXT: INVOKABLE<TEXT>;
static BLOB: INVOKABLE<BLOB>;
static JSON: JSON;
static JSONB: JSONB;
static BINARY: BINARY & INVOKABLE<BINARY>;
static VARBINARY: VARBINARY & INVOKABLE<VARBINARY>;
static DATE: DATE & INVOKABLE<DATE>;
static DATEONLY: DATEONLY;
static BOOLEAN: BOOLEAN;
static VIRTUAL: VIRTUAL;

}

Expand All @@ -35,8 +35,9 @@ declare class INTEGER extends DataType {
dataType: 'integer' | 'bigint' | 'decimal';
length: number;
constructor(length: number);
get UNSIGNED(): this;
get ZEROFILL(): this;
// avoid INTEGER.UNSIGNED.ZEROFILL.UNSIGNED.UNSIGNED
get UNSIGNED(): Omit<this, 'UNSIGNED' | 'ZEROFILL'>;
get ZEROFILL(): Omit<this, 'UNSIGNED' | 'ZEROFILL'>;
}

declare class BIGINT extends INTEGER {
Expand All @@ -53,7 +54,7 @@ declare class DECIMAL extends INTEGER {
declare class TEXT extends DataType {
dataType: 'text';
length: LENGTH_VARIANTS;
constructor(length: LENGTH_VARIANTS);
constructor(length: string);
}

declare class BLOB extends DataType {
Expand Down

0 comments on commit efd1eb0

Please sign in to comment.