Report hasn't been filed before.
What version of drizzle-orm are you using?
1.0.0-beta.18-7eb39f0
What version of drizzle-kit are you using?
1.0.0-beta.18-7eb39f0
Other packages
No response
Describe the Bug
Issue
The MSSQL real() column type returns imprecise float64 representations of float32 values. A value stored as 0.01 in a SQL Server real column is returned to JavaScript as 0.009999999776482582.
SQL Server's real type is IEEE 754 single-precision (float32, ~7 significant digits). The mssql Node.js driver (tedious) reads the 4-byte float32 from the wire and widens it to a JavaScript number (float64). This widening exposes the float32 representation error -- 0.01 cannot be represented exactly in 32 bits, so the float64 value becomes 0.009999999776482582.
The MsSqlReal class in drizzle-orm/mssql-core/columns/real.js has no mapFromDriverValue override, so the raw widened value is passed through as-is:
var MsSqlReal = class extends MsSqlColumnWithIdentity {
static [entityKind] = "MsSqlReal";
getSQLType() {
return "real";
}
// no mapFromDriverValue -- raw float64 value is used
};
By contrast, MsSqlFloat (which maps to float(53) / float64) does not have this problem because the driver value is already native float64 precision.
Expected behavior:
real() columns should return values rounded to 7 significant digits (the actual precision of float32), so 0.01 in the database comes back as 0.01 in JavaScript, not 0.009999999776482582.
Suggested fix:
Add a mapFromDriverValue to MsSqlReal that rounds to float32 precision:
class MsSqlReal extends MsSqlColumnWithIdentity {
static [entityKind] = "MsSqlReal";
getSQLType() {
return "real";
}
mapFromDriverValue(value: number): number {
return parseFloat(value.toPrecision(7));
}
}
Alternatively, Math.fround(value) could be used, but parseFloat(value.toPrecision(7)) produces cleaner decimal output.
Reproduction
import { drizzle } from 'drizzle-orm/node-mssql';
import { mssqlTable, real, int } from 'drizzle-orm/mssql-core';
const testTable = mssqlTable('test', {
id: int().primaryKey(),
tolerance: real(),
});
// Assume a row with tolerance = 0.01 exists in SQL Server
const rows = await db.select().from(testTable);
console.log(rows[0].tolerance);
// Actual: 0.009999999776482582
// Expected: 0.01
Current workaround
Replace real with a customType that includes fromDriver rounding:
import { customType } from 'drizzle-orm/mssql-core';
const real = customType<{ data: number; driverData: number }>({
dataType() { return 'real'; },
fromDriver(value: number): number {
return parseFloat(value.toPrecision(7));
},
});
Report hasn't been filed before.
What version of
drizzle-ormare you using?1.0.0-beta.18-7eb39f0
What version of
drizzle-kitare you using?1.0.0-beta.18-7eb39f0
Other packages
No response
Describe the Bug
Issue
The MSSQL real() column type returns imprecise float64 representations of float32 values. A value stored as 0.01 in a SQL Server real column is returned to JavaScript as 0.009999999776482582.
SQL Server's real type is IEEE 754 single-precision (float32, ~7 significant digits). The mssql Node.js driver (tedious) reads the 4-byte float32 from the wire and widens it to a JavaScript number (float64). This widening exposes the float32 representation error -- 0.01 cannot be represented exactly in 32 bits, so the float64 value becomes 0.009999999776482582.
The MsSqlReal class in drizzle-orm/mssql-core/columns/real.js has no mapFromDriverValue override, so the raw widened value is passed through as-is:
By contrast, MsSqlFloat (which maps to float(53) / float64) does not have this problem because the driver value is already native float64 precision.
Expected behavior:
real() columns should return values rounded to 7 significant digits (the actual precision of float32), so 0.01 in the database comes back as 0.01 in JavaScript, not 0.009999999776482582.
Suggested fix:
Add a mapFromDriverValue to MsSqlReal that rounds to float32 precision:
Alternatively, Math.fround(value) could be used, but parseFloat(value.toPrecision(7)) produces cleaner decimal output.
Reproduction
Current workaround
Replace real with a customType that includes fromDriver rounding: