Skip to content

Commit

Permalink
feat: add support for bigints (backport of #14485) (#15413)
Browse files Browse the repository at this point in the history
  • Loading branch information
marra85 committed Dec 12, 2022
1 parent 94beace commit 1247c01
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 62 deletions.
2 changes: 1 addition & 1 deletion src/data-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class NUMBER extends ABSTRACT {
return true;
}
_stringify(number) {
if (typeof number === 'number' || typeof number === 'boolean' || number === null || number === undefined) {
if (typeof number === 'number' || typeof number === 'bigint' || typeof number === 'boolean' || number === null || number === undefined) {
return number;
}
if (typeof number.toString === 'function') {
Expand Down
2 changes: 1 addition & 1 deletion src/dialects/abstract/query-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2792,7 +2792,7 @@ class QueryGenerator {
type: options.type
});
}
if (typeof smth === 'number') {
if (typeof smth === 'number' || typeof smth === 'bigint') {
let primaryKeys = factory ? Object.keys(factory.primaryKeys) : [];

if (primaryKeys.length > 0) {
Expand Down
24 changes: 15 additions & 9 deletions src/dialects/db2/query.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const util = require('node:util');

const AbstractQuery = require('../abstract/query');
const sequelizeErrors = require('../../errors');
const parserStore = require('../parserStore')('db2');
Expand All @@ -14,15 +16,19 @@ class Query extends AbstractQuery {
}

getSQLTypeFromJsType(value) {
const param = { ParamType: 'INPUT', Data: value };
if (Buffer.isBuffer(value)) {
param.DataType = 'BLOB';
return param;
return { ParamType: 'INPUT', DataType: 'BLOB', Data: value };
}

if (typeof value === 'bigint') {
// The ibm_db module does not handle bigint, send as a string instead:
return value.toString();
}

return value;
}

async _run(connection, sql, parameters) {
async _run(connection, sql, parameters) {
this.sql = sql;
const benchmark = this.sequelize.options.benchmark || this.options.benchmark;
let queryBegin;
Expand Down Expand Up @@ -98,10 +104,10 @@ class Query extends AbstractQuery {
}

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

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

if (err && err.message) {
Expand Down Expand Up @@ -454,7 +460,7 @@ class Query extends AbstractQuery {
result = result || this.sql.startsWith('SELECT NAME AS "name", TBNAME AS "tableName", UNIQUERULE AS "keyType", COLNAMES, INDEXTYPE AS "type" FROM SYSIBM.SYSINDEXES');
return result;
}

handleShowIndexesQuery(data) {
let currItem;
const result = [];
Expand All @@ -468,7 +474,7 @@ class Query extends AbstractQuery {
unique: item.keyType === 'U',
type: item.type
};

_.forEach(item.COLNAMES.replace(/\+|-/g, x => { return ` ${ x}`; }).split(' '), column => {
let columnName = column.trim();
if ( columnName ) {
Expand All @@ -484,7 +490,7 @@ class Query extends AbstractQuery {
result.push(currItem);
}
});
return result;
return result;
}

handleInsertQuery(results, metaData) {
Expand Down
3 changes: 3 additions & 0 deletions src/dialects/mssql/connection-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class ConnectionManager extends AbstractConnectionManager {
if (error.message.includes('connect EADDRNOTAVAIL')) {
throw new sequelizeErrors.HostNotReachableError(error);
}
if (error.message.includes('connect EAFNOSUPPORT')) {
throw new sequelizeErrors.HostNotReachableError(error);
}
if (error.message.includes('getaddrinfo ENOTFOUND')) {
throw new sequelizeErrors.HostNotFoundError(error);
}
Expand Down
13 changes: 11 additions & 2 deletions src/dialects/mssql/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const { logger } = require('../../utils/logger');

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

const minSafeIntegerAsBigInt = BigInt(Number.MIN_SAFE_INTEGER);
const maxSafeIntegerAsBigInt = BigInt(Number.MAX_SAFE_INTEGER);

function getScale(aNum) {
if (!Number.isFinite(aNum)) return 0;
let e = 1;
Expand All @@ -21,8 +24,7 @@ class Query extends AbstractQuery {
}

getSQLTypeFromJsType(value, TYPES) {
const paramType = { type: TYPES.VarChar, typeOptions: {} };
paramType.type = TYPES.NVarChar;
const paramType = { type: TYPES.NVarChar, typeOptions: {}, value };
if (typeof value === 'number') {
if (Number.isInteger(value)) {
if (value >= -2147483648 && value <= 2147483647) {
Expand All @@ -35,6 +37,13 @@ class Query extends AbstractQuery {
//Default to a reasonable numeric precision/scale pending more sophisticated logic
paramType.typeOptions = { precision: 30, scale: getScale(value) };
}
} else if (typeof value === 'bigint') {
if (value < minSafeIntegerAsBigInt || value > maxSafeIntegerAsBigInt) {
paramType.type = TYPES.VarChar;
paramType.value = value.toString();
} else {
return this.getSQLTypeFromJsType(Number(value), TYPES);
}
} else if (typeof value === 'boolean') {
paramType.type = TYPES.Bit;
}
Expand Down
30 changes: 19 additions & 11 deletions src/dialects/oracle/data-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@ module.exports = BaseTypes => {
// sending it over the wire as a string,
// We pass it through escape function to remove un-necessary quotes
// this.format in insert/bulkinsert query calls stringify hence we need to convert binary buffer
// to hex string. Since this block is used by both bind (insert/bulkinsert) and
// non-bind (select query where clause) hence we need to
// to hex string. Since this block is used by both bind (insert/bulkinsert) and
// non-bind (select query where clause) hence we need to
// have an operation that supports both
return options.escape(value.toString('hex'));
}
}
return options.escape(value);
}

_getBindDef(oracledb) {
if (this._binary) {
return { type: oracledb.DB_TYPE_RAW, maxSize: this._length };
}
}
return { type: oracledb.DB_TYPE_VARCHAR, maxSize: this._length };
}

Expand Down Expand Up @@ -93,7 +93,7 @@ module.exports = BaseTypes => {

_sanitize(value) {
if (typeof value === 'string') {
// If value is a string we return true if among '1' and 'true'
// If value is a string we return true if among '1' and 'true'
// We return false if among '0' and 'false'
// Else return the value as is and let the DB raise error for invalid values
return value === '1' || value === 'true' ? true : value === '0' || value === 'false' ? false : value;
Expand Down Expand Up @@ -212,7 +212,7 @@ module.exports = BaseTypes => {
*/
_bindParam(value, options) {
return options.bindParam(value);
}
}
}

DATE.prototype.escape = false;
Expand Down Expand Up @@ -302,6 +302,14 @@ module.exports = BaseTypes => {
_getBindDef(oracledb) {
return { type: oracledb.DB_TYPE_NUMBER };
}

_sanitize(value) {
if (typeof value === 'bigint' || typeof value === 'number') {
return value.toString();
}
return value;
}

}

class NUMBER extends BaseTypes.NUMBER {
Expand Down Expand Up @@ -335,7 +343,7 @@ module.exports = BaseTypes => {
_stringify(value) {
if (value === Number.POSITIVE_INFINITY) {
return 'inf';
}
}
if (value === Number.NEGATIVE_INFINITY) {
return '-inf';
}
Expand All @@ -348,11 +356,11 @@ module.exports = BaseTypes => {
}

class BLOB extends BaseTypes.BLOB {
// Generic hexify returns X'${hex}' but Oracle expects '${hex}' for BLOB datatype
// Generic hexify returns X'${hex}' but Oracle expects '${hex}' for BLOB datatype
_hexify(hex) {
return `'${hex}'`;
}

toSql() {
return 'BLOB';
}
Expand Down Expand Up @@ -438,9 +446,9 @@ module.exports = BaseTypes => {
_bindParam(value, options) {
if (typeof value === 'string') {
return options.bindParam(new Date(value));
}
}
return options.bindParam(value);

}
}

Expand Down

0 comments on commit 1247c01

Please sign in to comment.