Backend half
This commit is contained in:
+282
@@ -0,0 +1,282 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (c) 2015-2024 MariaDB Corporation Ab
|
||||
|
||||
'use strict';
|
||||
|
||||
const FieldType = require('../../const/field-type');
|
||||
const Errors = require('../../misc/errors');
|
||||
|
||||
module.exports.newRow = function (packet, columns) {
|
||||
packet.skip(1); // skip 0x00 header.
|
||||
const len = ~~((columns.length + 9) / 8);
|
||||
const nullBitMap = new Array(len);
|
||||
for (let i = 0; i < len; i++) nullBitMap[i] = packet.readUInt8();
|
||||
return nullBitMap;
|
||||
};
|
||||
module.exports.castWrapper = function (column, packet, opts, nullBitmap, index) {
|
||||
column.string = () => (isNullBitmap(index, nullBitmap) ? null : packet.readStringLengthEncoded());
|
||||
column.buffer = () => (isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded());
|
||||
column.float = () => (isNullBitmap(index, nullBitmap) ? null : packet.readFloat());
|
||||
column.tiny = () =>
|
||||
isNullBitmap(index, nullBitmap) ? null : column.signed() ? packet.readInt8() : packet.readUInt8();
|
||||
column.short = () =>
|
||||
isNullBitmap(index, nullBitmap) ? null : column.signed() ? packet.readInt16() : packet.readUInt16();
|
||||
column.int = () => (isNullBitmap(index, nullBitmap) ? null : packet.readInt32());
|
||||
column.long = () => (isNullBitmap(index, nullBitmap) ? null : packet.readBigInt64());
|
||||
column.decimal = () => (isNullBitmap(index, nullBitmap) ? null : packet.readDecimalLengthEncoded());
|
||||
column.date = () => (isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDate(opts));
|
||||
column.datetime = () => (isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTime());
|
||||
|
||||
column.geometry = () => {
|
||||
let defaultVal = null;
|
||||
if (column.dataTypeName) {
|
||||
switch (column.dataTypeName) {
|
||||
case 'point':
|
||||
defaultVal = { type: 'Point' };
|
||||
break;
|
||||
case 'linestring':
|
||||
defaultVal = { type: 'LineString' };
|
||||
break;
|
||||
case 'polygon':
|
||||
defaultVal = { type: 'Polygon' };
|
||||
break;
|
||||
case 'multipoint':
|
||||
defaultVal = { type: 'MultiPoint' };
|
||||
break;
|
||||
case 'multilinestring':
|
||||
defaultVal = { type: 'MultiLineString' };
|
||||
break;
|
||||
case 'multipolygon':
|
||||
defaultVal = { type: 'MultiPolygon' };
|
||||
break;
|
||||
default:
|
||||
defaultVal = { type: column.dataTypeName };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNullBitmap(index, nullBitmap)) {
|
||||
return defaultVal;
|
||||
}
|
||||
return packet.readGeometry(defaultVal);
|
||||
};
|
||||
};
|
||||
module.exports.parser = function (col, opts) {
|
||||
// set reader function read(col, packet, index, nullBitmap, opts, throwUnexpectedError)
|
||||
// this permit for multi-row result-set to avoid resolving type parsing each data.
|
||||
|
||||
// return constant parser (function not depending on column info other than type)
|
||||
const defaultParser = col.signed()
|
||||
? DEFAULT_SIGNED_PARSER_TYPE[col.columnType]
|
||||
: DEFAULT_UNSIGNED_PARSER_TYPE[col.columnType];
|
||||
if (defaultParser) return defaultParser;
|
||||
|
||||
// parser depending on column info
|
||||
switch (col.columnType) {
|
||||
case FieldType.BIGINT:
|
||||
if (col.signed()) {
|
||||
return opts.bigIntAsNumber || opts.supportBigNumbers ? readBigintAsIntBinarySigned : readBigintBinarySigned;
|
||||
}
|
||||
return opts.bigIntAsNumber || opts.supportBigNumbers ? readBigintAsIntBinaryUnsigned : readBigintBinaryUnsigned;
|
||||
|
||||
case FieldType.DATETIME:
|
||||
case FieldType.TIMESTAMP:
|
||||
return opts.dateStrings ? readTimestampStringBinary.bind(null, col.scale) : readTimestampBinary;
|
||||
|
||||
case FieldType.DECIMAL:
|
||||
case FieldType.NEWDECIMAL:
|
||||
return col.scale === 0 ? readDecimalAsIntBinary : readDecimalBinary;
|
||||
|
||||
case FieldType.GEOMETRY:
|
||||
let defaultVal = col.__getDefaultGeomVal();
|
||||
return readGeometryBinary.bind(null, defaultVal);
|
||||
|
||||
case FieldType.BIT:
|
||||
if (col.columnLength === 1 && opts.bitOneIsBoolean) {
|
||||
return readBitBinaryBoolean;
|
||||
}
|
||||
return readBinaryBuffer;
|
||||
case FieldType.JSON:
|
||||
return opts.jsonStrings ? readStringBinary : readJsonBinary;
|
||||
|
||||
default:
|
||||
if (col.dataTypeFormat && col.dataTypeFormat === 'json' && opts.autoJsonMap) {
|
||||
return readJsonBinary;
|
||||
}
|
||||
if (col.collation.index === 63) {
|
||||
return readBinaryBuffer;
|
||||
}
|
||||
if (col.isSet()) {
|
||||
return readBinarySet;
|
||||
}
|
||||
return readStringBinary;
|
||||
}
|
||||
};
|
||||
|
||||
const isNullBitmap = (index, nullBitmap) => {
|
||||
return (nullBitmap[~~((index + 2) / 8)] & (1 << (index + 2) % 8)) > 0;
|
||||
};
|
||||
|
||||
const readTinyBinarySigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readInt8();
|
||||
const readTinyBinaryUnsigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readUInt8();
|
||||
const readShortBinarySigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readInt16();
|
||||
const readShortBinaryUnsigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readUInt16();
|
||||
const readMediumBinarySigned = (packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
if (isNullBitmap(index, nullBitmap)) {
|
||||
return null;
|
||||
}
|
||||
const result = packet.readInt24();
|
||||
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
|
||||
return result;
|
||||
};
|
||||
const readMediumBinaryUnsigned = (packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
if (isNullBitmap(index, nullBitmap)) {
|
||||
return null;
|
||||
}
|
||||
const result = packet.readUInt24();
|
||||
packet.skip(1); // MEDIUMINT is encoded on 4 bytes in exchanges !
|
||||
return result;
|
||||
};
|
||||
const readIntBinarySigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readInt32();
|
||||
const readIntBinaryUnsigned = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readUInt32();
|
||||
const readFloatBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readFloat();
|
||||
const readDoubleBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readDouble();
|
||||
const readBigintBinaryUnsigned = function (packet, opts, throwUnexpectedError, nullBitmap, index) {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
return packet.readBigUInt64();
|
||||
};
|
||||
const readBigintBinarySigned = function (packet, opts, throwUnexpectedError, nullBitmap, index) {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
return packet.readBigInt64();
|
||||
};
|
||||
|
||||
const readBigintAsIntBinaryUnsigned = function (packet, opts, throwUnexpectedError, nullBitmap, index) {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
const val = packet.readBigUInt64();
|
||||
if (opts.bigIntAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(val))) {
|
||||
return throwUnexpectedError(
|
||||
`value ${val} can't safely be converted to number`,
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_PARSING_PRECISION
|
||||
);
|
||||
}
|
||||
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
|
||||
return val.toString();
|
||||
}
|
||||
return Number(val);
|
||||
};
|
||||
|
||||
const readBigintAsIntBinarySigned = function (packet, opts, throwUnexpectedError, nullBitmap, index) {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
const val = packet.readBigInt64();
|
||||
if (opts.bigIntAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(val))) {
|
||||
return throwUnexpectedError(
|
||||
`value ${val} can't safely be converted to number`,
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_PARSING_PRECISION
|
||||
);
|
||||
}
|
||||
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(val)))) {
|
||||
return val.toString();
|
||||
}
|
||||
return Number(val);
|
||||
};
|
||||
|
||||
const readGeometryBinary = (defaultVal, packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
if (isNullBitmap(index, nullBitmap)) {
|
||||
return defaultVal;
|
||||
}
|
||||
return packet.readGeometry(defaultVal);
|
||||
};
|
||||
const readDateBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDate(opts);
|
||||
const readTimestampBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTime();
|
||||
const readTimestampStringBinary = (scale, packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryDateTimeAsString(scale);
|
||||
const readTimeBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBinaryTime();
|
||||
const readDecimalAsIntBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
//checkNumberRange additional check is only done when
|
||||
// resulting value is an integer
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
const valDec = packet.readDecimalLengthEncoded();
|
||||
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
|
||||
if (opts.decimalAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(valDec))) {
|
||||
return throwUnexpectedError(
|
||||
`value ${valDec} can't safely be converted to number`,
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_PARSING_PRECISION
|
||||
);
|
||||
}
|
||||
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(Number(valDec)))) {
|
||||
return valDec;
|
||||
}
|
||||
return Number(valDec);
|
||||
}
|
||||
return valDec;
|
||||
};
|
||||
const readDecimalBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
const valDec = packet.readDecimalLengthEncoded();
|
||||
if (valDec != null && (opts.decimalAsNumber || opts.supportBigNumbers)) {
|
||||
const numberValue = Number(valDec);
|
||||
if (
|
||||
opts.supportBigNumbers &&
|
||||
(opts.bigNumberStrings || (Number.isInteger(numberValue) && !Number.isSafeInteger(numberValue)))
|
||||
) {
|
||||
return valDec;
|
||||
}
|
||||
return numberValue;
|
||||
}
|
||||
return valDec;
|
||||
};
|
||||
const readJsonBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : JSON.parse(packet.readStringLengthEncoded());
|
||||
const readBitBinaryBoolean = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded()[0] === 1;
|
||||
const readBinaryBuffer = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readBufferLengthEncoded();
|
||||
const readBinarySet = (packet, opts, throwUnexpectedError, nullBitmap, index) => {
|
||||
if (isNullBitmap(index, nullBitmap)) return null;
|
||||
const string = packet.readStringLengthEncoded();
|
||||
return string == null ? null : string === '' ? [] : string.split(',');
|
||||
};
|
||||
const readStringBinary = (packet, opts, throwUnexpectedError, nullBitmap, index) =>
|
||||
isNullBitmap(index, nullBitmap) ? null : packet.readStringLengthEncoded();
|
||||
|
||||
const DEFAULT_SIGNED_PARSER_TYPE = Array(256);
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.TINY] = readTinyBinarySigned;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.YEAR] = readShortBinarySigned;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.SHORT] = readShortBinarySigned;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.INT24] = readMediumBinarySigned;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.INT] = readIntBinarySigned;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.FLOAT] = readFloatBinary;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.DOUBLE] = readDoubleBinary;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.DATE] = readDateBinary;
|
||||
DEFAULT_SIGNED_PARSER_TYPE[FieldType.TIME] = readTimeBinary;
|
||||
|
||||
const DEFAULT_UNSIGNED_PARSER_TYPE = Array(256);
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.TINY] = readTinyBinaryUnsigned;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.YEAR] = readShortBinaryUnsigned;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.SHORT] = readShortBinaryUnsigned;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.INT24] = readMediumBinaryUnsigned;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.INT] = readIntBinaryUnsigned;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.FLOAT] = readFloatBinary;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.DOUBLE] = readDoubleBinary;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.DATE] = readDateBinary;
|
||||
DEFAULT_UNSIGNED_PARSER_TYPE[FieldType.TIME] = readTimeBinary;
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (c) 2015-2024 MariaDB Corporation Ab
|
||||
|
||||
'use strict';
|
||||
|
||||
const FieldType = require('../../const/field-type');
|
||||
const Errors = require('../../misc/errors');
|
||||
|
||||
module.exports.parser = function (col, opts) {
|
||||
// Fast path: For most types, we can directly return the default parser
|
||||
// This avoids the cost of the switch statement for common types
|
||||
const defaultParser = DEFAULT_PARSER_TYPE[col.columnType];
|
||||
if (defaultParser) return defaultParser;
|
||||
|
||||
// Parser depending on column info
|
||||
switch (col.columnType) {
|
||||
case FieldType.DECIMAL:
|
||||
case FieldType.NEWDECIMAL:
|
||||
return col.scale === 0 ? readDecimalAsIntLengthCoded : readDecimalLengthCoded;
|
||||
|
||||
case FieldType.BIGINT:
|
||||
if (opts.bigIntAsNumber || opts.supportBigNumbers) return readBigIntAsNumberLengthCoded;
|
||||
return readBigIntLengthCoded;
|
||||
|
||||
case FieldType.GEOMETRY:
|
||||
const defaultVal = col.__getDefaultGeomVal();
|
||||
return function (packet, opts, throwUnexpectedError) {
|
||||
return packet.readGeometry(defaultVal);
|
||||
};
|
||||
|
||||
case FieldType.BIT:
|
||||
if (col.columnLength === 1 && opts.bitOneIsBoolean) {
|
||||
return readBitAsBoolean;
|
||||
}
|
||||
return readBufferLengthEncoded;
|
||||
|
||||
case FieldType.JSON:
|
||||
return opts.jsonStrings ? readStringLengthEncoded : readJson;
|
||||
|
||||
default:
|
||||
if (col.dataTypeFormat === 'json' && opts.autoJsonMap) {
|
||||
return readJson;
|
||||
}
|
||||
if (col.collation.index === 63) {
|
||||
return readBufferLengthEncoded;
|
||||
}
|
||||
if (col.isSet()) {
|
||||
return readSet;
|
||||
}
|
||||
return readStringLengthEncoded;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.castWrapper = function (column, packet, opts, nullBitmap, index) {
|
||||
const p = packet;
|
||||
|
||||
column.string = () => p.readStringLengthEncoded();
|
||||
column.buffer = () => p.readBufferLengthEncoded();
|
||||
column.float = () => p.readFloatLengthCoded();
|
||||
column.tiny = column.short = column.int = () => p.readIntLengthEncoded();
|
||||
column.long = () => p.readBigIntLengthEncoded();
|
||||
column.decimal = () => p.readDecimalLengthEncoded();
|
||||
column.date = () => p.readDate(opts);
|
||||
column.datetime = () => p.readDateTime();
|
||||
|
||||
// Only define geometry method if needed (likely less common)
|
||||
// Inline the geometry switch case for better performance
|
||||
column.geometry = () => {
|
||||
let defaultVal = null;
|
||||
|
||||
if (column.dataTypeName) {
|
||||
// Use object lookup instead of switch for better performance
|
||||
const geoTypes = {
|
||||
point: { type: 'Point' },
|
||||
linestring: { type: 'LineString' },
|
||||
polygon: { type: 'Polygon' },
|
||||
multipoint: { type: 'MultiPoint' },
|
||||
multilinestring: { type: 'MultiLineString' },
|
||||
multipolygon: { type: 'MultiPolygon' }
|
||||
};
|
||||
|
||||
defaultVal = geoTypes[column.dataTypeName] || { type: column.dataTypeName };
|
||||
}
|
||||
|
||||
return p.readGeometry(defaultVal);
|
||||
};
|
||||
};
|
||||
|
||||
const readIntLengthEncoded = (packet, opts, throwUnexpectedError) => packet.readIntLengthEncoded();
|
||||
const readStringLengthEncoded = (packet, opts, throwUnexpectedError) => packet.readStringLengthEncoded();
|
||||
const readFloatLengthCoded = (packet, opts, throwUnexpectedError) => packet.readFloatLengthCoded();
|
||||
const readBigIntLengthCoded = (packet, opts, throwUnexpectedError) => packet.readBigIntLengthEncoded();
|
||||
const readAsciiStringLengthEncoded = (packet, opts, throwUnexpectedError) => packet.readAsciiStringLengthEncoded();
|
||||
const readBitAsBoolean = (packet, opts, throwUnexpectedError) => {
|
||||
const val = packet.readBufferLengthEncoded();
|
||||
return val == null ? null : val[0] === 1;
|
||||
};
|
||||
const readBufferLengthEncoded = (packet, opts, throwUnexpectedError) => packet.readBufferLengthEncoded();
|
||||
|
||||
const readJson = (packet, opts, throwUnexpectedError) => {
|
||||
const jsonStr = packet.readStringLengthEncoded();
|
||||
return jsonStr === null ? null : JSON.parse(jsonStr);
|
||||
};
|
||||
|
||||
const readSet = (packet, opts, throwUnexpectedError) => {
|
||||
const string = packet.readStringLengthEncoded();
|
||||
return string == null ? null : string === '' ? [] : string.split(',');
|
||||
};
|
||||
|
||||
const readDate = (packet, opts, throwUnexpectedError) =>
|
||||
opts.dateStrings ? packet.readAsciiStringLengthEncoded() : packet.readDate();
|
||||
|
||||
const readTimestamp = (packet, opts, throwUnexpectedError) =>
|
||||
opts.dateStrings ? packet.readAsciiStringLengthEncoded() : packet.readDateTime();
|
||||
|
||||
// Initialize the DEFAULT_PARSER_TYPE array with frequently used types
|
||||
// Use a typed array for performance when accessing elements
|
||||
const DEFAULT_PARSER_TYPE = new Array(256);
|
||||
DEFAULT_PARSER_TYPE[FieldType.TINY] = readIntLengthEncoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.SHORT] = readIntLengthEncoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.INT] = readIntLengthEncoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.INT24] = readIntLengthEncoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.YEAR] = readIntLengthEncoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.FLOAT] = readFloatLengthCoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.DOUBLE] = readFloatLengthCoded;
|
||||
DEFAULT_PARSER_TYPE[FieldType.DATE] = readDate;
|
||||
DEFAULT_PARSER_TYPE[FieldType.DATETIME] = readTimestamp;
|
||||
DEFAULT_PARSER_TYPE[FieldType.TIMESTAMP] = readTimestamp;
|
||||
DEFAULT_PARSER_TYPE[FieldType.TIME] = readAsciiStringLengthEncoded;
|
||||
|
||||
const readBigIntAsNumberLengthCoded = (packet, opts, throwUnexpectedError) => {
|
||||
const len = packet.readUnsignedLength();
|
||||
if (len === null) return null;
|
||||
|
||||
// Fast path for small integers
|
||||
if (len < 16) {
|
||||
const val = packet._atoi(len);
|
||||
// We know we're here because either bigIntAsNumber or supportBigNumbers is true
|
||||
if (opts.supportBigNumbers && opts.bigNumberStrings) {
|
||||
return `${val}`;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
const val = packet.readBigIntFromLen(len);
|
||||
if (opts.bigIntAsNumber && opts.checkNumberRange && !Number.isSafeInteger(Number(val))) {
|
||||
return throwUnexpectedError(
|
||||
`value ${val} can't safely be converted to number`,
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_PARSING_PRECISION
|
||||
);
|
||||
}
|
||||
const numVal = Number(val);
|
||||
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(numVal))) {
|
||||
return val.toString();
|
||||
}
|
||||
|
||||
return numVal;
|
||||
};
|
||||
|
||||
const readDecimalAsIntLengthCoded = (packet, opts, throwUnexpectedError) => {
|
||||
const valDec = packet.readDecimalLengthEncoded();
|
||||
if (valDec === null) return null;
|
||||
|
||||
// Only perform conversions if needed based on options
|
||||
if (!(opts.decimalAsNumber || opts.supportBigNumbers)) return valDec;
|
||||
|
||||
// Convert once
|
||||
const numValue = Number(valDec);
|
||||
|
||||
// Check number range if required
|
||||
if (opts.decimalAsNumber && opts.checkNumberRange && !Number.isSafeInteger(numValue)) {
|
||||
return throwUnexpectedError(
|
||||
`value ${valDec} can't safely be converted to number`,
|
||||
false,
|
||||
null,
|
||||
'42000',
|
||||
Errors.ER_PARSING_PRECISION
|
||||
);
|
||||
}
|
||||
|
||||
// Return string representation for big numbers if needed
|
||||
if (opts.supportBigNumbers && (opts.bigNumberStrings || !Number.isSafeInteger(numValue))) {
|
||||
return valDec;
|
||||
}
|
||||
|
||||
return numValue;
|
||||
};
|
||||
|
||||
const readDecimalLengthCoded = (packet, opts, throwUnexpectedError) => {
|
||||
const valDec = packet.readDecimalLengthEncoded();
|
||||
if (valDec === null) return null;
|
||||
|
||||
// Only perform conversions if needed based on options
|
||||
if (!(opts.decimalAsNumber || opts.supportBigNumbers)) return valDec;
|
||||
|
||||
const numberValue = Number(valDec);
|
||||
|
||||
// Handle big numbers specifically
|
||||
if (
|
||||
opts.supportBigNumbers &&
|
||||
(opts.bigNumberStrings || (Number.isInteger(numberValue) && !Number.isSafeInteger(numberValue)))
|
||||
) {
|
||||
return valDec;
|
||||
}
|
||||
|
||||
return numberValue;
|
||||
};
|
||||
Reference in New Issue
Block a user