Skip to content

feat: implement SQL type inference for MySQL and MSSQL, add tests for type inference functions#181

Open
durlabhjain wants to merge 1 commit into
mainfrom
durlabh/optmize-sql-parameter-type-inference
Open

feat: implement SQL type inference for MySQL and MSSQL, add tests for type inference functions#181
durlabhjain wants to merge 1 commit into
mainfrom
durlabh/optmize-sql-parameter-type-inference

Conversation

@durlabhjain

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings July 13, 2026 18:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces centralized SQL parameter type inference (primarily for MSSQL) and wires it into the shared Sql parameter-binding paths, while keeping MySQL behavior aligned with mysql2’s expectations. It also refactors existing decimal inference logic to reuse the new implementation and adds unit tests around the inference helpers.

Changes:

  • Added lib/sql-type-inference.js with MSSQL-focused type inference (ASCII-aware strings, bucketed lengths, bucketed Decimal precision/scale, scalar vs batch behavior).
  • Updated lib/sql.js to use inference for default parameter binding, added optional schema-driven type resolution via schemaTypes / schemaDrivenTypes, plus schema caching utilities.
  • Updated lib/mysql.js to override default inference so MySQL bindings use mysql.Types.* codes (or null) instead of MSSQL type constructors; added tests for inference helpers.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/sql-type-inference.test.js Adds unit tests for new inference helpers (currently has assertion issues noted in comments).
lib/sql.js Integrates inference into parameter binding; adds schema discovery/cache + schema-driven resolution options.
lib/sql-type-inference.js New module implementing MSSQL type inference and bucketing logic.
lib/mysql.js Overrides inference methods so MySQL continues using mysql2-appropriate type codes.
lib/business/business-base.mjs Reuses shared getDecimalSqlType instead of maintaining an inline implementation.

Comment on lines +29 to +44
test('inferSqlType: whole numbers map to Int within Int32 range', () => {
const sqlType = typeOf(inferSqlType(42));
assert.equal(sqlType.type, mssql.Int);
});

test('inferSqlType: whole numbers outside Int32 range map to BigInt', () => {
const sqlType = typeOf(inferSqlType(9999999999));
assert.equal(sqlType.type, mssql.BigInt);
});

test('inferSqlType: never infers TinyInt/SmallInt for a lone scalar (avoids plan-cache fragmentation)', () => {
for (const n of [1, 5, 200, 500]) {
const sqlType = typeOf(inferSqlType(n));
assert.equal(sqlType.type, mssql.Int, `expected Int for scalar ${n}, not a narrower type`);
}
});
Comment on lines +46 to +62
test('inferSqlType: fractional numbers map to Decimal, not Float', () => {
const sqlType = inferSqlType(12.5);
assert.equal(sqlType.type, mssql.Decimal);
assert.ok(sqlType.precision >= 3);
assert.ok(sqlType.scale >= 1);
});

test('inferSqlType: ASCII strings map to VarChar', () => {
const sqlType = inferSqlType('hello');
assert.equal(sqlType.type, mssql.VarChar);
assert.ok(sqlType.length >= 5);
});

test('inferSqlType: non-ASCII strings map to NVarChar', () => {
const sqlType = inferSqlType('Café');
assert.equal(sqlType.type, mssql.NVarChar);
});
Comment on lines +71 to +75
test('inferSqlType: Buffers map to VarBinary with a bucketed length', () => {
const sqlType = inferSqlType(Buffer.from('hello world'));
assert.equal(sqlType.type, mssql.VarBinary);
assert.ok(sqlType.length >= 11);
});
Comment on lines +101 to +109
test('inferBatchSqlType: scans every row, not just the first (fractional value later in the batch)', () => {
const sqlType = typeOf(inferBatchSqlType([1, 2, 3.5]));
assert.equal(sqlType.type, mssql.Decimal);
});

test('inferBatchSqlType: scans every row for strings (non-ASCII later in the batch)', () => {
const sqlType = inferBatchSqlType(['Alpha', 'Beta', 'Café']);
assert.equal(sqlType.type, mssql.NVarChar);
});
Comment thread lib/sql.js
Comment on lines +515 to +529
resolveColumnSqlType({ tableName, columnName, value }) {
if (tableName) {
const staticOverride = this.schemaTypes?.[tableName]?.[columnName] || this.schemaTypes?.[this._parseTableName(tableName).name]?.[columnName];
if (staticOverride) {
return staticOverride.sqlType || staticOverride;
}
if (this.schemaDrivenTypes) {
const cached = this._schemaCache.get(this._parseTableName(tableName).key);
if (cached && cached[columnName]) {
return cached[columnName];
}
}
}
return this.inferDefaultSqlType(value);
}
Comment thread lib/sql.js
request.input(paramName, sqlType, result.value);
} else {
request.input(paramName, result.value);
request.input(paramName, this.resolveColumnSqlType({ tableName, columnName: paramName, value: result.value }), result.value);
Comment thread lib/sql.js
request.input(paramName, sqlType, value);
} else {
request.input(paramName, value);
request.input(paramName, this.resolveColumnSqlType({ tableName, columnName: paramName, value }), value);
Comment thread lib/sql.js
Comment on lines +459 to +463
async discoverColumnTypes(tableName) {
const { schema, name, key } = this._parseTableName(tableName);
if (this._schemaCache.has(key)) {
return this._schemaCache.get(key);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants