Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/data-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export interface DataType {
generateTypeInfo(parameter: ParameterData, options: InternalConnectionOptions): Buffer;
generateParameterLength(parameter: ParameterData, options: InternalConnectionOptions): Buffer;
generateParameterData(parameter: ParameterData, options: InternalConnectionOptions): Generator<Buffer, void>;
validate(value: any, collation: Collation | undefined): any; // TODO: Refactor 'any' and replace with more specific type.
validate(value: any, collation: Collation | undefined, options?: InternalConnectionOptions): any; // TODO: Refactor 'any' and replace with more specific type.

hasTableName?: boolean;

Expand Down
23 changes: 21 additions & 2 deletions src/data-types/datetime.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { type DataType } from '../data-type';
import DateTimeN from './datetimen';
import { ChronoUnit, LocalDate } from '@js-joda/core';
import { type InternalConnectionOptions } from '../connection';

import { Collation } from '../collation';

const EPOCH_DATE = LocalDate.ofYearDay(1900, 1);
const NULL_LENGTH = Buffer.from([0x00]);
const DATA_LENGTH = Buffer.from([0x08]);

const MIN_DATE = new Date('January 1, 1753');
const MAX_DATE = new Date('December 31, 9999');


const DateTime: DataType = {
id: 0x3D,
type: 'DATETIME',
Expand Down Expand Up @@ -34,7 +41,7 @@ const DateTime: DataType = {

const value = parameter.value as any; // Temporary solution. Remove 'any' later.

let date;
let date: LocalDate;
if (options.useUTC) {
date = LocalDate.of(value.getUTCFullYear(), value.getUTCMonth() + 1, value.getUTCDate());
} else {
Expand Down Expand Up @@ -72,7 +79,7 @@ const DateTime: DataType = {
},

// TODO: type 'any' needs to be revisited.
validate: function(value): null | number {
validate: function(value: any, collation: Collation | undefined, options: InternalConnectionOptions): null | number {
if (value == null) {
return null;
}
Expand All @@ -85,6 +92,18 @@ const DateTime: DataType = {
throw new TypeError('Invalid date.');
}

value = value as Date;

// TODO: check date range: January 1, 1753, through December 31, 9999
// : time range: 00:00:00 through 23:59:59.997
if (options && options.useUTC) {
value = new Date(value.toUTCString());
}

if (value < MIN_DATE || value > MAX_DATE) {
throw new TypeError('Out of range.');
}

return value;
}
};
Expand Down
26 changes: 24 additions & 2 deletions src/data-types/smalldatetime.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { type InternalConnectionOptions } from '../connection';
import { type DataType } from '../data-type';
import DateTimeN from './datetimen';

import { Collation } from '../collation';
const EPOCH_DATE = new Date(1900, 0, 1);
const UTC_EPOCH_DATE = new Date(Date.UTC(1900, 0, 1));

const MIN_DATE = new Date(1900, 1, 1);
const MAX_DATE = new Date(2079, 5, 6, 23, 59, 59, 0);

const DATA_LENGTH = Buffer.from([0x04]);
const NULL_LENGTH = Buffer.from([0x00]);

Expand Down Expand Up @@ -51,7 +55,7 @@ const SmallDateTime: DataType = {
yield buffer;
},

validate: function(value): null | Date {
validate: function(value, collation: Collation | undefined, options: InternalConnectionOptions): null | Date {
if (value == null) {
return null;
}
Expand All @@ -64,6 +68,24 @@ const SmallDateTime: DataType = {
throw new TypeError('Invalid date.');
}

value = value as Date;

if (options && options.useUTC) {
value = new Date(value.toUTCString());
}

if (value < EPOCH_DATE) {
throw new TypeError('Out of range.');
}

if (value.getFullYear() < 1900) {
throw new TypeError('Out of range.');
}

if (value < MIN_DATE || value > MAX_DATE) {
throw new TypeError('Out of range.');
}

return value;
}
};
Expand Down
46 changes: 43 additions & 3 deletions test/unit/data-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,20 @@ describe('DateTime', function() {
assert.deepEqual(result, expected);
});
});

describe('.validate', function() {
it('returns a TypeError for dates that are below January 1, 1753', function() {
assert.throws(() => {
TYPES.DateTime.validate(new Date('January 1, 1752'));
}, TypeError, 'Out of range.');
});

it('returns a TypeError for dates that are greater than December 31, 9999', function() {
assert.throws(() => {
TYPES.DateTime.validate(new Date('December 31, 10000'));
}, TypeError, 'Out of range.');
});
});
});

describe('DateTime2', function() {
Expand Down Expand Up @@ -829,7 +843,7 @@ describe('NVarChar', function() {

describe('.generateTypeInfo', function() {
it('returns the correct type information', function() {
// Length <= Maximum Length
// Length <= Maximum Length
const type = TYPES.NVarChar;
const expected = Buffer.from([0xE7, 2, 0, 0x00, 0x00, 0x00, 0x00, 0x00]);

Expand Down Expand Up @@ -919,6 +933,32 @@ describe('SmallDateTime', function() {
assert.deepEqual(result, expected);
});
});

describe('.validate', function() {
it('throws Invalid Date error for NaN input', function() {
assert.throws(() => {
TYPES.SmallDateTime.validate('string');
}, TypeError, 'Invalid date.');
});

it('throws Out of Range error for dates out of range', function() {
assert.throws(() => {
TYPES.SmallDateTime.validate(new Date('January 1, 1899'));
}, TypeError, 'Out of range.');

assert.throws(() => {
TYPES.SmallDateTime.validate(new Date('January 1, 2080'));
}, TypeError, 'Out of range.');

assert.throws(() => {
TYPES.SmallDateTime.validate(new Date('July 1, 2079'));
}, TypeError, 'Out of range.');

assert.throws(() => {
TYPES.SmallDateTime.validate(new Date('June 7, 2079'));
}, TypeError, 'Out of range.');
});
});
});

describe('SmallInt', function() {
Expand Down Expand Up @@ -1152,7 +1192,7 @@ describe('TVP', function() {
TYPES.TVP.generateParameterLength({
value: {
columns: [{ name: 'user_id', type: TYPES.Int }],
rows: [[ 15 ], [ 16 ]]
rows: [[15], [16]]
}
}),
Buffer.from([0x01, 0x00])
Expand All @@ -1164,7 +1204,7 @@ describe('TVP', function() {
it('correctly converts TVP table values', function() {
const value = {
columns: [{ name: 'user_id', type: TYPES.Int }],
rows: [[ 15 ]]
rows: [[15]]
};
const expected = Buffer.from('0000000000002604000001040f00000000', 'hex');
const parameterValue = { value };
Expand Down