Skip to content

Commit 1247c01

Browse files
authored
feat: add support for bigints (backport of sequelize#14485) (sequelize#15413)
1 parent 94beace commit 1247c01

File tree

15 files changed

+270
-62
lines changed

15 files changed

+270
-62
lines changed

src/data-types.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class NUMBER extends ABSTRACT {
211211
return true;
212212
}
213213
_stringify(number) {
214-
if (typeof number === 'number' || typeof number === 'boolean' || number === null || number === undefined) {
214+
if (typeof number === 'number' || typeof number === 'bigint' || typeof number === 'boolean' || number === null || number === undefined) {
215215
return number;
216216
}
217217
if (typeof number.toString === 'function') {

src/dialects/abstract/query-generator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2792,7 +2792,7 @@ class QueryGenerator {
27922792
type: options.type
27932793
});
27942794
}
2795-
if (typeof smth === 'number') {
2795+
if (typeof smth === 'number' || typeof smth === 'bigint') {
27962796
let primaryKeys = factory ? Object.keys(factory.primaryKeys) : [];
27972797

27982798
if (primaryKeys.length > 0) {

src/dialects/db2/query.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const util = require('node:util');
4+
35
const AbstractQuery = require('../abstract/query');
46
const sequelizeErrors = require('../../errors');
57
const parserStore = require('../parserStore')('db2');
@@ -14,15 +16,19 @@ class Query extends AbstractQuery {
1416
}
1517

1618
getSQLTypeFromJsType(value) {
17-
const param = { ParamType: 'INPUT', Data: value };
1819
if (Buffer.isBuffer(value)) {
19-
param.DataType = 'BLOB';
20-
return param;
20+
return { ParamType: 'INPUT', DataType: 'BLOB', Data: value };
21+
}
22+
23+
if (typeof value === 'bigint') {
24+
// The ibm_db module does not handle bigint, send as a string instead:
25+
return value.toString();
2126
}
27+
2228
return value;
2329
}
2430

25-
async _run(connection, sql, parameters) {
31+
async _run(connection, sql, parameters) {
2632
this.sql = sql;
2733
const benchmark = this.sequelize.options.benchmark || this.options.benchmark;
2834
let queryBegin;
@@ -98,10 +104,10 @@ class Query extends AbstractQuery {
98104
}
99105

100106
stmt.execute(params, (err, result, outparams) => {
101-
debug(`executed(${this.connection.uuid || 'default'}):${newSql} ${parameters ? JSON.stringify(parameters) : ''}`);
107+
debug(`executed(${this.connection.uuid || 'default'}):${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`);
102108

103109
if (benchmark) {
104-
this.sequelize.log(`Executed (${ this.connection.uuid || 'default' }): ${ newSql} ${parameters ? JSON.stringify(parameters) : ''}`, Date.now() - queryBegin, this.options);
110+
this.sequelize.log(`Executed (${this.connection.uuid || 'default'}): ${newSql} ${parameters ? util.inspect(parameters, { compact: true, breakLength: Infinity }) : ''}`, Date.now() - queryBegin, this.options);
105111
}
106112

107113
if (err && err.message) {
@@ -454,7 +460,7 @@ class Query extends AbstractQuery {
454460
result = result || this.sql.startsWith('SELECT NAME AS "name", TBNAME AS "tableName", UNIQUERULE AS "keyType", COLNAMES, INDEXTYPE AS "type" FROM SYSIBM.SYSINDEXES');
455461
return result;
456462
}
457-
463+
458464
handleShowIndexesQuery(data) {
459465
let currItem;
460466
const result = [];
@@ -468,7 +474,7 @@ class Query extends AbstractQuery {
468474
unique: item.keyType === 'U',
469475
type: item.type
470476
};
471-
477+
472478
_.forEach(item.COLNAMES.replace(/\+|-/g, x => { return ` ${ x}`; }).split(' '), column => {
473479
let columnName = column.trim();
474480
if ( columnName ) {
@@ -484,7 +490,7 @@ class Query extends AbstractQuery {
484490
result.push(currItem);
485491
}
486492
});
487-
return result;
493+
return result;
488494
}
489495

490496
handleInsertQuery(results, metaData) {

src/dialects/mssql/connection-manager.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ class ConnectionManager extends AbstractConnectionManager {
129129
if (error.message.includes('connect EADDRNOTAVAIL')) {
130130
throw new sequelizeErrors.HostNotReachableError(error);
131131
}
132+
if (error.message.includes('connect EAFNOSUPPORT')) {
133+
throw new sequelizeErrors.HostNotReachableError(error);
134+
}
132135
if (error.message.includes('getaddrinfo ENOTFOUND')) {
133136
throw new sequelizeErrors.HostNotFoundError(error);
134137
}

src/dialects/mssql/query.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const { logger } = require('../../utils/logger');
88

99
const debug = logger.debugContext('sql:mssql');
1010

11+
const minSafeIntegerAsBigInt = BigInt(Number.MIN_SAFE_INTEGER);
12+
const maxSafeIntegerAsBigInt = BigInt(Number.MAX_SAFE_INTEGER);
13+
1114
function getScale(aNum) {
1215
if (!Number.isFinite(aNum)) return 0;
1316
let e = 1;
@@ -21,8 +24,7 @@ class Query extends AbstractQuery {
2124
}
2225

2326
getSQLTypeFromJsType(value, TYPES) {
24-
const paramType = { type: TYPES.VarChar, typeOptions: {} };
25-
paramType.type = TYPES.NVarChar;
27+
const paramType = { type: TYPES.NVarChar, typeOptions: {}, value };
2628
if (typeof value === 'number') {
2729
if (Number.isInteger(value)) {
2830
if (value >= -2147483648 && value <= 2147483647) {
@@ -35,6 +37,13 @@ class Query extends AbstractQuery {
3537
//Default to a reasonable numeric precision/scale pending more sophisticated logic
3638
paramType.typeOptions = { precision: 30, scale: getScale(value) };
3739
}
40+
} else if (typeof value === 'bigint') {
41+
if (value < minSafeIntegerAsBigInt || value > maxSafeIntegerAsBigInt) {
42+
paramType.type = TYPES.VarChar;
43+
paramType.value = value.toString();
44+
} else {
45+
return this.getSQLTypeFromJsType(Number(value), TYPES);
46+
}
3847
} else if (typeof value === 'boolean') {
3948
paramType.type = TYPES.Bit;
4049
}

src/dialects/oracle/data-types.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,18 @@ module.exports = BaseTypes => {
5151
// sending it over the wire as a string,
5252
// We pass it through escape function to remove un-necessary quotes
5353
// this.format in insert/bulkinsert query calls stringify hence we need to convert binary buffer
54-
// to hex string. Since this block is used by both bind (insert/bulkinsert) and
55-
// non-bind (select query where clause) hence we need to
54+
// to hex string. Since this block is used by both bind (insert/bulkinsert) and
55+
// non-bind (select query where clause) hence we need to
5656
// have an operation that supports both
5757
return options.escape(value.toString('hex'));
58-
}
58+
}
5959
return options.escape(value);
6060
}
6161

6262
_getBindDef(oracledb) {
6363
if (this._binary) {
6464
return { type: oracledb.DB_TYPE_RAW, maxSize: this._length };
65-
}
65+
}
6666
return { type: oracledb.DB_TYPE_VARCHAR, maxSize: this._length };
6767
}
6868

@@ -93,7 +93,7 @@ module.exports = BaseTypes => {
9393

9494
_sanitize(value) {
9595
if (typeof value === 'string') {
96-
// If value is a string we return true if among '1' and 'true'
96+
// If value is a string we return true if among '1' and 'true'
9797
// We return false if among '0' and 'false'
9898
// Else return the value as is and let the DB raise error for invalid values
9999
return value === '1' || value === 'true' ? true : value === '0' || value === 'false' ? false : value;
@@ -212,7 +212,7 @@ module.exports = BaseTypes => {
212212
*/
213213
_bindParam(value, options) {
214214
return options.bindParam(value);
215-
}
215+
}
216216
}
217217

218218
DATE.prototype.escape = false;
@@ -302,6 +302,14 @@ module.exports = BaseTypes => {
302302
_getBindDef(oracledb) {
303303
return { type: oracledb.DB_TYPE_NUMBER };
304304
}
305+
306+
_sanitize(value) {
307+
if (typeof value === 'bigint' || typeof value === 'number') {
308+
return value.toString();
309+
}
310+
return value;
311+
}
312+
305313
}
306314

307315
class NUMBER extends BaseTypes.NUMBER {
@@ -335,7 +343,7 @@ module.exports = BaseTypes => {
335343
_stringify(value) {
336344
if (value === Number.POSITIVE_INFINITY) {
337345
return 'inf';
338-
}
346+
}
339347
if (value === Number.NEGATIVE_INFINITY) {
340348
return '-inf';
341349
}
@@ -348,11 +356,11 @@ module.exports = BaseTypes => {
348356
}
349357

350358
class BLOB extends BaseTypes.BLOB {
351-
// Generic hexify returns X'${hex}' but Oracle expects '${hex}' for BLOB datatype
359+
// Generic hexify returns X'${hex}' but Oracle expects '${hex}' for BLOB datatype
352360
_hexify(hex) {
353361
return `'${hex}'`;
354362
}
355-
363+
356364
toSql() {
357365
return 'BLOB';
358366
}
@@ -438,9 +446,9 @@ module.exports = BaseTypes => {
438446
_bindParam(value, options) {
439447
if (typeof value === 'string') {
440448
return options.bindParam(new Date(value));
441-
}
449+
}
442450
return options.bindParam(value);
443-
451+
444452
}
445453
}
446454

0 commit comments

Comments
 (0)